diff --git a/crates/by-chain/icepick-solana/src/lib.rs b/crates/by-chain/icepick-solana/src/lib.rs index 1fbe94f..8f813fa 100644 --- a/crates/by-chain/icepick-solana/src/lib.rs +++ b/crates/by-chain/icepick-solana/src/lib.rs @@ -64,6 +64,18 @@ pub enum Operation { pub struct Solana; +impl Solana { + fn keypair_from_bytes(given_bytes: [u8; 32]) -> solana_sdk::signer::keypair::Keypair { + use ed25519_dalek::{PublicKey, SecretKey}; + let secret_key = SecretKey::from_bytes(&given_bytes).expect("key should be 32 bytes"); + let mut bytes = [0u8; 64]; + bytes[..32].clone_from_slice(&given_bytes); + bytes[32..].clone_from_slice(PublicKey::from(&secret_key).as_bytes()); + solana_sdk::signer::keypair::Keypair::from_bytes(&bytes) + .expect("solana sdk should expect 64 bytes") + } +} + impl Module for Solana { type Error = Error; @@ -178,17 +190,12 @@ impl Module for Solana { })) } Operation::GetWalletAddress(_) => { - use ed25519_dalek::{PublicKey, SecretKey}; // NOTE: panics if doesn't exist let key = request.derived_keys.unwrap()[0]; - let secret_key = SecretKey::from_bytes(&key).unwrap(); - let mut bytes = [0u8; 64]; - bytes[..32].clone_from_slice(&key); - bytes[32..].clone_from_slice(PublicKey::from(&secret_key).as_bytes()); - let pk = solana_sdk::signer::keypair::Keypair::from_bytes(&bytes).unwrap(); - let pk = pk.pubkey(); + let keypair = Self::keypair_from_bytes(key); + let pubkey = keypair.pubkey(); Ok(serde_json::json!({ - "blob": pk.to_string(), + "blob": pubkey.to_string(), })) } Operation::Transfer(Transfer { @@ -253,11 +260,22 @@ impl Module for Solana { } Operation::Sign(_) => { let blob = request.blob.expect("passed in instruction blob"); - let _transaction: solana_sdk::transaction::Transaction = + let mut transaction: solana_sdk::transaction::Transaction = serde_json::from_value(blob).expect("valid message blob"); - let _keys = request.derived_keys.unwrap_or_default(); + let keys = request + .derived_keys + .unwrap_or_default() + .iter() + .map(|k| Self::keypair_from_bytes(*k)) + .collect::>(); + + let hash = transaction.message.recent_blockhash; + transaction + .try_sign(&keys, hash) + .expect("not enough keys provided"); + use base64::prelude::*; Ok(serde_json::json!({ - "blob": [] + "blob": transaction })) } }