mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 19:11:04 +00:00
remove substrate compat (#1850)
* remove substrate compat * add hacky example * simplify substrate-compat example * simplify substrate-compat example * cargo fmt * fix build * add more examples * fix nit * fix test build * Update subxt/examples/substrate_compat_signer.rs Co-authored-by: James Wilson <james@jsdw.me> * keep only polkadot signer example * remove more substrate compat related stuff * fix example * link to substrate signer example in book * Update subxt/src/book/usage/transactions.rs * Update subxt/src/book/usage/transactions.rs * address grumbles * fix nits --------- Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
Generated
+2
@@ -3002,6 +3002,8 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "frame-decode"
|
name = "frame-decode"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8a784e501ed2cec99eb00a1e78e42740fcb05f1aea7bbea90bf46f0a9f255bb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"frame-metadata 18.0.0",
|
"frame-metadata 18.0.0",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
|
|||||||
+2
-5
@@ -28,7 +28,6 @@ std = [
|
|||||||
"impl-serde/std",
|
"impl-serde/std",
|
||||||
"primitive-types/std",
|
"primitive-types/std",
|
||||||
]
|
]
|
||||||
substrate-compat = ["polkadot-sdk/sp-core", "polkadot-sdk/sp-runtime", "polkadot-sdk/std"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codec = { package = "parity-scale-codec", workspace = true, default-features = false, features = ["derive"] }
|
codec = { package = "parity-scale-codec", workspace = true, default-features = false, features = ["derive"] }
|
||||||
@@ -44,6 +43,8 @@ derive-where = { workspace = true }
|
|||||||
hex = { workspace = true, default-features = false, features = ["alloc"] }
|
hex = { workspace = true, default-features = false, features = ["alloc"] }
|
||||||
serde = { workspace = true, default-features = false, features = ["derive"] }
|
serde = { workspace = true, default-features = false, features = ["derive"] }
|
||||||
serde_json = { workspace = true, default-features = false, features = ["raw_value", "alloc"] }
|
serde_json = { workspace = true, default-features = false, features = ["raw_value", "alloc"] }
|
||||||
|
tracing = { workspace = true, default-features = false }
|
||||||
|
polkadot-sdk = { workspace = true, features = ["sp-crypto-hashing"] }
|
||||||
hashbrown = { workspace = true }
|
hashbrown = { workspace = true }
|
||||||
thiserror = { workspace = true, default-features = false }
|
thiserror = { workspace = true, default-features = false }
|
||||||
|
|
||||||
@@ -55,10 +56,6 @@ blake2 = { workspace = true }
|
|||||||
# Provides some deserialization, types like U256/H256 and hashing impls like twox/blake256:
|
# Provides some deserialization, types like U256/H256 and hashing impls like twox/blake256:
|
||||||
impl-serde = { workspace = true, default-features = false }
|
impl-serde = { workspace = true, default-features = false }
|
||||||
primitive-types = { workspace = true, default-features = false, features = ["codec", "serde_no_std", "scale-info"] }
|
primitive-types = { workspace = true, default-features = false, features = ["codec", "serde_no_std", "scale-info"] }
|
||||||
polkadot-sdk = { workspace = true, features = ["sp-crypto-hashing"] }
|
|
||||||
|
|
||||||
# Included if the "substrate-compat" feature is enabled.
|
|
||||||
tracing = { workspace = true, default-features = false }
|
|
||||||
|
|
||||||
# AccountId20
|
# AccountId20
|
||||||
keccak-hash = { workspace = true}
|
keccak-hash = { workspace = true}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ pub mod polkadot;
|
|||||||
pub mod signed_extensions;
|
pub mod signed_extensions;
|
||||||
pub mod substrate;
|
pub mod substrate;
|
||||||
|
|
||||||
use crate::macros::cfg_substrate_compat;
|
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use scale_decode::DecodeAsType;
|
use scale_decode::DecodeAsType;
|
||||||
@@ -127,31 +126,3 @@ pub trait Header: Sized + Encode + Decode {
|
|||||||
Self::Hasher::hash_of(self)
|
Self::Hasher::hash_of(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_substrate_compat! {
|
|
||||||
/// implement subxt's Hasher and Header traits for some substrate structs
|
|
||||||
mod substrate_impls {
|
|
||||||
use super::*;
|
|
||||||
use polkadot_sdk::sp_runtime;
|
|
||||||
|
|
||||||
impl<T: sp_runtime::traits::Header> Header for T
|
|
||||||
where
|
|
||||||
<T as sp_runtime::traits::Header>::Number: Into<u64>,
|
|
||||||
{
|
|
||||||
type Number = T::Number;
|
|
||||||
type Hasher = T::Hashing;
|
|
||||||
|
|
||||||
fn number(&self) -> Self::Number {
|
|
||||||
*self.number()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: sp_runtime::traits::Hash> Hasher for T {
|
|
||||||
type Output = T::Output;
|
|
||||||
|
|
||||||
fn hash(s: &[u8]) -> Self::Output {
|
|
||||||
<T as sp_runtime::traits::Hash>::hash(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,9 +23,6 @@
|
|||||||
#![cfg_attr(not(feature = "std"), no_std)]
|
#![cfg_attr(not(feature = "std"), no_std)]
|
||||||
pub extern crate alloc;
|
pub extern crate alloc;
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
mod macros;
|
|
||||||
|
|
||||||
pub mod blocks;
|
pub mod blocks;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
@@ -50,9 +47,4 @@ pub mod ext {
|
|||||||
pub use scale_decode;
|
pub use scale_decode;
|
||||||
pub use scale_encode;
|
pub use scale_encode;
|
||||||
pub use scale_value;
|
pub use scale_value;
|
||||||
|
|
||||||
cfg_substrate_compat! {
|
|
||||||
pub use polkadot_sdk::sp_runtime;
|
|
||||||
pub use polkadot_sdk::sp_core;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
// Copyright 2019-2024 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
|
||||||
// see LICENSE for license details.
|
|
||||||
|
|
||||||
macro_rules! cfg_feature {
|
|
||||||
($feature:literal, $($item:item)*) => {
|
|
||||||
$(
|
|
||||||
#[cfg(feature = $feature)]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = $feature)))]
|
|
||||||
$item
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cfg_substrate_compat {
|
|
||||||
($($item:item)*) => {
|
|
||||||
crate::macros::cfg_feature!("substrate-compat", $($item)*);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) use {cfg_feature, cfg_substrate_compat};
|
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
//! A library to **sub**mit e**xt**rinsics to a
|
//! A library to **sub**mit e**xt**rinsics to a
|
||||||
//! [substrate](https://github.com/paritytech/substrate) node via RPC.
|
//! [substrate](https://github.com/paritytech/substrate) node via RPC.
|
||||||
|
|
||||||
use crate::macros::cfg_substrate_compat;
|
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
|
||||||
/// Signing transactions requires a [`Signer`]. This is responsible for
|
/// Signing transactions requires a [`Signer`]. This is responsible for
|
||||||
@@ -24,77 +23,3 @@ pub trait Signer<T: Config> {
|
|||||||
/// refused the operation.
|
/// refused the operation.
|
||||||
fn sign(&self, signer_payload: &[u8]) -> T::Signature;
|
fn sign(&self, signer_payload: &[u8]) -> T::Signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_substrate_compat! {
|
|
||||||
pub use pair_signer::PairSigner;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A signer suitable for substrate based chains. This provides compatibility with Substrate
|
|
||||||
// packages like sp_keyring and such, and so relies on sp_core and sp_runtime to be included.
|
|
||||||
#[cfg(feature = "substrate-compat")]
|
|
||||||
mod pair_signer {
|
|
||||||
use super::Signer;
|
|
||||||
use crate::Config;
|
|
||||||
use polkadot_sdk::sp_core::Pair as PairT;
|
|
||||||
use polkadot_sdk::sp_runtime::{
|
|
||||||
traits::{IdentifyAccount, Verify},
|
|
||||||
AccountId32 as SpAccountId32, MultiSignature as SpMultiSignature,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A [`Signer`] implementation that can be constructed from an [`sp_core::Pair`].
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct PairSigner<T: Config, Pair> {
|
|
||||||
account_id: T::AccountId,
|
|
||||||
signer: Pair,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, Pair> PairSigner<T, Pair>
|
|
||||||
where
|
|
||||||
T: Config,
|
|
||||||
Pair: PairT,
|
|
||||||
// We go via an `sp_runtime::MultiSignature`. We can probably generalise this
|
|
||||||
// by implementing some of these traits on our built-in MultiSignature and then
|
|
||||||
// requiring them on all T::Signatures, to avoid any go-between.
|
|
||||||
<SpMultiSignature as Verify>::Signer: From<Pair::Public>,
|
|
||||||
T::AccountId: From<SpAccountId32>,
|
|
||||||
{
|
|
||||||
/// Creates a new [`Signer`] from an [`sp_core::Pair`].
|
|
||||||
pub fn new(signer: Pair) -> Self {
|
|
||||||
let account_id =
|
|
||||||
<SpMultiSignature as Verify>::Signer::from(signer.public()).into_account();
|
|
||||||
Self {
|
|
||||||
account_id: account_id.into(),
|
|
||||||
signer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the [`sp_core::Pair`] implementation used to construct this.
|
|
||||||
pub fn signer(&self) -> &Pair {
|
|
||||||
&self.signer
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the account ID.
|
|
||||||
pub fn account_id(&self) -> &T::AccountId {
|
|
||||||
&self.account_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, Pair> Signer<T> for PairSigner<T, Pair>
|
|
||||||
where
|
|
||||||
T: Config,
|
|
||||||
Pair: PairT,
|
|
||||||
Pair::Signature: Into<T::Signature>,
|
|
||||||
{
|
|
||||||
fn account_id(&self) -> T::AccountId {
|
|
||||||
self.account_id.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn address(&self) -> T::Address {
|
|
||||||
self.account_id.clone().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sign(&self, signer_payload: &[u8]) -> T::Signature {
|
|
||||||
self.signer.sign(signer_payload).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -160,35 +160,9 @@ impl core::str::FromStr for AccountId32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Improve compat with the substrate version if we're using those crates:
|
|
||||||
#[cfg(feature = "substrate-compat")]
|
|
||||||
mod substrate_impls {
|
|
||||||
use super::*;
|
|
||||||
use polkadot_sdk::{sp_core, sp_runtime};
|
|
||||||
|
|
||||||
impl From<sp_runtime::AccountId32> for AccountId32 {
|
|
||||||
fn from(value: sp_runtime::AccountId32) -> Self {
|
|
||||||
Self(value.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<sp_core::sr25519::Public> for AccountId32 {
|
|
||||||
fn from(value: sp_core::sr25519::Public) -> Self {
|
|
||||||
let acc: sp_runtime::AccountId32 = value.into();
|
|
||||||
acc.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl From<sp_core::ed25519::Public> for AccountId32 {
|
|
||||||
fn from(value: sp_core::ed25519::Public) -> Self {
|
|
||||||
let acc: sp_runtime::AccountId32 = value.into();
|
|
||||||
acc.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use polkadot_sdk::sp_core::{self, crypto::Ss58Codec};
|
use polkadot_sdk::sp_core::{self, crypto::Ss58Codec};
|
||||||
use polkadot_sdk::sp_keyring::AccountKeyring;
|
use polkadot_sdk::sp_keyring::AccountKeyring;
|
||||||
|
|
||||||
@@ -202,8 +176,6 @@ mod test {
|
|||||||
|
|
||||||
for keyring in keyrings {
|
for keyring in keyrings {
|
||||||
let substrate_account = keyring.to_account_id();
|
let substrate_account = keyring.to_account_id();
|
||||||
// Avoid "From" impl hidden behind "substrate-compat" feature so that this test
|
|
||||||
// can work either way:
|
|
||||||
let local_account = AccountId32(substrate_account.clone().into());
|
let local_account = AccountId32(substrate_account.clone().into());
|
||||||
|
|
||||||
// Both should encode to ss58 the same way:
|
// Both should encode to ss58 the same way:
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ use alloc::vec::Vec;
|
|||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
|
|
||||||
/// A multi-format address wrapper for on-chain accounts. This is a simplified version of Substrate's
|
/// A multi-format address wrapper for on-chain accounts. This is a simplified version of Substrate's
|
||||||
/// `sp_runtime::MultiAddress`. To obtain more functionality, convert this into that type (this conversion
|
/// `sp_runtime::MultiAddress`.
|
||||||
/// functionality is provided via `From` impls if the `substrate-compat` feature is enabled).
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Clone,
|
Clone,
|
||||||
Eq,
|
Eq,
|
||||||
@@ -43,32 +42,3 @@ impl<AccountId, AccountIndex> From<AccountId> for MultiAddress<AccountId, Accoun
|
|||||||
Self::Id(a)
|
Self::Id(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Improve compat with the substrate version if we're using those crates:
|
|
||||||
#[cfg(feature = "substrate-compat")]
|
|
||||||
mod substrate_impls {
|
|
||||||
use super::{super::AccountId32, *};
|
|
||||||
use polkadot_sdk::sp_runtime;
|
|
||||||
|
|
||||||
impl<N> From<sp_runtime::AccountId32> for MultiAddress<AccountId32, N> {
|
|
||||||
fn from(value: sp_runtime::AccountId32) -> Self {
|
|
||||||
let val: AccountId32 = value.into();
|
|
||||||
val.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Id, N> From<sp_runtime::MultiAddress<Id, N>> for MultiAddress<AccountId32, N>
|
|
||||||
where
|
|
||||||
Id: Into<AccountId32>,
|
|
||||||
{
|
|
||||||
fn from(value: sp_runtime::MultiAddress<Id, N>) -> Self {
|
|
||||||
match value {
|
|
||||||
sp_runtime::MultiAddress::Id(v) => Self::Id(v.into()),
|
|
||||||
sp_runtime::MultiAddress::Index(v) => Self::Index(v),
|
|
||||||
sp_runtime::MultiAddress::Raw(v) => Self::Raw(v),
|
|
||||||
sp_runtime::MultiAddress::Address32(v) => Self::Address32(v),
|
|
||||||
sp_runtime::MultiAddress::Address20(v) => Self::Address20(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,41 +19,3 @@ pub enum MultiSignature {
|
|||||||
/// An ECDSA/SECP256k1 signature (a 512-bit value, plus 8 bits for recovery ID).
|
/// An ECDSA/SECP256k1 signature (a 512-bit value, plus 8 bits for recovery ID).
|
||||||
Ecdsa([u8; 65]),
|
Ecdsa([u8; 65]),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Improve compat with the substrate version if we're using those crates:
|
|
||||||
#[cfg(feature = "substrate-compat")]
|
|
||||||
mod substrate_impls {
|
|
||||||
use super::*;
|
|
||||||
use polkadot_sdk::{sp_core, sp_runtime};
|
|
||||||
|
|
||||||
impl From<sp_runtime::MultiSignature> for MultiSignature {
|
|
||||||
fn from(value: sp_runtime::MultiSignature) -> Self {
|
|
||||||
match value {
|
|
||||||
sp_runtime::MultiSignature::Ed25519(s) => Self::Ed25519(s.0),
|
|
||||||
sp_runtime::MultiSignature::Sr25519(s) => Self::Sr25519(s.0),
|
|
||||||
sp_runtime::MultiSignature::Ecdsa(s) => Self::Ecdsa(s.0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<sp_core::ed25519::Signature> for MultiSignature {
|
|
||||||
fn from(value: sp_core::ed25519::Signature) -> Self {
|
|
||||||
let sig: sp_runtime::MultiSignature = value.into();
|
|
||||||
sig.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<sp_core::sr25519::Signature> for MultiSignature {
|
|
||||||
fn from(value: sp_core::sr25519::Signature) -> Self {
|
|
||||||
let sig: sp_runtime::MultiSignature = value.into();
|
|
||||||
sig.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<sp_core::ecdsa::Signature> for MultiSignature {
|
|
||||||
fn from(value: sp_core::ecdsa::Signature) -> Self {
|
|
||||||
let sig: sp_runtime::MultiSignature = value.into();
|
|
||||||
sig.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ criterion = { workspace = true }
|
|||||||
scale-info = { workspace = true, features = ["bit-vec"] }
|
scale-info = { workspace = true, features = ["bit-vec"] }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
# Without this, libtest cli opts interfere with criteron benches:
|
# Without this, libtest cli opts interfere with criterion benches:
|
||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
|
|||||||
+1
-1
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
//! An ecdsa keypair implementation.
|
//! An ecdsa keypair implementation.
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use polkadot_sdk::sp_crypto_hashing;
|
|
||||||
|
|
||||||
use crate::crypto::{seed_from_entropy, DeriveJunction, SecretUri};
|
use crate::crypto::{seed_from_entropy, DeriveJunction, SecretUri};
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use hex::FromHex;
|
use hex::FromHex;
|
||||||
|
use polkadot_sdk::sp_crypto_hashing;
|
||||||
use secp256k1::{ecdsa::RecoverableSignature, Message, Secp256k1, SecretKey};
|
use secp256k1::{ecdsa::RecoverableSignature, Message, Secp256k1, SecretKey};
|
||||||
use secrecy::ExposeSecret;
|
use secrecy::ExposeSecret;
|
||||||
|
|
||||||
|
|||||||
+4
-9
@@ -64,11 +64,6 @@ jsonrpsee = [
|
|||||||
"runtime"
|
"runtime"
|
||||||
]
|
]
|
||||||
|
|
||||||
# Enable this to pull in extra Substrate dependencies which make it possible to
|
|
||||||
# use the `sp_core::crypto::Pair` Signer implementation, as well as adding some
|
|
||||||
# `From` impls for types like `AccountId32`. Cannot be used with "web".
|
|
||||||
substrate-compat = ["subxt-core/substrate-compat"]
|
|
||||||
|
|
||||||
# Enable this to fetch and utilize the latest unstable metadata from a node.
|
# Enable this to fetch and utilize the latest unstable metadata from a node.
|
||||||
# The unstable metadata is subject to breaking changes and the subxt might
|
# The unstable metadata is subject to breaking changes and the subxt might
|
||||||
# fail to decode the metadata properly. Use this to experiment with the
|
# fail to decode the metadata properly. Use this to experiment with the
|
||||||
@@ -95,6 +90,7 @@ futures = { workspace = true }
|
|||||||
hex = { workspace = true }
|
hex = { workspace = true }
|
||||||
serde = { workspace = true, features = ["derive"] }
|
serde = { workspace = true, features = ["derive"] }
|
||||||
serde_json = { workspace = true, features = ["default", "raw_value"] }
|
serde_json = { workspace = true, features = ["default", "raw_value"] }
|
||||||
|
polkadot-sdk = { workspace = true, features = ["sp-crypto-hashing"] }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
frame-metadata = { workspace = true }
|
frame-metadata = { workspace = true }
|
||||||
@@ -104,7 +100,6 @@ web-time = { workspace = true }
|
|||||||
# Provides some deserialization, types like U256/H256 and hashing impls like twox/blake256:
|
# Provides some deserialization, types like U256/H256 and hashing impls like twox/blake256:
|
||||||
impl-serde = { workspace = true }
|
impl-serde = { workspace = true }
|
||||||
primitive-types = { workspace = true, features = ["codec", "scale-info", "serde"] }
|
primitive-types = { workspace = true, features = ["codec", "scale-info", "serde"] }
|
||||||
polkadot-sdk = { workspace = true, features = ["sp-crypto-hashing"] }
|
|
||||||
|
|
||||||
# Included if the "jsonrpsee" feature is enabled.
|
# Included if the "jsonrpsee" feature is enabled.
|
||||||
jsonrpsee = { workspace = true, optional = true, features = ["jsonrpsee-types"] }
|
jsonrpsee = { workspace = true, optional = true, features = ["jsonrpsee-types"] }
|
||||||
@@ -136,7 +131,7 @@ bitvec = { workspace = true }
|
|||||||
codec = { workspace = true, features = ["derive", "bit-vec"] }
|
codec = { workspace = true, features = ["derive", "bit-vec"] }
|
||||||
scale-info = { workspace = true, features = ["bit-vec"] }
|
scale-info = { workspace = true, features = ["bit-vec"] }
|
||||||
tokio = { workspace = true, features = ["macros", "time", "rt-multi-thread", "sync"] }
|
tokio = { workspace = true, features = ["macros", "time", "rt-multi-thread", "sync"] }
|
||||||
polkadot-sdk = { workspace = true, features = ["sp-core", "sp-keyring", "sp-runtime", "sp-crypto-hashing"] }
|
polkadot-sdk = { workspace = true, features = ["sp-core", "sp-keyring", "sp-runtime", "std"] }
|
||||||
assert_matches = { workspace = true }
|
assert_matches = { workspace = true }
|
||||||
subxt-signer = { path = "../signer", features = ["unstable-eth"] }
|
subxt-signer = { path = "../signer", features = ["unstable-eth"] }
|
||||||
# Tracing subscriber is useful for light-client examples to ensure that
|
# Tracing subscriber is useful for light-client examples to ensure that
|
||||||
@@ -166,8 +161,8 @@ path = "examples/setup_reconnecting_rpc_client.rs"
|
|||||||
required-features = ["reconnecting-rpc-client"]
|
required-features = ["reconnecting-rpc-client"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["default", "substrate-compat", "unstable-light-client"]
|
features = ["default", "unstable-light-client"]
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[package.metadata.playground]
|
[package.metadata.playground]
|
||||||
features = ["default", "substrate-compat", "unstable-light-client"]
|
features = ["default", "unstable-light-client"]
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
//! This example demonstrates how to use to add a custom signer implementation to `subxt`
|
||||||
|
//! by using the signer implementation from polkadot-sdk.
|
||||||
|
//!
|
||||||
|
//! Similar functionality was provided by the `substrate-compat` feature in the original `subxt` crate.
|
||||||
|
//! which is now removed.
|
||||||
|
|
||||||
|
#![allow(missing_docs, unused)]
|
||||||
|
|
||||||
|
use polkadot_sdk::sp_core::{sr25519, Pair as _};
|
||||||
|
use subxt::config::substrate::MultiAddress;
|
||||||
|
use subxt::{Config, OnlineClient, PolkadotConfig};
|
||||||
|
|
||||||
|
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")]
|
||||||
|
pub mod polkadot {}
|
||||||
|
|
||||||
|
/// A concrete PairSigner implementation which relies on `sr25519::Pair` for signing
|
||||||
|
/// and that PolkadotConfig is the runtime configuration.
|
||||||
|
mod pair_signer {
|
||||||
|
use super::*;
|
||||||
|
use polkadot_sdk::sp_runtime::{
|
||||||
|
traits::{IdentifyAccount, Verify},
|
||||||
|
MultiSignature as SpMultiSignature,
|
||||||
|
};
|
||||||
|
use subxt::{
|
||||||
|
config::substrate::{AccountId32, MultiSignature},
|
||||||
|
tx::Signer,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A [`Signer`] implementation for [`polkadot_sdk::sp_core::sr25519::Pair`].
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PairSigner {
|
||||||
|
account_id: <PolkadotConfig as Config>::AccountId,
|
||||||
|
signer: sr25519::Pair,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PairSigner {
|
||||||
|
/// Creates a new [`Signer`] from an [`sp_core::sr25519::Pair`].
|
||||||
|
pub fn new(signer: sr25519::Pair) -> Self {
|
||||||
|
let account_id =
|
||||||
|
<SpMultiSignature as Verify>::Signer::from(signer.public()).into_account();
|
||||||
|
Self {
|
||||||
|
// Convert `sp_core::AccountId32` to `subxt::config::substrate::AccountId32`.
|
||||||
|
//
|
||||||
|
// This is necessary because we use `subxt::config::substrate::AccountId32` and no
|
||||||
|
// From/Into impls are provided between `sp_core::AccountId32` because `polkadot-sdk` isn't a direct
|
||||||
|
// dependency in subxt.
|
||||||
|
//
|
||||||
|
// This can also be done by provided a wrapper type around `subxt::config::substrate::AccountId32` to implement
|
||||||
|
// such conversions but that also most likely requires a custom `Config` with a separate `AccountId` type to work
|
||||||
|
// properly without additional hacks.
|
||||||
|
account_id: AccountId32(account_id.into()),
|
||||||
|
signer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the [`sp_core::sr25519::Pair`] implementation used to construct this.
|
||||||
|
pub fn signer(&self) -> &sr25519::Pair {
|
||||||
|
&self.signer
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the account ID.
|
||||||
|
pub fn account_id(&self) -> &AccountId32 {
|
||||||
|
&self.account_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Signer<PolkadotConfig> for PairSigner {
|
||||||
|
fn account_id(&self) -> <PolkadotConfig as Config>::AccountId {
|
||||||
|
self.account_id.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn address(&self) -> <PolkadotConfig as Config>::Address {
|
||||||
|
self.account_id.clone().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sign(&self, signer_payload: &[u8]) -> <PolkadotConfig as Config>::Signature {
|
||||||
|
let signature = self.signer.sign(signer_payload);
|
||||||
|
MultiSignature::Sr25519(signature.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
// Create a new API client, configured to talk to Polkadot nodes.
|
||||||
|
let api = OnlineClient::<PolkadotConfig>::new().await?;
|
||||||
|
|
||||||
|
let signer = {
|
||||||
|
let acc = sr25519::Pair::from_string("//Alice", None)?;
|
||||||
|
pair_signer::PairSigner::new(acc)
|
||||||
|
};
|
||||||
|
|
||||||
|
let dest = {
|
||||||
|
let acc = sr25519::Pair::from_string("//Bob", None)?;
|
||||||
|
MultiAddress::Address32(acc.public().0)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Build a balance transfer extrinsic.
|
||||||
|
let balance_transfer_tx = polkadot::tx()
|
||||||
|
.balances()
|
||||||
|
.transfer_allow_death(dest, 100_000);
|
||||||
|
|
||||||
|
// Submit the balance transfer extrinsic from Alice, and wait for it to be successful
|
||||||
|
// and in a finalized block. We get back the extrinsic events if all is well.
|
||||||
|
let events = api
|
||||||
|
.tx()
|
||||||
|
.sign_and_submit_then_watch_default(&balance_transfer_tx, &signer)
|
||||||
|
.await?
|
||||||
|
.wait_for_finalized_success()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Find a Transfer event and print it.
|
||||||
|
let transfer_event = events.find_first::<polkadot::balances::events::Transfer>()?;
|
||||||
|
if let Some(event) = transfer_event {
|
||||||
|
println!("Balance transfer success: {event:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -66,24 +66,23 @@
|
|||||||
//! There are two main ways to create a compatible signer instance:
|
//! There are two main ways to create a compatible signer instance:
|
||||||
//! 1. The `subxt_signer` crate provides a WASM compatible implementation of [`crate::tx::Signer`]
|
//! 1. The `subxt_signer` crate provides a WASM compatible implementation of [`crate::tx::Signer`]
|
||||||
//! for chains which require sr25519 or ecdsa signatures (requires the `subxt` feature to be enabled).
|
//! for chains which require sr25519 or ecdsa signatures (requires the `subxt` feature to be enabled).
|
||||||
//! 2. Alternately, Subxt can use instances of Substrate's `sp_core::Pair` to sign things by wrapping
|
//! 2. Alternately, implement your own [`crate::tx::Signer`] instance by wrapping it in a new type pattern.
|
||||||
//! them in a `crate::tx::PairSigner` (requires the `substrate-compat` feature to be enabled).
|
|
||||||
//!
|
//!
|
||||||
//! Going for 1 leads to fewer dependencies being imported and WASM compatibility out of the box via
|
//! Going for 1 leads to fewer dependencies being imported and WASM compatibility out of the box via
|
||||||
//! the `web` feature flag. Going for 2 is useful if you're already using the Substrate dependencies or
|
//! the `web` feature flag. Going for 2 is useful if you're already using the Substrate dependencies or
|
||||||
//! need additional signing algorithms that `subxt_signer` doesn't support, and don't care about WASM
|
//! need additional signing algorithms that `subxt_signer` doesn't support, and don't care about WASM
|
||||||
//! compatibility.
|
//! compatibility.
|
||||||
//!
|
//!
|
||||||
//! Let's see how to use each of these approaches:
|
//! Because 2 is more complex and require more code, we'll focus on 1 here.
|
||||||
|
//! For 2, see the example in `subxt/examples/substrate_compat_signer.rs` how
|
||||||
|
//! you can integrate things like sp_core's signer in subxt.
|
||||||
|
//!
|
||||||
|
//! Let's go through how to create a signer using the `subxt_signer` crate:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! # #[cfg(feature = "substrate-compat")]
|
|
||||||
//! # {
|
|
||||||
//! use subxt::config::PolkadotConfig;
|
//! use subxt::config::PolkadotConfig;
|
||||||
//! use std::str::FromStr;
|
//! use std::str::FromStr;
|
||||||
//! use polkadot_sdk::{sp_core, sp_keyring};
|
|
||||||
//!
|
//!
|
||||||
//! //// 1. Use a `subxt_signer` impl:
|
|
||||||
//! use subxt_signer::{SecretUri, sr25519};
|
//! use subxt_signer::{SecretUri, sr25519};
|
||||||
//!
|
//!
|
||||||
//! // Get hold of a `Signer` for a test account:
|
//! // Get hold of a `Signer` for a test account:
|
||||||
@@ -94,34 +93,9 @@
|
|||||||
//! .expect("valid URI");
|
//! .expect("valid URI");
|
||||||
//! let keypair = sr25519::Keypair::from_uri(&uri)
|
//! let keypair = sr25519::Keypair::from_uri(&uri)
|
||||||
//! .expect("valid keypair");
|
//! .expect("valid keypair");
|
||||||
|
//!```
|
||||||
//!
|
//!
|
||||||
//! //// 2. Use the corresponding `sp_core::Pair` impl:
|
//! After initializing the signer, let's also go through how to create a transaction and sign it:
|
||||||
//! use subxt::tx::PairSigner;
|
|
||||||
//! use sp_core::Pair;
|
|
||||||
//!
|
|
||||||
//! // Get hold of a `Signer` for a test account:
|
|
||||||
//! let alice = sp_keyring::AccountKeyring::Alice.pair();
|
|
||||||
//! let alice = PairSigner::<PolkadotConfig,_>::new(alice);
|
|
||||||
//!
|
|
||||||
//! // Or generate a keypair, here from an SURI:
|
|
||||||
//! let keypair = sp_core::sr25519::Pair::from_string("vessel ladder alter error federal sibling chat ability sun glass valve picture/0/1///Password", None)
|
|
||||||
//! .expect("valid URI");
|
|
||||||
//! let keypair = PairSigner::<PolkadotConfig,_>::new(keypair);
|
|
||||||
//! #
|
|
||||||
//! # // Test that these all impl Signer trait while we're here:
|
|
||||||
//! #
|
|
||||||
//! # fn is_subxt_signer(_signer: impl subxt::tx::Signer<PolkadotConfig>) {}
|
|
||||||
//! # is_subxt_signer(subxt_signer::sr25519::dev::alice());
|
|
||||||
//! # is_subxt_signer(subxt_signer::ecdsa::dev::alice());
|
|
||||||
//! # is_subxt_signer(PairSigner::<PolkadotConfig,_>::new(sp_keyring::AccountKeyring::Alice.pair()));
|
|
||||||
//! # }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! See the `subxt_signer` crate or the `sp_core::Pair` docs for more ways to construct
|
|
||||||
//! and work with key pairs.
|
|
||||||
//!
|
|
||||||
//! If this isn't suitable/available, you can either implement [`crate::tx::Signer`] yourself to use
|
|
||||||
//! custom signing logic, or you can use some external signing logic, like so:
|
|
||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! # #[tokio::main]
|
//! # #[tokio::main]
|
||||||
|
|||||||
@@ -18,9 +18,6 @@
|
|||||||
))]
|
))]
|
||||||
compile_error!("subxt: exactly one of the 'web' and 'native' features should be used.");
|
compile_error!("subxt: exactly one of the 'web' and 'native' features should be used.");
|
||||||
|
|
||||||
#[cfg(all(feature = "web", feature = "substrate-compat"))]
|
|
||||||
compile_error!("subxt: the 'substrate-compat' feature is not compatible with the 'web' feature.");
|
|
||||||
|
|
||||||
// The guide is here.
|
// The guide is here.
|
||||||
pub mod book;
|
pub mod book;
|
||||||
|
|
||||||
@@ -115,10 +112,6 @@ pub mod ext {
|
|||||||
cfg_jsonrpsee! {
|
cfg_jsonrpsee! {
|
||||||
pub use jsonrpsee;
|
pub use jsonrpsee;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_substrate_compat! {
|
|
||||||
pub use subxt_core::ext::{sp_runtime, sp_core};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a strongly typed API for interacting with a Substrate runtime from its metadata.
|
/// Generate a strongly typed API for interacting with a Substrate runtime from its metadata.
|
||||||
|
|||||||
+1
-8
@@ -12,12 +12,6 @@ macro_rules! cfg_feature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! cfg_substrate_compat {
|
|
||||||
($($item:item)*) => {
|
|
||||||
crate::macros::cfg_feature!("substrate-compat", $($item)*);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! cfg_unstable_light_client {
|
macro_rules! cfg_unstable_light_client {
|
||||||
($($item:item)*) => {
|
($($item:item)*) => {
|
||||||
crate::macros::cfg_feature!("unstable-light-client", $($item)*);
|
crate::macros::cfg_feature!("unstable-light-client", $($item)*);
|
||||||
@@ -64,8 +58,7 @@ macro_rules! cfg_reconnecting_rpc_client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use {
|
pub(crate) use {
|
||||||
cfg_feature, cfg_jsonrpsee, cfg_reconnecting_rpc_client, cfg_substrate_compat,
|
cfg_feature, cfg_jsonrpsee, cfg_reconnecting_rpc_client, cfg_unstable_light_client,
|
||||||
cfg_unstable_light_client,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only used by light-client.
|
// Only used by light-client.
|
||||||
|
|||||||
@@ -9,17 +9,9 @@
|
|||||||
//! additional and signed extra parameters are used when constructing an extrinsic, and is a part
|
//! additional and signed extra parameters are used when constructing an extrinsic, and is a part
|
||||||
//! of the chain configuration (see [`crate::config::Config`]).
|
//! of the chain configuration (see [`crate::config::Config`]).
|
||||||
|
|
||||||
use crate::macros::cfg_substrate_compat;
|
|
||||||
|
|
||||||
mod tx_client;
|
mod tx_client;
|
||||||
mod tx_progress;
|
mod tx_progress;
|
||||||
|
|
||||||
// The PairSigner impl currently relies on Substrate bits and pieces, so make it an optional
|
|
||||||
// feature if we want to avoid needing sp_core and sp_runtime.
|
|
||||||
cfg_substrate_compat! {
|
|
||||||
pub use subxt_core::tx::signer::PairSigner;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub use subxt_core::tx::payload::{dynamic, DefaultPayload, DynamicPayload, Payload};
|
pub use subxt_core::tx::payload::{dynamic, DefaultPayload, DynamicPayload, Payload};
|
||||||
pub use subxt_core::tx::signer::{self, Signer};
|
pub use subxt_core::tx::signer::{self, Signer};
|
||||||
pub use tx_client::{
|
pub use tx_client::{
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ hex = { workspace = true }
|
|||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
scale-info = { workspace = true, features = ["bit-vec"] }
|
scale-info = { workspace = true, features = ["bit-vec"] }
|
||||||
polkadot-sdk = { workspace = true, features = ["sp-core"] }
|
polkadot-sdk = { workspace = true, features = ["sp-core", "std"] }
|
||||||
syn = { workspace = true }
|
syn = { workspace = true }
|
||||||
subxt = { workspace = true, features = ["unstable-metadata", "native", "jsonrpsee", "substrate-compat", "reconnecting-rpc-client"] }
|
subxt = { workspace = true, features = ["unstable-metadata", "native", "jsonrpsee", "reconnecting-rpc-client"] }
|
||||||
subxt-signer = { workspace = true, features = ["default"] }
|
subxt-signer = { workspace = true, features = ["default"] }
|
||||||
subxt-codegen = { workspace = true }
|
subxt-codegen = { workspace = true }
|
||||||
subxt-metadata = { workspace = true }
|
subxt-metadata = { workspace = true }
|
||||||
|
|||||||
Reference in New Issue
Block a user