Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/gem_wallet_connect/src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ pub enum WalletConnectAction {
transaction_type: WalletConnectTransactionType,
data: String,
},
SignAllTransactions {
chain: Chain,
transaction_type: WalletConnectTransactionType,
transactions: Vec<String>,
},
SendTransaction {
chain: Chain,
transaction_type: WalletConnectTransactionType,
Expand Down
23 changes: 23 additions & 0 deletions crates/gem_wallet_connect/src/request_handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -217,6 +218,28 @@ mod tests {
assert!(WalletConnectRequestHandler::parse_request(request).is_ok());
}

#[test]
fn test_solana_sign_all_transactions_roundtrip() {
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(), 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"),
}
}

#[test]
fn test_parse_request_eth_sign_typed_data_v3_chain_mismatch() {
let eip712_json = mock_eip712_json(56);
Expand Down
17 changes: 14 additions & 3 deletions crates/gem_wallet_connect/src/request_handler/solana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,25 @@ impl SolanaRequestHandler {
}

pub fn parse_sign_all_transactions(params: Value) -> Result<WalletConnectAction, String> {
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<String> = array
.iter()
.map(|v| {
let transaction = v.string()?.to_string();
Ok(serde_json::json!({"transaction": transaction}).to_string())
})
.collect::<Result<Vec<String>, String>>()?;

Ok(WalletConnectAction::SignTransaction {
if transactions.is_empty() {
return Err("Empty transactions array".to_string());
}
Comment on lines +53 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For efficiency, it's better to check if the transactions array is empty before mapping over it and collecting the results into a new Vec. This check should be performed on the array variable right after it's created on line 44. This avoids unnecessary allocations and processing if the input array is empty.


Ok(WalletConnectAction::SignAllTransactions {
chain: Chain::Solana,
transaction_type: WalletConnectTransactionType::Solana {
output_type: TransferDataOutputType::EncodedTransaction,
},
data: transaction,
transactions,
})
}
}
Expand Down
14 changes: 14 additions & 0 deletions crates/gem_wallet_connect/src/response_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ impl WalletConnectResponseHandler {
}
}

pub fn encode_sign_all_transactions(signed_transactions: Vec<String>) -> 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 {
Expand Down Expand Up @@ -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"]}"#)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"transactions": [
"AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAEB4X7qT7inGBPqFijUWiMASkIQer7GcY6cKR108e8O++ff+KvGFsTU/tNNyl/GWd04onEeG60T3KS3sy+XeFY0Ki7nDUGiTeDXiXs77SALJIRnd7ysD54hjxwwqZWL45jVwMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAABSGfiZqB1P+E+1k9Lt+KkKwbOrNCWPffIz6lAwKxvS6uRHvTnhwX5MLyqWayYc3wikPwVLiIIofgiijQL5XRhtsX1PCpIazGy+0gPpCTePUXc/WDVmb3Qe5s/iGDPXfbOVNr91a1Z/vs5sRxA8hmPTdja26wmVOCqpF9Xf15KSAEAwAFAsPxAAADAAkDUMMAAAAAAAAEBgAHAQgJChHyI8aJUuHytv4gXacDAAAAAAQLAAcFBgEICQIICwomuBfuYWfF0z0gXacDAAAAAAEAAAAAAAAACKHsaQAAAAAAAAAAAAABe27qMoJyLSDj0LDOHu9s9YiqUZyCEDCEJV/DPetHbXIABQoLCQAB"
]
}
14 changes: 14 additions & 0 deletions gemstone/src/wallet_connect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ pub enum WalletConnectAction {
transaction_type: WalletConnectTransactionType,
data: String,
},
SignAllTransactions {
chain: Chain,
transaction_type: WalletConnectTransactionType,
transactions: Vec<String>,
},
SendTransaction {
chain: Chain,
transaction_type: WalletConnectTransactionType,
Expand Down Expand Up @@ -232,6 +237,11 @@ impl From<WcWalletConnectAction> 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(),
Expand Down Expand Up @@ -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<String>) -> 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()
}
Expand Down
Loading