mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 19:51:05 +00:00
Merge branch 'master' into staking
This commit is contained in:
+9
-5
@@ -43,12 +43,14 @@ use jsonrpsee::{
|
||||
};
|
||||
use sc_network::config::TransportConfig;
|
||||
pub use sc_service::{
|
||||
config::DatabaseConfig,
|
||||
config::{
|
||||
DatabaseConfig,
|
||||
KeystoreConfig,
|
||||
},
|
||||
Error as ServiceError,
|
||||
};
|
||||
use sc_service::{
|
||||
config::{
|
||||
KeystoreConfig,
|
||||
NetworkConfiguration,
|
||||
TaskType,
|
||||
},
|
||||
@@ -119,6 +121,8 @@ pub struct SubxtClientConfig<C: ChainSpec + 'static, S: AbstractService> {
|
||||
pub copyright_start_year: i32,
|
||||
/// Database configuration.
|
||||
pub db: DatabaseConfig,
|
||||
/// Keystore configuration.
|
||||
pub keystore: KeystoreConfig,
|
||||
/// Service builder.
|
||||
pub builder: fn(Configuration) -> Result<S, sc_service::Error>,
|
||||
/// Chain specification.
|
||||
@@ -216,13 +220,11 @@ fn start_subxt_client<C: ChainSpec + 'static, S: AbstractService>(
|
||||
})
|
||||
.into(),
|
||||
database: config.db,
|
||||
keystore: KeystoreConfig::InMemory,
|
||||
keystore: config.keystore,
|
||||
max_runtime_instances: 8,
|
||||
announce_block: true,
|
||||
dev_key_seed: config.role.into(),
|
||||
|
||||
base_path: Default::default(),
|
||||
informant_output_format: Default::default(),
|
||||
telemetry_endpoints: Default::default(),
|
||||
telemetry_external_transport: Default::default(),
|
||||
default_heap_pages: Default::default(),
|
||||
@@ -344,6 +346,7 @@ mod tests {
|
||||
path: tmp.path().into(),
|
||||
cache_size: 64,
|
||||
},
|
||||
keystore: KeystoreConfig::InMemory,
|
||||
builder: test_node::service::new_light,
|
||||
chain_spec,
|
||||
role: Role::Light,
|
||||
@@ -374,6 +377,7 @@ mod tests {
|
||||
path: tmp.path().into(),
|
||||
cache_size: 128,
|
||||
},
|
||||
keystore: KeystoreConfig::InMemory,
|
||||
builder: test_node::service::new_full,
|
||||
chain_spec: test_node::chain_spec::development_config(),
|
||||
role: Role::Authority(AccountKeyring::Alice),
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
use sp_keyring::AccountKeyring;
|
||||
use substrate_subxt::{
|
||||
balances::*,
|
||||
balances::{
|
||||
TransferCallExt,
|
||||
TransferEventExt,
|
||||
},
|
||||
ClientBuilder,
|
||||
DefaultNodeRuntime,
|
||||
PairSigner,
|
||||
|
||||
+99
-1
@@ -30,13 +30,111 @@ use synstructure::{
|
||||
Structure,
|
||||
};
|
||||
|
||||
/// Register type sizes for [EventsDecoder](struct.EventsDecoder.html) and set the `MODULE`.
|
||||
///
|
||||
/// The `module` macro registers the type sizes of the associated types of a trait so that [EventsDecoder](struct.EventsDecoder.html)
|
||||
/// can decode events of that type when received from Substrate. It also sets the `MODULE` constant
|
||||
/// to the name of the trait (must match the name of the Substrate pallet) that enables the [Call](), [Event]() and [Store]() macros to work.
|
||||
///
|
||||
/// If you do not want an associated type to be registered, likely because you never expect it as part of a response payload to be decoded, use `#[module(ignore)]` on the type.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```ignore
|
||||
/// #[module]
|
||||
/// pub trait Herd: Husbandry {
|
||||
/// type Hooves: HoofCounter;
|
||||
/// type Wool: WoollyAnimal;
|
||||
/// #[module(ignore)]
|
||||
/// type Digestion: EnergyProducer + std::fmt::Debug;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The above will produce the following code:
|
||||
///
|
||||
/// ```ignore
|
||||
/// pub trait Herd: Husbandry {
|
||||
/// type Hooves: HoofCounter;
|
||||
/// type Wool: WoollyAnimal;
|
||||
/// #[module(ignore)]
|
||||
/// type Digestion: EnergyProducer + std::fmt::Debug;
|
||||
/// }
|
||||
///
|
||||
/// const MODULE: &str = "Herd";
|
||||
///
|
||||
/// // `EventsDecoder` extension trait.
|
||||
/// pub trait HerdEventsDecoder {
|
||||
/// // Registers this modules types.
|
||||
/// fn with_herd(&mut self);
|
||||
/// }
|
||||
///
|
||||
/// impl<T: Herd> HerdEventsDecoder for
|
||||
/// substrate_subxt::EventsDecoder<T>
|
||||
/// {
|
||||
/// fn with_herd(&mut self) {
|
||||
/// self.with_husbandry();
|
||||
/// self.register_type_size::<T::Hooves>("Hooves");
|
||||
/// self.register_type_size::<T::Wool>("Wool");
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The following type sizes are registered by default: `bool, u8, u32, AccountId, AccountIndex,
|
||||
/// AuthorityId, AuthorityIndex, AuthorityWeight, BlockNumber, DispatchInfo, Hash, Kind,
|
||||
/// MemberCount, PhantomData, PropIndex, ProposalIndex, ReferendumIndex, SessionIndex, VoteThreshold`
|
||||
#[proc_macro_attribute]
|
||||
#[proc_macro_error]
|
||||
pub fn module(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
module::module(args.into(), input.into()).into()
|
||||
}
|
||||
|
||||
decl_derive!([Call] => #[proc_macro_error] call);
|
||||
decl_derive!(
|
||||
[Call] =>
|
||||
/// Derive macro that implements [substrate_subxt::Call](../substrate_subxt/trait.Call.html) for your struct
|
||||
/// and defines&implements the calls as an extension trait.
|
||||
///
|
||||
/// Use the `Call` derive macro in tandem with the [#module](../substrate_subxt/attr.module.html) macro to extend
|
||||
/// your struct to enable calls to substrate and to decode events. The struct maps to the corresponding Substrate runtime call, e.g.:
|
||||
///
|
||||
/// ```ignore
|
||||
/// decl_module! {
|
||||
/// /* … */
|
||||
/// pub fn fun_stuff(origin, something: Vec<u8>) -> DispatchResult { /* … */ }
|
||||
/// /* … */
|
||||
/// }
|
||||
///```
|
||||
///
|
||||
/// Implements [substrate_subxt::Call](../substrate_subxt/trait.Call.html) and adds an extension trait that
|
||||
/// provides two methods named as your struct.
|
||||
///
|
||||
/// Example:
|
||||
/// ```rust,ignore
|
||||
/// pub struct MyRuntime;
|
||||
///
|
||||
/// impl System for MyRuntime { /* … */ }
|
||||
/// impl Balances for MyRuntime { /* … */ }
|
||||
///
|
||||
/// #[module]
|
||||
/// pub trait MyTrait: System + Balances {}
|
||||
///
|
||||
/// #[derive(Call)]
|
||||
/// pub struct FunStuffCall<T: MyTrait> {
|
||||
/// /// Runtime marker.
|
||||
/// pub _runtime: PhantomData<T>,
|
||||
/// /// The argument passed to the call..
|
||||
/// pub something: Vec<u8>,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// When building a [Client](../substrate_subxt/struct.Client.html) parameterised to `MyRuntime`, you have access to
|
||||
/// two new methods: `fun_stuff()` and `fun_stuff_and_watch()` by way of the derived `FunStuffExt`
|
||||
/// trait. The `_and_watch` variant makes the call and waits for the result. The fields of the
|
||||
/// input struct become arguments to the calls (ignoring the marker field).
|
||||
///
|
||||
/// Under the hood the implementation calls [submit()](../substrate_subxt/struct.Client.html#method.submit) and
|
||||
/// [watch()](../substrate_subxt/struct.Client.html#method.watch) respectively.
|
||||
#[proc_macro_error] call
|
||||
);
|
||||
fn call(s: Structure) -> TokenStream {
|
||||
call::call(s).into()
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ fn events_decoder_trait_name(module: &syn::Ident) -> syn::Ident {
|
||||
fn with_module_ident(module: &syn::Ident) -> syn::Ident {
|
||||
format_ident!("with_{}", module.to_string().to_snake_case())
|
||||
}
|
||||
|
||||
/// Attribute macro that registers the type sizes used by the module; also sets the `MODULE` constant.
|
||||
pub fn module(_args: TokenStream, tokens: TokenStream) -> TokenStream {
|
||||
let input: Result<syn::ItemTrait, _> = syn::parse2(tokens.clone());
|
||||
let input = if let Ok(input) = input {
|
||||
@@ -187,4 +187,46 @@ mod tests {
|
||||
let result = module(attr, input);
|
||||
utils::assert_proc_macro(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_herd() {
|
||||
let attr = quote!(#[module]);
|
||||
let input = quote! {
|
||||
pub trait Herd: Husbandry {
|
||||
type Hoves: u8;
|
||||
type Wool: bool;
|
||||
#[module(ignore)]
|
||||
type Digestion: EnergyProducer + fmt::Debug;
|
||||
}
|
||||
};
|
||||
let expected = quote! {
|
||||
pub trait Herd: Husbandry {
|
||||
type Hoves: u8;
|
||||
type Wool: bool;
|
||||
#[module(ignore)]
|
||||
type Digestion: EnergyProducer + fmt::Debug;
|
||||
}
|
||||
|
||||
const MODULE: &str = "Herd";
|
||||
|
||||
/// `EventsDecoder` extension trait.
|
||||
pub trait HerdEventsDecoder {
|
||||
/// Registers this modules types.
|
||||
fn with_herd(&mut self);
|
||||
}
|
||||
|
||||
impl<T: Herd> HerdEventsDecoder for
|
||||
substrate_subxt::EventsDecoder<T>
|
||||
{
|
||||
fn with_herd(&mut self) {
|
||||
self.with_husbandry();
|
||||
self.register_type_size::<T::Hoves>("Hoves");
|
||||
self.register_type_size::<T::Wool>("Wool");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let result = module(attr, input);
|
||||
utils::assert_proc_macro(result, expected);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ pub struct RawEvent {
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Event decoder.
|
||||
/// Events decoder.
|
||||
#[derive(Debug)]
|
||||
pub struct EventsDecoder<T> {
|
||||
metadata: Metadata,
|
||||
|
||||
+80
-11
@@ -28,7 +28,6 @@
|
||||
path_statements,
|
||||
patterns_in_fns_without_body,
|
||||
private_in_public,
|
||||
missing_debug_implementations,
|
||||
unconditional_recursion,
|
||||
unused_allocation,
|
||||
unused_comparisons,
|
||||
@@ -36,8 +35,7 @@
|
||||
while_true,
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
unused_extern_crates,
|
||||
clippy::all
|
||||
unused_extern_crates
|
||||
)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
@@ -54,9 +52,12 @@ use codec::Decode;
|
||||
use futures::future;
|
||||
use jsonrpsee::client::Subscription;
|
||||
use sc_rpc_api::state::ReadProof;
|
||||
use sp_core::storage::{
|
||||
StorageChangeSet,
|
||||
StorageKey,
|
||||
use sp_core::{
|
||||
storage::{
|
||||
StorageChangeSet,
|
||||
StorageKey,
|
||||
},
|
||||
Bytes,
|
||||
};
|
||||
pub use sp_runtime::traits::SignedExtension;
|
||||
use sp_version::RuntimeVersion;
|
||||
@@ -107,7 +108,6 @@ use crate::{
|
||||
|
||||
/// ClientBuilder for constructing a Client.
|
||||
#[derive(Default)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct ClientBuilder<T: Runtime> {
|
||||
_marker: std::marker::PhantomData<T>,
|
||||
url: Option<String>,
|
||||
@@ -166,7 +166,6 @@ impl<T: Runtime> ClientBuilder<T> {
|
||||
}
|
||||
|
||||
/// Client to interface with a substrate node.
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct Client<T: Runtime> {
|
||||
rpc: Rpc<T>,
|
||||
genesis_hash: T::Hash,
|
||||
@@ -429,6 +428,41 @@ impl<T: Runtime> Client<T> {
|
||||
let decoder = self.events_decoder::<C>();
|
||||
self.submit_and_watch_extrinsic(extrinsic, decoder).await
|
||||
}
|
||||
|
||||
/// Insert a key into the keystore.
|
||||
pub async fn insert_key(
|
||||
&self,
|
||||
key_type: String,
|
||||
suri: String,
|
||||
public: Bytes,
|
||||
) -> Result<(), Error> {
|
||||
self.rpc.insert_key(key_type, suri, public).await
|
||||
}
|
||||
|
||||
/// Generate new session keys and returns the corresponding public keys.
|
||||
pub async fn rotate_keys(&self) -> Result<Bytes, Error> {
|
||||
self.rpc.rotate_keys().await
|
||||
}
|
||||
|
||||
/// Checks if the keystore has private keys for the given session public keys.
|
||||
///
|
||||
/// `session_keys` is the SCALE encoded session keys object from the runtime.
|
||||
///
|
||||
/// Returns `true` iff all private keys could be found.
|
||||
pub async fn has_session_keys(&self, session_keys: Bytes) -> Result<bool, Error> {
|
||||
self.rpc.has_session_keys(session_keys).await
|
||||
}
|
||||
|
||||
/// Checks if the keystore has private keys for the given public key and key type.
|
||||
///
|
||||
/// Returns `true` if a private key could be found.
|
||||
pub async fn has_key(
|
||||
&self,
|
||||
public_key: Bytes,
|
||||
key_type: String,
|
||||
) -> Result<bool, Error> {
|
||||
self.rpc.has_key(public_key, key_type).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps an already encoded byte vector, prevents being encoded as a raw byte vector as part of
|
||||
@@ -460,6 +494,7 @@ mod tests {
|
||||
use sp_runtime::MultiSignature;
|
||||
use substrate_subxt_client::{
|
||||
DatabaseConfig,
|
||||
KeystoreConfig,
|
||||
Role,
|
||||
SubxtClient,
|
||||
SubxtClientConfig,
|
||||
@@ -468,7 +503,9 @@ mod tests {
|
||||
|
||||
pub(crate) type TestRuntime = crate::NodeTemplateRuntime;
|
||||
|
||||
pub(crate) async fn test_client() -> (Client<TestRuntime>, TempDir) {
|
||||
pub(crate) async fn test_client_with(
|
||||
key: AccountKeyring,
|
||||
) -> (Client<TestRuntime>, TempDir) {
|
||||
env_logger::try_init().ok();
|
||||
let tmp = TempDir::new("subxt-").expect("failed to create tempdir");
|
||||
let config = SubxtClientConfig {
|
||||
@@ -477,12 +514,16 @@ mod tests {
|
||||
author: "substrate subxt",
|
||||
copyright_start_year: 2020,
|
||||
db: DatabaseConfig::RocksDb {
|
||||
path: tmp.path().into(),
|
||||
path: tmp.path().join("db"),
|
||||
cache_size: 128,
|
||||
},
|
||||
keystore: KeystoreConfig::Path {
|
||||
path: tmp.path().join("keystore"),
|
||||
password: None,
|
||||
},
|
||||
builder: test_node::service::new_full,
|
||||
chain_spec: test_node::chain_spec::development_config(),
|
||||
role: Role::Authority(AccountKeyring::Alice),
|
||||
role: Role::Authority(key),
|
||||
};
|
||||
let client = ClientBuilder::new()
|
||||
.set_client(SubxtClient::new(config).expect("Error creating subxt client"))
|
||||
@@ -492,6 +533,34 @@ mod tests {
|
||||
(client, tmp)
|
||||
}
|
||||
|
||||
pub(crate) async fn test_client() -> (Client<TestRuntime>, TempDir) {
|
||||
test_client_with(AccountKeyring::Alice).await
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_insert_key() {
|
||||
// Bob is not an authority, so block production should be disabled.
|
||||
let (client, _tmp) = test_client_with(AccountKeyring::Bob).await;
|
||||
let mut blocks = client.subscribe_blocks().await.unwrap();
|
||||
// get the genesis block.
|
||||
assert_eq!(blocks.next().await.number, 0);
|
||||
let public = AccountKeyring::Alice.public().as_array_ref().to_vec();
|
||||
client
|
||||
.insert_key(
|
||||
"aura".to_string(),
|
||||
"//Alice".to_string(),
|
||||
public.clone().into(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(client
|
||||
.has_key(public.clone().into(), "aura".to_string())
|
||||
.await
|
||||
.unwrap());
|
||||
// Alice is an authority, so blocks should be produced.
|
||||
assert_eq!(blocks.next().await.number, 1);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_tx_transfer_balance() {
|
||||
let mut signer = PairSigner::new(AccountKeyring::Alice.pair());
|
||||
|
||||
+47
@@ -396,6 +396,53 @@ impl<T: Runtime> Rpc<T> {
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
/// Insert a key into the keystore.
|
||||
pub async fn insert_key(
|
||||
&self,
|
||||
key_type: String,
|
||||
suri: String,
|
||||
public: Bytes,
|
||||
) -> Result<(), Error> {
|
||||
let params = Params::Array(vec![
|
||||
to_json_value(key_type)?,
|
||||
to_json_value(suri)?,
|
||||
to_json_value(public)?,
|
||||
]);
|
||||
self.client.request("author_insertKey", params).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate new session keys and returns the corresponding public keys.
|
||||
pub async fn rotate_keys(&self) -> Result<Bytes, Error> {
|
||||
Ok(self
|
||||
.client
|
||||
.request("author_rotateKeys", Params::None)
|
||||
.await?)
|
||||
}
|
||||
|
||||
/// Checks if the keystore has private keys for the given session public keys.
|
||||
///
|
||||
/// `session_keys` is the SCALE encoded session keys object from the runtime.
|
||||
///
|
||||
/// Returns `true` iff all private keys could be found.
|
||||
pub async fn has_session_keys(&self, session_keys: Bytes) -> Result<bool, Error> {
|
||||
let params = Params::Array(vec![to_json_value(session_keys)?]);
|
||||
Ok(self.client.request("author_hasSessionKeys", params).await?)
|
||||
}
|
||||
|
||||
/// Checks if the keystore has private keys for the given public key and key type.
|
||||
///
|
||||
/// Returns `true` if a private key could be found.
|
||||
pub async fn has_key(
|
||||
&self,
|
||||
public_key: Bytes,
|
||||
key_type: String,
|
||||
) -> Result<bool, Error> {
|
||||
let params =
|
||||
Params::Array(vec![to_json_value(public_key)?, to_json_value(key_type)?]);
|
||||
Ok(self.client.request("author_hasKey", params).await?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Captures data for when an extrinsic is successfully included in a block
|
||||
|
||||
@@ -33,7 +33,6 @@ use crate::{
|
||||
|
||||
/// Event subscription simplifies filtering a storage change set stream for
|
||||
/// events of interest.
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct EventSubscription<T: Runtime> {
|
||||
subscription: Subscription<StorageChangeSet<T::Hash>>,
|
||||
decoder: EventsDecoder<T>,
|
||||
|
||||
@@ -13,7 +13,7 @@ repository = "https://github.com/paritytech/substrate/"
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
||||
[dependencies]
|
||||
futures = { version = "0.3.5", package = "futures" }
|
||||
futures = "0.3.5"
|
||||
log = "0.4.8"
|
||||
structopt = "0.3.15"
|
||||
parking_lot = "0.11.0"
|
||||
|
||||
@@ -235,8 +235,6 @@ impl system::Trait for Runtime {
|
||||
type OnKilledAccount = ();
|
||||
/// The data to be stored in an account.
|
||||
type AccountData = balances::AccountData<Balance>;
|
||||
/// The base call filter.
|
||||
type BaseCallFilter = ();
|
||||
}
|
||||
|
||||
impl aura::Trait for Runtime {
|
||||
|
||||
Reference in New Issue
Block a user