From 122d6c9904bee9b77e5fabf6d2d1caa97acfad0c Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 11 Jul 2023 08:50:08 +0200 Subject: [PATCH 01/13] update author tests --- testing/examples/author_tests.rs | 49 ++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/testing/examples/author_tests.rs b/testing/examples/author_tests.rs index 878b817f8..bfa1c3d9f 100644 --- a/testing/examples/author_tests.rs +++ b/testing/examples/author_tests.rs @@ -63,8 +63,7 @@ async fn main() { println!("Success: submit_and_watch_extrinsic"); }); - // Test different _watch_untils. - + // Test different _watch_untils with events thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. let xt2 = api.balance_transfer_allow_death(bob.clone(), 1000); let report = api.submit_and_watch_extrinsic_until(xt2, XtStatus::Ready).unwrap(); @@ -74,46 +73,52 @@ async fn main() { thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. let xt3 = api.balance_transfer_allow_death(bob.clone(), 1000); + let report = api.submit_and_watch_extrinsic_until(xt3, XtStatus::Broadcast).unwrap(); // The xt is not broadcast - we only have one node running. Therefore, InBlock is returned. - let _some_hash = api - .submit_and_watch_extrinsic_until_without_events(xt3, XtStatus::Broadcast) - .unwrap() - .block_hash - .unwrap(); - println!("Success: submit_and_watch_extrinsic_until_without_events Broadcast"); + assert!(report.block_hash.is_some()); + // But we still don't fetch events, since we originally only waited for Broadcast. + assert!(report.events.is_none()); + println!("Success: submit_and_watch_extrinsic_until Broadcast"); let api2 = api.clone(); thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. let xt4 = api2.balance_transfer_allow_death(bob.clone(), 1000); let until_in_block_handle = thread::spawn(move || { - let _block_hash = api2 - .submit_and_watch_extrinsic_until_without_events(xt4, XtStatus::InBlock) - .unwrap() - .block_hash - .unwrap(); - println!("Success: submit_and_watch_extrinsic_until_without_events InBlock"); + let report = api2.submit_and_watch_extrinsic_until(xt4, XtStatus::InBlock).unwrap(); + assert!(report.block_hash.is_some()); + assert_assosciated_events_match_expected(report.events.unwrap()); + println!("Success: submit_and_watch_extrinsic_until InBlock"); }); let api3 = api.clone(); thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. let xt5 = api.balance_transfer_allow_death(bob.clone(), 1000); let until_finalized_handle = thread::spawn(move || { - let _block_hash = api3 - .submit_and_watch_extrinsic_until_without_events(xt5, XtStatus::Finalized) + let report = api3 + .submit_and_watch_extrinsic_until(xt5, XtStatus::Finalized) .unwrap() .block_hash .unwrap(); - println!("Success: submit_and_watch_extrinsic_until_without_events Finalized"); + assert!(report.block_hash.is_some()); + assert_assosciated_events_match_expected(report.events.unwrap()); + println!("Success: submit_and_watch_extrinsic_until Finalized"); }); - // Test Success. + // Test some _watch_untils_without_events. One is enough, because it is test implicitly by `submit_and_watch_extrinsic_until` + // as internal call. thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. let xt6 = api.balance_transfer_allow_death(bob, 1000); + let report = api + .submit_and_watch_extrinsic_until_without_events(xt6, XtStatus::Ready) + .unwrap(); + assert!(report.block_hash.is_none()); + assert!(report.events.is_none()); + println!("Success: submit_and_watch_extrinsic_until_without_events Ready!"); - let events = api - .submit_and_watch_extrinsic_until(xt6, XtStatus::InBlock) - .unwrap() - .events + thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. + let xt7 = api.balance_transfer_allow_death(bob, 1000); + let report = api + .submit_and_watch_extrinsic_until_without_events(xt7, XtStatus::InBlock) .unwrap(); println!("Extrinsic got successfully included in Block!"); assert_associated_events_match_expected(events); From 81633880805340d9bcf228c4d0ad6b04ddb931d8 Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 11 Jul 2023 08:50:28 +0200 Subject: [PATCH 02/13] fix comment --- src/api/rpc_api/author.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/rpc_api/author.rs b/src/api/rpc_api/author.rs index 75c53ac87..14515db49 100644 --- a/src/api/rpc_api/author.rs +++ b/src/api/rpc_api/author.rs @@ -321,7 +321,8 @@ where let block_hash = report.block_hash.ok_or(Error::BlockHashNotFound)?; let extrinsic_events = self.fetch_events_for_extrinsic(block_hash, report.extrinsic_hash).await?; - // Ensure that the extrins has been successful. If not, return an error. + + // Ensure that the extrinsic has been successful. If not, return an error. for event in &extrinsic_events { event.check_if_failed()?; } From f4da3ec4c5da0fdd02c0291ab83fa59c157264e4 Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 11 Jul 2023 08:50:36 +0200 Subject: [PATCH 03/13] use submit_and_watch_extrinsic_until instead of without_events in examples --- examples/examples/compose_extrinsic_offline.rs | 2 +- examples/examples/contract_instantiate_with_code.rs | 4 +--- examples/examples/custom_nonce.rs | 2 +- examples/examples/get_account_identity.rs | 2 +- examples/examples/staking_batch_payout.rs | 4 +--- examples/examples/sudo.rs | 2 +- examples/examples/transfer_with_tungstenite_client.rs | 2 +- examples/examples/transfer_with_ws_client.rs | 2 +- 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/examples/examples/compose_extrinsic_offline.rs b/examples/examples/compose_extrinsic_offline.rs index cb206d42a..ea9a7b047 100644 --- a/examples/examples/compose_extrinsic_offline.rs +++ b/examples/examples/compose_extrinsic_offline.rs @@ -66,7 +66,7 @@ async fn main() { // Send and watch extrinsic until in block (online). let block_hash = api - .submit_and_watch_extrinsic_until_without_events(xt, XtStatus::InBlock) + .submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) .unwrap() .block_hash .unwrap(); diff --git a/examples/examples/contract_instantiate_with_code.rs b/examples/examples/contract_instantiate_with_code.rs index 1f2759f61..fe79851ae 100644 --- a/examples/examples/contract_instantiate_with_code.rs +++ b/examples/examples/contract_instantiate_with_code.rs @@ -89,8 +89,6 @@ async fn main() { let xt = api.contract_call(contract.into(), 500_000, 500_000, vec![0u8]); println!("[+] Calling the contract with extrinsic Extrinsic:\n{:?}\n\n", xt); - let report = api - .submit_and_watch_extrinsic_until_without_events(xt, XtStatus::Finalized) - .unwrap(); + let report = api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); println!("[+] Extrinsic got finalized. Extrinsic Hash: {:?}", report.extrinsic_hash); } diff --git a/examples/examples/custom_nonce.rs b/examples/examples/custom_nonce.rs index d07395fd0..6dbd4f5f5 100644 --- a/examples/examples/custom_nonce.rs +++ b/examples/examples/custom_nonce.rs @@ -61,7 +61,7 @@ async fn main() { println!("[+] Composed Extrinsic:\n {:?}\n", xt); // Send and watch extrinsic until InBlock. - let result = api.submit_and_watch_extrinsic_until_without_events(xt, XtStatus::InBlock); + let result = api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock); println!("Returned Result {:?}", result); match result { Err(Error::UnexpectedTxStatus(UnexpectedTxStatus::Future)) => { diff --git a/examples/examples/get_account_identity.rs b/examples/examples/get_account_identity.rs index 14778a783..aada0d62d 100644 --- a/examples/examples/get_account_identity.rs +++ b/examples/examples/get_account_identity.rs @@ -65,7 +65,7 @@ async fn main() { // Send and watch extrinsic until InBlock. let _block_hash = api - .submit_and_watch_extrinsic_until_without_events(xt, XtStatus::InBlock) + .submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) .unwrap() .block_hash .unwrap(); diff --git a/examples/examples/staking_batch_payout.rs b/examples/examples/staking_batch_payout.rs index fbd196a0a..995843855 100644 --- a/examples/examples/staking_batch_payout.rs +++ b/examples/examples/staking_batch_payout.rs @@ -130,9 +130,7 @@ async fn main() { num_of_unclaimed_payouts -= tx_limit_in_current_batch; let batch_xt = api.batch(payout_calls); - let report = api - .submit_and_watch_extrinsic_until_without_events(batch_xt, XtStatus::InBlock) - .unwrap(); + let report = api.submit_and_watch_extrinsic_until(batch_xt, XtStatus::InBlock).unwrap(); results.push(format!("{report:?}")); } println!("{:?}", results); diff --git a/examples/examples/sudo.rs b/examples/examples/sudo.rs index b947435f9..60ade6121 100644 --- a/examples/examples/sudo.rs +++ b/examples/examples/sudo.rs @@ -75,7 +75,7 @@ async fn main() { // Send and watch extrinsic until in block. let block_hash = api - .submit_and_watch_extrinsic_until_without_events(xt, XtStatus::InBlock) + .submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) .unwrap() .block_hash .unwrap(); diff --git a/examples/examples/transfer_with_tungstenite_client.rs b/examples/examples/transfer_with_tungstenite_client.rs index 198e88f05..f50a3ea1b 100755 --- a/examples/examples/transfer_with_tungstenite_client.rs +++ b/examples/examples/transfer_with_tungstenite_client.rs @@ -64,7 +64,7 @@ fn main() { // Send and watch extrinsic until in block. let block_hash = api - .submit_and_watch_extrinsic_until_without_events(xt, XtStatus::InBlock) + .submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) .unwrap() .block_hash .unwrap(); diff --git a/examples/examples/transfer_with_ws_client.rs b/examples/examples/transfer_with_ws_client.rs index f15988ebe..d418e87e0 100755 --- a/examples/examples/transfer_with_ws_client.rs +++ b/examples/examples/transfer_with_ws_client.rs @@ -63,7 +63,7 @@ fn main() { // Send and watch extrinsic until in block. let block_hash = api - .submit_and_watch_extrinsic_until_without_events(xt, XtStatus::InBlock) + .submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) .unwrap() .block_hash .unwrap(); From cc6677999eddd8b7c44e1b9b22c62b950e08bfc6 Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 11 Jul 2023 09:15:12 +0200 Subject: [PATCH 04/13] add Txstatus --- testing/examples/author_tests.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/testing/examples/author_tests.rs b/testing/examples/author_tests.rs index bfa1c3d9f..8e4dbba5f 100644 --- a/testing/examples/author_tests.rs +++ b/testing/examples/author_tests.rs @@ -68,6 +68,7 @@ async fn main() { let xt2 = api.balance_transfer_allow_death(bob.clone(), 1000); let report = api.submit_and_watch_extrinsic_until(xt2, XtStatus::Ready).unwrap(); assert!(report.block_hash.is_none()); + assert!(matches!(report.status, TransactionStatus::Ready)); assert!(report.events.is_none()); println!("Success: submit_and_watch_extrinsic_until Ready"); @@ -76,6 +77,7 @@ async fn main() { let report = api.submit_and_watch_extrinsic_until(xt3, XtStatus::Broadcast).unwrap(); // The xt is not broadcast - we only have one node running. Therefore, InBlock is returned. assert!(report.block_hash.is_some()); + assert!(matches!(report.status, TransactionStatus::InBlock(_))); // But we still don't fetch events, since we originally only waited for Broadcast. assert!(report.events.is_none()); println!("Success: submit_and_watch_extrinsic_until Broadcast"); @@ -86,6 +88,7 @@ async fn main() { let until_in_block_handle = thread::spawn(move || { let report = api2.submit_and_watch_extrinsic_until(xt4, XtStatus::InBlock).unwrap(); assert!(report.block_hash.is_some()); + assert!(matches!(report.status, TransactionStatus::InBlock(_))); assert_assosciated_events_match_expected(report.events.unwrap()); println!("Success: submit_and_watch_extrinsic_until InBlock"); }); @@ -94,12 +97,9 @@ async fn main() { thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. let xt5 = api.balance_transfer_allow_death(bob.clone(), 1000); let until_finalized_handle = thread::spawn(move || { - let report = api3 - .submit_and_watch_extrinsic_until(xt5, XtStatus::Finalized) - .unwrap() - .block_hash - .unwrap(); + let report = api3.submit_and_watch_extrinsic_until(xt5, XtStatus::Finalized).unwrap(); assert!(report.block_hash.is_some()); + assert!(matches!(report.status, TransactionStatus::Finalized(_))); assert_assosciated_events_match_expected(report.events.unwrap()); println!("Success: submit_and_watch_extrinsic_until Finalized"); }); From 98e4c4486b854d2d46125766439834ea208ce01a Mon Sep 17 00:00:00 2001 From: haerdib Date: Tue, 11 Jul 2023 09:19:26 +0200 Subject: [PATCH 05/13] add .clone --- testing/examples/author_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/examples/author_tests.rs b/testing/examples/author_tests.rs index 8e4dbba5f..5a821cda3 100644 --- a/testing/examples/author_tests.rs +++ b/testing/examples/author_tests.rs @@ -107,7 +107,7 @@ async fn main() { // Test some _watch_untils_without_events. One is enough, because it is test implicitly by `submit_and_watch_extrinsic_until` // as internal call. thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. - let xt6 = api.balance_transfer_allow_death(bob, 1000); + let xt6 = api.balance_transfer_allow_death(bob.clone(), 1000); let report = api .submit_and_watch_extrinsic_until_without_events(xt6, XtStatus::Ready) .unwrap(); From 4fe5840c7c992a5285c12020b33914db1dd6557d Mon Sep 17 00:00:00 2001 From: haerdib Date: Wed, 12 Jul 2023 16:30:47 +0200 Subject: [PATCH 06/13] update examples --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ed139b05..b84224d1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,13 +134,13 @@ jobs: benchmark_bulk_xt, compose_extrinsic_offline, custom_nonce, - event_callback, - event_error_details, + check_extrinsic_events, get_account_identity, get_blocks_async, get_storage, print_metadata, staking_batch_payout, + subscribe_events, sudo, transfer_with_tungstenite_client, transfer_with_ws_client, From 4a93237d1d4f5420ef6f44f4492611fc0d1571e8 Mon Sep 17 00:00:00 2001 From: haerdib Date: Wed, 12 Jul 2023 16:43:34 +0200 Subject: [PATCH 07/13] rename files --- examples/examples/check_extrinsic_events.rs | 140 ++++++++++++++++++ examples/examples/event_error_details.rs | 77 ---------- ...{event_callback.rs => subscribe_events.rs} | 0 3 files changed, 140 insertions(+), 77 deletions(-) create mode 100644 examples/examples/check_extrinsic_events.rs delete mode 100644 examples/examples/event_error_details.rs rename examples/examples/{event_callback.rs => subscribe_events.rs} (100%) diff --git a/examples/examples/check_extrinsic_events.rs b/examples/examples/check_extrinsic_events.rs new file mode 100644 index 000000000..3742fdee0 --- /dev/null +++ b/examples/examples/check_extrinsic_events.rs @@ -0,0 +1,140 @@ +/* + Copyright 2019 Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +use sp_keyring::AccountKeyring; +use substrate_api_client::{ + ac_node_api::EventDetails, + ac_primitives::{AssetRuntimeConfig, Config, ExtrinsicSigner}, + extrinsic::BalancesExtrinsics, + rpc::JsonrpseeClient, + Api, GetAccountInformation, SubmitAndWatch, TransactionStatus, XtStatus, +}; + +// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig +// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. + +type Hash = ::Hash; + +#[tokio::main] +async fn main() { + env_logger::init(); + + // Initialize api and set the signer (sender) that is used to sign the extrinsics. + let alice_signer = AccountKeyring::Alice.pair(); + let client = JsonrpseeClient::with_default_url().unwrap(); + let mut api = Api::::new(client).unwrap(); + api.set_signer(ExtrinsicSigner::::new(alice_signer)); + + let alice = AccountKeyring::Alice.to_account_id(); + let balance_of_alice = api.get_account_data(&alice).unwrap().unwrap().free; + println!("[+] Alice's Free Balance is {balance_of_alice}\n"); + + let bob = AccountKeyring::Bob.to_account_id(); + let balance_of_bob = api.get_account_data(&bob).unwrap().unwrap_or_default().free; + println!("[+] Bob's Free Balance is {balance_of_bob}\n"); + + // First we want to see the events of a failed extrinsic. + // So lets create an extrinsic that will not succeed: + // Alice tries so transfer all her balance, but that will not work, because + // she will not have enough balance left to pay the fees. + let bad_transfer_extrinsic = + api.balance_transfer_allow_death(bob.clone().into(), balance_of_alice); + println!("[+] Composed extrinsic: {bad_transfer_extrinsic:?}\n",); + + // Send and watch extrinsic until InBlock. + let result = api.submit_and_watch_extrinsic_until(bad_transfer_extrinsic, XtStatus::InBlock); + println!("[+] Sent the transfer extrinsic. Result {result:?}"); + + // Check if the transfer really has failed: + match result { + Ok(_report) => { + panic!("Exptected the call to fail."); + }, + Err(e) => { + println!("[+] Couldn't execute the extrinsic due to {e:?}\n"); + let string_error = format!("{e:?}"); + assert!(string_error.contains("FundsUnavailable")); + }, + }; + + // Verify that Bob's free Balance hasn't changed. + let new_balance_of_bob = api.get_account_data(&bob).unwrap().unwrap().free; + println!("[+] Bob's Free Balance is now {}\n", new_balance_of_bob); + assert_eq!(balance_of_bob, new_balance_of_bob); + + // Verify that Alice's free Balance decreased: paid fees. + let new_balance_of_alice = api.get_account_data(&alice).unwrap().unwrap().free; + println!("[+] Alice's Free Balance is now {}\n", new_balance_of_alice); + assert!(balance_of_alice > new_balance_of_alice); + + // Next, we send an extrinsic that should succeed: + let balance_to_transfer = 1000; + let good_transfer_extrinsic = + api.balance_transfer_allow_death(bob.clone().into(), balance_to_transfer); + // Send and watch extrinsic until InBlock. + let result = api.submit_and_watch_extrinsic_until(good_transfer_extrinsic, XtStatus::InBlock); + println!("[+] Sent the transfer extrinsic."); + + // Check if the transfer really was successful: + match result { + Ok(report) => { + let extrinsic_hash = report.extrinsic_hash; + let block_hash = report.block_hash.unwrap(); + let extrinsic_status = report.status; + let extrinsic_events = report.events.unwrap(); + + println!("[+] Extrinsic with hash {extrinsic_hash:?} was successfully executed.",); + println!("[+] Extrinsic got included in block with hash {block_hash:?}"); + println!("[+] Watched extrinsic until it reached the status {extrinsic_status:?}"); + println!("[+] The following events were thrown when the extrinsic was executed: {extrinsic_events:?}"); + + assert!(matches!(extrinsic_status, TransactionStatus::InBlock(_block_hash))); + assert_assosciated_events_match_expected(extrinsic_events); + }, + Err(e) => { + panic!("Expected the transfer to succeed. Instead, it failed due to {e:?}"); + }, + }; + + // Verify that Bob release has received the transferred amount. + let new_balance_of_bob = api.get_account_data(&bob).unwrap().unwrap().free; + println!("[+] Bob's Free Balance is now {}\n", new_balance_of_bob); + let expected_balance_of_bob = balance_of_bob + balance_to_transfer; + assert_eq!(expected_balance_of_bob, new_balance_of_bob); +} + +fn assert_assosciated_events_match_expected(events: Vec>) { + // First event + assert_eq!(events[0].pallet_name(), "Balances"); + assert_eq!(events[0].variant_name(), "Withdraw"); + + assert_eq!(events[1].pallet_name(), "Balances"); + assert_eq!(events[1].variant_name(), "Transfer"); + + assert_eq!(events[2].pallet_name(), "Balances"); + assert_eq!(events[2].variant_name(), "Deposit"); + + assert_eq!(events[3].pallet_name(), "Treasury"); + assert_eq!(events[3].variant_name(), "Deposit"); + + assert_eq!(events[4].pallet_name(), "Balances"); + assert_eq!(events[4].variant_name(), "Deposit"); + + assert_eq!(events[5].pallet_name(), "TransactionPayment"); + assert_eq!(events[5].variant_name(), "TransactionFeePaid"); + + assert_eq!(events[6].pallet_name(), "System"); + assert_eq!(events[6].variant_name(), "ExtrinsicSuccess"); +} diff --git a/examples/examples/event_error_details.rs b/examples/examples/event_error_details.rs deleted file mode 100644 index 062520d1f..000000000 --- a/examples/examples/event_error_details.rs +++ /dev/null @@ -1,77 +0,0 @@ -/* - Copyright 2019 Supercomputing Systems AG - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -use sp_keyring::AccountKeyring; -use sp_runtime::MultiAddress; -use substrate_api_client::{ - ac_primitives::{AssetRuntimeConfig, ExtrinsicSigner}, - extrinsic::BalancesExtrinsics, - rpc::JsonrpseeClient, - Api, GetAccountInformation, SubmitAndWatch, XtStatus, -}; - -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. - -#[tokio::main] -async fn main() { - env_logger::init(); - - // Initialize api and set the signer (sender) that is used to sign the extrinsics. - let alice_signer = AccountKeyring::Alice.pair(); - let client = JsonrpseeClient::with_default_url().unwrap(); - let mut api = Api::::new(client).unwrap(); - api.set_signer(ExtrinsicSigner::::new(alice_signer)); - - let alice = AccountKeyring::Alice.to_account_id(); - let balance_of_alice = api.get_account_data(&alice).unwrap().unwrap().free; - println!("[+] Alice's Free Balance is {}\n", balance_of_alice); - - let bob = AccountKeyring::Bob.to_account_id(); - let balance_of_bob = api.get_account_data(&bob).unwrap().unwrap_or_default().free; - println!("[+] Bob's Free Balance is {}\n", balance_of_bob); - - // Generate a transfer extrinsic. - let xt = api.balance_transfer_allow_death(MultiAddress::Id(bob.clone()), balance_of_alice); - println!("Sending an extrinsic from Alice (Key = {}),\n\nto Bob (Key = {})\n", alice, bob); - println!("[+] Composed extrinsic: {:?}\n", xt); - - // Send and watch extrinsic until InBlock. - let result = api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock); - println!("[+] Transaction got included into the TxPool."); - - // We expect the transfer to fail as Alice wants to transfer all her balance. - // Therefore, she will not have enough money to pay the fees. - match result { - Ok(_report) => { - panic!("Exptected the call to fail."); - }, - Err(e) => { - println!("[+] Couldn't execute the extrinsic due to {:?}\n", e); - let string_error = format!("{:?}", e); - assert!(string_error.contains("FundsUnavailable")); - }, - }; - - // Verify that Bob's free Balance hasn't changed. - let new_balance_of_bob = api.get_account_data(&bob).unwrap().unwrap().free; - println!("[+] Bob's Free Balance is now {}\n", new_balance_of_bob); - assert_eq!(balance_of_bob, new_balance_of_bob); - - // Verify that Alice's free Balance decreased: paid fees. - let new_balance_of_alice = api.get_account_data(&alice).unwrap().unwrap().free; - println!("[+] Alice's Free Balance is now {}\n", new_balance_of_alice); - assert!(balance_of_alice > new_balance_of_alice); -} diff --git a/examples/examples/event_callback.rs b/examples/examples/subscribe_events.rs similarity index 100% rename from examples/examples/event_callback.rs rename to examples/examples/subscribe_events.rs From bbc1954760c7081af22c01cfba5e7278de29a2e6 Mon Sep 17 00:00:00 2001 From: haerdib Date: Wed, 12 Jul 2023 16:50:27 +0200 Subject: [PATCH 08/13] fix file comments --- examples/examples/benchmark_bulk_xt.rs | 9 ++++----- examples/examples/check_extrinsic_events.rs | 6 ++++-- examples/examples/compose_extrinsic_offline.rs | 8 +++++--- examples/examples/contract_instantiate_with_code.rs | 6 ++++-- examples/examples/get_account_identity.rs | 6 ++++-- examples/examples/get_blocks_async.rs | 6 ++++-- examples/examples/get_storage.rs | 6 ++++-- examples/examples/print_metadata.rs | 6 ++++-- examples/examples/staking_batch_payout.rs | 6 ++++-- examples/examples/subscribe_events.rs | 6 ++++-- examples/examples/sudo.rs | 6 ++++-- examples/examples/transfer_with_tungstenite_client.rs | 6 ++++-- examples/examples/transfer_with_ws_client.rs | 6 ++++-- 13 files changed, 53 insertions(+), 30 deletions(-) diff --git a/examples/examples/benchmark_bulk_xt.rs b/examples/examples/benchmark_bulk_xt.rs index a48c3ec65..b42156566 100644 --- a/examples/examples/benchmark_bulk_xt.rs +++ b/examples/examples/benchmark_bulk_xt.rs @@ -15,9 +15,6 @@ //! This example floods the node with a series of transactions. -// run this against test node with -// > substrate-test-node --dev --execution native --ws-port 9979 -ltxpool=debug - use kitchensink_runtime::{AccountId, BalancesCall, RuntimeCall}; use sp_keyring::AccountKeyring; use substrate_api_client::{ @@ -26,8 +23,10 @@ use substrate_api_client::{ Api, SubmitExtrinsic, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. // Define an extrinsic signer type which sets the generic types of the `GenericExtrinsicSigner`. // This way, the types don't have to be reassigned with every usage of this type and makes diff --git a/examples/examples/check_extrinsic_events.rs b/examples/examples/check_extrinsic_events.rs index 3742fdee0..4c32a4dc9 100644 --- a/examples/examples/check_extrinsic_events.rs +++ b/examples/examples/check_extrinsic_events.rs @@ -22,8 +22,10 @@ use substrate_api_client::{ Api, GetAccountInformation, SubmitAndWatch, TransactionStatus, XtStatus, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. type Hash = ::Hash; diff --git a/examples/examples/compose_extrinsic_offline.rs b/examples/examples/compose_extrinsic_offline.rs index ea9a7b047..a69f3e795 100644 --- a/examples/examples/compose_extrinsic_offline.rs +++ b/examples/examples/compose_extrinsic_offline.rs @@ -14,7 +14,7 @@ */ //! This example shows how to use the compose_extrinsic_offline macro which generates an extrinsic -//! without asking the node for nonce and does not need to know the metadata +//! without asking the node for nonce and does not need to know the metadata. use kitchensink_runtime::{BalancesCall, RuntimeCall}; use sp_keyring::AccountKeyring; @@ -25,8 +25,10 @@ use substrate_api_client::{ Api, GetChainInfo, SubmitAndWatch, XtStatus, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. #[tokio::main] async fn main() { diff --git a/examples/examples/contract_instantiate_with_code.rs b/examples/examples/contract_instantiate_with_code.rs index fe79851ae..7f017ab33 100644 --- a/examples/examples/contract_instantiate_with_code.rs +++ b/examples/examples/contract_instantiate_with_code.rs @@ -24,8 +24,10 @@ use substrate_api_client::{ SubmitAndWatch, XtStatus, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. #[allow(unused)] #[derive(Decode)] diff --git a/examples/examples/get_account_identity.rs b/examples/examples/get_account_identity.rs index aada0d62d..0e6f9ca77 100644 --- a/examples/examples/get_account_identity.rs +++ b/examples/examples/get_account_identity.rs @@ -33,8 +33,10 @@ type BalanceOf = <::Currency as Currency< type MaxRegistrarsOf = ::MaxRegistrars; type MaxAdditionalFieldsOf = ::MaxAdditionalFields; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. #[tokio::main] async fn main() { diff --git a/examples/examples/get_blocks_async.rs b/examples/examples/get_blocks_async.rs index a2ab63d09..5ab46485c 100644 --- a/examples/examples/get_blocks_async.rs +++ b/examples/examples/get_blocks_async.rs @@ -30,8 +30,10 @@ async fn main() { println!("Please compile this example with `--no-default-features` for it to run properly.") } -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. #[cfg(not(feature = "sync-examples"))] #[tokio::main] diff --git a/examples/examples/get_storage.rs b/examples/examples/get_storage.rs index 1a3b19890..0cb715f0a 100644 --- a/examples/examples/get_storage.rs +++ b/examples/examples/get_storage.rs @@ -25,8 +25,10 @@ use substrate_api_client::{ Api, GetAccountInformation, GetStorage, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. type AccountInfo = GenericAccountInfo< ::Index, diff --git a/examples/examples/print_metadata.rs b/examples/examples/print_metadata.rs index 4c61b32f7..5362e7f0a 100644 --- a/examples/examples/print_metadata.rs +++ b/examples/examples/print_metadata.rs @@ -18,8 +18,10 @@ use substrate_api_client::{ac_primitives::AssetRuntimeConfig, rpc::JsonrpseeClient, Api}; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. #[tokio::main] async fn main() { diff --git a/examples/examples/staking_batch_payout.rs b/examples/examples/staking_batch_payout.rs index 995843855..e66c2787f 100644 --- a/examples/examples/staking_batch_payout.rs +++ b/examples/examples/staking_batch_payout.rs @@ -24,8 +24,10 @@ use substrate_api_client::{ const MAX_BATCHED_TRANSACTION: u32 = 9; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. pub type EraIndex = u32; diff --git a/examples/examples/subscribe_events.rs b/examples/examples/subscribe_events.rs index dc1bc5b74..c068fd635 100644 --- a/examples/examples/subscribe_events.rs +++ b/examples/examples/subscribe_events.rs @@ -26,8 +26,10 @@ use substrate_api_client::{ // Replace this crate by your own if you run a custom substrate node to get your custom events. use kitchensink_runtime::RuntimeEvent; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. #[tokio::main] async fn main() { diff --git a/examples/examples/sudo.rs b/examples/examples/sudo.rs index 60ade6121..850ec65f6 100644 --- a/examples/examples/sudo.rs +++ b/examples/examples/sudo.rs @@ -29,8 +29,10 @@ use substrate_api_client::{ Api, GetAccountInformation, SubmitAndWatch, XtStatus, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. // Define an extrinsic signer type which sets the generic types of the `GenericExtrinsicSigner`. // This way, the types don't have to be reassigned with every usage of this type and makes diff --git a/examples/examples/transfer_with_tungstenite_client.rs b/examples/examples/transfer_with_tungstenite_client.rs index f50a3ea1b..e60695190 100755 --- a/examples/examples/transfer_with_tungstenite_client.rs +++ b/examples/examples/transfer_with_tungstenite_client.rs @@ -27,8 +27,10 @@ use substrate_api_client::{ Api, GetAccountInformation, SubmitAndWatch, XtStatus, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. fn main() { env_logger::init(); diff --git a/examples/examples/transfer_with_ws_client.rs b/examples/examples/transfer_with_ws_client.rs index d418e87e0..14581bd07 100755 --- a/examples/examples/transfer_with_ws_client.rs +++ b/examples/examples/transfer_with_ws_client.rs @@ -27,8 +27,10 @@ use substrate_api_client::{ Api, GetAccountInformation, SubmitAndWatch, XtStatus, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. fn main() { env_logger::init(); From 35181d3d2a10004c3488686f8a17c0bf61600451 Mon Sep 17 00:00:00 2001 From: haerdib Date: Wed, 12 Jul 2023 16:51:01 +0200 Subject: [PATCH 09/13] also update custom_nonce --- examples/examples/custom_nonce.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/examples/custom_nonce.rs b/examples/examples/custom_nonce.rs index 6dbd4f5f5..546b80e73 100644 --- a/examples/examples/custom_nonce.rs +++ b/examples/examples/custom_nonce.rs @@ -25,8 +25,10 @@ use substrate_api_client::{ Api, Error, GetChainInfo, SubmitAndWatch, UnexpectedTxStatus, XtStatus, }; -// To test this example in CI, we run it against the Substrate kitchensink node. Therefore, we use the AssetRuntimeConfig. -// ! Careful: Most runtimes uses plain as tips, they need a polkadot config. +// To test this example with CI we run it against the Substrate kitchensink node, which uses the asset pallet. +// Therefore, we need to use the `AssetRuntimeConfig` in this example. +// ! However, most Substrate runtimes do not use the asset pallet at all. So if you run an example against your own node +// you most likely should use `DefaultRuntimeConfig` instead. #[tokio::main] async fn main() { From 1f899add2fdbbdadfc896e6e8e8ba5bc6278a95a Mon Sep 17 00:00:00 2001 From: haerdib Date: Mon, 24 Jul 2023 13:58:08 +0200 Subject: [PATCH 10/13] fix typos --- examples/examples/check_extrinsic_events.rs | 4 ++-- testing/examples/author_tests.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/examples/check_extrinsic_events.rs b/examples/examples/check_extrinsic_events.rs index 4c32a4dc9..6cb85ca3d 100644 --- a/examples/examples/check_extrinsic_events.rs +++ b/examples/examples/check_extrinsic_events.rs @@ -103,7 +103,7 @@ async fn main() { println!("[+] The following events were thrown when the extrinsic was executed: {extrinsic_events:?}"); assert!(matches!(extrinsic_status, TransactionStatus::InBlock(_block_hash))); - assert_assosciated_events_match_expected(extrinsic_events); + assert_associated_events_match_expected(extrinsic_events); }, Err(e) => { panic!("Expected the transfer to succeed. Instead, it failed due to {e:?}"); @@ -117,7 +117,7 @@ async fn main() { assert_eq!(expected_balance_of_bob, new_balance_of_bob); } -fn assert_assosciated_events_match_expected(events: Vec>) { +fn assert_associated_events_match_expected(events: Vec>) { // First event assert_eq!(events[0].pallet_name(), "Balances"); assert_eq!(events[0].variant_name(), "Withdraw"); diff --git a/testing/examples/author_tests.rs b/testing/examples/author_tests.rs index 5a821cda3..1848dad79 100644 --- a/testing/examples/author_tests.rs +++ b/testing/examples/author_tests.rs @@ -89,7 +89,7 @@ async fn main() { let report = api2.submit_and_watch_extrinsic_until(xt4, XtStatus::InBlock).unwrap(); assert!(report.block_hash.is_some()); assert!(matches!(report.status, TransactionStatus::InBlock(_))); - assert_assosciated_events_match_expected(report.events.unwrap()); + assert_associated_events_match_expected(report.events.unwrap()); println!("Success: submit_and_watch_extrinsic_until InBlock"); }); @@ -100,7 +100,7 @@ async fn main() { let report = api3.submit_and_watch_extrinsic_until(xt5, XtStatus::Finalized).unwrap(); assert!(report.block_hash.is_some()); assert!(matches!(report.status, TransactionStatus::Finalized(_))); - assert_assosciated_events_match_expected(report.events.unwrap()); + assert_associated_events_match_expected(report.events.unwrap()); println!("Success: submit_and_watch_extrinsic_until Finalized"); }); From 408aee33041918e8e136893615e304a21a0d70d1 Mon Sep 17 00:00:00 2001 From: haerdib Date: Mon, 24 Jul 2023 14:17:04 +0200 Subject: [PATCH 11/13] fix tests --- testing/examples/author_tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/examples/author_tests.rs b/testing/examples/author_tests.rs index 1848dad79..f4f81191c 100644 --- a/testing/examples/author_tests.rs +++ b/testing/examples/author_tests.rs @@ -121,7 +121,6 @@ async fn main() { .submit_and_watch_extrinsic_until_without_events(xt7, XtStatus::InBlock) .unwrap(); println!("Extrinsic got successfully included in Block!"); - assert_associated_events_match_expected(events); watch_handle.join().unwrap(); until_in_block_handle.join().unwrap(); From c8f2b5d32d98870d04c519e73a8daa082b7c40bd Mon Sep 17 00:00:00 2001 From: haerdib Date: Mon, 24 Jul 2023 14:17:46 +0200 Subject: [PATCH 12/13] add some tests --- testing/examples/author_tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testing/examples/author_tests.rs b/testing/examples/author_tests.rs index f4f81191c..ea0eb2bbb 100644 --- a/testing/examples/author_tests.rs +++ b/testing/examples/author_tests.rs @@ -121,6 +121,8 @@ async fn main() { .submit_and_watch_extrinsic_until_without_events(xt7, XtStatus::InBlock) .unwrap(); println!("Extrinsic got successfully included in Block!"); + assert!(report.block_hash.is_some()); + assert!(report.events.is_none()); watch_handle.join().unwrap(); until_in_block_handle.join().unwrap(); From 208cf2dd35cfbfef549f8d24f61122fdfe5a2045 Mon Sep 17 00:00:00 2001 From: haerdib Date: Mon, 24 Jul 2023 14:18:19 +0200 Subject: [PATCH 13/13] fix typo --- testing/examples/author_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/examples/author_tests.rs b/testing/examples/author_tests.rs index ea0eb2bbb..0b9ac7868 100644 --- a/testing/examples/author_tests.rs +++ b/testing/examples/author_tests.rs @@ -104,7 +104,7 @@ async fn main() { println!("Success: submit_and_watch_extrinsic_until Finalized"); }); - // Test some _watch_untils_without_events. One is enough, because it is test implicitly by `submit_and_watch_extrinsic_until` + // Test some _watch_untils_without_events. One is enough, because it is tested implicitly by `submit_and_watch_extrinsic_until` // as internal call. thread::sleep(Duration::from_secs(6)); // Wait a little to avoid transaction too low priority error. let xt6 = api.balance_transfer_allow_death(bob.clone(), 1000);