From 5daff3b1ebfab23f663ac952843bf6855369f5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Obrok?= Date: Fri, 23 Dec 2022 16:01:17 +0100 Subject: [PATCH 1/6] Restore contract event listening --- aleph-client/Cargo.lock | 30 +++++-- aleph-client/Cargo.toml | 2 +- aleph-client/src/contract/event.rs | 133 +++++++++++++++++++++++++++++ aleph-client/src/contract/mod.rs | 1 + e2e-tests/Cargo.lock | 38 +++++++-- e2e-tests/src/test/adder.rs | 36 ++++++-- 6 files changed, 219 insertions(+), 21 deletions(-) create mode 100644 aleph-client/src/contract/event.rs diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index 33dfcb4bbf..7c49889f67 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -53,7 +53,7 @@ version = "2.5.0" dependencies = [ "anyhow", "async-trait", - "contract-metadata", + "contract-metadata 2.0.0-beta.1", "contract-transcode", "frame-support", "futures", @@ -362,8 +362,21 @@ checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" [[package]] name = "contract-metadata" version = "2.0.0-beta" +source = "git+https://github.com/obrok/cargo-contract?branch=send-sync-env-types#c0ade59847f09ef558c8bca0dc2cf8f78b031188" +dependencies = [ + "anyhow", + "impl-serde", + "semver", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "contract-metadata" +version = "2.0.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40248c6a648b3679ea52bb83d8921246d0347644eaf7b0eec4c5601fa8feb651" +checksum = "7bff7703529b16e9d8ba0d54e842b2051691772a822eb9bc130a91183ff9f6a6" dependencies = [ "anyhow", "impl-serde", @@ -376,11 +389,10 @@ dependencies = [ [[package]] name = "contract-transcode" version = "2.0.0-beta" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61159f8e266d4892be25f2b1e7ff2c4c6dd4338ca26498d907e5532a52a28e5f" +source = "git+https://github.com/obrok/cargo-contract?branch=send-sync-env-types#c0ade59847f09ef558c8bca0dc2cf8f78b031188" dependencies = [ "anyhow", - "contract-metadata", + "contract-metadata 2.0.0-beta", "env_logger", "escape8259", "hex", @@ -2578,18 +2590,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.148" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.148" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" dependencies = [ "proc-macro2", "quote", diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index e37a066193..2df927c43a 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -14,7 +14,7 @@ log = "0.4" serde_json = { version = "1.0" } thiserror = "1.0" contract-metadata = "2.0.0-beta" -contract-transcode = "2.0.0-beta" +contract-transcode = { git = "https://github.com/obrok/cargo-contract", branch = "send-sync-env-types" } ink_metadata = "4.0.0-beta" subxt = "0.25.0" futures = "0.3.25" diff --git a/aleph-client/src/contract/event.rs b/aleph-client/src/contract/event.rs new file mode 100644 index 0000000000..80e28e705e --- /dev/null +++ b/aleph-client/src/contract/event.rs @@ -0,0 +1,133 @@ +//! Utilities for listening for contract events. +//! +//! To use the module you will need to first create a subscription (a glorified `Receiver`), +//! then run the listen loop. You might want to run the loop in a separate thread. +//! +//! ```no_run +//! # use std::sync::Arc; +//! # use std::sync::mpsc::channel; +//! # use std::thread; +//! # use std::time::Duration; +//! # use aleph_client::{Connection, SignedConnection}; +//! # use aleph_client::contract::ContractInstance; +//! # use aleph_client::contract::event::{listen_contract_events, subscribe_events}; +//! # use anyhow::Result; +//! # use sp_core::crypto::AccountId32; +//! # fn example(conn: SignedConnection, address1: AccountId32, address2: AccountId32, path1: &str, path2: &str) -> Result<()> { +//! let subscription = subscribe_events(&conn)?; +//! +//! // The `Arc` makes it possible to pass a reference to the contract to another thread +//! let contract1 = Arc::new(ContractInstance::new(address1, path1)?); +//! let contract2 = Arc::new(ContractInstance::new(address2, path2)?); +//! let (cancel_tx, cancel_rx) = channel(); +//! +//! let contract1_copy = contract1.clone(); +//! let contract2_copy = contract2.clone(); +//! +//! thread::spawn(move || { +//! listen_contract_events( +//! subscription, +//! &[contract1_copy.as_ref(), &contract2_copy.as_ref()], +//! Some(cancel_rx), +//! |event_or_error| { println!("{:?}", event_or_error) } +//! ); +//! }); +//! +//! thread::sleep(Duration::from_secs(20)); +//! cancel_tx.send(()).unwrap(); +//! +//! contract1.contract_exec0(&conn, "some_method")?; +//! contract2.contract_exec0(&conn, "some_other_method")?; +//! +//! # Ok(()) +//! # } +//! ``` + +use std::collections::HashMap; + +use anyhow::{bail, Result}; +use contract_transcode::Value; +use futures::{channel::mpsc::UnboundedSender, StreamExt}; + +use crate::{contract::ContractInstance, AccountId, Connection}; + +/// Represents a single event emitted by a contract. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct ContractEvent { + /// The address of the contract that emitted the event. + pub contract: AccountId, + /// The name of the event. + pub ident: Option, + /// Data contained in the event. + pub data: HashMap, +} + +/// Starts an event listening loop. +/// +/// Will execute the handler for every contract event and every error encountered while fetching +/// from `subscription`. Only events coming from the address of one of the `contracts` will be +/// decoded. +/// +/// The loop will terminate once `subscription` is closed or once any message is received on +/// `cancel` (if provided). +pub async fn listen_contract_events( + conn: &Connection, + contracts: &[&ContractInstance], + sender: UnboundedSender>, +) -> Result<()> { + let mut block_subscription = conn.client.blocks().subscribe_finalized().await?; + + while let Some(block) = block_subscription.next().await { + if sender.is_closed() { + break; + } + + let block = block?; + + for event in block.events().await?.iter() { + let event = event?; + + if let Some(event) = + event.as_event::()? + { + if let Some(contract) = contracts + .iter() + .find(|contract| contract.address() == &event.contract) + { + let data = zero_prefixed(&event.data); + let event = contract + .transcoder + .decode_contract_event(&mut data.as_slice()); + + sender.unbounded_send(build_event(contract.address().clone(), event))?; + } + } + } + } + + Ok(()) +} + +/// The contract transcoder assumes there is an extra byte (that it discards) indicating the size of the data. However, +/// data arriving through the subscription as used in this file don't have this extra byte. This function adds it. +fn zero_prefixed(data: &[u8]) -> Vec { + let mut result = vec![0]; + result.extend_from_slice(data); + result +} + +fn build_event(address: AccountId, event_data: Result) -> Result { + let event_data = event_data?; + + match event_data { + Value::Map(map) => Ok(ContractEvent { + contract: address, + ident: map.ident(), + data: map + .iter() + .map(|(key, value)| (key.to_string(), value.clone())) + .collect(), + }), + _ => bail!("Contract event data is not a map"), + } +} diff --git a/aleph-client/src/contract/mod.rs b/aleph-client/src/contract/mod.rs index d40c662050..5f0404c3de 100644 --- a/aleph-client/src/contract/mod.rs +++ b/aleph-client/src/contract/mod.rs @@ -43,6 +43,7 @@ //! ``` mod convertible_value; +pub mod event; use std::fmt::{Debug, Formatter}; diff --git a/e2e-tests/Cargo.lock b/e2e-tests/Cargo.lock index 91ed27a6a8..19f2c30d6c 100644 --- a/e2e-tests/Cargo.lock +++ b/e2e-tests/Cargo.lock @@ -55,7 +55,7 @@ dependencies = [ "anyhow", "assert2", "clap", - "env_logger", + "env_logger 0.8.4", "frame-support", "frame-system", "futures", @@ -82,7 +82,7 @@ version = "2.5.0" dependencies = [ "anyhow", "async-trait", - "contract-metadata", + "contract-metadata 2.0.0-beta.1", "contract-transcode", "frame-support", "futures", @@ -459,6 +459,19 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" +[[package]] +name = "contract-metadata" +version = "2.0.0-beta" +source = "git+https://github.com/obrok/cargo-contract?branch=send-sync-env-types#c0ade59847f09ef558c8bca0dc2cf8f78b031188" +dependencies = [ + "anyhow", + "impl-serde", + "semver", + "serde", + "serde_json", + "url", +] + [[package]] name = "contract-metadata" version = "2.0.0-beta.1" @@ -475,12 +488,12 @@ dependencies = [ [[package]] name = "contract-transcode" -version = "2.0.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25e184ac4c29748e28c026f4c443fb94c002ad0877f0b190dccd624df8f893f" +version = "2.0.0-beta" +source = "git+https://github.com/obrok/cargo-contract?branch=send-sync-env-types#c0ade59847f09ef558c8bca0dc2cf8f78b031188" dependencies = [ "anyhow", - "contract-metadata", + "contract-metadata 2.0.0-beta", + "env_logger 0.9.3", "escape8259", "hex", "indexmap", @@ -875,6 +888,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "environmental" version = "1.1.4" diff --git a/e2e-tests/src/test/adder.rs b/e2e-tests/src/test/adder.rs index 3b32450795..a66a963fd9 100644 --- a/e2e-tests/src/test/adder.rs +++ b/e2e-tests/src/test/adder.rs @@ -1,8 +1,13 @@ -use std::str::FromStr; +use std::{fmt::Debug, str::FromStr, sync::Arc}; -use aleph_client::{contract::ContractInstance, AccountId, Connection, SignedConnection}; +use aleph_client::{ + contract::{event::listen_contract_events, ContractInstance}, + contract_transcode::Value, + AccountId, Connection, SignedConnection, +}; use anyhow::{Context, Result}; use assert2::assert; +use futures::{channel::mpsc::unbounded, StreamExt}; use crate::{config::setup_test, test::helpers::basic_test_context}; @@ -13,14 +18,31 @@ pub async fn adder() -> Result<()> { let config = setup_test(); let (conn, _authority, account) = basic_test_context(config).await?; - let contract = AdderInstance::new( + + let contract = Arc::new(AdderInstance::new( &config.test_case_params.adder, &config.test_case_params.adder_metadata, - )?; + )?); + + let listen_conn = conn.clone(); + let listen_contract = contract.clone(); + let (tx, mut rx) = unbounded(); + let listen = || async move { + listen_contract_events(&listen_conn, &[listen_contract.as_ref().into()], tx).await?; + >::Ok(()) + }; + let join = tokio::spawn(listen()); let increment = 10; let before = contract.get(&conn).await?; + contract.add(&account.sign(&conn), increment).await?; + + let event = rx.next().await.context("No event received")??; + assert!(event.ident == Some("ValueChanged".to_string())); + assert!(event.contract == *contract.contract.address()); + assert!(event.data["new_value"] == Value::UInt(before as u128 + 10)); + let after = contract.get(&conn).await?; assert!(after == before + increment); @@ -32,10 +54,14 @@ pub async fn adder() -> Result<()> { .await?; assert!(contract.get_name(&conn).await? == Some(new_name.to_string())); + rx.close(); + join.await??; + Ok(()) } -pub(super) struct AdderInstance { +#[derive(Debug)] +struct AdderInstance { contract: ContractInstance, } From e21d155d7f50ec2bd48b2655794699ab208ac3ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Obrok?= Date: Thu, 29 Dec 2022 16:02:33 +0100 Subject: [PATCH 2/6] Authenticate when installing protoc on CI This should reduce the number of failures caused by rate limiting. --- .github/workflows/build-and-push-cliain.yaml | 1 + .github/workflows/build-node-and-runtime.yml | 1 + .github/workflows/build-send-postsync-hook-runtime-image.yml | 1 + .github/workflows/check-excluded-packages.yml | 1 + .github/workflows/e2e-tests-main-devnet.yml | 4 ++++ .github/workflows/nightly-pipeline.yaml | 2 ++ .github/workflows/unit_tests.yml | 1 + 7 files changed, 11 insertions(+) diff --git a/.github/workflows/build-and-push-cliain.yaml b/.github/workflows/build-and-push-cliain.yaml index 32a2f983eb..2c46b098f1 100644 --- a/.github/workflows/build-and-push-cliain.yaml +++ b/.github/workflows/build-and-push-cliain.yaml @@ -21,6 +21,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Cargo | Build release binary run: | diff --git a/.github/workflows/build-node-and-runtime.yml b/.github/workflows/build-node-and-runtime.yml index 4c9d4597b1..43d0dde62f 100644 --- a/.github/workflows/build-node-and-runtime.yml +++ b/.github/workflows/build-node-and-runtime.yml @@ -37,6 +37,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown diff --git a/.github/workflows/build-send-postsync-hook-runtime-image.yml b/.github/workflows/build-send-postsync-hook-runtime-image.yml index e66e0093cf..dcc1ab2a67 100644 --- a/.github/workflows/build-send-postsync-hook-runtime-image.yml +++ b/.github/workflows/build-send-postsync-hook-runtime-image.yml @@ -37,6 +37,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Build binary run: | diff --git a/.github/workflows/check-excluded-packages.yml b/.github/workflows/check-excluded-packages.yml index 202fb804be..d241220bc7 100644 --- a/.github/workflows/check-excluded-packages.yml +++ b/.github/workflows/check-excluded-packages.yml @@ -31,6 +31,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Read excluded packages from Cargo.toml id: read_excluded diff --git a/.github/workflows/e2e-tests-main-devnet.yml b/.github/workflows/e2e-tests-main-devnet.yml index 839b64b956..08ed2180aa 100644 --- a/.github/workflows/e2e-tests-main-devnet.yml +++ b/.github/workflows/e2e-tests-main-devnet.yml @@ -69,6 +69,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Restore cache uses: ./.github/actions/restore-cache @@ -116,6 +117,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown @@ -154,6 +156,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Restore cache uses: ./.github/actions/restore-cache @@ -840,6 +843,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown diff --git a/.github/workflows/nightly-pipeline.yaml b/.github/workflows/nightly-pipeline.yaml index fe47743973..67d50d1ce9 100644 --- a/.github/workflows/nightly-pipeline.yaml +++ b/.github/workflows/nightly-pipeline.yaml @@ -60,6 +60,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown @@ -97,6 +98,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Restore cache uses: ./.github/actions/restore-cache diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 7e3431687a..96dfb90e8e 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -31,6 +31,7 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' + repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install clippy and fmt run: rustup component add clippy rustfmt From 9f9cdec7a98feaf13e33b616b9f40b2474f1f69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Obrok?= Date: Thu, 29 Dec 2022 16:04:08 +0100 Subject: [PATCH 3/6] Bump aleph-client version --- aleph-client/Cargo.lock | 2 +- aleph-client/Cargo.toml | 2 +- e2e-tests/Cargo.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index 7c49889f67..0b0abcf623 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -49,7 +49,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "2.5.0" +version = "2.6.0" dependencies = [ "anyhow", "async-trait", diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index 2df927c43a..6e4db36d36 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "aleph_client" # TODO bump major version when API stablize -version = "2.5.0" +version = "2.6.0" edition = "2021" license = "Apache 2.0" diff --git a/e2e-tests/Cargo.lock b/e2e-tests/Cargo.lock index 19f2c30d6c..d03153aed3 100644 --- a/e2e-tests/Cargo.lock +++ b/e2e-tests/Cargo.lock @@ -78,7 +78,7 @@ dependencies = [ [[package]] name = "aleph_client" -version = "2.5.0" +version = "2.6.0" dependencies = [ "anyhow", "async-trait", From 7a33ba523886ded8fa4c05d644859d904900ba22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Obrok?= Date: Thu, 29 Dec 2022 16:28:29 +0100 Subject: [PATCH 4/6] Update contract event docs --- aleph-client/Cargo.lock | 1 + aleph-client/Cargo.toml | 3 ++ aleph-client/src/contract/event.rs | 59 ++++++++++++++---------------- 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/aleph-client/Cargo.lock b/aleph-client/Cargo.lock index 0b0abcf623..f0ce7e0d9c 100644 --- a/aleph-client/Cargo.lock +++ b/aleph-client/Cargo.lock @@ -69,6 +69,7 @@ dependencies = [ "sp-runtime 6.0.0", "subxt", "thiserror", + "tokio", ] [[package]] diff --git a/aleph-client/Cargo.toml b/aleph-client/Cargo.toml index 6e4db36d36..7b6850dd1d 100644 --- a/aleph-client/Cargo.toml +++ b/aleph-client/Cargo.toml @@ -25,3 +25,6 @@ sp-core = { git = "https://github.com/Cardinal-Cryptography/substrate.git", bran sp-runtime = { git = "https://github.com/Cardinal-Cryptography/substrate.git", branch = "aleph-v0.9.32" } pallet-contracts-primitives = { git = "https://github.com/Cardinal-Cryptography/substrate.git", branch = "aleph-v0.9.32" } primitives = { path = "../primitives" } + +[dev-dependencies] +tokio = "1.21" diff --git a/aleph-client/src/contract/event.rs b/aleph-client/src/contract/event.rs index 80e28e705e..f87ecbca19 100644 --- a/aleph-client/src/contract/event.rs +++ b/aleph-client/src/contract/event.rs @@ -1,43 +1,42 @@ //! Utilities for listening for contract events. //! -//! To use the module you will need to first create a subscription (a glorified `Receiver`), -//! then run the listen loop. You might want to run the loop in a separate thread. +//! To use the module you will need to pass a connection, some contracts and an `UnboundedSender` to the +//! [listen_contract_events] function. You most likely want to `tokio::spawn` the resulting future, so that it runs +//! concurrently. //! //! ```no_run //! # use std::sync::Arc; //! # use std::sync::mpsc::channel; -//! # use std::thread; //! # use std::time::Duration; -//! # use aleph_client::{Connection, SignedConnection}; +//! # use aleph_client::{AccountId, Connection, SignedConnection}; //! # use aleph_client::contract::ContractInstance; -//! # use aleph_client::contract::event::{listen_contract_events, subscribe_events}; +//! # use aleph_client::contract::event::{listen_contract_events}; //! # use anyhow::Result; -//! # use sp_core::crypto::AccountId32; -//! # fn example(conn: SignedConnection, address1: AccountId32, address2: AccountId32, path1: &str, path2: &str) -> Result<()> { -//! let subscription = subscribe_events(&conn)?; +//! use futures::{channel::mpsc::unbounded, StreamExt}; //! -//! // The `Arc` makes it possible to pass a reference to the contract to another thread -//! let contract1 = Arc::new(ContractInstance::new(address1, path1)?); -//! let contract2 = Arc::new(ContractInstance::new(address2, path2)?); -//! let (cancel_tx, cancel_rx) = channel(); +//! # async fn example(conn: Connection, signed_conn: SignedConnection, address1: AccountId, address2: AccountId, path1: &str, path2: &str) -> Result<()> { +//! // The `Arc` makes it possible to pass a reference to the contract to another thread +//! let contract1 = Arc::new(ContractInstance::new(address1, path1)?); +//! let contract2 = Arc::new(ContractInstance::new(address2, path2)?); //! -//! let contract1_copy = contract1.clone(); -//! let contract2_copy = contract2.clone(); +//! let conn_copy = conn.clone(); +//! let contract1_copy = contract1.clone(); +//! let contract2_copy = contract2.clone(); //! -//! thread::spawn(move || { -//! listen_contract_events( -//! subscription, -//! &[contract1_copy.as_ref(), &contract2_copy.as_ref()], -//! Some(cancel_rx), -//! |event_or_error| { println!("{:?}", event_or_error) } -//! ); -//! }); +//! let (tx, mut rx) = unbounded(); +//! let listen = || async move { +//! listen_contract_events(&conn, &[contract1_copy.as_ref(), contract2_copy.as_ref()], tx).await?; +//! >::Ok(()) +//! }; +//! let join = tokio::spawn(listen()); //! -//! thread::sleep(Duration::from_secs(20)); -//! cancel_tx.send(()).unwrap(); +//! contract1.contract_exec0(&signed_conn, "some_method").await?; +//! contract2.contract_exec0(&signed_conn, "some_other_method").await?; //! -//! contract1.contract_exec0(&conn, "some_method")?; -//! contract2.contract_exec0(&conn, "some_other_method")?; +//! println!("Received event {:?}", rx.next().await); +//! +//! rx.close(); +//! join.await??; //! //! # Ok(()) //! # } @@ -64,12 +63,10 @@ pub struct ContractEvent { /// Starts an event listening loop. /// -/// Will execute the handler for every contract event and every error encountered while fetching -/// from `subscription`. Only events coming from the address of one of the `contracts` will be -/// decoded. +/// Will send contract event and every error encountered while fetching through the provided [UnboundedSender]. +/// Only events coming from the address of one of the `contracts` will be decoded. /// -/// The loop will terminate once `subscription` is closed or once any message is received on -/// `cancel` (if provided). +/// The loop will terminate once `sender` is closed. pub async fn listen_contract_events( conn: &Connection, contracts: &[&ContractInstance], From 971407f55e5c876c022f9c9680c7076829c825df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Obrok?= Date: Thu, 5 Jan 2023 13:02:46 +0100 Subject: [PATCH 5/6] Improve cosmetics --- aleph-client/src/contract/event.rs | 15 ++++++++------- e2e-tests/src/test/adder.rs | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/aleph-client/src/contract/event.rs b/aleph-client/src/contract/event.rs index f87ecbca19..e22893b32f 100644 --- a/aleph-client/src/contract/event.rs +++ b/aleph-client/src/contract/event.rs @@ -56,7 +56,7 @@ pub struct ContractEvent { /// The address of the contract that emitted the event. pub contract: AccountId, /// The name of the event. - pub ident: Option, + pub name: Option, /// Data contained in the event. pub data: HashMap, } @@ -66,7 +66,8 @@ pub struct ContractEvent { /// Will send contract event and every error encountered while fetching through the provided [UnboundedSender]. /// Only events coming from the address of one of the `contracts` will be decoded. /// -/// The loop will terminate once `sender` is closed. +/// The loop will terminate once `sender` is closed. The loop may also terminate in case of errors while fetching blocks +/// or decoding events (pallet events, contract event decoding errors are sent over the channel). pub async fn listen_contract_events( conn: &Connection, contracts: &[&ContractInstance], @@ -96,7 +97,9 @@ pub async fn listen_contract_events( .transcoder .decode_contract_event(&mut data.as_slice()); - sender.unbounded_send(build_event(contract.address().clone(), event))?; + sender.unbounded_send( + event.and_then(|event| build_event(contract.address().clone(), event)), + )?; } } } @@ -113,13 +116,11 @@ fn zero_prefixed(data: &[u8]) -> Vec { result } -fn build_event(address: AccountId, event_data: Result) -> Result { - let event_data = event_data?; - +fn build_event(address: AccountId, event_data: Value) -> Result { match event_data { Value::Map(map) => Ok(ContractEvent { contract: address, - ident: map.ident(), + name: map.ident(), data: map .iter() .map(|(key, value)| (key.to_string(), value.clone())) diff --git a/e2e-tests/src/test/adder.rs b/e2e-tests/src/test/adder.rs index a66a963fd9..37598693f7 100644 --- a/e2e-tests/src/test/adder.rs +++ b/e2e-tests/src/test/adder.rs @@ -39,7 +39,7 @@ pub async fn adder() -> Result<()> { contract.add(&account.sign(&conn), increment).await?; let event = rx.next().await.context("No event received")??; - assert!(event.ident == Some("ValueChanged".to_string())); + assert!(event.name == Some("ValueChanged".to_string())); assert!(event.contract == *contract.contract.address()); assert!(event.data["new_value"] == Value::UInt(before as u128 + 10)); From 9b0dfbf06c1592472b5533d0522ee288c29c441c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Obrok?= Date: Thu, 5 Jan 2023 13:18:53 +0100 Subject: [PATCH 6/6] This reverts commit e21d155d7f50ec2bd48b2655794699ab208ac3ee. --- .github/workflows/build-and-push-cliain.yaml | 1 - .github/workflows/build-node-and-runtime.yml | 1 - .github/workflows/build-send-postsync-hook-runtime-image.yml | 1 - .github/workflows/check-excluded-packages.yml | 1 - .github/workflows/e2e-tests-main-devnet.yml | 4 ---- .github/workflows/nightly-pipeline.yaml | 2 -- .github/workflows/unit_tests.yml | 1 - 7 files changed, 11 deletions(-) diff --git a/.github/workflows/build-and-push-cliain.yaml b/.github/workflows/build-and-push-cliain.yaml index 2c46b098f1..32a2f983eb 100644 --- a/.github/workflows/build-and-push-cliain.yaml +++ b/.github/workflows/build-and-push-cliain.yaml @@ -21,7 +21,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Cargo | Build release binary run: | diff --git a/.github/workflows/build-node-and-runtime.yml b/.github/workflows/build-node-and-runtime.yml index 43d0dde62f..4c9d4597b1 100644 --- a/.github/workflows/build-node-and-runtime.yml +++ b/.github/workflows/build-node-and-runtime.yml @@ -37,7 +37,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown diff --git a/.github/workflows/build-send-postsync-hook-runtime-image.yml b/.github/workflows/build-send-postsync-hook-runtime-image.yml index dcc1ab2a67..e66e0093cf 100644 --- a/.github/workflows/build-send-postsync-hook-runtime-image.yml +++ b/.github/workflows/build-send-postsync-hook-runtime-image.yml @@ -37,7 +37,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Build binary run: | diff --git a/.github/workflows/check-excluded-packages.yml b/.github/workflows/check-excluded-packages.yml index d241220bc7..202fb804be 100644 --- a/.github/workflows/check-excluded-packages.yml +++ b/.github/workflows/check-excluded-packages.yml @@ -31,7 +31,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Read excluded packages from Cargo.toml id: read_excluded diff --git a/.github/workflows/e2e-tests-main-devnet.yml b/.github/workflows/e2e-tests-main-devnet.yml index 08ed2180aa..839b64b956 100644 --- a/.github/workflows/e2e-tests-main-devnet.yml +++ b/.github/workflows/e2e-tests-main-devnet.yml @@ -69,7 +69,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Restore cache uses: ./.github/actions/restore-cache @@ -117,7 +116,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown @@ -156,7 +154,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Restore cache uses: ./.github/actions/restore-cache @@ -843,7 +840,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown diff --git a/.github/workflows/nightly-pipeline.yaml b/.github/workflows/nightly-pipeline.yaml index 67d50d1ce9..fe47743973 100644 --- a/.github/workflows/nightly-pipeline.yaml +++ b/.github/workflows/nightly-pipeline.yaml @@ -60,7 +60,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install WASM target run: rustup target add wasm32-unknown-unknown @@ -98,7 +97,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Restore cache uses: ./.github/actions/restore-cache diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index 96dfb90e8e..7e3431687a 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -31,7 +31,6 @@ jobs: uses: arduino/setup-protoc@v1 with: version: '3.6.1' - repo-token: ${{ secrets.CI_GH_TOKEN }} - name: Install clippy and fmt run: rustup component add clippy rustfmt