Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Event Subscription API #442

Merged
merged 27 commits into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
18b95a4
Add reworked event types
jsdw Feb 7, 2022
18482d8
first pass implementing event subscriptions
jsdw Feb 8, 2022
644b638
make clear that some methods are private
jsdw Feb 8, 2022
3443e6c
comment tidy
jsdw Feb 8, 2022
589d1a6
use Events in transaction stuff
jsdw Feb 8, 2022
8627117
align transaction and event APIs
jsdw Feb 9, 2022
9c409a6
remove __private_ prefixes; they are ugly
jsdw Feb 9, 2022
72e66a9
fix examples and remove old events and subscription code
jsdw Feb 9, 2022
1273c7e
better comments on hidden event functions
jsdw Feb 9, 2022
63a4e1a
re-add find_first_event; it's used a bunch in tests and examples
jsdw Feb 9, 2022
9ac234f
cargo check --all-targets now passes
jsdw Feb 9, 2022
9a40790
Fix up existing event tests
jsdw Feb 9, 2022
d9bc620
cargo fmt
jsdw Feb 9, 2022
457cd6e
change todo to note
jsdw Feb 9, 2022
b85acf1
clippy and doc niggles
jsdw Feb 9, 2022
9d99ddb
revert to find_first_event
jsdw Feb 9, 2022
ea71f74
Add specific subscription related tests
jsdw Feb 10, 2022
5b1ed7b
cargo fmt
jsdw Feb 10, 2022
221135c
Update tests and add/fix examples
jsdw Feb 10, 2022
4d0085d
cargo fmt
jsdw Feb 10, 2022
1d202b3
add a little to subscribe_all_events example
jsdw Feb 10, 2022
a74c8ed
cargo fmt
jsdw Feb 10, 2022
e20d171
move an example comment
jsdw Feb 11, 2022
aa96d8d
easy access to root mod for more clarity
jsdw Feb 11, 2022
18ca3be
add a couple of tests to ensure that events properly decoded until na…
jsdw Feb 11, 2022
4056f29
Simplify EventSubscription Stream impl a little
jsdw Feb 11, 2022
ef96407
Address some PR feedback
jsdw Feb 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codegen/src/api/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub fn generate_calls(
pub fn #fn_name(
&self,
#( #call_fn_args, )*
) -> ::subxt::SubmittableExtrinsic<'a, T, X, A, #call_struct_name, DispatchError> {
) -> ::subxt::SubmittableExtrinsic<'a, T, X, A, #call_struct_name, DispatchError, super::super::Event> {
ascjones marked this conversation as resolved.
Show resolved Hide resolved
let call = #call_struct_name { #( #call_args, )* };
::subxt::SubmittableExtrinsic::new(self.client, call)
}
Expand Down
25 changes: 23 additions & 2 deletions codegen/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,33 @@ impl RuntimeGenerator {
pub fn tx(&'a self) -> TransactionApi<'a, T, X, A> {
TransactionApi { client: &self.client, marker: ::core::marker::PhantomData }
}

pub fn events(&'a self) -> EventsApi<'a, T> {
EventsApi { client: &self.client }
}
}

pub struct EventsApi<'a, T: ::subxt::Config> {
client: &'a ::subxt::Client<T>,
}

impl <'a, T: ::subxt::Config> EventsApi<'a, T> {
pub async fn at(&self, block_hash: T::Hash) -> Result<::subxt::events::Events<'a, T, Event>, ::subxt::BasicError> {
::subxt::events::at::<T, Event>(self.client, block_hash).await
}

pub async fn subscribe(&self) -> Result<::subxt::events::EventSubscription<'a, T, Event>, ::subxt::BasicError> {
::subxt::events::subscribe::<T, Event>(self.client).await
}

pub async fn subscribe_finalized(&self) -> Result<::subxt::events::EventSubscription<'a, T, Event>, ::subxt::BasicError> {
::subxt::events::subscribe_finalized::<T, Event>(self.client).await
}
}

pub struct ConstantsApi;

impl ConstantsApi
{
impl ConstantsApi {
#(
pub fn #pallets_with_constants(&self) -> #pallets_with_constants::constants::ConstantsApi {
#pallets_with_constants::constants::ConstantsApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
//! ```

Expand Down
8 changes: 8 additions & 0 deletions examples/examples/custom_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions examples/examples/custom_type_derives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
generated_type_derives = "Clone, PartialEq"
)]
pub mod polkadot {}

Expand Down
4 changes: 2 additions & 2 deletions examples/examples/fetch_all_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
//! ```

Expand Down
Binary file modified examples/examples/polkadot_metadata.scale
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(())
Expand Down
13 changes: 6 additions & 7 deletions examples/examples/submit_and_watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
//! ```

Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -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");
Expand All @@ -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");
}
Expand Down
116 changes: 116 additions & 0 deletions examples/examples/subscribe_all_events.rs
Original file line number Diff line number Diff line change
@@ -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?;
dvdplm marked this conversation as resolved.
Show resolved Hide resolved

// 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?;
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
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:?}:");
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
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(())
}
Loading