ab_contracts_test_utils/
transaction_builder.rs1use ab_contracts_common::method::ExternalArgs;
2use ab_core_primitives::address::Address;
3use ab_core_primitives::block::BlockRoot;
4use ab_core_primitives::transaction::owned::{OwnedTransaction, OwnedTransactionError};
5use ab_core_primitives::transaction::{Gas, 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};
10
11#[derive(Debug, thiserror::Error)]
13pub enum TransactionBuilderError {
14 #[error("Failed to build the payload: {0}")]
16 Payload(TransactionPayloadBuilderError<'static>),
17 #[error("Failed to create the transaction: {0}")]
19 Transaction(OwnedTransactionError),
20}
21
22#[derive(Debug)]
23pub struct TransactionBuilder {
24 contract: Address,
25 transaction_payload_builder: TransactionPayloadBuilder,
26}
27
28impl TransactionBuilder {
29 pub fn new(
35 contract: Address,
36 max_payload_size: u32,
37 num_outputs: u8,
38 ) -> Result<Self, TransactionPayloadBuilderError<'static>> {
39 Ok(Self {
40 contract,
41 transaction_payload_builder: TransactionPayloadBuilder::new(
42 max_payload_size,
43 num_outputs,
44 )?,
45 })
46 }
47
48 pub fn with_method_call<Args>(
52 &mut self,
53 contract: &Address,
54 external_args: &Args,
55 method_context: TransactionMethodContext,
56 references: MethodCallReferences<'_>,
57 ) -> Result<(), TransactionPayloadBuilderError<'static>>
58 where
59 Args: ExternalArgs,
60 {
61 self.transaction_payload_builder.with_method_call(
62 contract,
63 external_args,
64 method_context,
65 references,
66 )
67 }
68
69 pub fn build(
74 self,
75 read_slots: &[TransactionSlot],
76 write_slots: &[TransactionSlot],
77 ) -> Result<OwnedTransaction, TransactionBuilderError> {
78 let header = TransactionHeader {
79 version: 0,
80 block_root: BlockRoot::default(),
81 gas_limit: Gas::default(),
82 contract: self.contract,
83 };
84 let payload = self
85 .transaction_payload_builder
86 .into_aligned_bytes()
87 .map_err(TransactionBuilderError::Payload)?;
88
89 OwnedTransaction::from_parts(
90 &header,
91 read_slots,
92 write_slots,
93 payload.as_u128_slice(),
94 &[],
95 )
96 .map_err(TransactionBuilderError::Transaction)
97 }
98}