Convert to std futures (#58)

* WIP

* Begin converting rpc layer to use std futures and jsonrpsee

* Convert metadata to async/await

* Convert block_hash to async/await

* Convert more methods to async/await

* Remove sp_rpc

* Fix more compilation errors

* Remove connect

* Starting to convert subscription functions

* Use jsonrpsee branch from PR for public client types

* Implement subscribe events with jsonrpsee subscription

* Converting subscriptions and wait_for_block_events

* WIP converting lib methods to async

* Use shared client reference directly for rpc call

`rpc_api!` macro currently only supports RawClient (which cannot be shared).
Also supports named params only which is not currently compatible with substrate rpd which accepts only positional params.

* Use &self instead of &mut self for shared Client

* Convert submit_and_watch to async/await

* Convert more Client fns to async

* Pin some trait futures

* Add serde error

* Fix client creation

* Fix client request compiler errors

* Unify metadata errors

* Add WS handshake error variant

* Fix some more compiler errors

* Fix more compiler errors

* Convert submit_extrinsic to async

* Convert submit and submit_and_watch

* Add Send + Sync constraints

* Clone clients

* Fix EventArg conversion error

* Fix remaining warnings/errors

* Replace deny warnings with specific lints

* Infallable subscription loops

* Use jsonrpsee wss branch

* Fix example

* Start to fix up tests

* Make contracts tests compile

* Make some more tests pass

* Fix up remaining tests

* Fmt

* Use correct event storage key type

* Fix finding events

* Use master jsonrpsee
This commit is contained in:
Andrew Jones
2020-01-20 12:00:08 +00:00
committed by GitHub
parent 691244fef2
commit 253a7d8b0b
10 changed files with 544 additions and 507 deletions
+24 -7
View File
@@ -16,7 +16,10 @@
//! Implements support for the pallet_balances module.
use std::fmt::Debug;
use std::{
fmt::Debug,
pin::Pin,
};
use futures::future::{
self,
@@ -74,17 +77,26 @@ pub trait BalancesStore {
fn free_balance(
&self,
account_id: <Self::Balances as System>::AccountId,
) -> Box<dyn Future<Item = <Self::Balances as Balances>::Balance, Error = Error> + Send>;
) -> Pin<
Box<
dyn Future<Output = Result<<Self::Balances as Balances>::Balance, Error>>
+ Send,
>,
>;
}
impl<T: Balances + 'static, S: 'static> BalancesStore for Client<T, S> {
impl<T: Balances + Sync + Send + 'static, S: 'static> BalancesStore for Client<T, S> {
type Balances = T;
fn free_balance(
&self,
account_id: <Self::Balances as System>::AccountId,
) -> Box<dyn Future<Item = <Self::Balances as Balances>::Balance, Error = Error> + Send>
{
) -> Pin<
Box<
dyn Future<Output = Result<<Self::Balances as Balances>::Balance, Error>>
+ Send,
>,
> {
let free_balance_map = || {
Ok(self
.metadata()
@@ -96,9 +108,14 @@ impl<T: Balances + 'static, S: 'static> BalancesStore for Client<T, S> {
};
let map = match free_balance_map() {
Ok(map) => map,
Err(err) => return Box::new(future::err(err)),
Err(err) => return Box::pin(future::err(err)),
};
Box::new(self.fetch_or(map.key(account_id), None, map.default()))
let client = self.clone();
Box::pin(async move {
client
.fetch_or(map.key(account_id), None, map.default())
.await
})
}
}
+38 -49
View File
@@ -139,11 +139,7 @@ pub fn call<T: Contracts>(
#[cfg(test)]
mod tests {
use codec::{
Codec,
Error as CodecError,
};
use futures::Future;
use codec::Codec;
use sp_core::Pair;
use sp_keyring::AccountKeyring;
use sp_runtime::traits::{
@@ -154,7 +150,7 @@ mod tests {
use super::events;
use crate::{
frame::contracts::MODULE,
tests::test_setup,
tests::test_client,
Balances,
Client,
DefaultNodeRuntime as Runtime,
@@ -164,17 +160,16 @@ mod tests {
type AccountId = <Runtime as System>::AccountId;
fn put_code<T, P, S>(
async fn put_code<T, P, S>(
client: &Client<T, S>,
signer: P,
) -> impl Future<Item = Option<Result<T::Hash, CodecError>>, Error = Error>
) -> Result<T::Hash, Error>
where
T: System + Balances + Send + Sync,
T::Address: From<T::AccountId>,
P: Pair,
P::Signature: Codec,
S: 'static,
S: Verify + Codec + From<P::Signature>,
S: Verify + Codec + From<P::Signature> + 'static,
S::Signer: From<P::Public> + IdentifyAccount<AccountId = T::AccountId>,
{
const CONTRACT: &str = r#"
@@ -185,70 +180,64 @@ mod tests {
"#;
let wasm = wabt::wat2wasm(CONTRACT).expect("invalid wabt");
client.xt(signer, None).and_then(|xt| {
xt.watch()
.submit(super::put_code(500_000, wasm))
.map(|result| result.find_event::<T::Hash>(MODULE, events::CODE_STORED))
})
let xt = client.xt(signer, None).await?;
let result = xt.watch().submit(super::put_code(500_000, wasm)).await?;
let code_hash = result
.find_event::<T::Hash>(MODULE, events::CODE_STORED)
.ok_or(Error::Other("Failed to find CodeStored event".into()))??;
Ok(code_hash)
}
#[test]
#[ignore] // requires locally running substrate node
fn tx_put_code() {
let (mut rt, client) = test_setup();
let signer = AccountKeyring::Alice.pair();
let code_hash = rt.block_on(put_code(&client, signer)).unwrap();
env_logger::try_init().ok();
let code_hash: Result<_, Error> = async_std::task::block_on(async move {
let signer = AccountKeyring::Alice.pair();
let client = test_client().await;
let code_hash = put_code(&client, signer).await?;
Ok(code_hash)
});
assert!(
code_hash.is_some(),
"Contracts CodeStored event should be present"
);
assert!(
code_hash.unwrap().is_ok(),
"CodeStored Hash should decode successfully"
code_hash.is_ok(),
"Contracts CodeStored event should be received and decoded"
);
}
#[test]
#[ignore] // requires locally running substrate node
fn tx_instantiate() {
let (mut rt, client) = test_setup();
env_logger::try_init().ok();
let result: Result<_, Error> = async_std::task::block_on(async move {
let signer = AccountKeyring::Alice.pair();
let client = test_client().await;
let signer = AccountKeyring::Alice.pair();
let code_hash = rt
.block_on(put_code(&client, signer.clone()))
.unwrap()
.unwrap()
.unwrap();
let code_hash = put_code(&client, signer.clone()).await?;
println!("{:?}", code_hash);
println!("{:?}", code_hash);
let instantiate = client.xt(signer, None).and_then(move |xt| {
xt.watch()
let xt = client.xt(signer, None).await?;
let result = xt
.watch()
.submit(super::instantiate::<Runtime>(
100_000_000_000_000,
500_000,
code_hash,
Vec::new(),
))
.map(|result| {
result.find_event::<(AccountId, AccountId)>(
MODULE,
events::INSTANTIATED,
)
})
.await?;
let event = result
.find_event::<(AccountId, AccountId)>(MODULE, events::INSTANTIATED)
.ok_or(Error::Other("Failed to find Instantiated event".into()))??;
Ok(event)
});
let result = rt.block_on(instantiate).unwrap();
assert!(
result.is_some(),
"Contracts Instantiated event should be present"
);
assert!(
result.unwrap().is_ok(),
"Instantiated Event should decode successfully"
result.is_ok(),
"Contracts CodeStored event should be received and decoded"
);
}
}
+21 -10
View File
@@ -16,16 +16,13 @@
//! Implements support for the frame_system module.
use std::fmt::Debug;
use codec::Codec;
use frame_support::Parameter;
use futures::future::{
self,
Future,
};
use serde::de::DeserializeOwned;
use frame_support::Parameter;
use sp_runtime::traits::{
Bounded,
CheckEqual,
@@ -39,6 +36,10 @@ use sp_runtime::traits::{
SimpleArithmetic,
SimpleBitOps,
};
use std::{
fmt::Debug,
pin::Pin,
};
use crate::{
error::Error,
@@ -123,17 +124,22 @@ pub trait SystemStore {
fn account_nonce(
&self,
account_id: <Self::System as System>::AccountId,
) -> Box<dyn Future<Item = <Self::System as System>::Index, Error = Error> + Send>;
) -> Pin<
Box<dyn Future<Output = Result<<Self::System as System>::Index, Error>> + Send>,
>;
}
impl<T: System + Balances + 'static, S: 'static> SystemStore for Client<T, S> {
impl<T: System + Balances + Sync + Send + 'static, S: 'static> SystemStore
for Client<T, S>
{
type System = T;
fn account_nonce(
&self,
account_id: <Self::System as System>::AccountId,
) -> Box<dyn Future<Item = <Self::System as System>::Index, Error = Error> + Send>
{
) -> Pin<
Box<dyn Future<Output = Result<<Self::System as System>::Index, Error>> + Send>,
> {
let account_nonce_map = || {
Ok(self
.metadata
@@ -143,9 +149,14 @@ impl<T: System + Balances + 'static, S: 'static> SystemStore for Client<T, S> {
};
let map = match account_nonce_map() {
Ok(map) => map,
Err(err) => return Box::new(future::err(err)),
Err(err) => return Box::pin(future::err(err)),
};
Box::new(self.fetch_or(map.key(account_id), None, map.default()))
let client = self.clone();
Box::pin(async move {
client
.fetch_or(map.key(account_id), None, map.default())
.await
})
}
}