mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 19:21:13 +00:00
New Event Subscription API (#442)
* Add reworked event types * first pass implementing event subscriptions * make clear that some methods are private * comment tidy * use Events in transaction stuff * align transaction and event APIs * remove __private_ prefixes; they are ugly * fix examples and remove old events and subscription code * better comments on hidden event functions * re-add find_first_event; it's used a bunch in tests and examples * cargo check --all-targets now passes * Fix up existing event tests * cargo fmt * change todo to note * clippy and doc niggles * revert to find_first_event * Add specific subscription related tests * cargo fmt * Update tests and add/fix examples * cargo fmt * add a little to subscribe_all_events example * cargo fmt * move an example comment * easy access to root mod for more clarity * add a couple of tests to ensure that events properly decoded until naff bytes * Simplify EventSubscription Stream impl a little * Address some PR feedback
This commit is contained in:
+2
-2
@@ -14,11 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running.
|
||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.11/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.13/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
@@ -14,6 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.13/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
use sp_keyring::AccountKeyring;
|
||||
use subxt::{
|
||||
ClientBuilder,
|
||||
|
||||
@@ -14,13 +14,17 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
|
||||
#![allow(clippy::redundant_clone)]
|
||||
|
||||
#[subxt::subxt(
|
||||
runtime_metadata_path = "examples/polkadot_metadata.scale",
|
||||
// We can add (certain) custom derives to the generated types by providing
|
||||
// a comma separated list to the below attribute. Most useful for adding `Clone`:
|
||||
generated_type_derives = "Clone, Hash"
|
||||
// a comma separated list to the below attribute. Most useful for adding `Clone`.
|
||||
// The derives that we can add ultiamtely is limited to the traits that the base
|
||||
// types relied upon by the codegen implement.
|
||||
generated_type_derives = "Clone, PartialEq"
|
||||
)]
|
||||
pub mod polkadot {}
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running.
|
||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.11/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.13/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
|
||||
Binary file not shown.
@@ -14,6 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.13/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
use subxt::{
|
||||
ClientBuilder,
|
||||
DefaultConfig,
|
||||
@@ -42,9 +50,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.await?;
|
||||
|
||||
if let Some(hash) = block_hash {
|
||||
println!("Block hash for block number {}: {}", block_number, hash);
|
||||
println!("Block hash for block number {block_number}: {hash}");
|
||||
} else {
|
||||
println!("Block number {} not found.", block_number);
|
||||
println!("Block number {block_number} not found.");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -14,11 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running.
|
||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.11/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.13/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
@@ -70,7 +70,7 @@ async fn simple_transfer() -> Result<(), Box<dyn std::error::Error>> {
|
||||
balance_transfer.find_first_event::<polkadot::balances::events::Transfer>()?;
|
||||
|
||||
if let Some(event) = transfer_event {
|
||||
println!("Balance transfer success: value: {:?}", event.2);
|
||||
println!("Balance transfer success: {event:?}");
|
||||
} else {
|
||||
println!("Failed to find Balances::Transfer Event");
|
||||
}
|
||||
@@ -119,7 +119,7 @@ async fn simple_transfer_separate_events() -> Result<(), Box<dyn std::error::Err
|
||||
let transfer_event =
|
||||
events.find_first_event::<polkadot::balances::events::Transfer>()?;
|
||||
if let Some(event) = transfer_event {
|
||||
println!("Balance transfer success: value: {:?}", event.2);
|
||||
println!("Balance transfer success: {event:?}");
|
||||
} else {
|
||||
println!("Failed to find Balances::Transfer Event");
|
||||
}
|
||||
@@ -165,8 +165,7 @@ async fn handle_transfer_events() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
if let Some(event) = transfer_event {
|
||||
println!(
|
||||
"Balance transfer is now in block (but not finalized): value: {:?}",
|
||||
event.2
|
||||
"Balance transfer is now in block (but not finalized): {event:?}"
|
||||
);
|
||||
} else {
|
||||
println!("Failed to find Balances::Transfer Event");
|
||||
@@ -185,7 +184,7 @@ async fn handle_transfer_events() -> Result<(), Box<dyn std::error::Error>> {
|
||||
events.find_first_event::<polkadot::balances::events::Transfer>()?;
|
||||
|
||||
if let Some(event) = transfer_event {
|
||||
println!("Balance transfer success: value: {:?}", event.2);
|
||||
println!("Balance transfer success: {event:?}");
|
||||
} else {
|
||||
println!("Failed to find Balances::Transfer Event");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of 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 subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.13/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
use futures::StreamExt;
|
||||
use sp_keyring::AccountKeyring;
|
||||
use std::time::Duration;
|
||||
use subxt::{
|
||||
ClientBuilder,
|
||||
DefaultConfig,
|
||||
DefaultExtra,
|
||||
PairSigner,
|
||||
};
|
||||
|
||||
#[subxt::subxt(runtime_metadata_path = "examples/polkadot_metadata.scale")]
|
||||
pub mod polkadot {}
|
||||
|
||||
/// Subscribe to all events, and then manually look through them and
|
||||
/// pluck out the events that we care about.
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
env_logger::init();
|
||||
|
||||
let api = ClientBuilder::new()
|
||||
.build()
|
||||
.await?
|
||||
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();
|
||||
|
||||
// Subscribe to any events that occur:
|
||||
let mut event_sub = api.events().subscribe().await?;
|
||||
|
||||
// While this subscription is active, balance transfers are made somewhere:
|
||||
async_std::task::spawn(async {
|
||||
let signer = PairSigner::new(AccountKeyring::Alice.pair());
|
||||
let api = ClientBuilder::new()
|
||||
.build()
|
||||
.await
|
||||
.unwrap()
|
||||
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();
|
||||
|
||||
let mut transfer_amount = 1_000_000_000;
|
||||
|
||||
// Make small balance transfers from Alice to Bob in a loop:
|
||||
loop {
|
||||
api.tx()
|
||||
.balances()
|
||||
.transfer(AccountKeyring::Bob.to_account_id().into(), transfer_amount)
|
||||
.sign_and_submit(&signer)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
async_std::task::sleep(Duration::from_secs(10)).await;
|
||||
transfer_amount += 100_000_000;
|
||||
}
|
||||
});
|
||||
|
||||
// Our subscription will see the events emitted as a result of this:
|
||||
while let Some(events) = event_sub.next().await {
|
||||
let events = events?;
|
||||
let block_hash = events.block_hash();
|
||||
|
||||
// We can iterate, statically decoding all events if we want:
|
||||
println!("All events in block {block_hash:?}:");
|
||||
println!(" Static event details:");
|
||||
for event in events.iter() {
|
||||
let event = event?;
|
||||
println!(" {event:?}");
|
||||
}
|
||||
|
||||
// Or we can dynamically decode events:
|
||||
println!(" Dynamic event details: {block_hash:?}:");
|
||||
for event in events.iter_raw() {
|
||||
let event = event?;
|
||||
let is_balance_transfer = event
|
||||
.as_event::<polkadot::balances::events::Transfer>()?
|
||||
.is_some();
|
||||
let pallet = event.pallet;
|
||||
let variant = event.variant;
|
||||
println!(
|
||||
" {pallet}::{variant} (is balance transfer? {is_balance_transfer})"
|
||||
);
|
||||
}
|
||||
|
||||
// Or we can dynamically find the first transfer event, ignoring any others:
|
||||
let transfer_event =
|
||||
events.find_first_event::<polkadot::balances::events::Transfer>()?;
|
||||
|
||||
if let Some(ev) = transfer_event {
|
||||
println!(" - Balance transfer success: value: {:?}", ev.amount);
|
||||
} else {
|
||||
println!(" - No balance transfer event found in this block");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of 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 subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.13-82616422d0-aarch64-macos.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.13/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
use futures::{
|
||||
future,
|
||||
stream,
|
||||
StreamExt,
|
||||
};
|
||||
use sp_keyring::AccountKeyring;
|
||||
use std::time::Duration;
|
||||
use subxt::{
|
||||
ClientBuilder,
|
||||
DefaultConfig,
|
||||
DefaultExtra,
|
||||
PairSigner,
|
||||
};
|
||||
|
||||
#[subxt::subxt(runtime_metadata_path = "examples/polkadot_metadata.scale")]
|
||||
pub mod polkadot {}
|
||||
|
||||
/// Subscribe to all events, and then manually look through them and
|
||||
/// pluck out the events that we care about.
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
env_logger::init();
|
||||
|
||||
// Subscribe to any events that occur:
|
||||
let api = ClientBuilder::new()
|
||||
.build()
|
||||
.await?
|
||||
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();
|
||||
|
||||
// Subscribe to just balance transfer events, making use of `flat_map` and
|
||||
// `filter_map` from the StreamExt trait to filter everything else out.
|
||||
let mut transfer_events = api
|
||||
.events()
|
||||
.subscribe()
|
||||
.await?
|
||||
// Ignore errors returning events:
|
||||
.filter_map(|events| future::ready(events.ok()))
|
||||
// Map events to just the one we care about:
|
||||
.flat_map(|events| {
|
||||
let transfer_events = events
|
||||
.find::<polkadot::balances::events::Transfer>()
|
||||
.collect::<Vec<_>>();
|
||||
stream::iter(transfer_events)
|
||||
});
|
||||
|
||||
// While this subscription is active, we imagine some balance transfers are made somewhere else:
|
||||
async_std::task::spawn(async {
|
||||
let signer = PairSigner::new(AccountKeyring::Alice.pair());
|
||||
let api = ClientBuilder::new()
|
||||
.build()
|
||||
.await
|
||||
.unwrap()
|
||||
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();
|
||||
|
||||
// Make small balance transfers from Alice to Bob in a loop:
|
||||
loop {
|
||||
api.tx()
|
||||
.balances()
|
||||
.transfer(AccountKeyring::Bob.to_account_id().into(), 1_000_000_000)
|
||||
.sign_and_submit(&signer)
|
||||
.await
|
||||
.unwrap();
|
||||
async_std::task::sleep(Duration::from_secs(10)).await;
|
||||
}
|
||||
});
|
||||
|
||||
// Our subscription will see all of the transfer events emitted as a result of this:
|
||||
while let Some(transfer_event) = transfer_events.next().await {
|
||||
println!("Balance transfer event: {transfer_event:?}");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
|
||||
// This file is part of 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 subxt. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! To run this example, a local polkadot node should be running.
|
||||
//!
|
||||
//! E.g.
|
||||
//! ```bash
|
||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.11/polkadot" --output /usr/local/bin/polkadot --location
|
||||
//! polkadot --dev --tmp
|
||||
//! ```
|
||||
|
||||
use sp_keyring::AccountKeyring;
|
||||
use subxt::{
|
||||
ClientBuilder,
|
||||
DefaultConfig,
|
||||
DefaultExtra,
|
||||
EventSubscription,
|
||||
PairSigner,
|
||||
};
|
||||
|
||||
#[subxt::subxt(runtime_metadata_path = "examples/polkadot_metadata.scale")]
|
||||
pub mod polkadot {}
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
env_logger::init();
|
||||
|
||||
let signer = PairSigner::new(AccountKeyring::Alice.pair());
|
||||
let dest = AccountKeyring::Bob.to_account_id().into();
|
||||
|
||||
let api = ClientBuilder::new()
|
||||
.build()
|
||||
.await?
|
||||
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();
|
||||
|
||||
let sub = api.client.rpc().subscribe_events().await?;
|
||||
let decoder = api.client.events_decoder();
|
||||
let mut sub = EventSubscription::<DefaultConfig>::new(sub, decoder);
|
||||
sub.filter_event::<polkadot::balances::events::Transfer>();
|
||||
|
||||
api.tx()
|
||||
.balances()
|
||||
.transfer(dest, 10_000)
|
||||
.sign_and_submit(&signer)
|
||||
.await?;
|
||||
|
||||
let raw = sub.next().await.unwrap().unwrap();
|
||||
let event = <polkadot::balances::events::Transfer as subxt::codec::Decode>::decode(
|
||||
&mut &raw.data[..],
|
||||
);
|
||||
if let Ok(e) = event {
|
||||
println!("Balance transfer success: value: {:?}", e.2);
|
||||
} else {
|
||||
println!("Failed to subscribe to Balances::Transfer Event");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user