1use super::{
16 balance_to_deposit_limit,
17 InstantiateDryRunResult,
18 Keypair,
19};
20use crate::{
21 backend::BuilderClient,
22 builders::CreateBuilderPartial,
23 CallBuilderFinal,
24 CallDryRunResult,
25 CallResult,
26 ContractsBackend,
27 InstantiationResult,
28 UploadResult,
29 H256,
30};
31use ink_env::Environment;
32use ink_primitives::{
33 reflect::{
34 AbiDecodeWith,
35 AbiEncodeWith,
36 },
37 DepositLimit,
38};
39use sp_weights::Weight;
40use std::marker::PhantomData;
41
42pub struct CallBuilder<'a, E, Args, RetType, B, Abi>
44where
45 E: Environment,
46 Args: AbiEncodeWith<Abi> + Clone,
47 RetType: Send + AbiDecodeWith<Abi>,
48
49 B: BuilderClient<E>,
50 Abi: Clone,
51{
52 client: &'a mut B,
53 caller: &'a Keypair,
54 message: &'a CallBuilderFinal<E, Args, RetType, Abi>,
55 value: E::Balance,
56 extra_gas_portion: Option<u64>,
57 gas_limit: Option<Weight>,
58 storage_deposit_limit: E::Balance,
59}
60
61impl<'a, E, Args, RetType, B, Abi> CallBuilder<'a, E, Args, RetType, B, Abi>
62where
63 E: Environment,
64 Args: Sync + AbiEncodeWith<Abi> + Clone,
65 RetType: Send + AbiDecodeWith<Abi>,
66
67 B: BuilderClient<E>,
68 Abi: Sync + Clone,
69{
70 pub fn new(
72 client: &'a mut B,
73 caller: &'a Keypair,
74 message: &'a CallBuilderFinal<E, Args, RetType, Abi>,
75 ) -> CallBuilder<'a, E, Args, RetType, B, Abi>
76 where
77 E::Balance: From<u32>,
78 {
79 Self {
80 client,
81 caller,
82 message,
83 value: 0u32.into(),
84 extra_gas_portion: None,
85 gas_limit: None,
86 storage_deposit_limit: 0u32.into(),
87 }
88 }
89
90 pub fn value(&mut self, value: E::Balance) -> &mut Self {
92 self.value = value;
93 self
94 }
95
96 pub fn extra_gas_portion(&mut self, per_cent: u64) -> &mut Self {
105 if per_cent == 0 {
106 self.extra_gas_portion = None
107 } else {
108 self.extra_gas_portion = Some(per_cent)
109 }
110 self
111 }
112
113 pub fn gas_limit(&mut self, limit: Weight) -> &mut Self {
120 if limit == Weight::from_parts(0, 0) {
121 self.gas_limit = None
122 } else {
123 self.gas_limit = Some(limit)
124 }
125 self
126 }
127
128 pub fn storage_deposit_limit(
130 &mut self,
131 storage_deposit_limit: E::Balance,
132 ) -> &mut Self {
133 self.storage_deposit_limit = storage_deposit_limit;
134 self
135 }
136
137 pub async fn submit(
142 &mut self,
143 ) -> Result<CallResult<E, RetType, B::EventLog>, B::Error>
144 where
145 CallBuilderFinal<E, Args, RetType, Abi>: Clone,
146 {
147 let _map = B::map_account(self.client, self.caller).await; let dry_run = B::bare_call_dry_run(
150 self.client,
151 self.caller,
152 self.message,
153 self.value,
154 balance_to_deposit_limit::<E>(self.storage_deposit_limit),
155 )
156 .await?;
157
158 let gas_limit = if let Some(limit) = self.gas_limit {
159 limit
160 } else {
161 let gas_required = dry_run.exec_result.gas_required;
162 let proof_size = gas_required.proof_size();
163 let ref_time = gas_required.ref_time();
164 calculate_weight(proof_size, ref_time, self.extra_gas_portion)
165 };
166
167 let (events, trace) = B::bare_call(
168 self.client,
169 self.caller,
170 self.message,
171 self.value,
172 gas_limit,
173 DepositLimit::Balance(dry_run.exec_result.storage_deposit.charge_or_zero()),
175 )
176 .await?;
177
178 Ok(CallResult {
179 dry_run,
180 events,
181 trace,
182 })
183 }
184
185 pub async fn dry_run(&mut self) -> Result<CallDryRunResult<E, RetType>, B::Error>
187 where
188 CallBuilderFinal<E, Args, RetType, Abi>: Clone,
189 {
190 B::bare_call_dry_run(
191 self.client,
192 self.caller,
193 self.message,
194 self.value,
195 balance_to_deposit_limit::<E>(self.storage_deposit_limit),
196 )
197 .await
198 }
199}
200
201pub struct InstantiateBuilder<'a, E, Contract, Args, R, B, Abi>
203where
204 E: Environment,
205 Args: AbiEncodeWith<Abi> + Clone,
206 Contract: Clone,
207
208 B: ContractsBackend<E>,
209{
210 client: &'a mut B,
211 caller: &'a Keypair,
212 contract_name: &'a str,
213 constructor: &'a mut CreateBuilderPartial<E, Contract, Args, R, Abi>,
214 value: E::Balance,
215 extra_gas_portion: Option<u64>,
216 gas_limit: Option<Weight>,
217 storage_deposit_limit: DepositLimit<E::Balance>,
218}
219
220impl<'a, E, Contract, Args, R, B, Abi>
221 InstantiateBuilder<'a, E, Contract, Args, R, B, Abi>
222where
223 E: Environment,
224 Args: AbiEncodeWith<Abi> + Clone + Send + Sync,
225 Contract: Clone,
226 B: BuilderClient<E>,
227 Abi: Send + Sync + Clone,
228{
229 pub fn new(
231 client: &'a mut B,
232 caller: &'a Keypair,
233 contract_name: &'a str,
234 constructor: &'a mut CreateBuilderPartial<E, Contract, Args, R, Abi>,
235 ) -> InstantiateBuilder<'a, E, Contract, Args, R, B, Abi>
236 where
237 E::Balance: From<u32>,
238 {
239 Self {
240 client,
241 caller,
242 contract_name,
243 constructor,
244 value: 0u32.into(),
245 extra_gas_portion: None,
246 gas_limit: None,
247 storage_deposit_limit: DepositLimit::Unchecked,
248 }
249 }
250
251 pub fn value(&mut self, value: E::Balance) -> &mut Self {
253 self.value = value;
254 self
255 }
256
257 pub fn extra_gas_portion(&mut self, per_cent: u64) -> &mut Self {
266 if per_cent == 0 {
267 self.extra_gas_portion = None
268 } else {
269 self.extra_gas_portion = Some(per_cent)
270 }
271 self
272 }
273
274 pub fn gas_limit(&mut self, limit: Weight) -> &mut Self {
281 if limit == Weight::from_parts(0, 0) {
282 self.gas_limit = None
283 } else {
284 self.gas_limit = Some(limit)
285 }
286 self
287 }
288
289 pub fn storage_deposit_limit(
291 &mut self,
292 storage_deposit_limit: DepositLimit<E::Balance>,
293 ) -> &mut Self {
294 self.storage_deposit_limit = storage_deposit_limit;
295 self
296 }
297
298 pub async fn submit(
303 &mut self,
304 ) -> Result<InstantiationResult<E, B::EventLog>, B::Error> {
305 let _map = B::map_account(self.client, self.caller).await; let dry_run = B::bare_instantiate_dry_run(
309 self.client,
310 self.contract_name,
311 self.caller,
312 self.constructor,
313 self.value,
314 self.storage_deposit_limit.clone(),
315 )
316 .await?;
317
318 let gas_limit = if let Some(limit) = self.gas_limit {
319 limit
320 } else {
321 let gas_required = dry_run.contract_result.gas_required;
322 let proof_size = gas_required.proof_size();
323 let ref_time = gas_required.ref_time();
324 calculate_weight(proof_size, ref_time, self.extra_gas_portion)
325 };
326
327 let instantiate_result = B::bare_instantiate(
328 self.client,
329 self.contract_name,
330 self.caller,
331 self.constructor,
332 self.value,
333 gas_limit,
334 balance_to_deposit_limit::<E>(
335 dry_run.contract_result.storage_deposit.charge_or_zero(),
336 ),
337 )
338 .await?;
339
340 Ok(InstantiationResult {
341 addr: instantiate_result.addr,
342 dry_run,
343 events: instantiate_result.events,
344 trace: instantiate_result.trace,
345 })
346 }
347
348 pub async fn dry_run(&mut self) -> Result<InstantiateDryRunResult<E>, B::Error> {
350 B::bare_instantiate_dry_run(
351 self.client,
352 self.contract_name,
353 self.caller,
354 self.constructor,
355 self.value,
356 self.storage_deposit_limit.clone(),
357 )
358 .await
359 }
360}
361
362pub struct UploadBuilder<'a, E, B>
364where
365 E: Environment,
366 B: BuilderClient<E>,
367{
368 client: &'a mut B,
369 contract_name: &'a str,
370 caller: &'a Keypair,
371 storage_deposit_limit: E::Balance,
372}
373
374impl<'a, E, B> UploadBuilder<'a, E, B>
375where
376 E: Environment,
377 B: BuilderClient<E>,
378{
379 pub fn new(client: &'a mut B, contract_name: &'a str, caller: &'a Keypair) -> Self {
381 Self {
382 client,
383 contract_name,
384 caller,
385 storage_deposit_limit: 0u32.into(),
386 }
387 }
388
389 pub fn storage_deposit_limit(
391 &mut self,
392 storage_deposit_limit: E::Balance,
393 ) -> &mut Self {
394 self.storage_deposit_limit = storage_deposit_limit;
395 self
396 }
397
398 pub async fn submit(&mut self) -> Result<UploadResult<E, B::EventLog>, B::Error> {
400 B::bare_upload(
401 self.client,
402 self.contract_name,
403 self.caller,
404 self.storage_deposit_limit,
405 )
406 .await
407 }
408}
409
410pub struct RemoveCodeBuilder<'a, E, B>
412where
413 E: Environment,
414 B: BuilderClient<E>,
415{
416 client: &'a mut B,
417 caller: &'a Keypair,
418 code_hash: crate::H256,
419 _phantom: PhantomData<fn() -> E>,
420}
421
422impl<'a, E, B> RemoveCodeBuilder<'a, E, B>
423where
424 E: Environment,
425 B: BuilderClient<E>,
426{
427 pub fn new(client: &'a mut B, caller: &'a Keypair, code_hash: H256) -> Self {
429 Self {
430 client,
431 caller,
432 code_hash,
433 _phantom: Default::default(),
434 }
435 }
436
437 pub async fn submit(&mut self) -> Result<B::EventLog, B::Error> {
439 B::bare_remove_code(self.client, self.caller, self.code_hash).await
440 }
441}
442
443fn calculate_weight(
444 mut proof_size: u64,
445 mut ref_time: u64,
446 portion: Option<u64>,
447) -> Weight {
448 if let Some(m) = portion {
449 ref_time += ref_time / 100 * m;
450 proof_size += proof_size / 100 * m;
451 }
452 Weight::from_parts(ref_time, proof_size)
453}