From 0d02ab1a24cacb67dfef05abfbf17430180ec98b Mon Sep 17 00:00:00 2001 From: 0xh3rman <119309671+0xh3rman@users.noreply.github.com> Date: Wed, 25 Mar 2026 20:45:51 +0900 Subject: [PATCH 1/2] Fix WalletConnect solana_signAllTransactions parsing and response format Two bugs fixed: - Parse error: raw base64 was stored as data but decode_send_transaction expects {"transaction":"..."} JSON format - Wrong response: was returning {"signature":"..."} instead of {"transactions":["..."]} Added SignAllTransactions action variant with Vec to support multiple transactions. --- crates/gem_wallet_connect/src/actions.rs | 5 +++ .../src/request_handler/mod.rs | 25 +++++++++++++ .../src/request_handler/solana.rs | 36 +++++++++++++++++-- .../src/response_handler.rs | 14 ++++++++ gemstone/src/wallet_connect/mod.rs | 14 ++++++++ 5 files changed, 91 insertions(+), 3 deletions(-) diff --git a/crates/gem_wallet_connect/src/actions.rs b/crates/gem_wallet_connect/src/actions.rs index ad1027ecf2..a803efd38a 100644 --- a/crates/gem_wallet_connect/src/actions.rs +++ b/crates/gem_wallet_connect/src/actions.rs @@ -13,6 +13,11 @@ pub enum WalletConnectAction { transaction_type: WalletConnectTransactionType, data: String, }, + SignAllTransactions { + chain: Chain, + transaction_type: WalletConnectTransactionType, + transactions: Vec, + }, SendTransaction { chain: Chain, transaction_type: WalletConnectTransactionType, diff --git a/crates/gem_wallet_connect/src/request_handler/mod.rs b/crates/gem_wallet_connect/src/request_handler/mod.rs index 9cd60267a7..dcff9ec402 100644 --- a/crates/gem_wallet_connect/src/request_handler/mod.rs +++ b/crates/gem_wallet_connect/src/request_handler/mod.rs @@ -135,6 +135,7 @@ mod tests { use super::*; use crate::sign_type::SignDigestType; use gem_evm::testkit::eip712_mock::mock_eip712_json; + use primitives::TransferDataOutputType; #[test] fn test_unsupported_method() { @@ -217,6 +218,30 @@ mod tests { assert!(WalletConnectRequestHandler::parse_request(request).is_ok()); } + #[test] + fn test_solana_sign_all_transactions_roundtrip() { + let params = r#"{"transactions":["AQAAAB64encoded","BBBBB64encoded"]}"#; + let request = WalletConnectRequest::mock("solana_signAllTransactions", params, Some("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")); + let action = WalletConnectRequestHandler::parse_request(request).unwrap(); + match &action { + WalletConnectAction::SignAllTransactions { chain, transaction_type, transactions } => { + assert_eq!(*chain, Chain::Solana); + assert_eq!(transactions.len(), 2); + for (i, expected) in ["AQAAAB64encoded", "BBBBB64encoded"].iter().enumerate() { + let transaction = WalletConnectRequestHandler::decode_send_transaction(transaction_type.clone(), transactions[i].clone()).unwrap(); + match transaction { + WalletConnectTransaction::Solana { data, output_type } => { + assert_eq!(data.transaction, *expected); + assert_eq!(output_type, TransferDataOutputType::EncodedTransaction); + } + _ => panic!("Expected Solana transaction"), + } + } + } + _ => panic!("Expected SignAllTransactions action"), + } + } + #[test] fn test_parse_request_eth_sign_typed_data_v3_chain_mismatch() { let eip712_json = mock_eip712_json(56); diff --git a/crates/gem_wallet_connect/src/request_handler/solana.rs b/crates/gem_wallet_connect/src/request_handler/solana.rs index 3cd2eeeafc..f8247665e6 100644 --- a/crates/gem_wallet_connect/src/request_handler/solana.rs +++ b/crates/gem_wallet_connect/src/request_handler/solana.rs @@ -41,14 +41,25 @@ impl SolanaRequestHandler { } pub fn parse_sign_all_transactions(params: Value) -> Result { - let transaction = params.get_value("transactions")?.at(0)?.string()?.to_string(); + let array = params.get_value("transactions")?.as_array().ok_or("Expected transactions array")?; + let transactions: Vec = array + .iter() + .map(|v| { + let transaction = v.string()?.to_string(); + Ok(serde_json::json!({"transaction": transaction}).to_string()) + }) + .collect::, String>>()?; - Ok(WalletConnectAction::SignTransaction { + if transactions.is_empty() { + return Err("Empty transactions array".to_string()); + } + + Ok(WalletConnectAction::SignAllTransactions { chain: Chain::Solana, transaction_type: WalletConnectTransactionType::Solana { output_type: TransferDataOutputType::EncodedTransaction, }, - data: transaction, + transactions, }) } } @@ -70,6 +81,25 @@ mod tests { ); } + #[test] + fn test_sign_all_transactions() { + let params: Value = serde_json::from_str(r#"{"transactions":["AQAAA","BBBBB"]}"#).unwrap(); + let result = SolanaRequestHandler::parse_sign_all_transactions(params).unwrap(); + assert_eq!( + result, + WalletConnectAction::SignAllTransactions { + chain: Chain::Solana, + transaction_type: WalletConnectTransactionType::Solana { + output_type: TransferDataOutputType::EncodedTransaction, + }, + transactions: vec![ + r#"{"transaction":"AQAAA"}"#.to_string(), + r#"{"transaction":"BBBBB"}"#.to_string(), + ], + } + ); + } + #[test] fn test_sign_transaction() { let params: Value = serde_json::from_str(r#"{"transaction":"AAACAAhkAAA"}"#).unwrap(); diff --git a/crates/gem_wallet_connect/src/response_handler.rs b/crates/gem_wallet_connect/src/response_handler.rs index 8985cf06f5..8a8d23bbaa 100644 --- a/crates/gem_wallet_connect/src/response_handler.rs +++ b/crates/gem_wallet_connect/src/response_handler.rs @@ -44,6 +44,12 @@ impl WalletConnectResponseHandler { } } + pub fn encode_sign_all_transactions(signed_transactions: Vec) -> WalletConnectResponseType { + WalletConnectResponseType::Object { + json: serde_json::json!({ "transactions": signed_transactions }).to_string(), + } + } + pub fn encode_send_transaction(chain_type: ChainType, transaction_id: String) -> WalletConnectResponseType { match chain_type { ChainType::Sui => WalletConnectResponseType::Object { @@ -113,4 +119,12 @@ mod tests { object(r#"{"result":true,"txid":"txid123"}"#) ); } + + #[test] + fn test_encode_sign_all_transactions() { + assert_eq!( + WalletConnectResponseHandler::encode_sign_all_transactions(vec!["signed_tx_1".to_string(), "signed_tx_2".to_string()]), + object(r#"{"transactions":["signed_tx_1","signed_tx_2"]}"#) + ); + } } diff --git a/gemstone/src/wallet_connect/mod.rs b/gemstone/src/wallet_connect/mod.rs index e7dcb55124..4a31267317 100644 --- a/gemstone/src/wallet_connect/mod.rs +++ b/gemstone/src/wallet_connect/mod.rs @@ -67,6 +67,11 @@ pub enum WalletConnectAction { transaction_type: WalletConnectTransactionType, data: String, }, + SignAllTransactions { + chain: Chain, + transaction_type: WalletConnectTransactionType, + transactions: Vec, + }, SendTransaction { chain: Chain, transaction_type: WalletConnectTransactionType, @@ -232,6 +237,11 @@ impl From for WalletConnectAction { transaction_type: transaction_type.into(), data, }, + WcWalletConnectAction::SignAllTransactions { chain, transaction_type, transactions } => Self::SignAllTransactions { + chain, + transaction_type: transaction_type.into(), + transactions, + }, WcWalletConnectAction::SendTransaction { chain, transaction_type, data } => Self::SendTransaction { chain, transaction_type: transaction_type.into(), @@ -348,6 +358,10 @@ impl WalletConnect { WalletConnectResponseHandler::encode_sign_transaction(chain.chain_type(), transaction_id).into() } + pub fn encode_sign_all_transactions(&self, signed_transactions: Vec) -> WalletConnectResponseType { + WalletConnectResponseHandler::encode_sign_all_transactions(signed_transactions).into() + } + pub fn encode_send_transaction(&self, chain: Chain, transaction_id: String) -> WalletConnectResponseType { WalletConnectResponseHandler::encode_send_transaction(chain.chain_type(), transaction_id).into() } From e2148dd20330f04f98c9f68bf2311762640e74c4 Mon Sep 17 00:00:00 2001 From: 0xh3rman <119309671+0xh3rman@users.noreply.github.com> Date: Thu, 26 Mar 2026 14:37:43 +0900 Subject: [PATCH 2/2] update real tx data --- .../src/request_handler/mod.rs | 18 ++++++++---------- .../src/request_handler/solana.rs | 19 ------------------- .../solana_sign_all_transactions.json | 5 +++++ 3 files changed, 13 insertions(+), 29 deletions(-) create mode 100644 crates/gem_wallet_connect/testdata/solana_sign_all_transactions.json diff --git a/crates/gem_wallet_connect/src/request_handler/mod.rs b/crates/gem_wallet_connect/src/request_handler/mod.rs index dcff9ec402..377ad0ac9b 100644 --- a/crates/gem_wallet_connect/src/request_handler/mod.rs +++ b/crates/gem_wallet_connect/src/request_handler/mod.rs @@ -220,22 +220,20 @@ mod tests { #[test] fn test_solana_sign_all_transactions_roundtrip() { - let params = r#"{"transactions":["AQAAAB64encoded","BBBBB64encoded"]}"#; + let params = include_str!("../../testdata/solana_sign_all_transactions.json"); let request = WalletConnectRequest::mock("solana_signAllTransactions", params, Some("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")); let action = WalletConnectRequestHandler::parse_request(request).unwrap(); match &action { WalletConnectAction::SignAllTransactions { chain, transaction_type, transactions } => { assert_eq!(*chain, Chain::Solana); - assert_eq!(transactions.len(), 2); - for (i, expected) in ["AQAAAB64encoded", "BBBBB64encoded"].iter().enumerate() { - let transaction = WalletConnectRequestHandler::decode_send_transaction(transaction_type.clone(), transactions[i].clone()).unwrap(); - match transaction { - WalletConnectTransaction::Solana { data, output_type } => { - assert_eq!(data.transaction, *expected); - assert_eq!(output_type, TransferDataOutputType::EncodedTransaction); - } - _ => panic!("Expected Solana transaction"), + assert_eq!(transactions.len(), 1); + let decoded = WalletConnectRequestHandler::decode_send_transaction(transaction_type.clone(), transactions[0].clone()).unwrap(); + match decoded { + WalletConnectTransaction::Solana { data, output_type } => { + assert!(data.transaction.starts_with("AQAAAAAAAAA")); + assert_eq!(output_type, TransferDataOutputType::EncodedTransaction); } + _ => panic!("Expected Solana transaction"), } } _ => panic!("Expected SignAllTransactions action"), diff --git a/crates/gem_wallet_connect/src/request_handler/solana.rs b/crates/gem_wallet_connect/src/request_handler/solana.rs index f8247665e6..8253aeca4a 100644 --- a/crates/gem_wallet_connect/src/request_handler/solana.rs +++ b/crates/gem_wallet_connect/src/request_handler/solana.rs @@ -81,25 +81,6 @@ mod tests { ); } - #[test] - fn test_sign_all_transactions() { - let params: Value = serde_json::from_str(r#"{"transactions":["AQAAA","BBBBB"]}"#).unwrap(); - let result = SolanaRequestHandler::parse_sign_all_transactions(params).unwrap(); - assert_eq!( - result, - WalletConnectAction::SignAllTransactions { - chain: Chain::Solana, - transaction_type: WalletConnectTransactionType::Solana { - output_type: TransferDataOutputType::EncodedTransaction, - }, - transactions: vec![ - r#"{"transaction":"AQAAA"}"#.to_string(), - r#"{"transaction":"BBBBB"}"#.to_string(), - ], - } - ); - } - #[test] fn test_sign_transaction() { let params: Value = serde_json::from_str(r#"{"transaction":"AAACAAhkAAA"}"#).unwrap(); diff --git a/crates/gem_wallet_connect/testdata/solana_sign_all_transactions.json b/crates/gem_wallet_connect/testdata/solana_sign_all_transactions.json new file mode 100644 index 0000000000..763c9185ba --- /dev/null +++ b/crates/gem_wallet_connect/testdata/solana_sign_all_transactions.json @@ -0,0 +1,5 @@ +{ + "transactions": [ + "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAEB4X7qT7inGBPqFijUWiMASkIQer7GcY6cKR108e8O++ff+KvGFsTU/tNNyl/GWd04onEeG60T3KS3sy+XeFY0Ki7nDUGiTeDXiXs77SALJIRnd7ysD54hjxwwqZWL45jVwMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAABSGfiZqB1P+E+1k9Lt+KkKwbOrNCWPffIz6lAwKxvS6uRHvTnhwX5MLyqWayYc3wikPwVLiIIofgiijQL5XRhtsX1PCpIazGy+0gPpCTePUXc/WDVmb3Qe5s/iGDPXfbOVNr91a1Z/vs5sRxA8hmPTdja26wmVOCqpF9Xf15KSAEAwAFAsPxAAADAAkDUMMAAAAAAAAEBgAHAQgJChHyI8aJUuHytv4gXacDAAAAAAQLAAcFBgEICQIICwomuBfuYWfF0z0gXacDAAAAAAEAAAAAAAAACKHsaQAAAAAAAAAAAAABe27qMoJyLSDj0LDOHu9s9YiqUZyCEDCEJV/DPetHbXIABQoLCQAB" + ] +}