clone_solana_signer/
lib.rs1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3use {
4 clone_solana_pubkey::Pubkey,
5 clone_solana_signature::Signature,
6 clone_solana_transaction_error::TransactionError,
7 core::fmt,
8 std::{
9 error,
10 fs::{self, File, OpenOptions},
11 io::{Read, Write},
12 ops::Deref,
13 path::Path,
14 },
15};
16
17pub mod null_signer;
18pub mod signers;
19
20#[derive(Debug, PartialEq, Eq)]
21pub enum PresignerError {
22 VerificationFailure,
23}
24
25impl std::error::Error for PresignerError {}
26
27impl fmt::Display for PresignerError {
28 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
29 match self {
30 Self::VerificationFailure => f.write_str("pre-generated signature cannot verify data"),
31 }
32 }
33}
34
35#[derive(Debug, PartialEq, Eq)]
36pub enum SignerError {
37 KeypairPubkeyMismatch,
38 NotEnoughSigners,
39 TransactionError(TransactionError),
40 Custom(String),
41 PresignerError(PresignerError),
43 Connection(String),
45 InvalidInput(String),
46 NoDeviceFound,
47 Protocol(String),
48 UserCancel(String),
49 TooManySigners,
50}
51
52impl std::error::Error for SignerError {
53 fn source(&self) -> ::core::option::Option<&(dyn std::error::Error + 'static)> {
54 match self {
55 Self::KeypairPubkeyMismatch => None,
56 Self::NotEnoughSigners => None,
57 Self::TransactionError(e) => Some(e),
58 Self::Custom(_) => None,
59 Self::PresignerError(e) => Some(e),
60 Self::Connection(_) => None,
61 Self::InvalidInput(_) => None,
62 Self::NoDeviceFound => None,
63 Self::Protocol(_) => None,
64 Self::UserCancel(_) => None,
65 Self::TooManySigners => None,
66 }
67 }
68}
69impl fmt::Display for SignerError {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71 match self {
72 SignerError::KeypairPubkeyMismatch => f.write_str("keypair-pubkey mismatch"),
73 SignerError::NotEnoughSigners => f.write_str("not enough signers"),
74 SignerError::TransactionError(_) => f.write_str("transaction error"),
75 SignerError::Custom(e) => write!(f, "custom error: {e}",),
76 SignerError::PresignerError(_) => f.write_str("presigner error"),
77 SignerError::Connection(e) => write!(f, "connection error: {e}",),
78 SignerError::InvalidInput(s) => write!(f, "invalid input: {s}",),
79 SignerError::NoDeviceFound => f.write_str("no device found"),
80 SignerError::Protocol(s) => {
81 write!(f, "{s}")
82 }
83 SignerError::UserCancel(s) => {
84 write!(f, "{s}")
85 }
86 SignerError::TooManySigners => f.write_str("too many signers"),
87 }
88 }
89}
90
91impl From<TransactionError> for SignerError {
92 fn from(source: TransactionError) -> Self {
93 SignerError::TransactionError(source)
94 }
95}
96
97impl From<PresignerError> for SignerError {
98 fn from(source: PresignerError) -> Self {
99 SignerError::PresignerError(source)
100 }
101}
102
103pub trait Signer {
107 fn pubkey(&self) -> Pubkey {
110 self.try_pubkey().unwrap_or_default()
111 }
112 fn try_pubkey(&self) -> Result<Pubkey, SignerError>;
114 fn sign_message(&self, message: &[u8]) -> Signature {
117 self.try_sign_message(message).unwrap_or_default()
118 }
119 fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError>;
121 fn is_interactive(&self) -> bool;
123}
124
125impl<Container: Deref<Target = impl Signer + ?Sized>> Signer for Container {
127 #[inline]
128 fn pubkey(&self) -> Pubkey {
129 self.deref().pubkey()
130 }
131
132 fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
133 self.deref().try_pubkey()
134 }
135
136 fn sign_message(&self, message: &[u8]) -> Signature {
137 self.deref().sign_message(message)
138 }
139
140 fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
141 self.deref().try_sign_message(message)
142 }
143
144 fn is_interactive(&self) -> bool {
145 self.deref().is_interactive()
146 }
147}
148
149impl PartialEq for dyn Signer {
150 fn eq(&self, other: &dyn Signer) -> bool {
151 self.pubkey() == other.pubkey()
152 }
153}
154
155impl Eq for dyn Signer {}
156
157impl std::fmt::Debug for dyn Signer {
158 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
159 write!(fmt, "Signer: {:?}", self.pubkey())
160 }
161}
162
163pub fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> {
165 let capacity = signers.len();
166 let mut out = Vec::with_capacity(capacity);
167 let mut seen = std::collections::HashSet::with_capacity(capacity);
168 for signer in signers {
169 let pubkey = signer.pubkey();
170 if !seen.contains(&pubkey) {
171 seen.insert(pubkey);
172 out.push(signer);
173 }
174 }
175 out
176}
177
178pub trait EncodableKey: Sized {
181 fn read<R: Read>(reader: &mut R) -> Result<Self, Box<dyn error::Error>>;
182 fn read_from_file<F: AsRef<Path>>(path: F) -> Result<Self, Box<dyn error::Error>> {
183 let mut file = File::open(path.as_ref())?;
184 Self::read(&mut file)
185 }
186 fn write<W: Write>(&self, writer: &mut W) -> Result<String, Box<dyn error::Error>>;
187 fn write_to_file<F: AsRef<Path>>(&self, outfile: F) -> Result<String, Box<dyn error::Error>> {
188 let outfile = outfile.as_ref();
189
190 if let Some(outdir) = outfile.parent() {
191 fs::create_dir_all(outdir)?;
192 }
193
194 let mut f = {
195 #[cfg(not(unix))]
196 {
197 OpenOptions::new()
198 }
199 #[cfg(unix)]
200 {
201 use std::os::unix::fs::OpenOptionsExt;
202 OpenOptions::new().mode(0o600)
203 }
204 }
205 .write(true)
206 .truncate(true)
207 .create(true)
208 .open(outfile)?;
209
210 self.write(&mut f)
211 }
212}
213
214pub trait EncodableKeypair: EncodableKey {
217 type Pubkey: ToString;
218
219 fn encodable_pubkey(&self) -> Self::Pubkey;
221}