1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use std::{path::Path, sync::Arc};
use crate::{
core::parse_zil,
core::{DeployContractResponse, ZilAddress},
middlewares::Middleware,
transaction::{Transaction, TransactionBuilder, TransactionParams},
Error,
};
use super::{compress_contract, BaseContract, Init};
pub struct Factory<T: Middleware> {
client: Arc<T>,
}
impl<T: Middleware> Factory<T> {
pub fn new(client: Arc<T>) -> Self {
Self { client }
}
/// The `deploy_from_file` function deploys a contract from a file path, with the option to override
/// transaction parameters.
///
/// Arguments:
///
/// * `path`: The `path` parameter is a reference to a `Path` object, which represents the path to a
/// file. It is used to specify the location of the file from which the contract code will be read.
/// * `init`: The `init` parameter is of type `Init`. It represents the initialization parameters for
/// the contract being deployed. The specific structure and fields of the `Init` type would depend on
/// the contract being deployed.
/// * `overridden_params`: `overridden_params` is an optional parameter of type `TransactionParams`. It
/// allows you to override the default transaction parameters when deploying the contract. If you don't
/// want to override any parameters, you can pass `None` as the value for this parameter.
/// * `do_contract_compression`: Set it to true if you want your contract gets compressed before deployment.
///
/// Returns:
///
/// a Result object with a value of type `BaseContract<T>` if the operation is successful, or an Error
/// object if there is an error.
/// # Example
/// ```
/// use zilliqa_rs::providers::{Http, Provider};
/// use zilliqa_rs::contract::ScillaVariable;
/// use zilliqa_rs::signers::LocalWallet;
/// use zilliqa_rs::contract::Init;
/// use zilliqa_rs::contract::ContractFactory;
/// use std::path::PathBuf;
///
/// #[tokio::main]
/// async fn main() -> anyhow::Result<()> {
/// const END_POINT: &str = "http://localhost:5555";
///
/// let wallet = "d96e9eb5b782a80ea153c937fa83e5948485fbfc8b7e7c069d7b914dbc350aba".parse::<LocalWallet>()?;
///
/// let provider = Provider::<Http>::try_from(END_POINT)?
/// .with_chain_id(222)
/// .with_signer(wallet.clone());
///
/// let factory = ContractFactory::new(provider.into());
/// let init = Init(vec![ScillaVariable::new_from_str("_scilla_version", "Uint32", "0")]);
/// let contract = factory.deploy_from_file(&PathBuf::from("./tests/contracts/Timestamp.scilla"), init, None, false).await?;
/// println!("addr: {:?}", contract);
/// Ok(())
/// }
/// ```
pub async fn deploy_from_file(
&self,
path: &Path,
init: Init,
overridden_params: Option<TransactionParams>,
do_contract_compression: bool,
) -> Result<BaseContract<T>, Error> {
let contract_code = {
let code = std::fs::read_to_string(path)?;
if do_contract_compression {
compress_contract(&code)?
} else {
code
}
};
self.deploy_str(contract_code, init, overridden_params).await
}
/// The `deploy_str` function deploys a contract with the given code and initialization parameters, and
/// returns a `BaseContract` object.
///
/// Arguments:
///
/// * `contract_code`: A string containing the code of the contract to be deployed.
/// * `init`: The `init` parameter is of type `Init`, which is a custom struct or enum that contains the
/// initialization data for the contract.
/// * `overridden_params`: `overridden_params` is an optional parameter of type
/// `Option<TransactionParams>`. It allows the caller to provide custom transaction parameters for
/// deploying the contract.
///
/// Returns:
///
/// The function `deploy_str` returns a `Result` containing either a `BaseContract<T>` or an `Error`.
/// # Example
/// ```
/// use zilliqa_rs::providers::{Http, Provider};
/// use zilliqa_rs::contract::ScillaVariable;
/// use zilliqa_rs::signers::LocalWallet;
/// use zilliqa_rs::contract::Init;
/// use zilliqa_rs::contract::ContractFactory;
/// use std::path::PathBuf;
///
/// #[tokio::main]
/// async fn main() -> anyhow::Result<()> {
/// const END_POINT: &str = "http://localhost:5555";
///
/// let wallet = "d96e9eb5b782a80ea153c937fa83e5948485fbfc8b7e7c069d7b914dbc350aba".parse::<LocalWallet>()?;
///
/// let provider = Provider::<Http>::try_from(END_POINT)?
/// .with_chain_id(222)
/// .with_signer(wallet.clone());
///
/// let factory = ContractFactory::new(provider.into());
/// let init = Init(vec![ScillaVariable::new_from_str("_scilla_version", "Uint32", "0")]);
/// let contract = factory.deploy_str(include_str!("../../tests/contracts/Timestamp.scilla").to_string(), init, None).await?;
/// println!("addr: {:?}", contract);
/// Ok(())
/// }
/// ```
pub async fn deploy_str(
&self,
contract_code: String,
init: Init,
overridden_params: Option<TransactionParams>,
) -> Result<BaseContract<T>, Error> {
let tx = overridden_params
.map(TransactionBuilder::from)
.unwrap_or_default()
.to_address(ZilAddress::nil())
.amount_if_none(0_u128)
.code(contract_code)
.data(serde_json::to_string(&init)?)
.gas_price_if_none(parse_zil("0.002")?)
.gas_limit_if_none(10000u64)
.build();
let response: DeployContractResponse = self.client.send_transaction_without_confirm(tx).await?;
let transaction = Transaction::new(response.response.tran_id, self.client.provider());
transaction.confirm().await?;
Ok(BaseContract {
address: response.contract_address,
client: self.client.clone(),
})
}
}