11use async_trait:: async_trait;
22use base64:: { engine:: general_purpose:: STANDARD , Engine as _} ;
3- use solana_client:: nonblocking:: rpc_client:: RpcClient ;
3+ use solana_client:: { nonblocking:: rpc_client:: RpcClient , rpc_config :: RpcSimulateTransactionConfig } ;
44use solana_commitment_config:: CommitmentConfig ;
55use solana_message:: { v0:: MessageAddressTableLookup , VersionedMessage } ;
66use solana_sdk:: {
@@ -79,6 +79,7 @@ impl VersionedTransactionResolved {
7979 pub async fn from_transaction (
8080 transaction : & VersionedTransaction ,
8181 rpc_client : & RpcClient ,
82+ sig_verify : bool ,
8283 ) -> Result < Self , KoraError > {
8384 let mut resolved = Self {
8485 transaction : transaction. clone ( ) ,
@@ -113,7 +114,7 @@ impl VersionedTransactionResolved {
113114 let outer_instructions =
114115 IxUtils :: uncompile_instructions ( transaction. message . instructions ( ) , & all_account_keys) ;
115116
116- let inner_instructions = resolved. fetch_inner_instructions ( rpc_client) . await ?;
117+ let inner_instructions = resolved. fetch_inner_instructions ( rpc_client, sig_verify ) . await ?;
117118
118119 resolved. all_instructions . extend ( outer_instructions) ;
119120 resolved. all_instructions . extend ( inner_instructions) ;
@@ -139,9 +140,17 @@ impl VersionedTransactionResolved {
139140 async fn fetch_inner_instructions (
140141 & mut self ,
141142 rpc_client : & RpcClient ,
143+ sig_verify : bool ,
142144 ) -> Result < Vec < Instruction > , KoraError > {
143145 let simulation_result = rpc_client
144- . simulate_transaction ( & self . transaction )
146+ . simulate_transaction_with_config (
147+ & self . transaction ,
148+ RpcSimulateTransactionConfig {
149+ commitment : Some ( rpc_client. commitment ( ) ) ,
150+ sig_verify,
151+ ..Default :: default ( )
152+ } ,
153+ )
145154 . await
146155 . map_err ( |e| KoraError :: RpcError ( format ! ( "Failed to simulate transaction: {e}" ) ) ) ?;
147156
@@ -669,9 +678,10 @@ mod tests {
669678 ) ;
670679 let rpc_client = RpcMockBuilder :: new ( ) . with_custom_mocks ( mocks) . build ( ) ;
671680
672- let resolved = VersionedTransactionResolved :: from_transaction ( & transaction, & rpc_client)
673- . await
674- . unwrap ( ) ;
681+ let resolved =
682+ VersionedTransactionResolved :: from_transaction ( & transaction, & rpc_client, true )
683+ . await
684+ . unwrap ( ) ;
675685
676686 assert_eq ! ( resolved. transaction, transaction) ;
677687 assert_eq ! ( resolved. all_account_keys, transaction. message. static_account_keys( ) ) ;
@@ -770,9 +780,10 @@ mod tests {
770780
771781 let rpc_client = RpcMockBuilder :: new ( ) . with_custom_mocks ( mocks) . build ( ) ;
772782
773- let resolved = VersionedTransactionResolved :: from_transaction ( & transaction, & rpc_client)
774- . await
775- . unwrap ( ) ;
783+ let resolved =
784+ VersionedTransactionResolved :: from_transaction ( & transaction, & rpc_client, true )
785+ . await
786+ . unwrap ( ) ;
776787
777788 assert_eq ! ( resolved. transaction, transaction) ;
778789
@@ -815,7 +826,7 @@ mod tests {
815826 let rpc_client = RpcMockBuilder :: new ( ) . with_custom_mocks ( mocks) . build ( ) ;
816827
817828 let result =
818- VersionedTransactionResolved :: from_transaction ( & transaction, & rpc_client) . await ;
829+ VersionedTransactionResolved :: from_transaction ( & transaction, & rpc_client, true ) . await ;
819830
820831 // The simulation should fail, but the exact error type depends on mock implementation
821832 // We expect either an RpcError (from mock deserialization) or InvalidTransaction (from simulation logic)
@@ -877,7 +888,60 @@ mod tests {
877888 let rpc_client = RpcMockBuilder :: new ( ) . with_custom_mocks ( mocks) . build ( ) ;
878889
879890 let mut resolved = VersionedTransactionResolved :: from_kora_built_transaction ( & transaction) ;
880- let inner_instructions = resolved. fetch_inner_instructions ( & rpc_client) . await . unwrap ( ) ;
891+ let inner_instructions =
892+ resolved. fetch_inner_instructions ( & rpc_client, true ) . await . unwrap ( ) ;
893+
894+ assert_eq ! ( inner_instructions. len( ) , 1 ) ;
895+ assert_eq ! ( inner_instructions[ 0 ] . data, vec![ 10 , 20 , 30 ] ) ;
896+ }
897+
898+ #[ tokio:: test]
899+ async fn test_fetch_inner_instructions_with_sig_verify_false ( ) {
900+ let config = setup_test_config ( ) ;
901+ let _m = setup_config_mock ( config) ;
902+
903+ let keypair = Keypair :: new ( ) ;
904+ let instruction = Instruction :: new_with_bytes (
905+ Pubkey :: new_unique ( ) ,
906+ & [ 1 , 2 , 3 ] ,
907+ vec ! [ AccountMeta :: new( keypair. pubkey( ) , true ) ] ,
908+ ) ;
909+ let message =
910+ VersionedMessage :: Legacy ( Message :: new ( & [ instruction] , Some ( & keypair. pubkey ( ) ) ) ) ;
911+ let transaction = VersionedTransaction :: try_new ( message, & [ & keypair] ) . unwrap ( ) ;
912+
913+ // Mock RPC client with inner instructions
914+ let inner_instruction_data = bs58:: encode ( & [ 10 , 20 , 30 ] ) . into_string ( ) ;
915+ let mut mocks = HashMap :: new ( ) ;
916+ mocks. insert (
917+ RpcRequest :: SimulateTransaction ,
918+ json ! ( {
919+ "context" : { "slot" : 1 } ,
920+ "value" : {
921+ "err" : null,
922+ "logs" : [ ] ,
923+ "accounts" : null,
924+ "unitsConsumed" : 1000 ,
925+ "innerInstructions" : [
926+ {
927+ "index" : 0 ,
928+ "instructions" : [
929+ {
930+ "programIdIndex" : 1 ,
931+ "accounts" : [ 0 ] ,
932+ "data" : inner_instruction_data
933+ }
934+ ]
935+ }
936+ ]
937+ }
938+ } ) ,
939+ ) ;
940+ let rpc_client = RpcMockBuilder :: new ( ) . with_custom_mocks ( mocks) . build ( ) ;
941+
942+ let mut resolved = VersionedTransactionResolved :: from_kora_built_transaction ( & transaction) ;
943+ let inner_instructions =
944+ resolved. fetch_inner_instructions ( & rpc_client, false ) . await . unwrap ( ) ;
881945
882946 assert_eq ! ( inner_instructions. len( ) , 1 ) ;
883947 assert_eq ! ( inner_instructions[ 0 ] . data, vec![ 10 , 20 , 30 ] ) ;
0 commit comments