Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use async-trait #264

Merged
merged 2 commits into from
Apr 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ tokio02 = ["jsonrpsee-http-client/tokio02"]
tokio1 = ["jsonrpsee-http-client/tokio1"]

[dependencies]
async-trait = "0.1.49"
log = "0.4.14"
thiserror = "1.0.24"
futures = "0.3.13"
Expand Down
1 change: 1 addition & 0 deletions proc-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ description = "Derive calls, events, storage and tests for interacting Substrate
proc-macro = true

[dependencies]
async-trait = "0.1.49"
heck = "0.3.2"
proc-macro2 = "1.0.24"
proc-macro-crate = "0.1.5"
Expand Down
44 changes: 24 additions & 20 deletions proc-macro/src/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,42 +50,44 @@ pub fn call(s: Structure) -> TokenStream {
}

/// Call extension trait.
#[async_trait::async_trait]
pub trait #call_trait<T: #subxt::Runtime + #module> {
/// Create and submit an extrinsic.
fn #call<'a>(
async fn #call<'a>(
&'a self,
signer: &'a (dyn #subxt::Signer<T> + Send + Sync),
#args
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<T::Hash, #subxt::Error>> + Send + 'a>>;
) -> Result<T::Hash, #subxt::Error>;

/// Create, submit and watch an extrinsic.
fn #call_and_watch<'a>(
async fn #call_and_watch<'a>(
&'a self,
signer: &'a (dyn #subxt::Signer<T> + Send + Sync),
#args
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<#subxt::ExtrinsicSuccess<T>, #subxt::Error>> + Send + 'a>>;
) -> Result<#subxt::ExtrinsicSuccess<T>, #subxt::Error>;
}

#[async_trait::async_trait]
impl<T: #subxt::Runtime + #module> #call_trait<T> for #subxt::Client<T>
where
<<T::Extra as #subxt::SignedExtra<T>>::Extra as #subxt::SignedExtension>::AdditionalSigned: Send + Sync,
{
fn #call<'a>(
async fn #call<'a>(
&'a self,
signer: &'a (dyn #subxt::Signer<T> + Send + Sync),
#args
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<T::Hash, #subxt::Error>> + Send + 'a>> {
) -> Result<T::Hash, #subxt::Error> {
let #marker = core::marker::PhantomData::<T>;
Box::pin(self.submit(#build_struct, signer))
self.submit(#build_struct, signer).await
}

fn #call_and_watch<'a>(
async fn #call_and_watch<'a>(
&'a self,
signer: &'a (dyn #subxt::Signer<T> + Send + Sync),
#args
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<#subxt::ExtrinsicSuccess<T>, #subxt::Error>> + Send + 'a>> {
) -> Result<#subxt::ExtrinsicSuccess<T>, #subxt::Error> {
let #marker = core::marker::PhantomData::<T>;
Box::pin(self.watch(#build_struct, signer))
self.watch(#build_struct, signer).await
}
}
}
Expand All @@ -112,46 +114,48 @@ mod tests {
}

/// Call extension trait.
#[async_trait::async_trait]
pub trait TransferCallExt<T: substrate_subxt::Runtime + Balances> {
/// Create and submit an extrinsic.
fn transfer<'a>(
async fn transfer<'a>(
&'a self,
signer: &'a (dyn substrate_subxt::Signer<T> + Send + Sync),
to: &'a <T as System>::Address,
amount: T::Balance,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<T::Hash, substrate_subxt::Error>> + Send + 'a>>;
) -> Result<T::Hash, substrate_subxt::Error>;

/// Create, submit and watch an extrinsic.
fn transfer_and_watch<'a>(
async fn transfer_and_watch<'a>(
&'a self,
signer: &'a (dyn substrate_subxt::Signer<T> + Send + Sync),
to: &'a <T as System>::Address,
amount: T::Balance,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<substrate_subxt::ExtrinsicSuccess<T>, substrate_subxt::Error>> + Send + 'a>>;
) -> Result<substrate_subxt::ExtrinsicSuccess<T>, substrate_subxt::Error>;
}

#[async_trait::async_trait]
impl<T: substrate_subxt::Runtime + Balances> TransferCallExt<T> for substrate_subxt::Client<T>
where
<<T::Extra as substrate_subxt::SignedExtra<T>>::Extra as substrate_subxt::SignedExtension>::AdditionalSigned: Send + Sync,
{
fn transfer<'a>(
async fn transfer<'a>(
&'a self,
signer: &'a (dyn substrate_subxt::Signer<T> + Send + Sync),
to: &'a <T as System>::Address,
amount: T::Balance,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<T::Hash, substrate_subxt::Error>> + Send + 'a>> {
) -> Result<T::Hash, substrate_subxt::Error> {
let _ = core::marker::PhantomData::<T>;
Box::pin(self.submit(TransferCall { to, amount, }, signer))
self.submit(TransferCall { to, amount, }, signer).await
}

fn transfer_and_watch<'a>(
async fn transfer_and_watch<'a>(
&'a self,
signer: &'a (dyn substrate_subxt::Signer<T> + Send + Sync),
to: &'a <T as System>::Address,
amount: T::Balance,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<substrate_subxt::ExtrinsicSuccess<T>, substrate_subxt::Error>> + Send + 'a>> {
) -> Result<substrate_subxt::ExtrinsicSuccess<T>, substrate_subxt::Error> {
let _ = core::marker::PhantomData::<T>;
Box::pin(self.watch(TransferCall { to, amount, }, signer))
self.watch(TransferCall { to, amount, }, signer).await
}
}
};
Expand Down
44 changes: 24 additions & 20 deletions proc-macro/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,36 +141,38 @@ pub fn store(s: Structure) -> TokenStream {
}

/// Store extension trait.
#[async_trait::async_trait]
pub trait #store_trait<T: #subxt::Runtime + #module> {
/// Retrieve the store element.
fn #store<'a>(
async fn #store<'a>(
&'a self,
#args
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<#ret, #subxt::Error>> + Send + 'a>>;
) -> Result<#ret, #subxt::Error>;

/// Iterate over the store element.
fn #store_iter<'a>(
async fn #store_iter<'a>(
&'a self,
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<#key_iter, #subxt::Error>> + Send + 'a>>;
) -> Result<#key_iter, #subxt::Error>;
}

#[async_trait::async_trait]
impl<T: #subxt::Runtime + #module> #store_trait<T> for #subxt::Client<T> {
fn #store<'a>(
async fn #store<'a>(
&'a self,
#args
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<#ret, #subxt::Error>> + Send + 'a>> {
) -> Result<#ret, #subxt::Error> {
let #marker = core::marker::PhantomData::<T>;
Box::pin(async move { self.#fetch(&#build_struct, hash).await })
self.#fetch(&#build_struct, hash).await
}

fn #store_iter<'a>(
async fn #store_iter<'a>(
&'a self,
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<#key_iter, #subxt::Error>> + Send + 'a>> {
Box::pin(self.iter(hash))
) -> Result<#key_iter, #subxt::Error> {
self.iter(hash).await
}
}
}
Expand Down Expand Up @@ -217,36 +219,38 @@ mod tests {
}

/// Store extension trait.
#[async_trait::async_trait]
pub trait AccountStoreExt<T: substrate_subxt::Runtime + Balances> {
/// Retrieve the store element.
fn account<'a>(
async fn account<'a>(
&'a self,
account_id: &'a <T as System>::AccountId,
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<AccountData<T::Balance>, substrate_subxt::Error>> + Send + 'a>>;
) -> Result<AccountData<T::Balance>, substrate_subxt::Error>;
/// Iterate over the store element.
fn account_iter<'a>(
async fn account_iter<'a>(
&'a self,
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<substrate_subxt::KeyIter<T, AccountStore<'a, T>>, substrate_subxt::Error>> + Send + 'a>>;
) -> Result<substrate_subxt::KeyIter<T, AccountStore<'a, T>>, substrate_subxt::Error>;
}

#[async_trait::async_trait]
impl<T: substrate_subxt::Runtime + Balances> AccountStoreExt<T> for substrate_subxt::Client<T> {
fn account<'a>(
async fn account<'a>(
&'a self,
account_id: &'a <T as System>::AccountId,
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<AccountData<T::Balance>, substrate_subxt::Error>> + Send + 'a>>
) -> Result<AccountData<T::Balance>, substrate_subxt::Error>
{
let _ = core::marker::PhantomData::<T>;
Box::pin(async move { self.fetch_or_default(&AccountStore { account_id, }, hash).await })
self.fetch_or_default(&AccountStore { account_id, }, hash).await
}

fn account_iter<'a>(
async fn account_iter<'a>(
&'a self,
hash: Option<T::Hash>,
) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<substrate_subxt::KeyIter<T, AccountStore<'a, T>>, substrate_subxt::Error>> + Send + 'a>> {
Box::pin(self.iter(hash))
) -> Result<substrate_subxt::KeyIter<T, AccountStore<'a, T>>, substrate_subxt::Error> {
self.iter(hash).await
}
}
};
Expand Down
16 changes: 7 additions & 9 deletions src/extrinsic/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,9 @@ use sp_runtime::traits::{
SignedExtension,
Verify,
};
use std::{
future::Future,
pin::Pin,
};

/// Extrinsic signer.
#[async_trait::async_trait]
pub trait Signer<T: Runtime> {
/// Returns the account id.
fn account_id(&self) -> &T::AccountId;
Expand All @@ -47,10 +44,10 @@ pub trait Signer<T: Runtime> {
///
/// Some signers may fail, for instance because the hardware on which the keys are located has
/// refused the operation.
fn sign(
async fn sign(
&self,
extrinsic: SignedPayload<T>,
) -> Pin<Box<dyn Future<Output = Result<UncheckedExtrinsic<T>, String>> + Send>>;
) -> Result<UncheckedExtrinsic<T>, String>;
}

/// Extrinsic signer using a private key.
Expand Down Expand Up @@ -96,6 +93,7 @@ where
}
}

#[async_trait::async_trait]
impl<T, P> Signer<T> for PairSigner<T, P>
where
T: Runtime,
Expand All @@ -112,10 +110,10 @@ where
self.nonce
}

fn sign(
async fn sign(
&self,
extrinsic: SignedPayload<T>,
) -> Pin<Box<dyn Future<Output = Result<UncheckedExtrinsic<T>, String>> + Send>> {
) -> Result<UncheckedExtrinsic<T>, String> {
let signature = extrinsic.using_encoded(|payload| self.signer.sign(payload));
let (call, extra, _) = extrinsic.deconstruct();
let extrinsic = UncheckedExtrinsic::<T>::new_signed(
Expand All @@ -124,6 +122,6 @@ where
signature.into(),
extra,
);
Box::pin(async move { Ok(extrinsic) })
Ok(extrinsic)
}
}