1use crate::{
2 call_data,
3 order_book::{
4 CreateOrderParams,
5 OrderBookManager,
6 },
7 parallel_nonce::{
8 generate_parallel_session_digest,
9 generate_parallel_session_signing_payload,
10 },
11 trial_trade_account_deploy::{
12 CallContractArg,
13 CallParams,
14 OrderBookCleanup,
15 ParallelCallContractArgs,
16 ParallelMultiCallContractArgs,
17 ParallelRevokeArgs,
18 ParallelSessionArgs,
19 Secp256k1,
20 Session,
21 Signature,
22 Time,
23 TrialCloseAccountArgs as TrialCloseAccountPayload,
24 TrialLinkAccountArgs as TrialLinkAccountPayload,
25 TrialTradeAccountDeploy,
26 TrialTradingAccount,
27 TrialTradingAccountProxy,
28 TrialWithdrawArgs as TrialWithdrawPayload,
29 },
30};
31use fuels::{
32 accounts::signers::private_key::PrivateKeySigner,
33 core::traits::Tokenizable,
34 crypto::Message,
35 prelude::*,
36 types::{
37 Bytes32,
38 Identity,
39 U256,
40 },
41};
42use rand::{
43 SeedableRng,
44 rngs::StdRng,
45};
46use sha2::{
47 Digest,
48 Sha256,
49};
50use std::time::{
51 SystemTime,
52 UNIX_EPOCH,
53};
54
55const TRADE_APPROVAL_DIGEST_TAG: u8 = 0x02;
56const PROXY_OWNER_OPERATION_DIGEST_TAG: u8 = 0x03;
57const LINK_DIGEST_TAG: u8 = 0x04;
58
59pub struct TrialCallContractParams {
60 pub contract_id: ContractId,
61 pub function_selector: Vec<u8>,
62 pub forward: CallParams,
63 pub args: Option<Vec<u8>>,
64 pub nonce: U256,
65 pub variable_outputs: Option<u16>,
66}
67
68#[derive(Debug, Clone)]
69pub enum TrialContractCalls {
70 Call(TrialCallContractArgs),
71 Calls(TrialCallContractsArgs),
72}
73
74impl TrialContractCalls {
75 pub fn contract_ids(&self) -> Vec<ContractId> {
76 match self {
77 TrialContractCalls::Call(call) => {
78 vec![call.call.call_contract_args.contract_id]
79 }
80 TrialContractCalls::Calls(calls) => calls
81 .calls
82 .call_contract_args
83 .iter()
84 .map(|c| c.contract_id)
85 .collect(),
86 }
87 }
88}
89
90#[derive(Debug, Clone)]
91pub struct TrialCallContractArgs {
92 pub user_signature: Signature,
93 pub cosigner_signature: Signature,
94 pub call: ParallelCallContractArgs,
95 pub variable_outputs: Option<u16>,
96 pub contracts: Option<Vec<ContractId>>,
97}
98
99#[derive(Debug, Clone)]
100pub struct TrialCallContractsArgs {
101 pub user_signature: Signature,
102 pub cosigner_signature: Signature,
103 pub calls: ParallelMultiCallContractArgs,
104 pub variable_outputs: Option<u16>,
105 pub contracts: Option<Vec<ContractId>>,
106}
107
108#[derive(Debug, Clone)]
109pub struct TrialCosignerCallRequest {
110 pub signature: Signature,
111 pub args: ParallelCallContractArgs,
112 pub variable_outputs: Option<u16>,
113 pub contracts: Option<Vec<ContractId>>,
114}
115
116#[derive(Debug, Clone)]
117pub struct TrialCosignerCallContractsRequest {
118 pub signature: Signature,
119 pub args: ParallelMultiCallContractArgs,
120 pub variable_outputs: Option<u16>,
121 pub contracts: Option<Vec<ContractId>>,
122}
123
124#[derive(Debug, Clone)]
125pub struct TrialCloseAccountRequest {
126 pub signature: Signature,
127 pub args: TrialCloseAccountPayload,
128 pub contracts: Option<Vec<ContractId>>,
129}
130
131#[derive(Debug, Clone)]
132pub struct TrialWithdrawRequest {
133 pub signature: Signature,
134 pub args: TrialWithdrawPayload,
135 pub contracts: Option<Vec<ContractId>>,
136}
137
138#[derive(Debug, Clone)]
139pub struct TrialSetSessionRequest {
140 pub args: ParallelSessionArgs,
141 pub contracts: Option<Vec<ContractId>>,
142}
143
144#[derive(Debug, Clone)]
145pub struct TrialRevokeSessionRequest {
146 pub args: ParallelRevokeArgs,
147 pub contracts: Option<Vec<ContractId>>,
148}
149
150#[derive(Debug, Clone)]
151pub struct TrialLinkAccountRequest {
152 pub session_signature: Signature,
153 pub args: TrialLinkAccountPayload,
154 pub contracts: Option<Vec<ContractId>>,
155}
156
157impl TrialCallContractParams {
158 pub fn new(
159 contract_id: ContractId,
160 function_selector: Vec<u8>,
161 forward: CallParams,
162 args: Option<Vec<u8>>,
163 nonce: U256,
164 variable_outputs: Option<u16>,
165 ) -> Self {
166 Self {
167 contract_id,
168 function_selector,
169 forward,
170 args,
171 nonce,
172 variable_outputs,
173 }
174 }
175
176 pub fn call_args(&self) -> CallContractArg {
177 CallContractArg {
178 contract_id: self.contract_id,
179 function_selector: Bytes(self.function_selector.clone()),
180 call_params: self.forward.clone(),
181 call_data: self.args.clone().map(Bytes),
182 }
183 }
184
185 pub fn user_message(&self) -> Message {
186 generate_parallel_session_signing_payload(self.nonce, self.call_args())
187 }
188
189 pub fn trade_approval_message(
190 &self,
191 chain_id: u64,
192 account_contract_id: ContractId,
193 ) -> Message {
194 generate_trial_trade_approval_signing_payload(
195 chain_id,
196 account_contract_id,
197 self.nonce,
198 self.call_args(),
199 )
200 }
201}
202
203fn sha256_digest(bytes: &[u8]) -> [u8; 32] {
204 Sha256::digest(bytes).into()
205}
206
207fn message_from_digest(digest: [u8; 32]) -> Message {
208 Message::from_bytes(digest)
209}
210
211pub fn generate_trial_trade_approval_digest<T: Tokenizable>(
212 chain_id: u64,
213 account_contract_id: ContractId,
214 nonce: U256,
215 call_contract_arg: T,
216) -> [u8; 32] {
217 let session_digest = generate_parallel_session_digest(nonce, call_contract_arg);
218 generate_trial_trade_approval_digest_from_session_digest(
219 chain_id,
220 account_contract_id,
221 session_digest,
222 )
223}
224
225pub fn generate_trial_trade_approval_digest_from_session_digest(
226 chain_id: u64,
227 account_contract_id: ContractId,
228 session_digest: [u8; 32],
229) -> [u8; 32] {
230 let mut bytes = Vec::new();
231 bytes.push(TRADE_APPROVAL_DIGEST_TAG);
232 bytes.extend_from_slice(&chain_id.to_be_bytes());
233 bytes.extend_from_slice(account_contract_id.as_slice());
234 bytes.extend_from_slice(&session_digest);
235 sha256_digest(&bytes)
236}
237
238pub fn generate_trial_trade_approval_signing_payload<T: Tokenizable>(
239 chain_id: u64,
240 account_contract_id: ContractId,
241 nonce: U256,
242 call_contract_arg: T,
243) -> Message {
244 message_from_digest(generate_trial_trade_approval_digest(
245 chain_id,
246 account_contract_id,
247 nonce,
248 call_contract_arg,
249 ))
250}
251
252pub fn generate_trial_proxy_owner_operation_digest<T: Tokenizable>(
253 chain_id: u64,
254 account_contract_id: ContractId,
255 args: T,
256) -> [u8; 32] {
257 let mut bytes = Vec::new();
258 bytes.push(PROXY_OWNER_OPERATION_DIGEST_TAG);
259 bytes.extend_from_slice(&chain_id.to_be_bytes());
260 bytes.extend_from_slice(account_contract_id.as_slice());
261 bytes.extend_from_slice(&call_data!(args));
262 sha256_digest(&bytes)
263}
264
265pub fn generate_trial_proxy_owner_operation_signing_payload<T: Tokenizable>(
266 chain_id: u64,
267 account_contract_id: ContractId,
268 args: T,
269) -> Message {
270 message_from_digest(generate_trial_proxy_owner_operation_digest(
271 chain_id,
272 account_contract_id,
273 args,
274 ))
275}
276
277pub fn generate_trial_link_account_digest<T: Tokenizable>(
278 chain_id: u64,
279 account_contract_id: ContractId,
280 args: T,
281) -> [u8; 32] {
282 let mut bytes = Vec::new();
283 bytes.push(LINK_DIGEST_TAG);
284 bytes.extend_from_slice(&chain_id.to_be_bytes());
285 bytes.extend_from_slice(account_contract_id.as_slice());
286 bytes.extend_from_slice(&call_data!(args));
287 sha256_digest(&bytes)
288}
289
290pub fn generate_trial_link_account_signing_payload<T: Tokenizable>(
291 chain_id: u64,
292 account_contract_id: ContractId,
293 args: T,
294) -> Message {
295 message_from_digest(generate_trial_link_account_digest(
296 chain_id,
297 account_contract_id,
298 args,
299 ))
300}
301
302#[derive(Clone)]
303pub struct TrialTradeAccountManager<Wallet: Account + Clone> {
304 pub owner: Wallet,
305 pub oracle_id: Option<ContractId>,
306 pub proxy: TrialTradingAccountProxy<Wallet>,
307 pub contract: TrialTradingAccount<Wallet>,
308 pub session_signer: Option<PrivateKeySigner>,
309 pub cosigner_signer: Option<PrivateKeySigner>,
310}
311
312impl TrialTradeAccountManager<Wallet> {
313 pub fn contract_id(&self) -> ContractId {
314 self.contract.id()
315 }
316
317 pub fn identity(&self) -> Identity {
318 Identity::ContractId(self.contract.contract_id())
319 }
320
321 pub fn session_signer(&self) -> anyhow::Result<PrivateKeySigner> {
322 self.session_signer
323 .clone()
324 .ok_or_else(|| anyhow::anyhow!("Session signer not initialized"))
325 }
326
327 pub fn cosigner_signer(&self) -> anyhow::Result<PrivateKeySigner> {
328 self.cosigner_signer
329 .clone()
330 .ok_or_else(|| anyhow::anyhow!("Cosigner signer not initialized"))
331 }
332
333 pub async fn new(owner: &Wallet, contract_id: ContractId) -> anyhow::Result<Self> {
334 let proxy = TrialTradingAccountProxy::new(contract_id, owner.clone());
335 let contract = TrialTradingAccount::new(contract_id, owner.clone());
336 Ok(Self {
337 owner: owner.clone(),
338 oracle_id: None,
339 contract,
340 proxy,
341 session_signer: None,
342 cosigner_signer: None,
343 })
344 }
345
346 pub fn create(
347 owner: &Wallet,
348 deployment: &TrialTradeAccountDeploy<Wallet>,
349 ) -> anyhow::Result<Self> {
350 if deployment.proxy_id.is_none() || deployment.proxy.is_none() {
351 return Err(anyhow::anyhow!(
352 "Trial trade account deploy proxy ID or instance is not set"
353 ));
354 }
355 let contract =
356 TrialTradingAccount::new(deployment.proxy_id.unwrap(), owner.clone());
357 Ok(Self {
358 owner: owner.clone(),
359 contract,
360 oracle_id: Some(deployment.oracle_id),
361 session_signer: None,
362 cosigner_signer: None,
363 proxy: deployment.proxy.clone().unwrap(),
364 })
365 }
366
367 pub fn create_with_signers(
368 owner: &Wallet,
369 deployment: &TrialTradeAccountDeploy<Wallet>,
370 contract_ids: &[ContractId],
371 cosigner_signer: PrivateKeySigner,
372 ) -> anyhow::Result<Self> {
373 let mut trial_account = Self::create(owner, deployment)?;
374 let mut rng = StdRng::seed_from_u64(2322u64);
375 let session_signer = PrivateKeySigner::random(&mut rng);
376 let session_address = Identity::Address(session_signer.address());
377 trial_account.session_signer = Some(session_signer);
378 trial_account.cosigner_signer = Some(cosigner_signer);
379
380 let _session = trial_account.new_session(session_address, contract_ids, None);
381
382 Ok(trial_account)
383 }
384
385 pub fn new_session(
386 &self,
387 session_address: Identity,
388 contract_ids: &[ContractId],
389 expiry: Option<u64>,
390 ) -> Session {
391 let default_expiry = SystemTime::now()
392 .duration_since(UNIX_EPOCH)
393 .expect("Time went backwards")
394 .as_millis() as u64
395 + (30 * 24 * 60 * 60 * 1000);
396 Session {
397 session_id: session_address,
398 expiry: Time {
399 unix: expiry.unwrap_or(default_expiry),
400 },
401 contract_ids: contract_ids.to_vec(),
402 }
403 }
404
405 async fn chain_id(&self) -> anyhow::Result<u64> {
406 Ok(*self
407 .owner
408 .provider()
409 .consensus_parameters()
410 .await?
411 .chain_id())
412 }
413
414 fn tx_contract_ids(
415 &self,
416 required: impl IntoIterator<Item = ContractId>,
417 extra: Option<Vec<ContractId>>,
418 ) -> Vec<ContractId> {
419 let mut contract_ids = extra.unwrap_or_default();
420
421 for contract_id in required {
422 if !contract_ids.contains(&contract_id) {
423 contract_ids.push(contract_id);
424 }
425 }
426
427 if let Some(oracle_id) = self.oracle_id
428 && !contract_ids.contains(&oracle_id)
429 {
430 contract_ids.push(oracle_id);
431 }
432
433 contract_ids
434 }
435
436 async fn create_proxy_owner_operation_signature<T: Tokenizable>(
437 &self,
438 args: T,
439 ) -> anyhow::Result<Signature> {
440 let chain_id = self.chain_id().await?;
441 let message = generate_trial_proxy_owner_operation_signing_payload(
442 chain_id,
443 self.contract_id(),
444 args,
445 );
446 let signature = self.cosigner_signer()?.sign(message).await?;
447 Ok(Signature::Secp256k1(Secp256k1 {
448 bits: signature.as_slice().try_into()?,
449 }))
450 }
451
452 pub async fn create_call_args(
453 &self,
454 params: TrialCallContractParams,
455 ) -> anyhow::Result<TrialCallContractArgs> {
456 let chain_id = self.chain_id().await?;
457 let call_arg = params.call_args();
458 let call = ParallelCallContractArgs {
459 nonce: params.nonce,
460 call_contract_args: call_arg,
461 };
462 let user_message = generate_parallel_session_signing_payload(
463 call.nonce,
464 call.call_contract_args.clone(),
465 );
466 let trade_approval_message = generate_trial_trade_approval_signing_payload(
467 chain_id,
468 self.contract_id(),
469 call.nonce,
470 call.call_contract_args.clone(),
471 );
472 let user_signature = self.session_signer()?.sign(user_message).await?;
473 let cosigner_signature =
474 self.cosigner_signer()?.sign(trade_approval_message).await?;
475
476 Ok(TrialCallContractArgs {
477 user_signature: Signature::Secp256k1(Secp256k1 {
478 bits: user_signature.as_slice().try_into()?,
479 }),
480 cosigner_signature: Signature::Secp256k1(Secp256k1 {
481 bits: cosigner_signature.as_slice().try_into()?,
482 }),
483 variable_outputs: params.variable_outputs,
484 call,
485 contracts: None,
486 })
487 }
488
489 pub async fn create_calls_args(
490 &self,
491 params: Vec<TrialCallContractParams>,
492 ) -> anyhow::Result<TrialCallContractsArgs> {
493 let call_contract_args = params
494 .iter()
495 .map(|param| param.call_args())
496 .collect::<Vec<_>>();
497 let nonce = params
498 .first()
499 .map(|param| param.nonce)
500 .unwrap_or_else(U256::zero);
501 let calls = ParallelMultiCallContractArgs {
502 nonce,
503 call_contract_args,
504 };
505 let chain_id = self.chain_id().await?;
506 let user_message = generate_parallel_session_signing_payload(
507 calls.nonce,
508 calls.call_contract_args.clone(),
509 );
510 let trade_approval_message = generate_trial_trade_approval_signing_payload(
511 chain_id,
512 self.contract_id(),
513 calls.nonce,
514 calls.call_contract_args.clone(),
515 );
516 let user_signature = self.session_signer()?.sign(user_message).await?;
517 let cosigner_signature =
518 self.cosigner_signer()?.sign(trade_approval_message).await?;
519
520 Ok(TrialCallContractsArgs {
521 user_signature: Signature::Secp256k1(Secp256k1 {
522 bits: user_signature.as_slice().try_into()?,
523 }),
524 cosigner_signature: Signature::Secp256k1(Secp256k1 {
525 bits: cosigner_signature.as_slice().try_into()?,
526 }),
527 calls,
528 variable_outputs: None,
529 contracts: None,
530 })
531 }
532
533 pub fn call_contract(
534 &self,
535 call_args: &TrialCallContractArgs,
536 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
537 let contracts = self.tx_contract_ids(
538 [call_args.call.call_contract_args.contract_id],
539 call_args.contracts.clone(),
540 );
541 self.contract
542 .methods()
543 .call_contract(
544 call_args.user_signature.clone(),
545 call_args.cosigner_signature.clone(),
546 call_args.call.clone(),
547 )
548 .with_contract_ids(&contracts)
549 .with_variable_output_policy(VariableOutputPolicy::Exactly(
550 call_args.variable_outputs.unwrap_or_default() as usize,
551 ))
552 }
553
554 pub fn call_contracts(
555 &self,
556 call_args: &TrialCallContractsArgs,
557 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
558 let contracts = self.tx_contract_ids(
559 call_args
560 .calls
561 .call_contract_args
562 .iter()
563 .map(|call| call.contract_id),
564 call_args.contracts.clone(),
565 );
566 self.contract
567 .methods()
568 .call_contracts(
569 call_args.user_signature.clone(),
570 call_args.cosigner_signature.clone(),
571 call_args.calls.clone(),
572 )
573 .with_contract_ids(&contracts)
574 .with_variable_output_policy(VariableOutputPolicy::Exactly(
575 call_args.variable_outputs.unwrap_or_default() as usize,
576 ))
577 }
578
579 pub async fn create_link_account_args(
580 &self,
581 nonce: U256,
582 parent_account: Identity,
583 ) -> anyhow::Result<TrialLinkAccountRequest> {
584 let args = TrialLinkAccountPayload {
585 nonce,
586 parent_account,
587 };
588 let message = generate_trial_link_account_signing_payload(
589 self.chain_id().await?,
590 self.contract_id(),
591 args.clone(),
592 );
593 let session_signature = self.session_signer()?.sign(message).await?;
594 Ok(TrialLinkAccountRequest {
595 session_signature: Signature::Secp256k1(Secp256k1 {
596 bits: session_signature.as_slice().try_into()?,
597 }),
598 args,
599 contracts: None,
600 })
601 }
602
603 pub fn link_account(
604 &self,
605 link_args: &TrialLinkAccountRequest,
606 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
607 let contracts = self.tx_contract_ids([], link_args.contracts.clone());
608 self.contract
609 .methods()
610 .link_account(link_args.session_signature.clone(), link_args.args.clone())
611 .with_contract_ids(&contracts)
612 }
613
614 pub async fn create_cosigner_call_args(
615 &self,
616 params: TrialCallContractParams,
617 ) -> anyhow::Result<TrialCosignerCallRequest> {
618 let call = params.call_args();
619 let args = ParallelCallContractArgs {
620 nonce: params.nonce,
621 call_contract_args: call,
622 };
623 let signature = self
624 .create_proxy_owner_operation_signature(args.clone())
625 .await?;
626 Ok(TrialCosignerCallRequest {
627 signature,
628 args,
629 variable_outputs: params.variable_outputs,
630 contracts: None,
631 })
632 }
633
634 pub async fn create_cosigner_calls_args(
635 &self,
636 params: Vec<TrialCallContractParams>,
637 ) -> anyhow::Result<TrialCosignerCallContractsRequest> {
638 let calls = params
639 .iter()
640 .map(|param| param.call_args())
641 .collect::<Vec<_>>();
642 let nonce = params
643 .first()
644 .map(|param| param.nonce)
645 .unwrap_or_else(U256::zero);
646 let args = ParallelMultiCallContractArgs {
647 nonce,
648 call_contract_args: calls,
649 };
650 let signature = self
651 .create_proxy_owner_operation_signature(args.clone())
652 .await?;
653 Ok(TrialCosignerCallContractsRequest {
654 signature,
655 args,
656 variable_outputs: None,
657 contracts: None,
658 })
659 }
660
661 pub fn cosigner_call(
662 &self,
663 call_args: &TrialCosignerCallRequest,
664 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
665 let contracts = self.tx_contract_ids(
666 [call_args.args.call_contract_args.contract_id],
667 call_args.contracts.clone(),
668 );
669 self.contract
670 .methods()
671 .cosigner_call(Some(call_args.signature.clone()), call_args.args.clone())
672 .with_contract_ids(&contracts)
673 .with_variable_output_policy(VariableOutputPolicy::Exactly(
674 call_args.variable_outputs.unwrap_or_default() as usize,
675 ))
676 }
677
678 pub fn cosigner_call_contracts(
679 &self,
680 call_args: &TrialCosignerCallContractsRequest,
681 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
682 let contracts = self.tx_contract_ids(
683 call_args
684 .args
685 .call_contract_args
686 .iter()
687 .map(|call| call.contract_id),
688 call_args.contracts.clone(),
689 );
690 self.contract
691 .methods()
692 .cosigner_call_contracts(
693 Some(call_args.signature.clone()),
694 call_args.args.clone(),
695 )
696 .with_contract_ids(&contracts)
697 .with_variable_output_policy(VariableOutputPolicy::Exactly(
698 call_args.variable_outputs.unwrap_or_default() as usize,
699 ))
700 }
701
702 pub async fn create_close_account_args(
703 &self,
704 order_book_cleanups: Vec<OrderBookCleanup>,
705 ) -> anyhow::Result<TrialCloseAccountRequest> {
706 let args = TrialCloseAccountPayload {
707 order_book_cleanups,
708 };
709 let signature = self
710 .create_proxy_owner_operation_signature(args.clone())
711 .await?;
712 Ok(TrialCloseAccountRequest {
713 signature,
714 args,
715 contracts: None,
716 })
717 }
718
719 pub fn close_account(
720 &self,
721 close_account_args: &TrialCloseAccountRequest,
722 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
723 let contracts = self.tx_contract_ids(
724 close_account_args
725 .args
726 .order_book_cleanups
727 .iter()
728 .map(|cleanup| cleanup.order_book_id),
729 close_account_args.contracts.clone(),
730 );
731 self.contract
732 .methods()
733 .close_account(
734 Some(close_account_args.signature.clone()),
735 close_account_args.args.clone(),
736 )
737 .with_contract_ids(&contracts)
738 }
739
740 pub async fn create_withdraw_args(
741 &self,
742 nonce: U256,
743 asset_id: AssetId,
744 amount: u64,
745 to: Identity,
746 ) -> anyhow::Result<TrialWithdrawRequest> {
747 let args = TrialWithdrawPayload {
748 nonce,
749 asset_id,
750 amount,
751 to,
752 };
753 let signature = self
754 .create_proxy_owner_operation_signature(args.clone())
755 .await?;
756 Ok(TrialWithdrawRequest {
757 signature,
758 args,
759 contracts: None,
760 })
761 }
762
763 pub fn withdraw(
764 &self,
765 withdraw_args: &TrialWithdrawRequest,
766 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
767 let (recipient_contracts, variable_outputs) = match withdraw_args.args.to {
771 Identity::ContractId(contract_id) => (vec![contract_id], 0usize),
772 Identity::Address(_) => (vec![], 1usize),
773 };
774 let contracts =
775 self.tx_contract_ids(recipient_contracts, withdraw_args.contracts.clone());
776 self.contract
777 .methods()
778 .withdraw(
779 Some(withdraw_args.signature.clone()),
780 withdraw_args.args.clone(),
781 )
782 .with_contract_ids(&contracts)
783 .with_variable_output_policy(VariableOutputPolicy::Exactly(variable_outputs))
784 }
785
786 pub fn create_set_session_args(
787 &self,
788 nonce: U256,
789 session: Session,
790 ) -> TrialSetSessionRequest {
791 let args = ParallelSessionArgs {
792 nonce,
793 session_id: session.session_id,
794 expiry: session.expiry,
795 contract_ids: session.contract_ids,
796 };
797 TrialSetSessionRequest {
798 args,
799 contracts: None,
800 }
801 }
802
803 pub fn set_session(
804 &self,
805 session_args: &TrialSetSessionRequest,
806 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
807 let contracts = self.tx_contract_ids([], session_args.contracts.clone());
808 self.contract
809 .methods()
810 .set_session(session_args.args.clone())
811 .with_contract_ids(&contracts)
812 }
813
814 pub fn create_revoke_session_args(&self, nonce: U256) -> TrialRevokeSessionRequest {
815 let args = ParallelRevokeArgs { nonce };
816 TrialRevokeSessionRequest {
817 args,
818 contracts: None,
819 }
820 }
821
822 pub fn revoke_session(
823 &self,
824 revoke_args: &TrialRevokeSessionRequest,
825 ) -> CallHandler<Wallet, fuels::programs::calls::ContractCall, ()> {
826 let contracts = self.tx_contract_ids([], revoke_args.contracts.clone());
827 self.contract
828 .methods()
829 .revoke_session(revoke_args.args.clone())
830 .with_contract_ids(&contracts)
831 }
832
833 pub fn cancel_orders_args(
834 &self,
835 order_book: &OrderBookManager<Wallet>,
836 order_id: Bytes32,
837 gas: Option<u64>,
838 nonce: U256,
839 ) -> TrialCallContractParams {
840 TrialCallContractParams::new(
841 order_book.contract.contract_id(),
842 crate::fn_selector!(cancel_order(OrderId)),
843 CallParams {
844 coins: 0,
845 asset_id: AssetId::default(),
846 gas: gas.unwrap_or(u64::MAX),
847 },
848 Some(call_data!(*order_id)),
849 nonce,
850 None,
851 )
852 }
853
854 pub async fn cancel_order(
855 &mut self,
856 order_book: &OrderBookManager<Wallet>,
857 order_id: Bytes32,
858 gas: Option<u64>,
859 nonce: U256,
860 ) -> anyhow::Result<TrialCallContractArgs> {
861 self.create_call_args(self.cancel_orders_args(order_book, order_id, gas, nonce))
862 .await
863 }
864
865 pub fn create_order_args(
866 &self,
867 order_book: &OrderBookManager<Wallet>,
868 params: &CreateOrderParams,
869 gas: Option<u64>,
870 nonce: U256,
871 ) -> TrialCallContractParams {
872 let forward = order_book.create_call_params(params, gas);
873 TrialCallContractParams::new(
874 order_book.contract.contract_id(),
875 crate::fn_selector!(create_order(OrderArgs)),
876 CallParams {
877 coins: forward.coins,
878 asset_id: forward.asset_id,
879 gas: forward.gas,
880 },
881 Some(call_data!(params.to_order_args())),
882 nonce,
883 None,
884 )
885 }
886
887 pub async fn create_order(
888 &mut self,
889 order_book: &OrderBookManager<Wallet>,
890 params: &CreateOrderParams,
891 gas: Option<u64>,
892 nonce: U256,
893 ) -> anyhow::Result<TrialCallContractArgs> {
894 self.create_call_args(self.create_order_args(order_book, params, gas, nonce))
895 .await
896 }
897}