multiversx_sc_snippets/multi/
homogenous_tx_buffer.rs

1use multiversx_sc_scenario::{
2    multiversx_sc::{
3        tuple_util::NestedTupleFlatten,
4        types::{RHListExec, TxBaseWithEnv},
5    },
6    scenario::tx_to_step::{StepWrapper, TxToStep},
7    scenario_model::TxResponse,
8    ScenarioTxEnvData,
9};
10use multiversx_sdk::gateway::GatewayAsyncService;
11
12use crate::{InteractorBase, InteractorEnvExec, InteractorStep, StepBuffer};
13
14pub struct HomogenousTxBuffer<'w, GatewayProxy, Step, RH>
15where
16    GatewayProxy: GatewayAsyncService,
17{
18    env: InteractorEnvExec<'w, GatewayProxy>,
19    steps: Vec<StepWrapper<ScenarioTxEnvData, Step, RH>>,
20}
21
22impl<GatewayProxy> InteractorBase<GatewayProxy>
23where
24    GatewayProxy: GatewayAsyncService,
25{
26    /// Creates a buffer that can hold multiple transactions, and then execute them all at once.
27    ///
28    /// This buffer holds transactions of the same type (call/deploy) and with identical result handler types.
29    /// Therefore, after execution, all results will have the same type.
30    pub fn homogenous_call_buffer<Step, RH>(
31        &mut self,
32    ) -> HomogenousTxBuffer<'_, GatewayProxy, Step, RH> {
33        let data = self.new_env_data();
34        let env = InteractorEnvExec { world: self, data };
35        HomogenousTxBuffer {
36            env,
37            steps: Vec::new(),
38        }
39    }
40}
41
42impl<GatewayProxy, Step, RH> HomogenousTxBuffer<'_, GatewayProxy, Step, RH>
43where
44    GatewayProxy: GatewayAsyncService,
45    Step: InteractorStep,
46    RH: RHListExec<TxResponse, ScenarioTxEnvData>,
47    RH::ListReturns: NestedTupleFlatten,
48{
49    pub fn push_tx<Tx, F>(&mut self, f: F) -> &mut Self
50    where
51        Tx: TxToStep<ScenarioTxEnvData, RH, Step = Step>,
52        F: FnOnce(TxBaseWithEnv<ScenarioTxEnvData>) -> Tx,
53    {
54        let env = self.env.world.new_env_data();
55        let tx_base = TxBaseWithEnv::new_with_env(env);
56        let tx = f(tx_base);
57
58        self.steps.push(tx.tx_to_step());
59
60        self
61    }
62
63    pub async fn run(mut self) -> Vec<<RH::ListReturns as NestedTupleFlatten>::Unpacked> {
64        let mut step_buffer = StepBuffer::default();
65        for step in &mut self.steps {
66            step_buffer.refs.push(step.step.as_interactor_step());
67        }
68        self.env.world.multi_sc_exec(step_buffer).await;
69
70        self.steps
71            .into_iter()
72            .map(|step| step.process_result())
73            .collect()
74    }
75}