fuels_accounts/
predicate.rs

1use std::{fmt::Debug, fs};
2
3#[cfg(feature = "std")]
4use fuels_core::types::{coin_type_id::CoinTypeId, input::Input, AssetId};
5use fuels_core::{
6    error,
7    types::{bech32::Bech32Address, errors::Result},
8    Configurables,
9};
10
11#[cfg(feature = "std")]
12use crate::accounts_utils::try_provider_error;
13#[cfg(feature = "std")]
14use crate::{provider::Provider, Account, ViewOnlyAccount};
15
16#[derive(Debug, Clone)]
17pub struct Predicate {
18    address: Bech32Address,
19    code: Vec<u8>,
20    data: Vec<u8>,
21    #[cfg(feature = "std")]
22    provider: Option<Provider>,
23}
24
25impl Predicate {
26    pub fn address(&self) -> &Bech32Address {
27        &self.address
28    }
29
30    pub fn code(&self) -> &[u8] {
31        &self.code
32    }
33
34    pub fn data(&self) -> &[u8] {
35        &self.data
36    }
37
38    pub fn calculate_address(code: &[u8]) -> Bech32Address {
39        fuel_tx::Input::predicate_owner(code).into()
40    }
41
42    pub fn load_from(file_path: &str) -> Result<Self> {
43        let code = fs::read(file_path).map_err(|e| {
44            error!(
45                IO,
46                "could not read predicate binary {file_path:?}. Reason: {e}"
47            )
48        })?;
49        Ok(Self::from_code(code))
50    }
51
52    pub fn from_code(code: Vec<u8>) -> Self {
53        Self {
54            address: Self::calculate_address(&code),
55            code,
56            data: Default::default(),
57            #[cfg(feature = "std")]
58            provider: None,
59        }
60    }
61
62    pub fn with_data(mut self, data: Vec<u8>) -> Self {
63        self.data = data;
64        self
65    }
66
67    pub fn with_code(self, code: Vec<u8>) -> Self {
68        let address = Self::calculate_address(&code);
69        Self {
70            code,
71            address,
72            ..self
73        }
74    }
75
76    pub fn with_configurables(mut self, configurables: impl Into<Configurables>) -> Self {
77        let configurables: Configurables = configurables.into();
78        configurables.update_constants_in(&mut self.code);
79        let address = Self::calculate_address(&self.code);
80        self.address = address;
81        self
82    }
83}
84
85#[cfg(feature = "std")]
86impl Predicate {
87    pub fn provider(&self) -> Option<&Provider> {
88        self.provider.as_ref()
89    }
90
91    pub fn set_provider(&mut self, provider: Provider) {
92        self.provider = Some(provider);
93    }
94
95    pub fn with_provider(self, provider: Provider) -> Self {
96        Self {
97            provider: Some(provider),
98            ..self
99        }
100    }
101}
102
103#[cfg(feature = "std")]
104#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
105impl ViewOnlyAccount for Predicate {
106    fn address(&self) -> &Bech32Address {
107        self.address()
108    }
109
110    fn try_provider(&self) -> Result<&Provider> {
111        self.provider.as_ref().ok_or_else(try_provider_error)
112    }
113
114    async fn get_asset_inputs_for_amount(
115        &self,
116        asset_id: AssetId,
117        amount: u64,
118        excluded_coins: Option<Vec<CoinTypeId>>,
119    ) -> Result<Vec<Input>> {
120        Ok(self
121            .get_spendable_resources(asset_id, amount, excluded_coins)
122            .await?
123            .into_iter()
124            .map(|resource| {
125                Input::resource_predicate(resource, self.code.clone(), self.data.clone())
126            })
127            .collect::<Vec<Input>>())
128    }
129}
130
131#[cfg(feature = "std")]
132impl Account for Predicate {}