1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use async_trait::async_trait; pub use keybase_keystore::{bip39, NotEnoughEntropyError}; pub use secrecy::{ExposeSecret, SecretString}; use sp_core::crypto::{Pair, PublicError, SecretStringError, Ss58Codec}; use sp_runtime::traits::{IdentifyAccount, Verify}; use std::str::FromStr; pub use substrate_subxt::Signer as ChainSigner; use substrate_subxt::{ sp_core, sp_runtime, system::System, PairSigner, Runtime, SignedExtension, SignedExtra, }; use thiserror::Error; #[async_trait] pub trait ChainClient<T: Runtime>: Send + Sync { type Keystore: Keystore<T>; type OffchainClient: Send + Sync; type Error: std::error::Error + std::fmt::Debug + Send + 'static + From<<Self::Keystore as Keystore<T>>::Error> + From<substrate_subxt::Error> + From<codec::Error> + From<libipld::error::Error>; fn keystore(&self) -> &Self::Keystore; fn keystore_mut(&mut self) -> &mut Self::Keystore; fn chain_client(&self) -> &substrate_subxt::Client<T>; fn chain_signer(&self) -> Result<&(dyn ChainSigner<T> + Send + Sync), Self::Error>; fn offchain_client(&self) -> &Self::OffchainClient; fn offchain_signer(&self) -> Result<&dyn OffchainSigner<T>, Self::Error>; } #[async_trait] pub trait Keystore<T: Runtime>: Send + Sync { type Key: Key<T>; type Error: std::error::Error; fn chain_signer(&self) -> Option<&(dyn ChainSigner<T> + Send + Sync)>; fn offchain_signer(&self) -> Option<&dyn OffchainSigner<T>>; async fn set_device_key( &mut self, key: &Self::Key, password: &SecretString, force: bool, ) -> Result<(), Self::Error>; async fn lock(&mut self) -> Result<(), Self::Error>; async fn unlock(&mut self, password: &SecretString) -> Result<(), Self::Error>; async fn gen(&self) -> u16; async fn change_password_mask(&self, password: &SecretString) -> Result<[u8; 32], Self::Error>; async fn apply_mask(&self, mask: &[u8; 32], gen: u16) -> Result<(), Self::Error>; } #[async_trait] pub trait Key<T: Runtime>: Sized + Send + Sync { async fn generate() -> Self; fn from_mnemonic(mnemonic: &bip39::Mnemonic) -> Result<Self, NotEnoughEntropyError>; fn from_suri(suri: &str) -> Result<Self, InvalidSuri>; fn to_account_id(&self) -> <T as System>::AccountId; } pub trait OffchainSigner<T: Runtime>: Send + Sync { fn sign(&self, payload: &[u8]) -> T::Signature; } impl<T: Runtime, P: Pair> OffchainSigner<T> for PairSigner<T, P> where T::AccountId: Into<T::Address>, T::Signature: From<P::Signature>, <T::Signature as Verify>::Signer: From<P::Public> + IdentifyAccount<AccountId = T::AccountId>, <<T::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned: Send + Sync, { fn sign(&self, payload: &[u8]) -> T::Signature { self.signer().sign(payload).into() } } #[derive(Debug, Error)] #[error("Invalid suri encoded key pair: {0:?}")] pub struct InvalidSuri(pub SecretStringError); #[derive(Clone, Debug, Eq, PartialEq)] pub struct Ss58<T: System>(pub T::AccountId); #[derive(Debug, Error)] #[error("Invalid ss58 encoded public key: {0:?}")] pub struct InvalidSs58(pub PublicError); impl<T: System> FromStr for Ss58<T> where T::AccountId: Ss58Codec, { type Err = InvalidSs58; fn from_str(string: &str) -> Result<Self, Self::Err> { Ok(Self( <T::AccountId as Ss58Codec>::from_string(string).map_err(InvalidSs58)?, )) } }