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

Replace custom RPCs by state_call #701

Merged
merged 1 commit into from
Aug 23, 2022
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
71 changes: 25 additions & 46 deletions src/cmd/extrinsics/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
use super::{
display_contract_exec_result,
display_events,
error_details,
load_metadata,
parse_balance,
prompt_confirm_tx,
state_call,
submit_extrinsic,
Balance,
Client,
ContractMessageTranscoder,
ContractsRpcError,
DefaultConfig,
ExtrinsicOpts,
PairSigner,
Expand All @@ -38,30 +39,16 @@ use anyhow::{
anyhow,
Result,
};
use jsonrpsee::{
core::client::ClientT,
rpc_params,
ws_client::WsClientBuilder,
};
use pallet_contracts_primitives::{
ContractResult,
ExecReturnValue,
};
use serde::Serialize;
use sp_core::Bytes;
use std::{
fmt::Debug,
result,
};

use pallet_contracts_primitives::ContractExecResult;
use scale::Encode;

use std::fmt::Debug;
use subxt::{
rpc::NumberOrHex,
Config,
OnlineClient,
};

type ContractExecResult =
ContractResult<result::Result<ExecReturnValue, ContractsRpcError>, Balance>;

#[derive(Debug, clap::Args)]
#[clap(name = "call", about = "Call a contract")]
pub struct CallCommand {
Expand Down Expand Up @@ -124,7 +111,7 @@ impl CallCommand {
display_contract_exec_result::<_, DEFAULT_KEY_COL_WIDTH>(&result)
}
Err(ref err) => {
let err = err.error_details(&client.metadata())?;
let err = error_details(err, &client.metadata())?;
name_value_println!("Result", err, MAX_KEY_COL_WIDTH);
display_contract_exec_result::<_, MAX_KEY_COL_WIDTH>(&result)
}
Expand All @@ -137,28 +124,21 @@ impl CallCommand {

async fn call_dry_run(
&self,
data: Vec<u8>,
input_data: Vec<u8>,
signer: &PairSigner,
) -> Result<ContractExecResult> {
) -> Result<ContractExecResult<Balance>> {
let url = self.extrinsic_opts.url_to_string();
let cli = WsClientBuilder::default().build(&url).await?;
let gas_limit = self.gas_limit.as_ref().unwrap_or(&5_000_000_000_000);
let storage_deposit_limit = self
.extrinsic_opts
.storage_deposit_limit
.as_ref()
.map(|limit| NumberOrHex::Hex((*limit).into()));
let call_request = RpcCallRequest {
let gas_limit = *self.gas_limit.as_ref().unwrap_or(&5_000_000_000_000);
let storage_deposit_limit = self.extrinsic_opts.storage_deposit_limit;
let call_request = CallRequest {
origin: signer.account_id().clone(),
dest: self.contract.clone(),
value: NumberOrHex::Hex(self.value.into()),
gas_limit: NumberOrHex::Number(*gas_limit),
value: self.value,
gas_limit,
storage_deposit_limit,
input_data: Bytes(data),
input_data,
};
let params = rpc_params![call_request];
let result = cli.request("contracts_call", params).await?;
Ok(result)
state_call(&url, "ContractsApi_call", call_request).await
}

async fn call(
Expand Down Expand Up @@ -230,7 +210,7 @@ impl CallCommand {
Ok(gas_limit)
}
Err(ref err) => {
let err = err.error_details(&client.metadata())?;
let err = error_details(err, &client.metadata())?;
name_value_println!("Result", err, MAX_KEY_COL_WIDTH);
display_contract_exec_result::<_, MAX_KEY_COL_WIDTH>(&call_result)?;
Err(anyhow!("Pre-submission dry-run failed. Use --skip-dry-run to skip this step."))
Expand All @@ -241,14 +221,13 @@ impl CallCommand {

/// A struct that encodes RPC parameters required for a call to a smart contract.
///
/// Copied from `pallet-contracts-rpc`.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RpcCallRequest {
/// Copied from `pallet-contracts-rpc-runtime-api`.
#[derive(Encode)]
pub struct CallRequest {
origin: <DefaultConfig as Config>::AccountId,
dest: <DefaultConfig as Config>::AccountId,
value: NumberOrHex,
gas_limit: NumberOrHex,
storage_deposit_limit: Option<NumberOrHex>,
input_data: Bytes,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option<Balance>,
input_data: Vec<u8>,
}
87 changes: 33 additions & 54 deletions src/cmd/extrinsics/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@
use super::{
display_contract_exec_result,
display_events,
error_details,
parse_balance,
prompt_confirm_tx,
runtime_api::api,
state_call,
submit_extrinsic,
Balance,
Client,
CodeHash,
ContractAccount,
ContractMessageTranscoder,
ContractsRpcError,
DefaultConfig,
ExtrinsicOpts,
PairSigner,
Expand All @@ -43,16 +44,10 @@ use anyhow::{
Context,
Result,
};
use jsonrpsee::{
core::client::ClientT,
rpc_params,
ws_client::WsClientBuilder,
};
use pallet_contracts_primitives::{
ContractResult,
InstantiateReturnValue,
};
use serde::Serialize;

use pallet_contracts_primitives::ContractInstantiateResult;

use scale::Encode;
use sp_core::{
crypto::Ss58Codec,
Bytes,
Expand All @@ -63,19 +58,12 @@ use std::{
Path,
PathBuf,
},
result,
};
use subxt::{
rpc::NumberOrHex,
Config,
OnlineClient,
};

type ContractInstantiateResult = ContractResult<
result::Result<InstantiateReturnValue<ContractAccount>, ContractsRpcError>,
Balance,
>;

#[derive(Debug, clap::Args)]
pub struct InstantiateCommand {
/// Path to Wasm contract code, defaults to `./target/ink/<name>.wasm`.
Expand Down Expand Up @@ -145,7 +133,7 @@ impl InstantiateCommand {
tracing::debug!("Contract code path: {}", wasm_path.display());
let code = fs::read(&wasm_path)
.context(format!("Failed to read from {}", wasm_path.display()))?;
Ok(Code::Upload(code.into()))
Ok(Code::Upload(code))
}

let code = match (self.wasm_path.as_ref(), self.code_hash.as_ref()) {
Expand All @@ -162,7 +150,7 @@ impl InstantiateCommand {
}
(None, Some(code_hash)) => Ok(Code::Existing(*code_hash)),
}?;
let salt = self.salt.clone().unwrap_or_else(|| Bytes(Vec::new()));
let salt = self.salt.clone().map(|s| s.0).unwrap_or_default();

let args = InstantiateArgs {
constructor: self.constructor.clone(),
Expand Down Expand Up @@ -199,7 +187,7 @@ struct InstantiateArgs {
gas_limit: Option<u64>,
storage_deposit_limit: Option<Balance>,
data: Vec<u8>,
salt: Bytes,
salt: Vec<u8>,
}

pub struct Exec<'a> {
Expand Down Expand Up @@ -243,7 +231,7 @@ impl<'a> Exec<'a> {
}
Err(ref err) => {
let metadata = self.client.metadata();
let err = err.error_details(&metadata)?;
let err = error_details(err, &metadata)?;
name_value_println!("Result", err, MAX_KEY_COL_WIDTH);
display_contract_exec_result::<_, MAX_KEY_COL_WIDTH>(&result)
}
Expand All @@ -269,7 +257,7 @@ impl<'a> Exec<'a> {

async fn instantiate_with_code(
&self,
code: Bytes,
code: Vec<u8>,
) -> Result<(Option<CodeHash>, ContractAccount)> {
let gas_limit = self
.pre_submit_dry_run_gas_estimate(Code::Upload(code.clone()))
Expand All @@ -285,7 +273,7 @@ impl<'a> Exec<'a> {
self.args.storage_deposit_limit,
code.to_vec(),
self.args.data.clone(),
self.args.salt.0.clone(),
self.args.salt.clone(),
);

let result = submit_extrinsic(&self.client, &call, &self.signer).await?;
Expand Down Expand Up @@ -331,7 +319,7 @@ impl<'a> Exec<'a> {
self.args.storage_deposit_limit,
code_hash,
self.args.data.clone(),
self.args.salt.0.clone(),
self.args.salt.clone(),
);

let result = submit_extrinsic(&self.client, &call, &self.signer).await?;
Expand All @@ -356,30 +344,23 @@ impl<'a> Exec<'a> {
name_value_println!("Gas limit", gas_limit.to_string(), DEFAULT_KEY_COL_WIDTH);
}

async fn instantiate_dry_run(&self, code: Code) -> Result<ContractInstantiateResult> {
let cli = WsClientBuilder::default().build(&self.url).await?;
let gas_limit = self.args.gas_limit.as_ref().unwrap_or(&5_000_000_000_000);
let storage_deposit_limit = self
.args
.storage_deposit_limit
.as_ref()
.map(|limit| NumberOrHex::Hex((*limit).into()));
async fn instantiate_dry_run(
&self,
code: Code,
) -> Result<ContractInstantiateResult<<DefaultConfig as Config>::AccountId, Balance>>
{
let gas_limit = *self.args.gas_limit.as_ref().unwrap_or(&5_000_000_000_000);
let storage_deposit_limit = self.args.storage_deposit_limit;
let call_request = InstantiateRequest {
origin: self.signer.account_id().clone(),
value: NumberOrHex::Hex(self.args.value.into()),
gas_limit: NumberOrHex::Number(*gas_limit),
value: self.args.value,
gas_limit,
storage_deposit_limit,
code,
data: self.args.data.clone().into(),
data: self.args.data.clone(),
salt: self.args.salt.clone(),
};
let params = rpc_params![call_request];
let result: ContractInstantiateResult = cli
.request("contracts_instantiate", params)
.await
.context("contracts_instantiate RPC error")?;

Ok(result)
state_call(&self.url, "ContractsApi_instantiate", &call_request).await
}

/// Dry run the instantiation before tx submission. Returns the gas required estimate.
Expand All @@ -406,7 +387,7 @@ impl<'a> Exec<'a> {
Ok(gas_limit)
}
Err(ref err) => {
let err = err.error_details(&self.client.metadata())?;
let err = error_details(err, &self.client.metadata())?;
name_value_println!("Result", err, MAX_KEY_COL_WIDTH);
display_contract_exec_result::<_, MAX_KEY_COL_WIDTH>(
&instantiate_result,
Expand All @@ -418,24 +399,22 @@ impl<'a> Exec<'a> {
}

/// A struct that encodes RPC parameters required to instantiate a new smart contract.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
#[derive(Encode)]
struct InstantiateRequest {
origin: <DefaultConfig as Config>::AccountId,
value: NumberOrHex,
gas_limit: NumberOrHex,
storage_deposit_limit: Option<NumberOrHex>,
value: Balance,
gas_limit: u64,
storage_deposit_limit: Option<Balance>,
code: Code,
data: Bytes,
salt: Bytes,
data: Vec<u8>,
salt: Vec<u8>,
}

/// Reference to an existing code hash or a new Wasm module.
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
#[derive(Encode)]
enum Code {
/// A Wasm module as raw bytes.
Upload(Bytes),
Upload(Vec<u8>),
/// The code hash of an on-chain Wasm blob.
Existing(<DefaultConfig as Config>::Hash),
}
Expand Down
Loading