3333use alloy_primitives:: Bytes ;
3434use rollup_node:: test_utils:: { EventAssertions , TestFixture } ;
3535use serde_json:: Value ;
36+ use std:: { collections:: HashMap , sync:: LazyLock } ;
3637
37- /// Helper to read pre-signed transactions from `test_transactions.json`.
38+ /// Lazily load and cache all test transactions from `test_transactions.json`.
39+ ///
40+ /// This loads the file only once and keeps all transactions in memory for efficient access
41+ /// throughout the test suite. The cache is organized as a nested map:
42+ /// `tx_type -> index -> raw_bytes`
43+ static TEST_TRANSACTIONS : LazyLock < HashMap < String , HashMap < String , Bytes > > > = LazyLock :: new ( || {
44+ let tx_json_path = "./tests/testdata/test_transactions.json" ;
45+ let tx_json_content = std:: fs:: read_to_string ( tx_json_path)
46+ . unwrap_or_else ( |e| panic ! ( "Failed to read {}: {}" , tx_json_path, e) ) ;
47+
48+ let tx_data: Value = serde_json:: from_str ( & tx_json_content)
49+ . unwrap_or_else ( |e| panic ! ( "Failed to parse JSON: {}" , e) ) ;
50+
51+ let mut cache = HashMap :: new ( ) ;
52+
53+ if let Value :: Object ( map) = tx_data {
54+ for ( tx_type, tx_group) in map {
55+ if let Value :: Object ( transactions) = tx_group {
56+ let mut tx_map = HashMap :: new ( ) ;
57+ for ( index, raw_tx_hex) in transactions {
58+ if let Value :: String ( hex) = raw_tx_hex {
59+ if !hex. is_empty ( ) {
60+ // Decode hex string to bytes
61+ let raw_tx_bytes = if let Some ( stripped) = hex. strip_prefix ( "0x" ) {
62+ alloy_primitives:: hex:: decode ( stripped)
63+ } else {
64+ alloy_primitives:: hex:: decode ( hex. as_str ( ) )
65+ }
66+ . unwrap_or_else ( |e| {
67+ panic ! ( "Failed to decode hex for {}.{}: {}" , tx_type, index, e)
68+ } ) ;
69+ tx_map. insert ( index, Bytes :: from ( raw_tx_bytes) ) ;
70+ }
71+ }
72+ }
73+ cache. insert ( tx_type, tx_map) ;
74+ }
75+ }
76+ }
77+
78+ cache
79+ } ) ;
80+
81+ /// Helper to read pre-signed transactions from the cached transaction data.
3882///
3983/// The test data file contains signed transactions for various L1 batch operations:
4084/// - `commitBatch`: Transactions that commit L2 batches to the L1 contract
@@ -48,31 +92,11 @@ use serde_json::Value;
4892/// # Returns
4993/// The raw transaction bytes ready to be sent to Anvil via `eth_sendRawTransaction`.
5094fn read_test_transaction ( tx_type : & str , index : & str ) -> eyre:: Result < Bytes > {
51- let tx_json_path = "./tests/testdata/test_transactions.json" ;
52- let tx_json_content = std:: fs:: read_to_string ( tx_json_path)
53- . map_err ( |e| eyre:: eyre!( "Failed to read {}: {}" , tx_json_path, e) ) ?;
54-
55- let tx_data: Value = serde_json:: from_str ( & tx_json_content)
56- . map_err ( |e| eyre:: eyre!( "Failed to parse JSON: {}" , e) ) ?;
57-
58- let raw_tx_hex = tx_data
95+ TEST_TRANSACTIONS
5996 . get ( tx_type)
60- . and_then ( |t| t. get ( index) )
61- . and_then ( |v| v. as_str ( ) )
62- . ok_or_else ( || eyre:: eyre!( "Transaction not found: {}.{}" , tx_type, index) ) ?;
63-
64- if raw_tx_hex. is_empty ( ) {
65- return Err ( eyre:: eyre!( "Transaction {}.{} is empty" , tx_type, index) ) ;
66- }
67-
68- // Decode hex string to bytes
69- let raw_tx_bytes = if let Some ( stripped) = raw_tx_hex. strip_prefix ( "0x" ) {
70- alloy_primitives:: hex:: decode ( stripped) ?
71- } else {
72- alloy_primitives:: hex:: decode ( raw_tx_hex) ?
73- } ;
74-
75- Ok ( Bytes :: from ( raw_tx_bytes) )
97+ . and_then ( |tx_group| tx_group. get ( index) )
98+ . cloned ( )
99+ . ok_or_else ( || eyre:: eyre!( "Transaction not found: {}.{}" , tx_type, index) )
76100}
77101
78102// =============================================================================
0 commit comments