fuels_accounts/
predicate.rs

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