Skip to content
This repository was archived by the owner on Jul 7, 2021. It is now read-only.

Allow Paying of Transactions via Assets #51

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 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
609 changes: 460 additions & 149 deletions Cargo.lock

Large diffs are not rendered by default.

210 changes: 209 additions & 1 deletion Cargo.toml

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions pallets/asset-tx-payment/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[package]
name = "pallet-asset-tx-payment"
version = "3.0.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
description = "FRAME pallet to manage transaction payments"
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
serde = { version = "1.0.101", optional = true }
sp-std = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate", branch = "rococo-v1" }
sp-runtime = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate", branch = "rococo-v1" }
frame-support = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate", branch = "rococo-v1"}
frame-system = { version = "3.0.0", default-features = false, git = "https://github.com/paritytech/substrate", branch = "rococo-v1"}
smallvec = "1.4.1"
sp-io = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1", default-features = false }
sp-core = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1", default-features = false }
pallet-authorship = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1", default-features = false }
pallet-assets = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1", default-features = false }
pallet-balances = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1", default-features = false }
pallet-transaction-payment = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1", default-features = false }

[dev-dependencies]
serde_json = "1.0.41"
pallet-balances = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1"}
sp-storage = { version = "3.0.0", git = "https://github.com/paritytech/substrate", branch = "rococo-v1" }

[features]
default = ["std"]
std = [
"serde",
"codec/std",
"sp-std/std",
"sp-runtime/std",
"frame-support/std",
"frame-system/std",
"sp-io/std",
"sp-core/std",
"pallet-transaction-payment/std",
]
try-runtime = ["frame-support/try-runtime"]
16 changes: 16 additions & 0 deletions pallets/asset-tx-payment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Transaction Payment Module

This module provides the basic logic needed to pay the absolute minimum amount needed for a
transaction to be included. This includes:
- _weight fee_: A fee proportional to amount of weight a transaction consumes.
- _length fee_: A fee proportional to the encoded length of the transaction.
- _tip_: An optional tip. Tip increases the priority of the transaction, giving it a higher
chance to be included by the transaction queue.

Additionally, this module allows one to configure:
- The mapping between one unit of weight to one unit of fee via [`Config::WeightToFee`].
- A means of updating the fee for the next block, via defining a multiplier, based on the
final state of the chain at the end of the previous block. This can be configured via
[`Config::FeeMultiplierUpdate`]

License: Apache-2.0
25 changes: 25 additions & 0 deletions pallets/asset-tx-payment/rpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "pallet-transaction-payment-rpc"
version = "3.0.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
description = "RPC interface for the transaction payment module."
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
codec = { package = "parity-scale-codec", version = "2.0.0" }
jsonrpc-core = "15.1.0"
jsonrpc-core-client = "15.1.0"
jsonrpc-derive = "15.1.0"
sp-core = { version = "3.0.0", path = "../../../primitives/core" }
sp-rpc = { version = "3.0.0", path = "../../../primitives/rpc" }
sp-runtime = { version = "3.0.0", path = "../../../primitives/runtime" }
sp-api = { version = "3.0.0", path = "../../../primitives/api" }
sp-blockchain = { version = "3.0.0", path = "../../../primitives/blockchain" }
pallet-transaction-payment-rpc-runtime-api = { version = "3.0.0", path = "./runtime-api" }
3 changes: 3 additions & 0 deletions pallets/asset-tx-payment/rpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
RPC interface for the transaction payment module.

License: Apache-2.0
28 changes: 28 additions & 0 deletions pallets/asset-tx-payment/rpc/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "pallet-transaction-payment-rpc-runtime-api"
version = "3.0.0"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
description = "RPC runtime API for transaction payment FRAME pallet"
readme = "README.md"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
sp-api = { version = "3.0.0", default-features = false, path = "../../../../primitives/api" }
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
sp-runtime = { version = "3.0.0", default-features = false, path = "../../../../primitives/runtime" }
pallet-transaction-payment = { version = "3.0.0", default-features = false, path = "../../../transaction-payment" }

[features]
default = ["std"]
std = [
"sp-api/std",
"codec/std",
"sp-runtime/std",
"pallet-transaction-payment/std",
]
3 changes: 3 additions & 0 deletions pallets/asset-tx-payment/rpc/runtime-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Runtime API definition for transaction payment module.

License: Apache-2.0
34 changes: 34 additions & 0 deletions pallets/asset-tx-payment/rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// This file is part of Substrate.

// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Runtime API definition for transaction payment module.

#![cfg_attr(not(feature = "std"), no_std)]

use codec::Codec;
use sp_runtime::traits::MaybeDisplay;

pub use pallet_transaction_payment::{FeeDetails, InclusionFee, RuntimeDispatchInfo};

sp_api::decl_runtime_apis! {
pub trait TransactionPaymentApi<Balance> where
Balance: Codec + MaybeDisplay,
{
fn query_info(uxt: Block::Extrinsic, len: u32) -> RuntimeDispatchInfo<Balance>;
fn query_fee_details(uxt: Block::Extrinsic, len: u32) -> FeeDetails<Balance>;
}
}
158 changes: 158 additions & 0 deletions pallets/asset-tx-payment/rpc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// This file is part of Substrate.

// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! RPC interface for the transaction payment module.

use std::sync::Arc;
use std::convert::TryInto;
use codec::{Codec, Decode};
use sp_blockchain::HeaderBackend;
use jsonrpc_core::{Error as RpcError, ErrorCode, Result};
use jsonrpc_derive::rpc;
use sp_runtime::{generic::BlockId, traits::{Block as BlockT, MaybeDisplay}};
use sp_api::ProvideRuntimeApi;
use sp_core::Bytes;
use sp_rpc::number::NumberOrHex;
use pallet_transaction_payment_rpc_runtime_api::{FeeDetails, InclusionFee, RuntimeDispatchInfo};
pub use pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi as TransactionPaymentRuntimeApi;
pub use self::gen_client::Client as TransactionPaymentClient;

#[rpc]
pub trait TransactionPaymentApi<BlockHash, ResponseType> {
#[rpc(name = "payment_queryInfo")]
fn query_info(
&self,
encoded_xt: Bytes,
at: Option<BlockHash>
) -> Result<ResponseType>;
#[rpc(name = "payment_queryFeeDetails")]
fn query_fee_details(
&self,
encoded_xt: Bytes,
at: Option<BlockHash>
) -> Result<FeeDetails<NumberOrHex>>;
}

/// A struct that implements the [`TransactionPaymentApi`].
pub struct TransactionPayment<C, P> {
client: Arc<C>,
_marker: std::marker::PhantomData<P>,
}

impl<C, P> TransactionPayment<C, P> {
/// Create new `TransactionPayment` with the given reference to the client.
pub fn new(client: Arc<C>) -> Self {
Self { client, _marker: Default::default() }
}
}

/// Error type of this RPC api.
pub enum Error {
/// The transaction was not decodable.
DecodeError,
/// The call to runtime failed.
RuntimeError,
}

impl From<Error> for i64 {
fn from(e: Error) -> i64 {
match e {
Error::RuntimeError => 1,
Error::DecodeError => 2,
}
}
}

impl<C, Block, Balance> TransactionPaymentApi<
<Block as BlockT>::Hash,
RuntimeDispatchInfo<Balance>,
> for TransactionPayment<C, Block>
where
Block: BlockT,
C: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
C::Api: TransactionPaymentRuntimeApi<Block, Balance>,
Balance: Codec + MaybeDisplay + Copy + TryInto<NumberOrHex>,
{
fn query_info(
&self,
encoded_xt: Bytes,
at: Option<<Block as BlockT>::Hash>
) -> Result<RuntimeDispatchInfo<Balance>> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(||
// If the block hash is not supplied assume the best block.
self.client.info().best_hash
));

let encoded_len = encoded_xt.len() as u32;

let uxt: Block::Extrinsic = Decode::decode(&mut &*encoded_xt).map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::DecodeError.into()),
message: "Unable to query dispatch info.".into(),
data: Some(format!("{:?}", e).into()),
})?;
api.query_info(&at, uxt, encoded_len).map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::RuntimeError.into()),
message: "Unable to query dispatch info.".into(),
data: Some(format!("{:?}", e).into()),
})
}

fn query_fee_details(
&self,
encoded_xt: Bytes,
at: Option<<Block as BlockT>::Hash>,
) -> Result<FeeDetails<NumberOrHex>> {
let api = self.client.runtime_api();
let at = BlockId::hash(at.unwrap_or_else(||
// If the block hash is not supplied assume the best block.
self.client.info().best_hash
));

let encoded_len = encoded_xt.len() as u32;

let uxt: Block::Extrinsic = Decode::decode(&mut &*encoded_xt).map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::DecodeError.into()),
message: "Unable to query fee details.".into(),
data: Some(format!("{:?}", e).into()),
})?;
let fee_details = api.query_fee_details(&at, uxt, encoded_len).map_err(|e| RpcError {
code: ErrorCode::ServerError(Error::RuntimeError.into()),
message: "Unable to query fee details.".into(),
data: Some(format!("{:?}", e).into()),
})?;

let try_into_rpc_balance = |value: Balance| value.try_into().map_err(|_| RpcError {
code: ErrorCode::InvalidParams,
message: format!("{} doesn't fit in NumberOrHex representation", value),
data: None,
});

Ok(FeeDetails {
inclusion_fee: if let Some(inclusion_fee) = fee_details.inclusion_fee {
Some(InclusionFee {
base_fee: try_into_rpc_balance(inclusion_fee.base_fee)?,
len_fee: try_into_rpc_balance(inclusion_fee.len_fee)?,
adjusted_weight_fee: try_into_rpc_balance(inclusion_fee.adjusted_weight_fee)?,
})
} else {
None
},
tip: Default::default(),
})
}
}
Loading