Skip to main content

polymesh_api_tester/
account.rs

1use std::sync::Arc;
2
3use sp_keyring::{ed25519, sr25519};
4use sp_runtime::MultiSignature;
5
6use polymesh_api::client::{AccountId, KeypairSigner, LockableSigner, PairSigner, Signer};
7
8use crate::error::Result;
9use crate::Db;
10
11/// DbAccountSigner is wrapper for signing keys (sr25519, ed25519, etc...) and using
12/// a local Database for managing account nonces.
13#[derive(Clone)]
14pub struct DbAccountSigner {
15  signer: Arc<dyn Signer + Send + Sync>,
16  db: Db,
17  account: AccountId,
18}
19
20impl DbAccountSigner {
21  pub fn new<P: KeypairSigner + 'static>(db: Db, pair: P) -> Self {
22    let signer = PairSigner::new(pair);
23    let account = signer.account();
24    Self {
25      signer: Arc::new(signer),
26      db: db.clone(),
27      account,
28    }
29  }
30
31  pub fn alice(db: Db) -> Self {
32    Self::new(db, sr25519::Keyring::Alice.pair())
33  }
34
35  pub fn bob(db: Db) -> Self {
36    Self::new(db, sr25519::Keyring::Bob.pair())
37  }
38
39  /// Generate signing key pair from string `s`.
40  pub fn from_string(db: Db, s: &str) -> Result<Self> {
41    Ok(Self::new(
42      db,
43      <sr25519::sr25519::Pair as KeypairSigner>::from_string(s, None)?,
44    ))
45  }
46}
47
48#[cfg(feature = "signer_delay")]
49async fn signer_delay() {
50  // Slow down the signer for the ci-runtime, which has a very short block time (0.5 seconds).
51  use std::time::Duration;
52  tokio::time::sleep(Duration::from_millis(200)).await;
53}
54
55#[async_trait::async_trait]
56impl Signer for DbAccountSigner {
57  fn account(&self) -> AccountId {
58    self.account
59  }
60
61  async fn nonce(&self) -> Option<u32> {
62    self.db.get_next_nonce(self.account).await.ok()
63  }
64
65  async fn sign(&self, msg: &[u8]) -> polymesh_api::client::Result<MultiSignature> {
66    #[cfg(feature = "signer_delay")]
67    signer_delay().await;
68    Ok(self.signer.sign(msg).await?)
69  }
70}
71
72/// AccountSigner is wrapper for signing keys (sr25519, ed25519, etc...).
73#[derive(Clone)]
74pub struct AccountSigner {
75  signer: Arc<LockableSigner<Box<dyn Signer>>>,
76  account: AccountId,
77}
78
79impl AccountSigner {
80  pub fn new<P: KeypairSigner + 'static>(pair: P) -> Self {
81    let signer = PairSigner::new(pair);
82    let account = signer.account();
83    Self {
84      signer: Arc::new(LockableSigner::new(Box::new(signer))),
85      account,
86    }
87  }
88
89  /// Generate signing key pair from string `s`.
90  pub fn from_string(s: &str) -> Result<Self> {
91    Ok(Self::new(
92      <sr25519::sr25519::Pair as KeypairSigner>::from_string(s, None)?,
93    ))
94  }
95}
96
97impl From<sr25519::Keyring> for AccountSigner {
98  fn from(key: sr25519::Keyring) -> Self {
99    Self::new(key.pair())
100  }
101}
102
103impl From<ed25519::Keyring> for AccountSigner {
104  fn from(key: ed25519::Keyring) -> Self {
105    Self::new(key.pair())
106  }
107}
108
109#[async_trait::async_trait]
110impl Signer for AccountSigner {
111  fn account(&self) -> AccountId {
112    self.account.clone()
113  }
114
115  async fn sign(&self, msg: &[u8]) -> polymesh_api::client::Result<MultiSignature> {
116    let locked = self.signer.lock().await;
117
118    #[cfg(feature = "signer_delay")]
119    signer_delay().await;
120
121    locked.sign(msg).await
122  }
123
124  async fn lock(&self) -> Option<Box<dyn Signer>> {
125    let locked = self.signer.lock().await;
126    Some(Box::new(locked))
127  }
128}