use crate::config::transaction_extension_traits::TransactionExtension;
use crate::config::{ClientState, Config, HashFor};
use crate::error::TransactionExtensionError;
use crate::utils::Era;
use codec::{Compact, Encode};
use core::fmt::Debug;
use derive_where::derive_where;
use scale_decode::DecodeAsType;
use scale_encode::EncodeAsType;
use scale_info::PortableRegistry;
pub use super::transaction_extension_traits::Params;
pub struct VerifySignature<T: Config>(VerifySignatureDetails<T>);
impl<T: Config> TransactionExtension<T> for VerifySignature<T> {
type Decoded = VerifySignatureDetails<T>;
type Params = ();
fn new(
_client: &ClientState<T>,
_params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(VerifySignature(VerifySignatureDetails::Disabled))
}
fn inject_signature(&mut self, account: &T::AccountId, signature: &T::Signature) {
self.0 = VerifySignatureDetails::Signed {
signature: signature.clone(),
account: account.clone(),
}
}
}
impl<T: Config> frame_decode::extrinsics::TransactionExtension<PortableRegistry>
for VerifySignature<T>
{
const NAME: &str = "VerifySignature";
fn encode_value_to(
&self,
type_id: u32,
type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
self.0.encode_as_type_to(type_id, type_resolver, v)?;
Ok(())
}
fn encode_value_for_signer_payload_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
v.clear();
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
v.clear();
Ok(())
}
}
#[derive(EncodeAsType, DecodeAsType)]
#[decode_as_type(trait_bounds = "")]
#[encode_as_type(trait_bounds = "")]
pub enum VerifySignatureDetails<T: Config> {
Signed {
signature: T::Signature,
account: T::AccountId,
},
Disabled,
}
pub struct CheckMetadataHash {
}
impl<T: Config> TransactionExtension<T> for CheckMetadataHash {
type Decoded = CheckMetadataHashMode;
type Params = ();
fn new(
_client: &ClientState<T>,
_params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(CheckMetadataHash {})
}
}
impl frame_decode::extrinsics::TransactionExtension<PortableRegistry> for CheckMetadataHash {
const NAME: &str = "CheckMetadataHash";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
0u8.encode_to(v);
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
None::<()>.encode_to(v);
Ok(())
}
}
#[derive(Copy, Clone, Debug, DecodeAsType)]
pub enum CheckMetadataHashMode {
Disabled,
Enabled,
}
impl CheckMetadataHashMode {
pub fn is_enabled(&self) -> bool {
match self {
CheckMetadataHashMode::Disabled => false,
CheckMetadataHashMode::Enabled => true,
}
}
}
pub struct CheckSpecVersion(u32);
impl<T: Config> TransactionExtension<T> for CheckSpecVersion {
type Decoded = ();
type Params = ();
fn new(
client: &ClientState<T>,
_params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(CheckSpecVersion(client.spec_version))
}
}
impl frame_decode::extrinsics::TransactionExtension<PortableRegistry> for CheckSpecVersion {
const NAME: &str = "CheckSpecVersion";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
_v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
self.0.encode_to(v);
Ok(())
}
}
pub struct CheckNonce(u64);
impl<T: Config> TransactionExtension<T> for CheckNonce {
type Decoded = u64;
type Params = CheckNonceParams;
fn new(
_client: &ClientState<T>,
params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(CheckNonce(params.0.unwrap_or(0)))
}
}
impl frame_decode::extrinsics::TransactionExtension<PortableRegistry> for CheckNonce {
const NAME: &str = "CheckNonce";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
Compact(self.0).encode_to(v);
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
_v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
Ok(())
}
}
#[derive(Debug, Clone, Default)]
pub struct CheckNonceParams(Option<u64>);
impl CheckNonceParams {
pub fn from_chain() -> Self {
Self(None)
}
pub fn with_nonce(nonce: u64) -> Self {
Self(Some(nonce))
}
}
impl<T: Config> Params<T> for CheckNonceParams {
fn inject_account_nonce(&mut self, nonce: u64) {
if self.0.is_none() {
self.0 = Some(nonce)
}
}
}
pub struct CheckTxVersion(u32);
impl<T: Config> TransactionExtension<T> for CheckTxVersion {
type Decoded = ();
type Params = ();
fn new(
client: &ClientState<T>,
_params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(CheckTxVersion(client.transaction_version))
}
}
impl frame_decode::extrinsics::TransactionExtension<PortableRegistry> for CheckTxVersion {
const NAME: &str = "CheckTxVersion";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
_v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
self.0.encode_to(v);
Ok(())
}
}
pub struct CheckGenesis<T: Config>(HashFor<T>);
impl<T: Config> TransactionExtension<T> for CheckGenesis<T> {
type Decoded = ();
type Params = ();
fn new(
client: &ClientState<T>,
_params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(CheckGenesis(client.genesis_hash))
}
}
impl<T: Config> frame_decode::extrinsics::TransactionExtension<PortableRegistry>
for CheckGenesis<T>
{
const NAME: &str = "CheckGenesis";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
_v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
self.0.encode_to(v);
Ok(())
}
}
pub struct CheckMortality<T: Config> {
params: CheckMortalityParamsInner<T>,
genesis_hash: HashFor<T>,
}
impl<T: Config> TransactionExtension<T> for CheckMortality<T> {
type Decoded = Era;
type Params = CheckMortalityParams<T>;
fn new(
client: &ClientState<T>,
params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
if matches!(¶ms.0, CheckMortalityParamsInner::MortalForBlocks(_)) {
return Err(TransactionExtensionError::custom(
"CheckMortality: We cannot construct an offline extrinsic with only the number of blocks it is mortal for. Use mortal_from_unchecked instead.",
));
}
Ok(CheckMortality {
params: params.0,
genesis_hash: client.genesis_hash,
})
}
}
impl<T: Config> frame_decode::extrinsics::TransactionExtension<PortableRegistry>
for CheckMortality<T>
{
const NAME: &str = "CheckMortality";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
match &self.params {
CheckMortalityParamsInner::MortalFromBlock {
for_n_blocks,
from_block_n,
..
} => {
Era::mortal(*for_n_blocks, *from_block_n).encode_to(v);
}
_ => {
Era::Immortal.encode_to(v);
}
}
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
match &self.params {
CheckMortalityParamsInner::MortalFromBlock {
from_block_hash, ..
} => {
from_block_hash.encode_to(v);
}
_ => {
self.genesis_hash.encode_to(v);
}
}
Ok(())
}
}
pub struct CheckMortalityParams<T: Config>(CheckMortalityParamsInner<T>);
enum CheckMortalityParamsInner<T: Config> {
Immortal,
MortalForBlocks(u64),
MortalForBlocksOrImmortalIfNotPossible(u64),
MortalFromBlock {
for_n_blocks: u64,
from_block_n: u64,
from_block_hash: HashFor<T>,
},
}
impl<T: Config> Default for CheckMortalityParams<T> {
fn default() -> Self {
CheckMortalityParams(CheckMortalityParamsInner::MortalForBlocksOrImmortalIfNotPossible(32))
}
}
impl<T: Config> CheckMortalityParams<T> {
pub fn mortal(for_n_blocks: u64) -> Self {
Self(CheckMortalityParamsInner::MortalForBlocks(for_n_blocks))
}
pub fn mortal_from_unchecked(
for_n_blocks: u64,
from_block_n: u64,
from_block_hash: HashFor<T>,
) -> Self {
Self(CheckMortalityParamsInner::MortalFromBlock {
for_n_blocks,
from_block_n,
from_block_hash,
})
}
pub fn immortal() -> Self {
Self(CheckMortalityParamsInner::Immortal)
}
}
impl<T: Config> Params<T> for CheckMortalityParams<T> {
fn inject_block(&mut self, from_block_n: u64, from_block_hash: HashFor<T>) {
match &self.0 {
CheckMortalityParamsInner::MortalForBlocks(n)
| CheckMortalityParamsInner::MortalForBlocksOrImmortalIfNotPossible(n) => {
self.0 = CheckMortalityParamsInner::MortalFromBlock {
for_n_blocks: *n,
from_block_n,
from_block_hash,
}
}
_ => {
}
}
}
}
#[derive(DecodeAsType)]
#[derive_where(Clone, Debug; T::AssetId)]
#[decode_as_type(trait_bounds = "T::AssetId: DecodeAsType")]
pub struct ChargeAssetTxPayment<T: Config> {
tip: Compact<u128>,
asset_id: Option<T::AssetId>,
}
impl<T: Config> ChargeAssetTxPayment<T> {
pub fn tip(&self) -> u128 {
self.tip.0
}
pub fn asset_id(&self) -> Option<&T::AssetId> {
self.asset_id.as_ref()
}
}
impl<T: Config> TransactionExtension<T> for ChargeAssetTxPayment<T> {
type Decoded = Self;
type Params = ChargeAssetTxPaymentParams<T>;
fn new(
_client: &ClientState<T>,
params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(ChargeAssetTxPayment {
tip: Compact(params.tip),
asset_id: params.asset_id,
})
}
}
impl<T: Config> frame_decode::extrinsics::TransactionExtension<PortableRegistry>
for ChargeAssetTxPayment<T>
{
const NAME: &str = "ChargeAssetTxPayment";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
(self.tip, &self.asset_id).encode_to(v);
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
_v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
Ok(())
}
}
#[cfg_attr(test, derive_where(PartialEq; T::AssetId))]
#[derive_where(Debug)]
pub struct ChargeAssetTxPaymentParams<T: Config> {
tip: u128,
asset_id: Option<T::AssetId>,
}
impl<T: Config> Default for ChargeAssetTxPaymentParams<T> {
fn default() -> Self {
ChargeAssetTxPaymentParams {
tip: Default::default(),
asset_id: Default::default(),
}
}
}
impl<T: Config> ChargeAssetTxPaymentParams<T> {
pub fn no_tip() -> Self {
ChargeAssetTxPaymentParams {
tip: 0,
asset_id: None,
}
}
pub fn tip(tip: u128) -> Self {
ChargeAssetTxPaymentParams {
tip,
asset_id: None,
}
}
pub fn tip_of(tip: u128, asset_id: T::AssetId) -> Self {
ChargeAssetTxPaymentParams {
tip,
asset_id: Some(asset_id),
}
}
}
impl<T: Config> Params<T> for ChargeAssetTxPaymentParams<T> {}
#[derive(Clone, Debug, DecodeAsType)]
pub struct ChargeTransactionPayment {
tip: Compact<u128>,
}
impl ChargeTransactionPayment {
pub fn tip(&self) -> u128 {
self.tip.0
}
}
impl<T: Config> TransactionExtension<T> for ChargeTransactionPayment {
type Decoded = Self;
type Params = ChargeTransactionPaymentParams;
fn new(
_client: &ClientState<T>,
params: Self::Params,
) -> Result<Self, TransactionExtensionError> {
Ok(ChargeTransactionPayment {
tip: Compact(params.tip),
})
}
}
impl frame_decode::extrinsics::TransactionExtension<PortableRegistry> for ChargeTransactionPayment {
const NAME: &str = "ChargeTransactionPayment";
fn encode_value_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
self.tip.encode_to(v);
Ok(())
}
fn encode_implicit_to(
&self,
_type_id: u32,
_type_resolver: &PortableRegistry,
_v: &mut Vec<u8>,
) -> Result<(), frame_decode::extrinsics::TransactionExtensionError> {
Ok(())
}
}
#[cfg_attr(test, derive(PartialEq))]
#[derive(Default, Debug)]
pub struct ChargeTransactionPaymentParams {
tip: u128,
}
impl ChargeTransactionPaymentParams {
pub fn no_tip() -> Self {
ChargeTransactionPaymentParams { tip: 0 }
}
pub fn tip(tip: u128) -> Self {
ChargeTransactionPaymentParams { tip }
}
}
impl<T: Config> Params<T> for ChargeTransactionPaymentParams {}