use ink_env::{
DefaultEnvironment,
Environment,
};
use std::{
fmt::Debug,
str::FromStr,
};
use subxt::{
config::{
PolkadotExtrinsicParams,
SubstrateExtrinsicParams,
},
ext::{
sp_core,
sp_core::Pair,
},
tx::{
PairSigner,
Signer as SignerT,
},
Config,
PolkadotConfig,
SubstrateConfig,
};
pub trait SignerConfig<C: Config + Environment> {
type Signer: SignerT<C> + FromStr + Clone;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Ecdsachain {}
impl Config for Ecdsachain {
type Hash = <SubstrateConfig as Config>::Hash;
type AccountId = <SubstrateConfig as Config>::AccountId;
type Address = <SubstrateConfig as Config>::Address;
type Signature = <SubstrateConfig as Config>::Signature;
type Hasher = <SubstrateConfig as Config>::Hasher;
type Header = <SubstrateConfig as Config>::Header;
type ExtrinsicParams = SubstrateExtrinsicParams<Self>;
type AssetId = <SubstrateConfig as Config>::AssetId;
}
impl Environment for Ecdsachain {
const MAX_EVENT_TOPICS: usize = <DefaultEnvironment as Environment>::MAX_EVENT_TOPICS;
type AccountId = <DefaultEnvironment as Environment>::AccountId;
type Balance = <DefaultEnvironment as Environment>::Balance;
type Hash = <DefaultEnvironment as Environment>::Hash;
type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
type BlockNumber = <DefaultEnvironment as Environment>::BlockNumber;
type ChainExtension = <DefaultEnvironment as Environment>::ChainExtension;
}
impl SignerConfig<Self> for Ecdsachain
where
<Self as Config>::Signature: From<sp_core::ecdsa::Signature>,
{
type Signer = SignerEcdsa<Self>;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Substrate {}
impl Config for Substrate {
type Hash = <SubstrateConfig as Config>::Hash;
type AccountId = <SubstrateConfig as Config>::AccountId;
type Address = <SubstrateConfig as Config>::Address;
type Signature = <SubstrateConfig as Config>::Signature;
type Hasher = <SubstrateConfig as Config>::Hasher;
type Header = <SubstrateConfig as Config>::Header;
type ExtrinsicParams = SubstrateExtrinsicParams<Self>;
type AssetId = <SubstrateConfig as Config>::AssetId;
}
impl Environment for Substrate {
const MAX_EVENT_TOPICS: usize = <DefaultEnvironment as Environment>::MAX_EVENT_TOPICS;
type AccountId = <DefaultEnvironment as Environment>::AccountId;
type Balance = <DefaultEnvironment as Environment>::Balance;
type Hash = <DefaultEnvironment as Environment>::Hash;
type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
type BlockNumber = <DefaultEnvironment as Environment>::BlockNumber;
type ChainExtension = <DefaultEnvironment as Environment>::ChainExtension;
}
impl SignerConfig<Self> for Substrate {
type Signer = SignerSR25519<Self>;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Polkadot {}
impl Config for Polkadot {
type Hash = <PolkadotConfig as Config>::Hash;
type AccountId = <PolkadotConfig as Config>::AccountId;
type Address = <PolkadotConfig as Config>::Address;
type Signature = <PolkadotConfig as Config>::Signature;
type Hasher = <PolkadotConfig as Config>::Hasher;
type Header = <PolkadotConfig as Config>::Header;
type ExtrinsicParams = PolkadotExtrinsicParams<Self>;
type AssetId = <PolkadotConfig as Config>::AssetId;
}
impl Environment for Polkadot {
const MAX_EVENT_TOPICS: usize = <DefaultEnvironment as Environment>::MAX_EVENT_TOPICS;
type AccountId = <DefaultEnvironment as Environment>::AccountId;
type Balance = <DefaultEnvironment as Environment>::Balance;
type Hash = <DefaultEnvironment as Environment>::Hash;
type Timestamp = <DefaultEnvironment as Environment>::Timestamp;
type BlockNumber = <DefaultEnvironment as Environment>::BlockNumber;
type ChainExtension = <DefaultEnvironment as Environment>::ChainExtension;
}
impl SignerConfig<Self> for Polkadot {
type Signer = SignerSR25519<Self>;
}
#[derive(Clone)]
pub struct SignerSR25519<C: Config>(pub PairSigner<C, sp_core::sr25519::Pair>);
impl<C: Config> FromStr for SignerSR25519<C>
where
<C as Config>::AccountId: From<sp_core::crypto::AccountId32>,
{
type Err = anyhow::Error;
fn from_str(input: &str) -> Result<SignerSR25519<C>, Self::Err> {
let keypair = sp_core::sr25519::Pair::from_string(input, None)?;
let signer = PairSigner::<C, _>::new(keypair);
Ok(Self(signer))
}
}
impl<C: Config> SignerT<C> for SignerSR25519<C>
where
<C as Config>::Signature: From<sp_core::sr25519::Signature>,
{
fn account_id(&self) -> <C as Config>::AccountId {
self.0.account_id().clone()
}
fn address(&self) -> C::Address {
self.0.address()
}
fn sign(&self, signer_payload: &[u8]) -> C::Signature {
self.0.sign(signer_payload)
}
}
#[derive(Clone)]
pub struct SignerEcdsa<C: Config>(pub PairSigner<C, sp_core::ecdsa::Pair>);
impl<C: Config> FromStr for SignerEcdsa<C>
where
<C as Config>::AccountId: From<sp_core::crypto::AccountId32>,
{
type Err = anyhow::Error;
fn from_str(input: &str) -> Result<SignerEcdsa<C>, Self::Err> {
let keypair = sp_core::ecdsa::Pair::from_string(input, None)?;
let signer = PairSigner::<C, _>::new(keypair);
Ok(Self(signer))
}
}
impl<C: Config> SignerT<C> for SignerEcdsa<C>
where
<C as Config>::Signature: From<sp_core::ecdsa::Signature>,
{
fn account_id(&self) -> <C as Config>::AccountId {
self.0.account_id().clone()
}
fn address(&self) -> C::Address {
self.0.address()
}
fn sign(&self, signer_payload: &[u8]) -> C::Signature {
self.0.sign(signer_payload)
}
}
#[macro_export]
macro_rules! call_with_config_internal {
($obj:tt ,$function:tt, $config_name:expr, $($config:ty),*) => {
match $config_name {
$(
stringify!($config) => $obj.$function::<$config>().await,
)*
_ => {
let configs = vec![$(stringify!($config)),*].iter()
.map(|s| s.trim_start_matches("crate::cmd::config::"))
.collect::<Vec<_>>()
.join(", ");
Err(ErrorVariant::Generic(
contract_extrinsics::GenericError::from_message(
format!("Chain configuration not found, Allowed configurations: {configs}")
)))
},
}
};
}
#[macro_export]
macro_rules! call_with_config {
($obj:tt, $function:ident, $config_name:expr) => {{
let config_name = format!("crate::cmd::config::{}", $config_name);
$crate::call_with_config_internal!(
$obj,
$function,
config_name.as_str(),
$crate::cmd::config::Polkadot,
$crate::cmd::config::Substrate,
$crate::cmd::config::Ecdsachain
)
}};
}