mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-08 13:38:11 +00:00
Refactor: extract functions and types for creating extrinsics (#138)
* Extract extrinsic * Extract extrinsic types to own module * Fix compiler errors * Fix warnings * Fmt * Pin wabt-sys to 0.7.1, it fails (on my machine) with 0.7.2 * Fix up tests * Fmt * Reexport RuntimeVersion
This commit is contained in:
@@ -47,6 +47,7 @@ substrate-subxt-proc-macro = { version = "0.9.0", path = "proc-macro" }
|
||||
async-std = { version = "=1.5.0", features = ["attributes"] }
|
||||
env_logger = "0.7.1"
|
||||
wabt = "0.9.2"
|
||||
wabt-sys = "=0.7.1" # pinned because 0.7.2 fails to compile
|
||||
frame-system = { version = "2.0.0-rc4", package = "frame-system" }
|
||||
pallet-balances = { version = "2.0.0-rc4", package = "pallet-balances" }
|
||||
sp-keyring = { version = "2.0.0-rc4", package = "sp-keyring" }
|
||||
|
||||
@@ -28,11 +28,17 @@ use sp_runtime::{
|
||||
transaction_validity::TransactionValidityError,
|
||||
};
|
||||
|
||||
use crate::frame::{
|
||||
balances::Balances,
|
||||
system::System,
|
||||
use crate::{
|
||||
frame::{
|
||||
balances::Balances,
|
||||
system::System,
|
||||
},
|
||||
runtimes::Runtime,
|
||||
};
|
||||
|
||||
/// Extra type.
|
||||
pub type Extra<T> = <<T as Runtime>::Extra as SignedExtra<T>>::Extra;
|
||||
|
||||
/// SignedExtra checks copied from substrate, in order to remove requirement to implement
|
||||
/// substrate's `frame_system::Trait`
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of substrate-subxt.
|
||||
//
|
||||
// subxt is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// subxt is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with substrate-subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Create signed or unsigned extrinsics.
|
||||
|
||||
mod extra;
|
||||
mod signer;
|
||||
|
||||
pub use self::{
|
||||
extra::{
|
||||
DefaultExtra,
|
||||
Extra,
|
||||
SignedExtra,
|
||||
},
|
||||
signer::{
|
||||
PairSigner,
|
||||
Signer,
|
||||
},
|
||||
};
|
||||
|
||||
use sp_runtime::traits::SignedExtension;
|
||||
use sp_version::RuntimeVersion;
|
||||
|
||||
use crate::{
|
||||
frame::system::System,
|
||||
runtimes::Runtime,
|
||||
Encoded,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// UncheckedExtrinsic type.
|
||||
pub type UncheckedExtrinsic<T> = sp_runtime::generic::UncheckedExtrinsic<
|
||||
<T as System>::Address,
|
||||
Encoded,
|
||||
<T as Runtime>::Signature,
|
||||
Extra<T>,
|
||||
>;
|
||||
|
||||
/// SignedPayload type.
|
||||
pub type SignedPayload<T> = sp_runtime::generic::SignedPayload<Encoded, Extra<T>>;
|
||||
|
||||
/// Creates a signed extrinsic
|
||||
pub async fn create_signed<T>(
|
||||
runtime_version: &RuntimeVersion,
|
||||
genesis_hash: T::Hash,
|
||||
nonce: T::Index,
|
||||
call: Encoded,
|
||||
signer: &(dyn Signer<T> + Send + Sync),
|
||||
) -> Result<UncheckedExtrinsic<T>, Error>
|
||||
where
|
||||
T: Runtime,
|
||||
<<T::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
|
||||
Send + Sync,
|
||||
{
|
||||
let spec_version = runtime_version.spec_version;
|
||||
let tx_version = runtime_version.transaction_version;
|
||||
let extra: T::Extra = T::Extra::new(spec_version, tx_version, nonce, genesis_hash);
|
||||
let payload = SignedPayload::<T>::new(call, extra.extra())?;
|
||||
let signed = signer.sign(payload).await?;
|
||||
Ok(signed)
|
||||
}
|
||||
|
||||
/// Creates an unsigned extrinsic
|
||||
pub fn create_unsigned<T>(call: Encoded) -> UncheckedExtrinsic<T>
|
||||
where
|
||||
T: Runtime,
|
||||
{
|
||||
UncheckedExtrinsic::<T>::new_unsigned(call)
|
||||
}
|
||||
@@ -17,14 +17,12 @@
|
||||
//! A library to **sub**mit e**xt**rinsics to a
|
||||
//! [substrate](https://github.com/paritytech/substrate) node via RPC.
|
||||
|
||||
use crate::{
|
||||
extra::SignedExtra,
|
||||
runtimes::{
|
||||
Runtime,
|
||||
SignedPayload,
|
||||
UncheckedExtrinsic,
|
||||
},
|
||||
use super::{
|
||||
SignedExtra,
|
||||
SignedPayload,
|
||||
UncheckedExtrinsic,
|
||||
};
|
||||
use crate::runtimes::Runtime;
|
||||
use codec::Encode;
|
||||
use sp_core::Pair;
|
||||
use sp_runtime::traits::{
|
||||
@@ -115,7 +115,7 @@ mod tests {
|
||||
RuntimeError,
|
||||
},
|
||||
events::EventsDecoder,
|
||||
signer::{
|
||||
extrinsic::{
|
||||
PairSigner,
|
||||
Signer,
|
||||
},
|
||||
|
||||
+1
-1
@@ -44,8 +44,8 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
error::Error,
|
||||
extrinsic::PairSigner,
|
||||
frame::balances::TransferCall,
|
||||
signer::PairSigner,
|
||||
tests::{
|
||||
test_client,
|
||||
TestRuntime,
|
||||
|
||||
+30
-104
@@ -60,17 +60,16 @@ use sp_core::{
|
||||
Bytes,
|
||||
};
|
||||
pub use sp_runtime::traits::SignedExtension;
|
||||
use sp_version::RuntimeVersion;
|
||||
pub use sp_version::RuntimeVersion;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
mod error;
|
||||
mod events;
|
||||
mod extra;
|
||||
pub mod extrinsic;
|
||||
mod frame;
|
||||
mod metadata;
|
||||
mod rpc;
|
||||
mod runtimes;
|
||||
mod signer;
|
||||
mod subscription;
|
||||
|
||||
pub use crate::{
|
||||
@@ -79,7 +78,12 @@ pub use crate::{
|
||||
EventsDecoder,
|
||||
RawEvent,
|
||||
},
|
||||
extra::*,
|
||||
extrinsic::{
|
||||
PairSigner,
|
||||
SignedExtra,
|
||||
Signer,
|
||||
UncheckedExtrinsic,
|
||||
},
|
||||
frame::*,
|
||||
metadata::{
|
||||
Metadata,
|
||||
@@ -90,7 +94,6 @@ pub use crate::{
|
||||
ExtrinsicSuccess,
|
||||
},
|
||||
runtimes::*,
|
||||
signer::*,
|
||||
subscription::*,
|
||||
substrate_subxt_proc_macro::*,
|
||||
};
|
||||
@@ -311,49 +314,13 @@ impl<T: Runtime> Client<T> {
|
||||
.and_then(|module| module.call(C::FUNCTION, call))?)
|
||||
}
|
||||
|
||||
/// Creates an payload for an extrinsic.
|
||||
///
|
||||
/// If `nonce` is `None` the nonce will be fetched from the chain.
|
||||
pub async fn create_payload<C: Call<T>>(
|
||||
&self,
|
||||
call: C,
|
||||
account_id: &<T as System>::AccountId,
|
||||
nonce: Option<T::Index>,
|
||||
) -> Result<SignedPayload<T>, Error>
|
||||
where
|
||||
<<T::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
|
||||
Send + Sync,
|
||||
{
|
||||
let account_nonce = if let Some(nonce) = nonce {
|
||||
nonce
|
||||
} else {
|
||||
self.account(account_id, None).await?.nonce
|
||||
};
|
||||
let spec_version = self.runtime_version.spec_version;
|
||||
let tx_version = self.runtime_version.transaction_version;
|
||||
let genesis_hash = self.genesis_hash;
|
||||
let call = self.encode(call)?;
|
||||
let extra: T::Extra =
|
||||
T::Extra::new(spec_version, tx_version, account_nonce, genesis_hash);
|
||||
let raw_payload = SignedPayload::<T>::new(call, extra.extra())?;
|
||||
Ok(raw_payload)
|
||||
}
|
||||
|
||||
/// Creates an unsigned extrinsic.
|
||||
pub async fn create_unsigned<C: Call<T> + Send + Sync>(
|
||||
pub fn create_unsigned<C: Call<T> + Send + Sync>(
|
||||
&self,
|
||||
call: C,
|
||||
account_id: &<T as System>::AccountId,
|
||||
nonce: Option<T::Index>,
|
||||
) -> Result<UncheckedExtrinsic<T>, Error>
|
||||
where
|
||||
<<T::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
|
||||
Send + Sync,
|
||||
{
|
||||
let payload = self.create_payload(call, account_id, nonce).await?;
|
||||
let (call, _, _) = payload.deconstruct();
|
||||
let unsigned = UncheckedExtrinsic::<T>::new_unsigned(call);
|
||||
Ok(unsigned)
|
||||
) -> Result<UncheckedExtrinsic<T>, Error> {
|
||||
let call = self.encode(call)?;
|
||||
Ok(extrinsic::create_unsigned::<T>(call))
|
||||
}
|
||||
|
||||
/// Creates a signed extrinsic.
|
||||
@@ -366,10 +333,20 @@ impl<T: Runtime> Client<T> {
|
||||
<<T::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
|
||||
Send + Sync,
|
||||
{
|
||||
let payload = self
|
||||
.create_payload(call, signer.account_id(), signer.nonce())
|
||||
.await?;
|
||||
let signed = signer.sign(payload).await?;
|
||||
let account_nonce = if let Some(nonce) = signer.nonce() {
|
||||
nonce
|
||||
} else {
|
||||
self.account(signer.account_id(), None).await?.nonce
|
||||
};
|
||||
let call = self.encode(call)?;
|
||||
let signed = extrinsic::create_signed(
|
||||
&self.runtime_version,
|
||||
self.genesis_hash,
|
||||
account_nonce,
|
||||
call,
|
||||
signer,
|
||||
)
|
||||
.await?;
|
||||
Ok(signed)
|
||||
}
|
||||
|
||||
@@ -479,19 +456,11 @@ impl codec::Encode for Encoded {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use codec::Encode;
|
||||
use sp_core::{
|
||||
storage::{
|
||||
well_known_keys,
|
||||
StorageKey,
|
||||
},
|
||||
Pair,
|
||||
use sp_core::storage::{
|
||||
well_known_keys,
|
||||
StorageKey,
|
||||
};
|
||||
use sp_keyring::{
|
||||
AccountKeyring,
|
||||
Ed25519Keyring,
|
||||
};
|
||||
use sp_runtime::MultiSignature;
|
||||
use sp_keyring::AccountKeyring;
|
||||
use substrate_subxt_client::{
|
||||
DatabaseConfig,
|
||||
KeystoreConfig,
|
||||
@@ -640,47 +609,4 @@ mod tests {
|
||||
let mut blocks = client.subscribe_finalized_blocks().await.unwrap();
|
||||
blocks.next().await;
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_create_raw_payload() {
|
||||
let signer_pair = Ed25519Keyring::Alice.pair();
|
||||
let signer_account_id = Ed25519Keyring::Alice.to_account_id();
|
||||
let dest = AccountKeyring::Bob.to_account_id().into();
|
||||
|
||||
let (client, _) = test_client().await;
|
||||
|
||||
// create raw payload with AccoundId and sign it
|
||||
let raw_payload = client
|
||||
.create_payload(
|
||||
balances::TransferCall {
|
||||
to: &dest,
|
||||
amount: 10_000,
|
||||
},
|
||||
&signer_account_id,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let raw_signature = signer_pair.sign(raw_payload.encode().as_slice());
|
||||
let raw_multisig = MultiSignature::from(raw_signature);
|
||||
|
||||
// create signature with Xtbuilder
|
||||
let signer = PairSigner::new(Ed25519Keyring::Alice.pair());
|
||||
let xt_multi_sig = client
|
||||
.create_signed(
|
||||
balances::TransferCall {
|
||||
to: &dest,
|
||||
amount: 10_000,
|
||||
},
|
||||
&signer,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.signature
|
||||
.unwrap()
|
||||
.1;
|
||||
|
||||
// compare signatures
|
||||
assert_eq!(raw_multisig, xt_multi_sig);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-16
@@ -27,7 +27,7 @@ use sp_runtime::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
extra::{
|
||||
extrinsic::{
|
||||
DefaultExtra,
|
||||
SignedExtra,
|
||||
},
|
||||
@@ -40,7 +40,6 @@ use crate::{
|
||||
sudo::Sudo,
|
||||
system::System,
|
||||
},
|
||||
Encoded,
|
||||
};
|
||||
|
||||
/// Runtime trait.
|
||||
@@ -51,20 +50,6 @@ pub trait Runtime: System + Sized + Send + Sync + 'static {
|
||||
type Extra: SignedExtra<Self> + Send + Sync + 'static;
|
||||
}
|
||||
|
||||
/// Extra type.
|
||||
pub type Extra<T> = <<T as Runtime>::Extra as SignedExtra<T>>::Extra;
|
||||
|
||||
/// UncheckedExtrinsic type.
|
||||
pub type UncheckedExtrinsic<T> = sp_runtime::generic::UncheckedExtrinsic<
|
||||
<T as System>::Address,
|
||||
Encoded,
|
||||
<T as Runtime>::Signature,
|
||||
Extra<T>,
|
||||
>;
|
||||
|
||||
/// SignedPayload type.
|
||||
pub type SignedPayload<T> = sp_runtime::generic::SignedPayload<Encoded, Extra<T>>;
|
||||
|
||||
/// Concrete type definitions compatible with those in the default substrate `node_runtime`
|
||||
///
|
||||
/// # Note
|
||||
|
||||
Reference in New Issue
Block a user