Skip to main content

ab_contracts_test_utils/
transaction_builder.rs

1use ab_aligned_buffer::OwnedAlignedBuffer;
2use ab_contracts_common::method::ExternalArgs;
3use ab_core_primitives::address::Address;
4use ab_core_primitives::block::BlockRoot;
5use ab_core_primitives::transaction::{Gas, Transaction, TransactionHeader, TransactionSlot};
6use ab_system_contract_simple_wallet_base::payload::TransactionMethodContext;
7use ab_system_contract_simple_wallet_base::payload::builder::{
8    MethodCallReferences, TransactionPayloadBuilder, TransactionPayloadBuilderError,
9};
10use alloc::vec::Vec;
11
12#[derive(Debug, Clone)]
13pub struct OwnedTransaction {
14    pub header: TransactionHeader,
15    pub read_slots: Vec<TransactionSlot>,
16    pub write_slots: Vec<TransactionSlot>,
17    pub payload: OwnedAlignedBuffer,
18    pub seal: Vec<u8>,
19}
20
21impl OwnedTransaction {
22    /// Get [`Transaction`] out of owned transaction
23    pub fn as_ref(&self) -> Transaction<'_> {
24        Transaction {
25            header: &self.header,
26            read_slots: &self.read_slots,
27            write_slots: &self.write_slots,
28            payload: self.payload.as_u128_slice(),
29            seal: &self.seal,
30        }
31    }
32}
33
34#[derive(Debug)]
35pub struct TransactionBuilder {
36    contract: Address,
37    transaction_payload_builder: TransactionPayloadBuilder,
38}
39
40impl TransactionBuilder {
41    /// Create a transaction for `contract` with a payload of up to `max_payload_size` bytes that
42    /// declares `num_outputs` outputs.
43    ///
44    /// See [`TransactionPayloadBuilder::new()`] for details of `max_payload_size` and
45    /// `num_outputs`.
46    pub fn new(
47        contract: Address,
48        max_payload_size: u32,
49        num_outputs: u8,
50    ) -> Result<Self, TransactionPayloadBuilderError<'static>> {
51        Ok(Self {
52            contract,
53            transaction_payload_builder: TransactionPayloadBuilder::new(
54                max_payload_size,
55                num_outputs,
56            )?,
57        })
58    }
59
60    /// Add method call to the transaction.
61    ///
62    /// See [`TransactionPayloadBuilder::with_method_call()`] for details of this API.
63    pub fn with_method_call<Args>(
64        &mut self,
65        contract: &Address,
66        external_args: &Args,
67        method_context: TransactionMethodContext,
68        references: MethodCallReferences<'_>,
69    ) -> Result<(), TransactionPayloadBuilderError<'static>>
70    where
71        Args: ExternalArgs,
72    {
73        self.transaction_payload_builder.with_method_call(
74            contract,
75            external_args,
76            method_context,
77            references,
78        )
79    }
80
81    /// Build the transaction.
82    ///
83    /// See [`TransactionPayloadBuilder::into_aligned_bytes()`] for errors.
84    pub fn build(
85        self,
86        read_slots: Vec<TransactionSlot>,
87        write_slots: Vec<TransactionSlot>,
88    ) -> Result<OwnedTransaction, TransactionPayloadBuilderError<'static>> {
89        Ok(OwnedTransaction {
90            header: TransactionHeader {
91                version: 0,
92                block_root: BlockRoot::default(),
93                gas_limit: Gas::default(),
94                contract: self.contract,
95            },
96            read_slots,
97            write_slots,
98            payload: self.transaction_payload_builder.into_aligned_bytes()?,
99            seal: Vec::new(),
100        })
101    }
102}