multiversx_sc_snippets/interactor/
interactor_sender.rs

1use std::collections::HashMap;
2
3use crate::sdk::{data::transaction::Transaction, wallet::Wallet};
4use multiversx_sc_scenario::multiversx_sc::types::Address;
5use multiversx_sdk::data::account::Account;
6use multiversx_sdk::data::esdt::EsdtBalance;
7use multiversx_sdk::gateway::{
8    GatewayAsyncService, GetAccountEsdtTokensRequest, GetAccountRequest, GetAccountStorageRequest,
9};
10
11use crate::InteractorBase;
12
13/// A user account that can sign transactions (a pem is present).
14pub struct Sender {
15    pub address: Address,
16    pub hrp: String,
17    pub wallet: Wallet,
18    pub current_nonce: Option<u64>,
19}
20
21impl<GatewayProxy> InteractorBase<GatewayProxy>
22where
23    GatewayProxy: GatewayAsyncService,
24{
25    pub async fn recall_nonce(&self, address: &Address) -> u64 {
26        let account = self
27            .proxy
28            .request(GetAccountRequest::new(&address.to_bech32(self.get_hrp())))
29            .await
30            .expect("failed to retrieve account nonce");
31
32        account.nonce
33    }
34
35    pub async fn get_account(&self, address: &Address) -> Account {
36        self.proxy
37            .request(GetAccountRequest::new(&address.to_bech32(self.get_hrp())))
38            .await
39            .expect("failed to retrieve account")
40    }
41
42    pub async fn get_account_storage(&self, address: &Address) -> HashMap<String, String> {
43        self.proxy
44            .request(GetAccountStorageRequest::new(
45                &address.to_bech32(self.get_hrp()),
46            ))
47            .await
48            .expect("failed to retrieve account")
49    }
50
51    pub async fn get_account_esdt(&self, address: &Address) -> HashMap<String, EsdtBalance> {
52        self.proxy
53            .request(GetAccountEsdtTokensRequest::new(
54                &address.to_bech32(self.get_hrp()),
55            ))
56            .await
57            .expect("failed to retrieve account")
58    }
59
60    pub(crate) async fn set_nonce_and_sign_tx(
61        &mut self,
62        sender_address: &Address,
63        transaction: &mut Transaction,
64    ) {
65        // read
66        let sender = self
67            .sender_map
68            .get(sender_address)
69            .expect("the wallet that was supposed to sign is not registered");
70
71        // recall
72        let nonce = self.recall_nonce(&sender.address).await;
73        println!("sender's recalled nonce: {nonce}");
74
75        // set tx nonce
76        transaction.nonce = nonce;
77        println!("-- tx nonce: {}", transaction.nonce);
78
79        // update
80        let sender = self
81            .sender_map
82            .get_mut(sender_address)
83            .expect("the wallet that was supposed to sign is not registered");
84        sender.current_nonce = Some(nonce + 1);
85
86        // sign
87        let signature = sender.wallet.sign_tx(transaction);
88        transaction.signature = Some(hex::encode(signature));
89    }
90}