diff --git a/Cargo.toml b/Cargo.toml index 9b98fb18e1..254d303767 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"] [dependencies] log = "0.4" thiserror = "1.0" -futures = "0.3" +futures = "0.3.5" jsonrpsee = { version = "0.1", features = ["ws"] } num-traits = { version = "0.2", default-features = false } serde = { version = "1.0", features = ["derive"] } diff --git a/proc-macro/src/call.rs b/proc-macro/src/call.rs index 234edbd8dd..d1eab81899 100644 --- a/proc-macro/src/call.rs +++ b/proc-macro/src/call.rs @@ -82,6 +82,7 @@ pub fn call(s: Structure) -> TokenStream { T: #module + #subxt::system::System + Send + Sync + 'static, S: #codec::Encode + Send + Sync + 'static, E: #subxt::SignedExtra + #subxt::sp_runtime::traits::SignedExtension + Send + Sync + 'static, + <>::Extra as #subxt::sp_runtime::traits::SignedExtension>::AdditionalSigned: Send + Sync, { fn #call<'a>( &'a self, @@ -154,6 +155,7 @@ mod tests { T: Balances + substrate_subxt::system::System + Send + Sync + 'static, S: codec::Encode + Send + Sync + 'static, E: substrate_subxt::SignedExtra + substrate_subxt::sp_runtime::traits::SignedExtension + Send + Sync + 'static, + <>::Extra as substrate_subxt::sp_runtime::traits::SignedExtension>::AdditionalSigned: Send + Sync, { fn transfer<'a>( &'a self, diff --git a/src/lib.rs b/src/lib.rs index 9d38535627..5c28706056 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,7 +118,7 @@ pub struct ClientBuilder> { client: Option, } -impl ClientBuilder { +impl ClientBuilder { /// Creates a new ClientBuilder. pub fn new() -> Self { Self { @@ -327,18 +327,22 @@ where } /// Creates a signed extrinsic. - pub async fn create_signed>( + pub async fn create_signed + Send + Sync>( &self, call: C, signer: &(dyn Signer + Send + Sync), ) -> Result< UncheckedExtrinsic>::Extra>, Error, - > { + > + where + <>::Extra as SignedExtension>::AdditionalSigned: Send + Sync, + { let unsigned = self .create_unsigned(call, signer.account_id(), signer.nonce()) .await?; - Ok(signer.sign(unsigned)) + let signed = signer.sign(unsigned).await?; + Ok(signed) } /// Returns an events decoder for a call. @@ -379,21 +383,27 @@ where } /// Submits a transaction to the chain. - pub async fn submit>( + pub async fn submit + Send + Sync>( &self, call: C, signer: &(dyn Signer + Send + Sync), - ) -> Result { + ) -> Result + where + <>::Extra as SignedExtension>::AdditionalSigned: Send + Sync, + { let extrinsic = self.create_signed(call, signer).await?; self.submit_extrinsic(extrinsic).await } /// Submits transaction to the chain and watch for events. - pub async fn watch>( + pub async fn watch + Send + Sync>( &self, call: C, signer: &(dyn Signer + Send + Sync), - ) -> Result, Error> { + ) -> Result, Error> + where + <>::Extra as SignedExtension>::AdditionalSigned: Send + Sync, + { let extrinsic = self.create_signed(call, signer).await?; let decoder = self.events_decoder::()?; self.submit_and_watch_extrinsic(extrinsic, decoder).await diff --git a/src/signer.rs b/src/signer.rs index b33b3fdd33..ec60b195e4 100644 --- a/src/signer.rs +++ b/src/signer.rs @@ -31,13 +31,21 @@ use sp_runtime::{ }, traits::{ IdentifyAccount, + SignedExtension, Verify, }, }; -use std::marker::PhantomData; +use std::{ + future::Future, + marker::PhantomData, + pin::Pin, +}; /// Extrinsic signer. -pub trait Signer> { +pub trait Signer> +where + <>::Extra as SignedExtension>::AdditionalSigned: Send + Sync, +{ /// Returns the account id. fn account_id(&self) -> &T::AccountId; @@ -45,10 +53,23 @@ pub trait Signer> { fn nonce(&self) -> Option; /// Takes an unsigned extrinsic and returns a signed extrinsic. + /// + /// Some signers may fail, for instance because the hardware on which the keys are located has + /// refused the operation. fn sign( &self, extrinsic: SignedPayload, - ) -> UncheckedExtrinsic; + ) -> Pin< + Box< + dyn Future< + Output = Result< + UncheckedExtrinsic, + String, + >, + > + Send + + Sync, + >, + >; } /// Extrinsic signer using a private key. @@ -91,12 +112,13 @@ where impl Signer for PairSigner where - T: System, - T::AccountId: Into, - S: Encode, - E: SignedExtra, - P: Pair, - P::Signature: Into, + T: System + 'static, + T::AccountId: Into + 'static, + S: Encode + 'static + Send + Sync, + E: SignedExtra + 'static, + P: Pair + 'static, + P::Signature: Into + 'static, + <>::Extra as SignedExtension>::AdditionalSigned: Send + Sync, { fn account_id(&self) -> &T::AccountId { &self.account_id @@ -109,14 +131,24 @@ where fn sign( &self, extrinsic: SignedPayload, - ) -> UncheckedExtrinsic { + ) -> Pin< + Box< + dyn Future< + Output = Result< + UncheckedExtrinsic, + String, + >, + > + Send + + Sync, + >, + > { let signature = extrinsic.using_encoded(|payload| self.signer.sign(payload)); let (call, extra, _) = extrinsic.deconstruct(); - UncheckedExtrinsic::new_signed( + Box::pin(futures::future::ok(UncheckedExtrinsic::new_signed( call, self.account_id.clone().into(), signature.into(), extra, - ) + ))) } }