polymesh_api_client/
signer.rs

1#[cfg(feature = "std")]
2use sp_core::Pair;
3
4use sp_runtime::MultiSignature;
5use sp_std::prelude::*;
6
7use async_trait::async_trait;
8
9#[cfg(not(feature = "std"))]
10use alloc::string::ToString;
11
12use crate::*;
13
14#[cfg(feature = "std")]
15pub type DefaultSigner = PairSigner<sp_core::sr25519::Pair>;
16#[cfg(not(feature = "std"))]
17pub type DefaultSigner = PairSigner<subxt_signer::sr25519::Keypair>;
18
19pub mod dev {
20  use super::DefaultSigner;
21
22  pub fn alice() -> DefaultSigner {
23    DefaultSigner::from_string("//Alice", None).expect("Const seed")
24  }
25
26  pub fn bob() -> DefaultSigner {
27    DefaultSigner::from_string("//Bob", None).expect("Const seed")
28  }
29
30  pub fn charlie() -> DefaultSigner {
31    DefaultSigner::from_string("//Charlie", None).expect("Const seed")
32  }
33
34  pub fn dave() -> DefaultSigner {
35    DefaultSigner::from_string("//Dave", None).expect("Const seed")
36  }
37
38  pub fn eve() -> DefaultSigner {
39    DefaultSigner::from_string("//Eve", None).expect("Const seed")
40  }
41
42  pub fn ferdie() -> DefaultSigner {
43    DefaultSigner::from_string("//Ferdie", None).expect("Const seed")
44  }
45
46  pub fn one() -> DefaultSigner {
47    DefaultSigner::from_string("//One", None).expect("Const seed")
48  }
49
50  pub fn two() -> DefaultSigner {
51    DefaultSigner::from_string("//Two", None).expect("Const seed")
52  }
53
54  pub fn alice_stash() -> DefaultSigner {
55    DefaultSigner::from_string("//Alice//stash", None).expect("Const seed")
56  }
57
58  pub fn bob_stash() -> DefaultSigner {
59    DefaultSigner::from_string("//Bob//stash", None).expect("Const seed")
60  }
61
62  pub fn charlie_stash() -> DefaultSigner {
63    DefaultSigner::from_string("//Charlie//stash", None).expect("Const seed")
64  }
65
66  pub fn dave_stash() -> DefaultSigner {
67    DefaultSigner::from_string("//Dave//stash", None).expect("Const seed")
68  }
69
70  pub fn eve_stash() -> DefaultSigner {
71    DefaultSigner::from_string("//Eve//stash", None).expect("Const seed")
72  }
73
74  pub fn ferdie_stash() -> DefaultSigner {
75    DefaultSigner::from_string("//Ferdie//stash", None).expect("Const seed")
76  }
77}
78
79#[async_trait]
80pub trait Signer: Send + Sync {
81  fn account(&self) -> AccountId;
82
83  /// Optional - The signer can manage their `nonce` for improve transaction performance.
84  /// The default implmentation will query the next `nonce` from chain storage.
85  async fn nonce(&self) -> Option<u32> {
86    None
87  }
88
89  /// Optional - The signer can manage their `nonce` for improve transaction performance.
90  /// If the transaction is accepted by the RPC node, then the `nonce` we be increased, to
91  /// allow the next transaction to be signed & submitted without waiting for the next block.
92  async fn set_nonce(&mut self, _nonce: u32) {}
93
94  async fn sign(&self, msg: &[u8]) -> Result<MultiSignature>;
95
96  /// Optional support for locking the signer.
97  async fn lock(&self) -> Option<Box<dyn Signer>> {
98    None
99  }
100}
101
102pub trait KeypairSigner: Send + Sync + Sized + Clone {
103  fn account(&self) -> AccountId;
104  fn sign(&self, message: &[u8]) -> MultiSignature;
105  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self>;
106
107  fn verify<M: AsRef<[u8]>>(&self, _sig: &MultiSignature, _message: M) -> Result<bool> {
108    unimplemented!()
109  }
110}
111
112#[cfg(feature = "std")]
113impl KeypairSigner for sp_core::ed25519::Pair {
114  fn account(&self) -> AccountId {
115    self.public().into()
116  }
117
118  fn sign(&self, message: &[u8]) -> MultiSignature {
119    <sp_core::ed25519::Pair as sp_core::Pair>::sign(self, message).into()
120  }
121
122  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
123    Ok(<sp_core::ed25519::Pair as sp_core::Pair>::from_string(
124      s,
125      password_override,
126    )?)
127  }
128
129  fn verify<M: AsRef<[u8]>>(&self, sig: &MultiSignature, message: M) -> Result<bool> {
130    let sig = match sig {
131      MultiSignature::Ed25519(sig) => sig,
132      _ => {
133        return Err(Error::CoreCryptoError(format!(
134          "Invalid signature type: {sig:?}"
135        )))
136      }
137    };
138    Ok(<sp_core::ed25519::Pair as sp_core::Pair>::verify(
139      sig,
140      message.as_ref(),
141      &self.public(),
142    ))
143  }
144}
145
146#[cfg(feature = "std")]
147impl KeypairSigner for sp_core::sr25519::Pair {
148  fn account(&self) -> AccountId {
149    self.public().into()
150  }
151
152  fn sign(&self, message: &[u8]) -> MultiSignature {
153    <sp_core::sr25519::Pair as sp_core::Pair>::sign(self, message).into()
154  }
155
156  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
157    Ok(<sp_core::sr25519::Pair as sp_core::Pair>::from_string(
158      s,
159      password_override,
160    )?)
161  }
162
163  fn verify<M: AsRef<[u8]>>(&self, sig: &MultiSignature, message: M) -> Result<bool> {
164    let sig = match sig {
165      MultiSignature::Sr25519(sig) => sig,
166      _ => {
167        return Err(Error::CoreCryptoError(format!(
168          "Invalid signature type: {sig:?}"
169        )))
170      }
171    };
172    Ok(<sp_core::sr25519::Pair as sp_core::Pair>::verify(
173      sig,
174      message.as_ref(),
175      &self.public(),
176    ))
177  }
178}
179
180impl KeypairSigner for subxt_signer::sr25519::Keypair {
181  fn account(&self) -> AccountId {
182    AccountId(self.public_key().0)
183  }
184
185  fn sign(&self, message: &[u8]) -> MultiSignature {
186    let sig = subxt_signer::sr25519::Keypair::sign(self, message).0;
187    MultiSignature::Sr25519(sig.into())
188  }
189
190  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
191    use alloc::str::FromStr;
192    let mut uri = subxt_signer::SecretUri::from_str(s)?;
193    if let Some(password_override) = password_override {
194      uri.password = Some(password_override.to_string().into());
195    }
196    Ok(subxt_signer::sr25519::Keypair::from_uri(&uri)?)
197  }
198}
199
200impl KeypairSigner for subxt_signer::ecdsa::Keypair {
201  fn account(&self) -> AccountId {
202    let pub_key = self.public_key();
203    let hash = sp_core::hashing::blake2_256(&pub_key.0[..]);
204    AccountId(hash)
205  }
206
207  fn sign(&self, message: &[u8]) -> MultiSignature {
208    let sig = subxt_signer::ecdsa::Keypair::sign(self, message).0;
209    MultiSignature::Ecdsa(sig.into())
210  }
211
212  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
213    use alloc::str::FromStr;
214    let mut uri = subxt_signer::SecretUri::from_str(s)?;
215    if let Some(password_override) = password_override {
216      uri.password = Some(password_override.to_string().into());
217    }
218    Ok(subxt_signer::ecdsa::Keypair::from_uri(&uri)?)
219  }
220}
221
222#[derive(Clone)]
223pub struct PairSigner<P: KeypairSigner + Clone> {
224  pub pair: P,
225  pub nonce: u32,
226  pub account: AccountId,
227}
228
229impl<P> PairSigner<P>
230where
231  P: KeypairSigner,
232{
233  pub fn new(pair: P) -> Self {
234    let account = pair.account();
235    Self {
236      pair,
237      nonce: 0,
238      account,
239    }
240  }
241
242  /// Generate signing key pair from string `s`.
243  pub fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
244    Ok(Self::new(P::from_string(s, password_override)?))
245  }
246}
247
248#[async_trait]
249impl Signer for Box<dyn Signer> {
250  fn account(&self) -> AccountId {
251    self.as_ref().account()
252  }
253
254  async fn nonce(&self) -> Option<u32> {
255    self.as_ref().nonce().await
256  }
257
258  async fn set_nonce(&mut self, nonce: u32) {
259    self.as_mut().set_nonce(nonce).await
260  }
261
262  async fn sign(&self, msg: &[u8]) -> Result<MultiSignature> {
263    self.as_ref().sign(msg).await
264  }
265
266  async fn lock(&self) -> Option<Box<dyn Signer>> {
267    self.as_ref().lock().await
268  }
269}
270
271#[async_trait]
272impl<P: KeypairSigner> Signer for PairSigner<P> {
273  fn account(&self) -> AccountId {
274    self.account.clone()
275  }
276
277  async fn nonce(&self) -> Option<u32> {
278    if self.nonce > 0 {
279      Some(self.nonce)
280    } else {
281      None
282    }
283  }
284
285  async fn set_nonce(&mut self, nonce: u32) {
286    self.nonce = nonce;
287  }
288
289  async fn sign(&self, msg: &[u8]) -> Result<MultiSignature> {
290    Ok(self.pair.sign(msg))
291  }
292}