Allow either submit or submit_and_watch on the builder. (#9)

* Refactor: allow submit and submit_and_watch, separate module builders

* Convert Balances, and use generic ModuleCalls

* Convert System, and use generic ModuleCalls

* Extract common calls to set_call

* rustfmt

* Test contract put_code with valid contract

* Patch jsonrpc client dependency for bugfix

* Handle result from call builder inside submit

* Use patched version of jsonrpc

* Lift module calls to Error

* jsonrpc 13.0

* Remove unused static constraints
This commit is contained in:
Andrew Jones
2019-08-20 16:57:06 +01:00
committed by GitHub
parent 151c7f7e0a
commit d46b6a975e
9 changed files with 379 additions and 311 deletions
+61 -90
View File
@@ -1,18 +1,18 @@
//! Implements support for the srml_contracts module.
use crate::{
codec::compact,
error::Error,
codec::{
compact,
Encoded,
},
metadata::MetadataError,
srml::{
balances::Balances,
system::System,
ModuleCalls,
},
Valid,
XtBuilder,
};
use futures::future::{
self,
Future,
};
use parity_scale_codec::Codec;
use runtime_primitives::traits::StaticLookup;
use substrate_primitives::Pair;
@@ -24,18 +24,51 @@ pub type Gas = u64;
pub trait Contracts: System + Balances {}
/// The Contracts extension trait for the XtBuilder.
pub trait ContractsCall {
pub trait ContractsXt {
/// Contracts type.
type Contracts: Contracts;
/// Key Pair Type
type Pair: Pair;
/// Create a call for the srml contracts module
fn contracts<F>(&self, f: F) -> XtBuilder<Self::Contracts, Self::Pair, Valid>
where
F: FnOnce(
ModuleCalls<Self::Contracts, Self::Pair>,
) -> Result<Encoded, MetadataError>;
}
impl<T: Contracts + 'static, P, V> ContractsXt for XtBuilder<T, P, V>
where
P: Pair,
{
type Contracts = T;
type Pair = P;
fn contracts<F>(&self, f: F) -> XtBuilder<T, P, Valid>
where
F: FnOnce(
ModuleCalls<Self::Contracts, Self::Pair>,
) -> Result<Encoded, MetadataError>,
{
self.set_call("Contracts", f)
}
}
impl<T: Contracts + 'static, P> ModuleCalls<T, P>
where
P: Pair,
{
/// Stores the given binary Wasm code into the chain's storage and returns
/// its `codehash`.
/// You can instantiate contracts only with stored code.
fn put_code(
&mut self,
pub fn put_code(
&self,
gas_limit: Gas,
code: Vec<u8>,
) -> Box<dyn Future<Item = <Self::Contracts as System>::Hash, Error = Error> + Send>;
) -> Result<Encoded, MetadataError> {
self.module.call("put_code", (compact(gas_limit), code))
}
/// Creates a new contract from the `codehash` generated by `put_code`,
/// optionally transferring some balance.
@@ -50,13 +83,18 @@ pub trait ContractsCall {
/// of the account. That code will be invoked upon any call received by
/// this account.
/// - The contract is initialized.
fn create(
&mut self,
endowment: <Self::Contracts as Balances>::Balance,
pub fn create(
&self,
endowment: <T as Balances>::Balance,
gas_limit: Gas,
code_hash: <Self::Contracts as System>::Hash,
code_hash: <T as System>::Hash,
data: Vec<u8>,
) -> Box<dyn Future<Item = <Self::Contracts as System>::Hash, Error = Error> + Send>;
) -> Result<Encoded, MetadataError> {
self.module.call(
"create",
(compact(endowment), compact(gas_limit), code_hash, data),
)
}
/// Makes a call to an account, optionally transferring some balance.
///
@@ -66,81 +104,14 @@ pub trait ContractsCall {
/// * If no account exists and the call value is not less than
/// `existential_deposit`, a regular account will be created and any value
/// will be transferred.
fn call(
&mut self,
dest: <<Self::Contracts as System>::Lookup as StaticLookup>::Source,
value: <Self::Contracts as Balances>::Balance,
pub fn call(
&self,
dest: <<T as System>::Lookup as StaticLookup>::Source,
value: <T as Balances>::Balance,
gas_limit: Gas,
data: Vec<u8>,
) -> Box<dyn Future<Item = <Self::Contracts as System>::Hash, Error = Error> + Send>;
}
impl<T: Contracts + 'static, P> ContractsCall for XtBuilder<T, P>
where
P: Pair,
P::Public: Into<<<T as System>::Lookup as StaticLookup>::Source>,
P::Signature: Codec,
{
type Contracts = T;
fn put_code(
&mut self,
gas_limit: Gas,
code: Vec<u8>,
) -> Box<dyn Future<Item = <Self::Contracts as System>::Hash, Error = Error> + Send>
{
let put_code_call = || {
Ok(self
.metadata()
.module("Contracts")?
.call("put_code", (compact(gas_limit), code))?)
};
let call = match put_code_call() {
Ok(call) => call,
Err(err) => return Box::new(future::err(err)),
};
Box::new(self.submit(call))
}
fn create(
&mut self,
endowment: <Self::Contracts as Balances>::Balance,
gas_limit: Gas,
code_hash: <Self::Contracts as System>::Hash,
data: Vec<u8>,
) -> Box<dyn Future<Item = <Self::Contracts as System>::Hash, Error = Error> + Send>
{
let create_call = || {
Ok(self.metadata().module("Contracts")?.call(
"create",
(compact(endowment), compact(gas_limit), code_hash, data),
)?)
};
let call = match create_call() {
Ok(call) => call,
Err(err) => return Box::new(future::err(err)),
};
Box::new(self.submit(call))
}
fn call(
&mut self,
dest: <<Self::Contracts as System>::Lookup as StaticLookup>::Source,
value: <Self::Contracts as Balances>::Balance,
gas_limit: Gas,
data: Vec<u8>,
) -> Box<dyn Future<Item = <Self::Contracts as System>::Hash, Error = Error> + Send>
{
let call_call = || {
Ok(self
.metadata()
.module("Contracts")?
.call("call", (dest, compact(value), compact(gas_limit), data))?)
};
let call = match call_call() {
Ok(call) => call,
Err(err) => return Box::new(future::err(err)),
};
Box::new(self.submit(call))
) -> Result<Encoded, MetadataError> {
self.module
.call("call", (dest, compact(value), compact(gas_limit), data))
}
}