1mod keypair_util;
4
5use crate::{
6 error::SignerError,
7 sdk_adapter::keypair_from_bytes,
8 traits::{SignedTransaction, SolanaSigner},
9 transaction_util::TransactionUtil,
10};
11
12use crate::sdk_adapter::{
13 keypair_pubkey, keypair_sign_message, Keypair, Pubkey, Signature, Transaction,
14};
15use keypair_util::KeypairUtil;
16
17pub struct MemorySigner {
19 keypair: Keypair,
20}
21
22impl std::fmt::Debug for MemorySigner {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 f.debug_struct("MemorySigner")
25 .field("pubkey", &keypair_pubkey(&self.keypair))
26 .finish_non_exhaustive()
27 }
28}
29
30impl MemorySigner {
31 pub fn new(keypair: Keypair) -> Self {
33 Self { keypair }
34 }
35
36 pub fn from_bytes(private_key: &[u8]) -> Result<Self, SignerError> {
38 let keypair = keypair_from_bytes(private_key).map_err(|e| {
39 SignerError::InvalidPrivateKey(format!("Invalid private key bytes: {e}"))
40 })?;
41 Ok(Self { keypair })
42 }
43
44 pub fn from_private_key_string(private_key: &str) -> Result<Self, SignerError> {
49 let keypair = KeypairUtil::from_private_key_string(private_key)?;
50 Ok(Self::new(keypair))
51 }
52
53 async fn sign_bytes(&self, serialized: &[u8]) -> Result<Signature, SignerError> {
54 Ok(keypair_sign_message(&self.keypair, serialized))
55 }
56}
57
58#[async_trait::async_trait]
59impl SolanaSigner for MemorySigner {
60 fn pubkey(&self) -> Pubkey {
61 keypair_pubkey(&self.keypair)
62 }
63
64 async fn sign_transaction(
65 &self,
66 tx: &mut Transaction,
67 ) -> Result<SignedTransaction, SignerError> {
68 let signature = self.sign_bytes(&tx.message_data()).await?;
69
70 TransactionUtil::add_signature_to_transaction(tx, &self.pubkey(), signature)?;
71
72 Ok((TransactionUtil::serialize_transaction(tx)?, signature))
73 }
74
75 async fn sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
76 self.sign_bytes(message).await
77 }
78
79 async fn sign_partial_transaction(
80 &self,
81 tx: &mut Transaction,
82 ) -> Result<SignedTransaction, SignerError> {
83 let signature = self.sign_bytes(&tx.message_data()).await?;
84
85 TransactionUtil::add_signature_to_transaction(tx, &self.pubkey(), signature)?;
86
87 Ok((TransactionUtil::serialize_transaction(tx)?, signature))
88 }
89
90 async fn is_available(&self) -> bool {
91 true
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use crate::test_util::create_test_transaction;
99
100 use super::*;
101
102 const TEST_KEYPAIR_BYTES: &str = "[41,99,180,88,51,57,48,80,61,63,219,75,176,49,116,254,227,176,196,204,122,47,166,133,155,252,217,0,253,17,49,143,47,94,121,167,195,136,72,22,157,48,77,88,63,96,57,122,181,243,236,188,241,134,174,224,100,246,17,170,104,17,151,48]";
103 const TEST_PUBKEY: &str = "4BuiY9QUUfPoAGNJBja3JapAuVWMc9c7in6UCgyC2zPR";
104
105 fn create_test_signer() -> MemorySigner {
106 MemorySigner::from_private_key_string(TEST_KEYPAIR_BYTES)
107 .expect("Failed to create test signer")
108 }
109
110 #[test]
111 fn test_create_from_u8_array() {
112 let signer = MemorySigner::from_private_key_string(TEST_KEYPAIR_BYTES);
113 assert!(signer.is_ok());
114 }
115
116 #[test]
117 fn test_pubkey() {
118 let signer = create_test_signer();
119 let pubkey = signer.pubkey();
120 assert_eq!(pubkey.to_string(), TEST_PUBKEY);
121 }
122
123 #[tokio::test]
124 async fn test_sign_message() {
125 let signer = create_test_signer();
126 let message = b"Hello Solana!";
127 let signature = signer.sign_message(message).await;
128
129 assert!(signature.is_ok());
130 let sig = signature.unwrap();
131 assert_eq!(sig.as_ref().len(), 64);
133 }
134
135 #[tokio::test]
136 async fn test_is_available() {
137 let signer = create_test_signer();
138 assert!(signer.is_available().await);
139 }
140
141 #[tokio::test]
142 async fn test_sign_transaction() {
143 let signer = create_test_signer();
144
145 let mut tx = create_test_transaction(&keypair_pubkey(&signer.keypair));
146
147 let result = signer.sign_transaction(&mut tx).await;
148 assert!(result.is_ok());
149
150 let (serialized_tx, signature) = result.unwrap();
151
152 assert_eq!(signature.as_ref().len(), 64);
154
155 assert!(!serialized_tx.is_empty());
157
158 assert_eq!(tx.signatures.len(), 1);
160 assert_eq!(tx.signatures[0], signature);
161 }
162
163 #[tokio::test]
164 async fn test_sign_partial_transaction() {
165 let signer = create_test_signer();
166
167 let mut tx = create_test_transaction(&keypair_pubkey(&signer.keypair));
168
169 let result = signer.sign_partial_transaction(&mut tx).await;
170 assert!(result.is_ok());
171
172 let (serialized_tx, signature) = result.unwrap();
173
174 assert_eq!(signature.as_ref().len(), 64);
176
177 assert!(!serialized_tx.is_empty());
179
180 assert_eq!(tx.signatures.len(), 1);
182 assert_eq!(tx.signatures[0], signature);
183 }
184}