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
108#[cfg(feature = "std")]
109impl KeypairSigner for sp_core::ed25519::Pair {
110  fn account(&self) -> AccountId {
111    self.public().into()
112  }
113
114  fn sign(&self, message: &[u8]) -> MultiSignature {
115    <sp_core::ed25519::Pair as sp_core::Pair>::sign(self, message).into()
116  }
117
118  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
119    Ok(<sp_core::ed25519::Pair as sp_core::Pair>::from_string(
120      s,
121      password_override,
122    )?)
123  }
124}
125
126#[cfg(feature = "std")]
127impl KeypairSigner for sp_core::sr25519::Pair {
128  fn account(&self) -> AccountId {
129    self.public().into()
130  }
131
132  fn sign(&self, message: &[u8]) -> MultiSignature {
133    <sp_core::sr25519::Pair as sp_core::Pair>::sign(self, message).into()
134  }
135
136  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
137    Ok(<sp_core::sr25519::Pair as sp_core::Pair>::from_string(
138      s,
139      password_override,
140    )?)
141  }
142}
143
144impl KeypairSigner for subxt_signer::sr25519::Keypair {
145  fn account(&self) -> AccountId {
146    AccountId(self.public_key().0)
147  }
148
149  fn sign(&self, message: &[u8]) -> MultiSignature {
150    let sig = subxt_signer::sr25519::Keypair::sign(self, message).0;
151    MultiSignature::Sr25519(sp_core::sr25519::Signature(sig))
152  }
153
154  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
155    use alloc::str::FromStr;
156    let mut uri = subxt_signer::SecretUri::from_str(s)?;
157    if let Some(password_override) = password_override {
158      uri.password = Some(password_override.to_string().into());
159    }
160    Ok(subxt_signer::sr25519::Keypair::from_uri(&uri)?)
161  }
162}
163
164impl KeypairSigner for subxt_signer::ecdsa::Keypair {
165  fn account(&self) -> AccountId {
166    let pub_key = self.public_key();
167    let hash = sp_core::hashing::blake2_256(&pub_key.0[..]);
168    AccountId(hash)
169  }
170
171  fn sign(&self, message: &[u8]) -> MultiSignature {
172    let sig = subxt_signer::ecdsa::Keypair::sign(self, message).0;
173    MultiSignature::Ecdsa(sp_core::ecdsa::Signature(sig))
174  }
175
176  fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
177    use alloc::str::FromStr;
178    let mut uri = subxt_signer::SecretUri::from_str(s)?;
179    if let Some(password_override) = password_override {
180      uri.password = Some(password_override.to_string().into());
181    }
182    Ok(subxt_signer::ecdsa::Keypair::from_uri(&uri)?)
183  }
184}
185
186#[derive(Clone)]
187pub struct PairSigner<P: KeypairSigner + Clone> {
188  pub pair: P,
189  pub nonce: u32,
190  pub account: AccountId,
191}
192
193impl<P> PairSigner<P>
194where
195  P: KeypairSigner,
196{
197  pub fn new(pair: P) -> Self {
198    let account = pair.account();
199    Self {
200      pair,
201      nonce: 0,
202      account,
203    }
204  }
205
206  /// Generate signing key pair from string `s`.
207  pub fn from_string(s: &str, password_override: Option<&str>) -> Result<Self> {
208    Ok(Self::new(P::from_string(s, password_override)?))
209  }
210}
211
212#[async_trait]
213impl Signer for Box<dyn Signer> {
214  fn account(&self) -> AccountId {
215    self.as_ref().account()
216  }
217
218  async fn nonce(&self) -> Option<u32> {
219    self.as_ref().nonce().await
220  }
221
222  async fn set_nonce(&mut self, nonce: u32) {
223    self.as_mut().set_nonce(nonce).await
224  }
225
226  async fn sign(&self, msg: &[u8]) -> Result<MultiSignature> {
227    self.as_ref().sign(msg).await
228  }
229
230  async fn lock(&self) -> Option<Box<dyn Signer>> {
231    self.as_ref().lock().await
232  }
233}
234
235#[async_trait]
236impl<P: KeypairSigner> Signer for PairSigner<P> {
237  fn account(&self) -> AccountId {
238    self.account.clone()
239  }
240
241  async fn nonce(&self) -> Option<u32> {
242    if self.nonce > 0 {
243      Some(self.nonce)
244    } else {
245      None
246    }
247  }
248
249  async fn set_nonce(&mut self, nonce: u32) {
250    self.nonce = nonce;
251  }
252
253  async fn sign(&self, msg: &[u8]) -> Result<MultiSignature> {
254    Ok(self.pair.sign(msg))
255  }
256}