diff --git a/src/extrinsic/balances.rs b/src/extrinsic/balances.rs index 709a9d816..ebb4a2c57 100644 --- a/src/extrinsic/balances.rs +++ b/src/extrinsic/balances.rs @@ -30,11 +30,15 @@ use codec::{Compact, Encode}; pub const BALANCES_MODULE: &str = "Balances"; pub const TRANSFER_ALLOW_DEATH: &str = "transfer_allow_death"; +pub const TRANSFER_KEEP_ALIVE: &str = "transfer_keep_alive"; pub const FORCE_SET_BALANCE: &str = "force_set_balance"; /// Call for a balance transfer. pub type TransferAllowDeathCall = (CallIndex, Address, Compact); +/// Call for a balance transfer. +pub type TransferKeepAliveCall = (CallIndex, Address, Compact); + /// Call to the balance of an account. pub type ForceSetBalanceCall = (CallIndex, Address, Compact); @@ -52,6 +56,14 @@ pub trait BalancesExtrinsics { amount: Self::Balance, ) -> Option>>; + /// Transfer some liquid free balance to another account. + #[allow(clippy::type_complexity)] + async fn balance_transfer_keep_alive( + &self, + to: Self::Address, + amount: Self::Balance, + ) -> Option>>; + /// Set the balances of a given account. #[allow(clippy::type_complexity)] async fn balance_force_set_balance( @@ -85,6 +97,15 @@ where compose_extrinsic!(self, BALANCES_MODULE, TRANSFER_ALLOW_DEATH, to, Compact(amount)) } + #[allow(clippy::type_complexity)] + async fn balance_transfer_keep_alive( + &self, + to: Self::Address, + amount: Self::Balance, + ) -> Option>> { + compose_extrinsic!(self, BALANCES_MODULE, TRANSFER_KEEP_ALIVE, to, Compact(amount)) + } + async fn balance_force_set_balance( &self, who: Self::Address, diff --git a/testing/async/examples/dispatch_errors_tests.rs b/testing/async/examples/dispatch_errors_tests.rs index 0ebc516b7..c1ab12e88 100644 --- a/testing/async/examples/dispatch_errors_tests.rs +++ b/testing/async/examples/dispatch_errors_tests.rs @@ -20,7 +20,7 @@ use sp_keyring::AccountKeyring; use sp_runtime::MultiAddress; use substrate_api_client::{ ac_primitives::AssetRuntimeConfig, extrinsic::BalancesExtrinsics, rpc::JsonrpseeClient, Api, - Error, GetAccountInformation, SubmitAndWatch, XtStatus, + Error, GetAccountInformation, GetBalance, SubmitAndWatch, XtStatus, }; #[tokio::main] @@ -59,10 +59,10 @@ async fn main() { assert!(report.block_hash.is_some()); assert!(report.events.is_some()); assert!(format!("{dispatch_error:?}").contains("BadOrigin")); + println!("[+] BadOrigin error: Bob can't force set balance"); }, _ => panic!("Expected Failed Extrinisc Error"), } - println!("[+] BadOrigin error: Bob can't force set balance"); //BelowMinimum api.set_signer(alice_signer.into()); @@ -80,5 +80,9 @@ async fn main() { }, _ => panic!("Expected Failed Extrinisc Error"), } - println!("[+] BelowMinimum error: balance (999999) is below the existential deposit"); + let existential_deposit = api.get_existential_deposit().await.unwrap(); + println!( + "[+] BelowMinimum error: balance (999999) is below the existential deposit ({})", + &existential_deposit + ); } diff --git a/testing/async/examples/pallet_balances_tests.rs b/testing/async/examples/pallet_balances_tests.rs index 0eae6abca..cfb6b1039 100644 --- a/testing/async/examples/pallet_balances_tests.rs +++ b/testing/async/examples/pallet_balances_tests.rs @@ -15,15 +15,52 @@ //! Tests for the pallet balances interface functions. +use sp_core::H256; +use sp_keyring::AccountKeyring; +use sp_runtime::MultiAddress; use substrate_api_client::{ - ac_primitives::AssetRuntimeConfig, rpc::JsonrpseeClient, Api, GetBalance, + ac_primitives::AssetRuntimeConfig, extrinsic::BalancesExtrinsics, rpc::JsonrpseeClient, Api, + Error, GetAccountInformation, GetBalance, SubmitAndWatch, XtStatus, }; #[tokio::main] async fn main() { // Setup let client = JsonrpseeClient::with_default_url().await.unwrap(); - let api = Api::::new(client).await.unwrap(); + let mut api = Api::::new(client).await.unwrap(); let _ed = api.get_existential_deposit().await.unwrap(); + + let alice_signer = AccountKeyring::Alice.pair(); + + let alice = AccountKeyring::Alice.to_account_id(); + let balance_of_alice = api.get_account_data(&alice).await.unwrap().unwrap().free; + println!("[+] Alice's Free Balance is is {}\n", balance_of_alice); + + let one = AccountKeyring::One.to_account_id(); + + //BadOrigin + api.set_signer(alice_signer.into()); + //Can only be called by root + let xt = api + .balance_force_set_balance(MultiAddress::Id(alice.clone()), 100000000000000000) + .await + .unwrap(); + + let result = api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock).await; + match result { + Err(Error::FailedExtrinsic(extrinsic_error)) => { + let dispatch_error = extrinsic_error.dispatch_error(); + let report = extrinsic_error.get_report::().unwrap(); + assert!(report.block_hash.is_some()); + assert!(report.events.is_some()); + assert!(format!("{dispatch_error:?}").contains("BadOrigin")); + println!("{dispatch_error:?}"); + println!("[+] BadOrigin error: Bob can't force set balance"); + }, + _ => panic!("Expected Failed Extrinisc Error"), + } + + let balance_of_one = api.get_account_data(&one).await.unwrap().unwrap_or_default().free; + println!("[+] One's Free Balance is {}\n", balance_of_one); }