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

Fix optional store items. #120

Merged
merged 2 commits into from
Jun 1, 2020
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
26 changes: 20 additions & 6 deletions proc-macro/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,16 @@ impl Parse for StoreAttr {

type StoreAttrs = utils::Attrs<StoreAttr>;

fn parse_returns_attr(attr: &syn::Attribute) -> Option<syn::Type> {
fn parse_returns_attr(attr: &syn::Attribute) -> Option<(syn::Type, syn::Type, bool)> {
let attrs: StoreAttrs = syn::parse2(attr.tokens.clone()).unwrap();
attrs.attrs.into_iter().next().map(|attr| {
let StoreAttr::Returns(attr) = attr;
attr.value
let ty = attr.value;
if let Some(inner) = utils::parse_option(&ty) {
(ty, inner, false)
} else {
(ty.clone(), ty, true)
}
})
}

Expand All @@ -72,11 +77,16 @@ pub fn store(s: Structure) -> TokenStream {
let filtered_fields = utils::filter_fields(&fields, &marker);
let args = utils::fields_to_args(&filtered_fields);
let build_struct = utils::build_struct(ident, &fields);
let ret = bindings
let (ret, store_ret, uses_default) = bindings
.iter()
.filter_map(|bi| bi.ast().attrs.iter().filter_map(parse_returns_attr).next())
.next()
.expect("#[store(returns = ..)] needs to be specified.");
let fetch = if uses_default {
quote!(fetch_or_default)
} else {
quote!(fetch)
};
let store_ty = format_ident!(
"{}",
match filtered_fields.len() {
Expand All @@ -94,7 +104,7 @@ pub fn store(s: Structure) -> TokenStream {
impl#generics #subxt::Store<T> for #ident<#(#params),*> {
const MODULE: &'static str = MODULE;
const FIELD: &'static str = #store_name;
type Returns = #ret;
type Returns = #store_ret;
fn key(
&self,
metadata: &#subxt::Metadata,
Expand All @@ -113,6 +123,7 @@ pub fn store(s: Structure) -> TokenStream {
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>>;
}

Expand All @@ -125,9 +136,10 @@ pub fn store(s: Structure) -> TokenStream {
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>> {
let #marker = core::marker::PhantomData::<T>;
Box::pin(self.fetch(#build_struct, None))
Box::pin(self.#fetch(#build_struct, hash))
}
}
}
Expand Down Expand Up @@ -169,6 +181,7 @@ mod tests {
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>>;
}

Expand All @@ -181,10 +194,11 @@ mod tests {
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>>
{
let _ = core::marker::PhantomData::<T>;
Box::pin(self.fetch(AccountStore { account_id, }, None))
Box::pin(self.fetch_or_default(AccountStore { account_id, }, hash))
}
}
};
Expand Down
10 changes: 5 additions & 5 deletions proc-macro/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ impl Step {
};
let build_struct = quote! {
#(
let #state_name = client.fetch(#state, None).await.unwrap();
let #state_name = client.fetch_or_default(#state, None).await.unwrap();
)*
State { #(#state_name),* }
};
Expand Down Expand Up @@ -477,11 +477,11 @@ mod tests {

let pre = {
let alice = client
.fetch(AccountStore { account_id: &alice }, None)
.fetch_or_default(AccountStore { account_id: &alice }, None)
.await
.unwrap();
let bob = client
.fetch(AccountStore { account_id: &bob }, None)
.fetch_or_default(AccountStore { account_id: &bob }, None)
.await
.unwrap();
State { alice, bob }
Expand Down Expand Up @@ -510,11 +510,11 @@ mod tests {

let post = {
let alice = client
.fetch(AccountStore { account_id: &alice }, None)
.fetch_or_default(AccountStore { account_id: &alice }, None)
.await
.unwrap();
let bob = client
.fetch(AccountStore { account_id: &bob }, None)
.fetch_or_default(AccountStore { account_id: &bob }, None)
.await
.unwrap();
State { alice, bob }
Expand Down
28 changes: 28 additions & 0 deletions proc-macro/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,21 @@ pub fn type_params(generics: &syn::Generics) -> Vec<TokenStream> {
.collect()
}

pub fn parse_option(ty: &syn::Type) -> Option<syn::Type> {
if let syn::Type::Path(ty_path) = ty {
if let Some(seg) = ty_path.path.segments.first() {
if seg.ident.to_string() == "Option" {
if let syn::PathArguments::AngleBracketed(args) = &seg.arguments {
if let Some(syn::GenericArgument::Type(ty)) = args.args.first() {
return Some(ty.clone())
}
}
}
}
}
None
}

#[derive(Debug)]
pub struct Attrs<A> {
pub paren: syn::token::Paren,
Expand Down Expand Up @@ -209,3 +224,16 @@ pub(crate) fn assert_proc_macro(
let expected = expected.to_string();
pretty_assertions::assert_eq!(result, expected);
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse_option() {
let option_t: syn::Type = syn::parse2(quote!(Option<T>)).unwrap();
let t: syn::Type = syn::parse2(quote!(T)).unwrap();
assert_eq!(parse_option(&option_t), Some(t.clone()));
assert_eq!(parse_option(&t), None);
}
}
8 changes: 4 additions & 4 deletions proc-macro/tests/balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ async fn transfer_balance_example() -> Result<(), Box<dyn std::error::Error>> {
let alice = AccountKeyring::Alice.to_account_id();
let bob = AccountKeyring::Bob.to_account_id();

let alice_account = client.account(&alice).await?;
let bob_account = client.account(&bob).await?;
let alice_account = client.account(&alice, None).await?;
let bob_account = client.account(&bob, None).await?;
let pre = (alice_account, bob_account);

let _hash = client
Expand All @@ -138,8 +138,8 @@ async fn transfer_balance_example() -> Result<(), Box<dyn std::error::Error>> {
})
);

let alice_account = client.account(&alice).await?;
let bob_account = client.account(&bob).await?;
let alice_account = client.account(&alice, None).await?;
let bob_account = client.account(&bob, None).await?;
let post = (alice_account, bob_account);

assert_eq!(pre.0.free, post.0.free - 10_000);
Expand Down
4 changes: 2 additions & 2 deletions src/frame/balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ mod tests {
async fn test_state_total_issuance() {
env_logger::try_init().ok();
let client = test_client().await;
let total_issuance = client.total_issuance().await.unwrap();
let total_issuance = client.total_issuance(None).await.unwrap();
assert_ne!(total_issuance, 0);
}

Expand All @@ -156,7 +156,7 @@ mod tests {
env_logger::try_init().ok();
let client = test_client().await;
let account = AccountKeyring::Alice.to_account_id();
let info = client.account(&account).await.unwrap();
let info = client.account(&account, None).await.unwrap();
assert_ne!(info.data.free, 0);
}
}
32 changes: 24 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ extern crate substrate_subxt_proc_macro;
pub use sp_core;
pub use sp_runtime;

use codec::Encode;
use codec::{
Decode,
Encode,
};
use futures::future;
use jsonrpsee::client::Subscription;
use sc_rpc_api::state::ReadProof;
Expand Down Expand Up @@ -200,21 +203,34 @@ impl<T: System, S, E> Client<T, S, E> {
&self.metadata
}

/// Fetch a StorageKey.
pub async fn fetch<F: Store<T>>(
/// Fetch a StorageKey with default value.
pub async fn fetch_or_default<F: Store<T>>(
&self,
store: F,
hash: Option<T::Hash>,
) -> Result<F::Returns, Error> {
let key = store.key(&self.metadata)?;
let value = self.rpc.storage::<F::Returns>(key, hash).await?;
if let Some(v) = value {
Ok(v)
if let Some(data) = self.rpc.storage(key, hash).await? {
Ok(Decode::decode(&mut &data.0[..])?)
} else {
Ok(store.default(&self.metadata)?)
}
}

/// Fetch a StorageKey an optional storage key.
pub async fn fetch<F: Store<T>>(
&self,
store: F,
hash: Option<T::Hash>,
) -> Result<Option<F::Returns>, Error> {
let key = store.key(&self.metadata)?;
if let Some(data) = self.rpc.storage(key, hash).await? {
Ok(Some(Decode::decode(&mut &data.0[..])?))
} else {
Ok(None)
}
}

/// Query historical storage entries
pub async fn query_storage(
&self,
Expand Down Expand Up @@ -312,7 +328,7 @@ where
let account_nonce = if let Some(nonce) = nonce {
nonce
} else {
self.account(account_id).await?.nonce
self.account(account_id, None).await?.nonce
};
let spec_version = self.runtime_version.spec_version;
let tx_version = self.runtime_version.transaction_version;
Expand Down Expand Up @@ -453,7 +469,7 @@ mod tests {

let client = test_client().await;
let nonce = client
.account(&AccountKeyring::Alice.to_account_id())
.account(&AccountKeyring::Alice.to_account_id(), None)
.await
.unwrap()
.nonce;
Expand Down
17 changes: 5 additions & 12 deletions src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,22 +132,15 @@ impl<T: System> Rpc<T> {
}

/// Fetch a storage key
pub async fn storage<V: Decode>(
pub async fn storage(
&self,
key: StorageKey,
hash: Option<T::Hash>,
) -> Result<Option<V>, Error> {
) -> Result<Option<StorageData>, Error> {
let params = Params::Array(vec![to_json_value(key)?, to_json_value(hash)?]);
let data: Option<StorageData> =
self.client.request("state_getStorage", params).await?;
match data {
Some(data) => {
log::debug!("state_getStorage {:?}", data.0);
let value = Decode::decode(&mut &data.0[..])?;
Ok(Some(value))
}
None => Ok(None),
}
let data = self.client.request("state_getStorage", params).await?;
log::debug!("state_getStorage {:?}", data);
Ok(data)
}

/// Query historical storage entries
Expand Down
7 changes: 6 additions & 1 deletion src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,15 @@ where
self.nonce = Some(nonce);
}

/// Increment the nonce
/// Increment the nonce.
pub fn increment_nonce(&mut self) {
self.nonce = self.nonce.map(|nonce| nonce + 1.into());
}

/// Returns the signer.
pub fn signer(&self) -> &P {
&self.signer
}
}

impl<T, S, E, P> Signer<T, S, E> for PairSigner<T, S, E, P>
Expand Down