mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 10:31:04 +00:00
Generate runtime API from metadata (#294)
* Remove test macro * Remove client crate * Create tests crate and move pallet specific tests there * Extract client, remove metadata and extra, more demolition * Update substrate dependencies to git dependencies * Remove Store stuff for now * Comment out some Call usages * Add back Runtime trait coped from original System trait * Make subxt lib compile * Delete old proc macros and copy over type generation from chameleon * WIP make transfer balance test pass * Change to subxt attribute macro * WIP provide user defined type substitutes * User defined type substitutes compile * WIP submitting transactions * WIP transfer balance test * Fix macro * Cargo fmt * WIP generating storage hashers * WIP add AccountData trait for fetching the nonce * Support single type storage map keys * WIP impl AccountInfo retrieval * Fix up storage struct generation * Implement AccountData triait directly on storage entry * Borrow storage map key and convert account id * Implement storage fetch client methods * Remove legacy metadata storage key construction * Rename CheckEra to CheckMortality * Substitute perthings types for compact impls * Fmt * Downgrade dyn-clone for cargo-contract compat * Scale-fo 1.0 * scale-info 1.0 * Remove special range handling * Restore wildcard type params * Frame metadata 14.0 * WIP decoding events * WIP more dynamically decoding events * Fmt * Decode events, handle errors * Uncomment some tests * Remove unused get_mod function * Fix some warnings * Fix some more warnings * Fix some more warnings * Add tests mod * Rename node-runtime tests mod to frame * Fix some warnings * Fmt * WIP generate storage client with getters * Storage client compiling * Generate storage client api * Fix up system account query account ids * WIP generating tx api fns * Only generate tx api fields when calls available * Fix tx api call fns * Fmt * WIP generate event structs * call functions not async * Derive Eq for comparison on generated types * Generate event structs * Fix call name * Fmt * Update node runtime metadata to substrate c000780db * Download latest substrate release for integration testing * Fix event decoding * Remove unused imports * Fix plain storage access, total_issuance pass * Fmt * Restore contracts tests * Backoff connecting to substrate node * Add required TypeInfo impls for local SignedExtension impls * Remove unnecessary assert formatting * Fix handling of DispatchError * Refactor contracts tests * Troubleshooting contract not found * Remove more client feature stuff * Fix dynamic event variant decoding, write consumed index to output * Fmt * Use substrate branch with heavy dependency removed * Remove sp-rcp dependency, define types locally * Ignore cargo timeing files * Use my branch for substrate test deps * Fix storage key type gen * Comment out fetching contract info * Add key iteration, extract storage client from main client * Debugging key generation * Use substrate master branch * Fix call test * Remove TypeSegmenter and dynclone dependency * Publicly expose Rpc mod * Unused import warnings * Add getter for runtime metadata * Add pallet and event indices for raw events * Add is_call and is_event convenience trait functions * Add missing docs * Refactor tests crate * Restore remaining client tests * Fmt * Fix warnings * Restore get_mod as test helper and fmt * Use client references for api calls * Fix api usages with methods * Use Bytes for RawEvent debug * Update metadata * Restoring some Balances tests * Populate runtime storage metadata * Restore balances lock test * Restore Balances error test * Fmt * Restore transfer subscription API * Staking test * Restore another staking test * Restore another staking test * Restore another staking test * Partially restore chill_works_for_controller_only staking test * Fix fetching Optional storage entries * Restore staking bond test * Restore remaining staking tests * Fmt * Restore sudo tests * Add some system tests * Fmt * Resolve some todos * Remove pass through rpc methods on Client, expose via rpc() getter * Remove more rpc pass through methods * Remove submit tx pass through rpc methods * Add some comments to SubmittableExtrinsic methods * Construct the runtime api from the client * Fmt * Use From trait instead of new for AccountData query * Rename subxt_proc_macro crate to subxt_macro * Fix AccountData From impl * Extract codegen crate from macro crate * Fmt * Replace chameleon hidden field name * Extract StructDef for generating structs * More refactoring of StructDef, moving towards sharing with typegen * Replace explicit tests crate with single implicit integration tests crate * Rename from substrate-subxt to subxt * Fix runtime path relative to root Cargo.toml * Move RpcClient creation to RpcClient * WIP get examples to compile * Rename Runtime to Config trait * WIP implementing default Config * WIP implementing default extrinsic extras * fix metadata constants (#299) * Move DefaultConfig definition and impl to macro * Extract type substitute parsing to ir mod * Extract calls, events and storage from api generation * Add some hardcoded type substitute defaults * Fmt * Add utility pallet tests (#300) * add batch call test example * add pallet utility tests * add utility module * fix warnings * Add polkadot runtime metadata for example * Fix system errors and fmt * Add subxt-cli crate * Add metadata and codegen subcommands * Make subxt-cli codegen command work * Fmt * Add polkadot codegen test * Comment about how to run codegen * Derive AsCompact for structs with single concrete unsigned int field * Fix bitvec codegen, adds as non optional dependency * Regenerate polkadot api with bitvec fix * Edition 2021 * Fix polkadot codegen with bitvec * Polkadot balance transfer is working * Fix fetch remote * Fix transfer_subscribe example * Fix submit_and_watch example * Fmt * Generate storage iter method for iterating over keys * Fmt * Fix existential deposit test * Fix staking tests * Add option for custom generated type derives * Add generated type derives for test runtime api * Fmt * Copy WrapperTypeOpaque from substrate, add Encode/Decode * Fmt * Extract type generator to module, separate & fix tests * Fully qualified primitive and prelude types * Fix up remaining type gen tests * Skip formatting of generated polkadot example code * Remove empty utility test file. * Newline * Update cli/src/main.rs Co-authored-by: David <dvdplm@gmail.com> * Rename subxt-cli executable to subxt * Update src/client.rs Co-authored-by: David <dvdplm@gmail.com> * Add some code docs to TypeGenerator. * Extract TypePath to own file * Extract type def generation to separate file * Renamed ModuleType to TypeDefGen * Fmt * Factor out type parameter from final_key * Fix some type paths * Resolve some todos * Resolve some panic todos in events * Add EventsDecodingError * Decode compact composite types with a single primitive field * Decode compact composite types with a single primitive field * Update src/metadata.rs Co-authored-by: Andrew Plaza <aplaza@liquidthink.net> * Remove Perbill compact substitute types * Remove todos regarding maintaining Rust code items, promoted to follow up issue. * Remove todo regarding overridding default config impl * Remove todo regarding overridding default Extra * Remove todo regarding AccountData storage type defintion * Remove todo regarding borrowing storage key arguments * Remove type substitution tests todo * Remove `Box` field name type hack todo * Remove Compact todo * Remove sudo todos * Remove BitVec implementation todo * Fmt * Add health warning to README * Fix up health warning Co-authored-by: Paulo Martins <paulormart@users.noreply.github.com> Co-authored-by: David <dvdplm@gmail.com> Co-authored-by: Andrew Plaza <aplaza@liquidthink.net>
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use crate::{
|
||||
node_runtime::{
|
||||
balances,
|
||||
runtime_types,
|
||||
system,
|
||||
DefaultConfig,
|
||||
},
|
||||
test_context,
|
||||
};
|
||||
use codec::Decode;
|
||||
use sp_core::{
|
||||
sr25519::Pair,
|
||||
Pair as _,
|
||||
};
|
||||
use sp_keyring::AccountKeyring;
|
||||
use subxt::{
|
||||
extrinsic::{
|
||||
PairSigner,
|
||||
Signer,
|
||||
},
|
||||
Error,
|
||||
EventSubscription,
|
||||
PalletError,
|
||||
RuntimeError,
|
||||
};
|
||||
|
||||
#[async_std::test]
|
||||
async fn tx_basic_transfer() {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let bob = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Bob.pair());
|
||||
let bob_address = bob.account_id().clone().into();
|
||||
let cxt = test_context().await;
|
||||
let api = &cxt.api;
|
||||
|
||||
let alice_pre = api
|
||||
.storage()
|
||||
.system()
|
||||
.account(alice.account_id().clone().into(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
let bob_pre = api
|
||||
.storage()
|
||||
.system()
|
||||
.account(bob.account_id().clone().into(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let result = api
|
||||
.tx()
|
||||
.balances()
|
||||
.transfer(bob_address, 10_000)
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await
|
||||
.unwrap();
|
||||
let event = result
|
||||
.find_event::<balances::events::Transfer>()
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let _extrinsic_success = result
|
||||
.find_event::<system::events::ExtrinsicSuccess>()
|
||||
.expect("Failed to decode ExtrinisicSuccess".into())
|
||||
.expect("Failed to find ExtrinisicSuccess");
|
||||
|
||||
let expected_event = balances::events::Transfer(
|
||||
alice.account_id().clone(),
|
||||
bob.account_id().clone(),
|
||||
10_000,
|
||||
);
|
||||
assert_eq!(event, expected_event);
|
||||
|
||||
let alice_post = api
|
||||
.storage()
|
||||
.system()
|
||||
.account(alice.account_id().clone().into(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
let bob_post = api
|
||||
.storage()
|
||||
.system()
|
||||
.account(bob.account_id().clone().into(), None)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(alice_pre.data.free - 10_000 >= alice_post.data.free);
|
||||
assert_eq!(bob_pre.data.free + 10_000, bob_post.data.free);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn storage_total_issuance() {
|
||||
let cxt = test_context().await;
|
||||
let total_issuance = cxt
|
||||
.api
|
||||
.storage()
|
||||
.balances()
|
||||
.total_issuance(None)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_ne!(total_issuance, 0);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn storage_balance_lock() -> Result<(), subxt::Error> {
|
||||
let bob = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Bob.pair());
|
||||
let charlie = AccountKeyring::Charlie.to_account_id();
|
||||
let cxt = test_context().await;
|
||||
|
||||
let result = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.bond(
|
||||
charlie.into(),
|
||||
100_000_000_000_000,
|
||||
runtime_types::pallet_staking::RewardDestination::Stash,
|
||||
)
|
||||
.sign_and_submit_then_watch(&bob)
|
||||
.await?;
|
||||
|
||||
let success = result.find_event::<system::events::ExtrinsicSuccess>()?;
|
||||
assert!(success.is_some(), "No ExtrinsicSuccess Event found");
|
||||
|
||||
let locks = cxt
|
||||
.api
|
||||
.storage()
|
||||
.balances()
|
||||
.locks(AccountKeyring::Bob.to_account_id(), None)
|
||||
.await?;
|
||||
|
||||
assert_eq!(
|
||||
locks.0,
|
||||
vec![runtime_types::pallet_balances::BalanceLock {
|
||||
id: *b"staking ",
|
||||
amount: 100_000_000_000_000,
|
||||
reasons: runtime_types::pallet_balances::Reasons::All,
|
||||
}]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn transfer_error() {
|
||||
env_logger::try_init().ok();
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let alice_addr = alice.account_id().clone().into();
|
||||
let hans = PairSigner::<DefaultConfig, _>::new(Pair::generate().0);
|
||||
let hans_address = hans.account_id().clone().into();
|
||||
let cxt = test_context().await;
|
||||
|
||||
cxt.api
|
||||
.tx()
|
||||
.balances()
|
||||
.transfer(hans_address, 100_000_000_000_000_000)
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let res = cxt
|
||||
.api
|
||||
.tx()
|
||||
.balances()
|
||||
.transfer(alice_addr, 100_000_000_000_000_000)
|
||||
.sign_and_submit_then_watch(&hans)
|
||||
.await;
|
||||
|
||||
if let Err(Error::Runtime(RuntimeError::Module(error))) = res {
|
||||
let error2 = PalletError {
|
||||
pallet: "Balances".into(),
|
||||
error: "InsufficientBalance".into(),
|
||||
description: vec!["Balance too low to send value".to_string()],
|
||||
};
|
||||
assert_eq!(error, error2);
|
||||
} else {
|
||||
panic!("expected an error");
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn transfer_subscription() {
|
||||
env_logger::try_init().ok();
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let bob = AccountKeyring::Bob.to_account_id();
|
||||
let bob_addr = bob.clone().into();
|
||||
let cxt = test_context().await;
|
||||
let sub = cxt.client().rpc().subscribe_events().await.unwrap();
|
||||
let decoder = cxt.client().events_decoder();
|
||||
let mut sub = EventSubscription::<DefaultConfig>::new(sub, &decoder);
|
||||
sub.filter_event::<balances::events::Transfer>();
|
||||
|
||||
cxt.api
|
||||
.tx()
|
||||
.balances()
|
||||
.transfer(bob_addr, 10_000)
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let raw = sub.next().await.unwrap().unwrap();
|
||||
let event = balances::events::Transfer::decode(&mut &raw.data[..]).unwrap();
|
||||
assert_eq!(
|
||||
event,
|
||||
balances::events::Transfer(alice.account_id().clone(), bob.clone(), 10_000,)
|
||||
);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn constant_existential_deposit() {
|
||||
let cxt = test_context().await;
|
||||
let balances_metadata = cxt.client().metadata().pallet("Balances").unwrap();
|
||||
let constant_metadata = balances_metadata.constant("ExistentialDeposit").unwrap();
|
||||
let existential_deposit = u128::decode(&mut &constant_metadata.value[..]).unwrap();
|
||||
assert_eq!(existential_deposit, 100_000_000_000_000);
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use sp_keyring::AccountKeyring;
|
||||
|
||||
use crate::{
|
||||
node_runtime::{
|
||||
contracts::{
|
||||
calls::TransactionApi,
|
||||
events,
|
||||
storage,
|
||||
},
|
||||
system,
|
||||
DefaultConfig,
|
||||
},
|
||||
test_context,
|
||||
TestContext,
|
||||
};
|
||||
use sp_core::sr25519::Pair;
|
||||
use sp_runtime::MultiAddress;
|
||||
use subxt::{
|
||||
Client,
|
||||
Config,
|
||||
Error,
|
||||
ExtrinsicSuccess,
|
||||
PairSigner,
|
||||
};
|
||||
|
||||
struct ContractsTestContext {
|
||||
cxt: TestContext,
|
||||
signer: PairSigner<DefaultConfig, Pair>,
|
||||
}
|
||||
|
||||
type Hash = <DefaultConfig as Config>::Hash;
|
||||
type AccountId = <DefaultConfig as Config>::AccountId;
|
||||
|
||||
impl ContractsTestContext {
|
||||
async fn init() -> Self {
|
||||
let cxt = test_context().await;
|
||||
let signer = PairSigner::new(AccountKeyring::Alice.pair());
|
||||
|
||||
Self { cxt, signer }
|
||||
}
|
||||
|
||||
fn client(&self) -> &Client<DefaultConfig> {
|
||||
&self.cxt.client()
|
||||
}
|
||||
|
||||
fn contracts_tx(&self) -> TransactionApi<DefaultConfig> {
|
||||
self.cxt.api.tx().contracts()
|
||||
}
|
||||
|
||||
async fn instantiate_with_code(&self) -> Result<(Hash, AccountId), Error> {
|
||||
log::info!("instantiate_with_code:");
|
||||
const CONTRACT: &str = r#"
|
||||
(module
|
||||
(func (export "call"))
|
||||
(func (export "deploy"))
|
||||
)
|
||||
"#;
|
||||
let code = wabt::wat2wasm(CONTRACT).expect("invalid wabt");
|
||||
|
||||
let result = self
|
||||
.cxt
|
||||
.api
|
||||
.tx()
|
||||
.contracts()
|
||||
.instantiate_with_code(
|
||||
100_000_000_000_000_000, // endowment
|
||||
500_000_000_000, // gas_limit
|
||||
code,
|
||||
vec![], // data
|
||||
vec![], // salt
|
||||
)
|
||||
.sign_and_submit_then_watch(&self.signer)
|
||||
.await?;
|
||||
|
||||
let code_stored = result
|
||||
.find_event::<events::CodeStored>()?
|
||||
.ok_or_else(|| Error::Other("Failed to find a CodeStored event".into()))?;
|
||||
let instantiated = result
|
||||
.find_event::<events::Instantiated>()?
|
||||
.ok_or_else(|| Error::Other("Failed to find a Instantiated event".into()))?;
|
||||
let _extrinsic_success = result
|
||||
.find_event::<system::events::ExtrinsicSuccess>()?
|
||||
.ok_or_else(|| {
|
||||
Error::Other("Failed to find a ExtrinsicSuccess event".into())
|
||||
})?;
|
||||
|
||||
log::info!(" Block hash: {:?}", result.block);
|
||||
log::info!(" Code hash: {:?}", code_stored.code_hash);
|
||||
log::info!(" Contract address: {:?}", instantiated.contract);
|
||||
Ok((code_stored.code_hash, instantiated.contract))
|
||||
}
|
||||
|
||||
async fn instantiate(
|
||||
&self,
|
||||
code_hash: Hash,
|
||||
data: Vec<u8>,
|
||||
salt: Vec<u8>,
|
||||
) -> Result<AccountId, Error> {
|
||||
// call instantiate extrinsic
|
||||
let result = self
|
||||
.contracts_tx()
|
||||
.instantiate(
|
||||
100_000_000_000_000_000, // endowment
|
||||
500_000_000_000, // gas_limit
|
||||
code_hash,
|
||||
data,
|
||||
salt,
|
||||
)
|
||||
.sign_and_submit_then_watch(&self.signer)
|
||||
.await?;
|
||||
|
||||
log::info!("Instantiate result: {:?}", result);
|
||||
let instantiated = result
|
||||
.find_event::<events::Instantiated>()?
|
||||
.ok_or_else(|| Error::Other("Failed to find a Instantiated event".into()))?;
|
||||
|
||||
Ok(instantiated.contract)
|
||||
}
|
||||
|
||||
async fn call(
|
||||
&self,
|
||||
contract: AccountId,
|
||||
input_data: Vec<u8>,
|
||||
) -> Result<ExtrinsicSuccess<DefaultConfig>, Error> {
|
||||
log::info!("call: {:?}", contract);
|
||||
let result = self
|
||||
.contracts_tx()
|
||||
.call(
|
||||
MultiAddress::Id(contract),
|
||||
0, // value
|
||||
500_000_000, // gas_limit
|
||||
input_data,
|
||||
)
|
||||
.sign_and_submit_then_watch(&self.signer)
|
||||
.await?;
|
||||
|
||||
log::info!("Call result: {:?}", result);
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn tx_instantiate_with_code() {
|
||||
let ctx = ContractsTestContext::init().await;
|
||||
let result = ctx.instantiate_with_code().await;
|
||||
|
||||
assert!(
|
||||
result.is_ok(),
|
||||
"Error calling instantiate_with_code and receiving CodeStored and Instantiated Events: {:?}",
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn tx_instantiate() {
|
||||
let ctx = ContractsTestContext::init().await;
|
||||
let (code_hash, _) = ctx.instantiate_with_code().await.unwrap();
|
||||
|
||||
let instantiated = ctx.instantiate(code_hash.into(), vec![], vec![1u8]).await;
|
||||
|
||||
assert!(
|
||||
instantiated.is_ok(),
|
||||
"Error instantiating contract: {:?}",
|
||||
instantiated
|
||||
);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn tx_call() {
|
||||
let cxt = ContractsTestContext::init().await;
|
||||
let (_, contract) = cxt.instantiate_with_code().await.unwrap();
|
||||
|
||||
let contract_info = cxt
|
||||
.cxt
|
||||
.api
|
||||
.storage()
|
||||
.contracts()
|
||||
.contract_info_of(contract.clone(), None)
|
||||
.await;
|
||||
assert!(contract_info.is_ok());
|
||||
|
||||
let keys = cxt
|
||||
.client()
|
||||
.storage()
|
||||
.fetch_keys::<storage::ContractInfoOf>(5, None, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|key| hex::encode(&key.0))
|
||||
.collect::<Vec<_>>();
|
||||
println!("keys post: {:?}", keys);
|
||||
|
||||
let executed = cxt.call(contract, vec![]).await;
|
||||
|
||||
assert!(executed.is_ok(), "Error calling contract: {:?}", executed);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
//! Test interactions with some built-in FRAME pallets.
|
||||
|
||||
mod balances;
|
||||
mod contracts;
|
||||
mod staking;
|
||||
mod sudo;
|
||||
mod system;
|
||||
@@ -0,0 +1,258 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use crate::{
|
||||
node_runtime::{
|
||||
runtime_types::pallet_staking::{
|
||||
RewardDestination,
|
||||
ValidatorPrefs,
|
||||
},
|
||||
staking,
|
||||
system,
|
||||
DefaultConfig,
|
||||
},
|
||||
test_context,
|
||||
};
|
||||
use assert_matches::assert_matches;
|
||||
use sp_core::{
|
||||
sr25519,
|
||||
Pair,
|
||||
};
|
||||
use sp_keyring::AccountKeyring;
|
||||
use subxt::{
|
||||
extrinsic::{
|
||||
PairSigner,
|
||||
Signer,
|
||||
},
|
||||
Error,
|
||||
RuntimeError,
|
||||
};
|
||||
|
||||
/// Helper function to generate a crypto pair from seed
|
||||
fn get_from_seed(seed: &str) -> sr25519::Pair {
|
||||
sr25519::Pair::from_string(&format!("//{}", seed), None)
|
||||
.expect("static values are valid; qed")
|
||||
}
|
||||
|
||||
fn default_validator_prefs() -> ValidatorPrefs {
|
||||
ValidatorPrefs {
|
||||
commission: sp_runtime::Perbill::default(),
|
||||
blocked: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn validate_with_controller_account() -> Result<(), Error> {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let cxt = test_context().await;
|
||||
let result = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.validate(default_validator_prefs())
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await?;
|
||||
|
||||
let success = result.find_event::<system::events::ExtrinsicSuccess>()?;
|
||||
assert!(success.is_some());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn validate_not_possible_for_stash_account() -> Result<(), Error> {
|
||||
let alice_stash = PairSigner::<DefaultConfig, _>::new(get_from_seed("Alice//stash"));
|
||||
let cxt = test_context().await;
|
||||
let announce_validator = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.validate(default_validator_prefs())
|
||||
.sign_and_submit_then_watch(&alice_stash)
|
||||
.await;
|
||||
assert_matches!(announce_validator, Err(Error::Runtime(RuntimeError::Module(module_err))) => {
|
||||
assert_eq!(module_err.pallet, "Staking");
|
||||
assert_eq!(module_err.error, "NotController");
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn nominate_with_controller_account() -> Result<(), Error> {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let bob = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Bob.pair());
|
||||
let cxt = test_context().await;
|
||||
|
||||
let result = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.nominate(vec![bob.account_id().clone().into()])
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await?;
|
||||
|
||||
let success = result.find_event::<system::events::ExtrinsicSuccess>()?;
|
||||
assert!(success.is_some());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn nominate_not_possible_for_stash_account() -> Result<(), Error> {
|
||||
let alice_stash =
|
||||
PairSigner::<DefaultConfig, sr25519::Pair>::new(get_from_seed("Alice//stash"));
|
||||
let bob = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Bob.pair());
|
||||
let cxt = test_context().await;
|
||||
|
||||
let nomination = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.nominate(vec![bob.account_id().clone().into()])
|
||||
.sign_and_submit_then_watch(&alice_stash)
|
||||
.await;
|
||||
|
||||
assert_matches!(nomination, Err(Error::Runtime(RuntimeError::Module(module_err))) => {
|
||||
assert_eq!(module_err.pallet, "Staking");
|
||||
assert_eq!(module_err.error, "NotController");
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn chill_works_for_controller_only() -> Result<(), Error> {
|
||||
let alice_stash =
|
||||
PairSigner::<DefaultConfig, sr25519::Pair>::new(get_from_seed("Alice//stash"));
|
||||
let bob_stash =
|
||||
PairSigner::<DefaultConfig, sr25519::Pair>::new(get_from_seed("Bob//stash"));
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let cxt = test_context().await;
|
||||
|
||||
// this will fail the second time, which is why this is one test, not two
|
||||
cxt.api
|
||||
.tx()
|
||||
.staking()
|
||||
.nominate(vec![bob_stash.account_id().clone().into()])
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await?;
|
||||
|
||||
let ledger = cxt
|
||||
.api
|
||||
.storage()
|
||||
.staking()
|
||||
.ledger(alice.account_id().clone(), None)
|
||||
.await?
|
||||
.unwrap();
|
||||
assert_eq!(alice_stash.account_id(), &ledger.stash);
|
||||
|
||||
let chill = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.chill()
|
||||
.sign_and_submit_then_watch(&alice_stash)
|
||||
.await;
|
||||
|
||||
assert_matches!(chill, Err(Error::Runtime(RuntimeError::Module(module_err))) => {
|
||||
assert_eq!(module_err.pallet, "Staking");
|
||||
assert_eq!(module_err.error, "NotController");
|
||||
});
|
||||
|
||||
let result = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.chill()
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await?;
|
||||
let chill = result.find_event::<staking::events::Chilled>()?;
|
||||
assert!(chill.is_some());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn tx_bond() -> Result<(), Error> {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let cxt = test_context().await;
|
||||
|
||||
let bond = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.bond(
|
||||
AccountKeyring::Bob.to_account_id().into(),
|
||||
100_000_000_000_000,
|
||||
RewardDestination::Stash,
|
||||
)
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await;
|
||||
|
||||
assert!(bond.is_ok());
|
||||
|
||||
let bond_again = cxt
|
||||
.api
|
||||
.tx()
|
||||
.staking()
|
||||
.bond(
|
||||
AccountKeyring::Bob.to_account_id().into(),
|
||||
100_000_000_000_000,
|
||||
RewardDestination::Stash,
|
||||
)
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await;
|
||||
|
||||
assert_matches!(bond_again, Err(Error::Runtime(RuntimeError::Module(module_err))) => {
|
||||
assert_eq!(module_err.pallet, "Staking");
|
||||
assert_eq!(module_err.error, "AlreadyBonded");
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn storage_history_depth() -> Result<(), Error> {
|
||||
let cxt = test_context().await;
|
||||
let history_depth = cxt.api.storage().staking().history_depth(None).await?;
|
||||
assert_eq!(history_depth, 84);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn storage_current_era() -> Result<(), Error> {
|
||||
let cxt = test_context().await;
|
||||
let _current_era = cxt
|
||||
.api
|
||||
.storage()
|
||||
.staking()
|
||||
.current_era(None)
|
||||
.await?
|
||||
.expect("current era always exists");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn storage_era_reward_points() -> Result<(), Error> {
|
||||
let cxt = test_context().await;
|
||||
let current_era_result = cxt
|
||||
.api
|
||||
.storage()
|
||||
.staking()
|
||||
.eras_reward_points(0, None)
|
||||
.await;
|
||||
assert!(current_era_result.is_ok());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use crate::{
|
||||
node_runtime::{
|
||||
runtime_types,
|
||||
sudo,
|
||||
DefaultConfig,
|
||||
},
|
||||
test_context,
|
||||
};
|
||||
use assert_matches::assert_matches;
|
||||
use sp_keyring::AccountKeyring;
|
||||
use subxt::extrinsic::PairSigner;
|
||||
|
||||
type Call = runtime_types::node_runtime::Call;
|
||||
type BalancesCall = runtime_types::pallet_balances::pallet::Call;
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_sudo() {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let bob = AccountKeyring::Bob.to_account_id().clone().into();
|
||||
let cxt = test_context().await;
|
||||
|
||||
let call = Call::Balances(BalancesCall::transfer {
|
||||
dest: bob,
|
||||
value: 10_000,
|
||||
});
|
||||
|
||||
let res = cxt
|
||||
.api
|
||||
.tx()
|
||||
.sudo()
|
||||
.sudo(call)
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await
|
||||
.unwrap();
|
||||
let sudid = res.find_event::<sudo::events::Sudid>();
|
||||
assert_matches!(sudid, Ok(Some(_)))
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn test_sudo_unchecked_weight() {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let bob = AccountKeyring::Bob.to_account_id().into();
|
||||
let cxt = test_context().await;
|
||||
|
||||
let call = Call::Balances(BalancesCall::transfer {
|
||||
dest: bob,
|
||||
value: 10_000,
|
||||
});
|
||||
|
||||
let res = cxt
|
||||
.api
|
||||
.tx()
|
||||
.sudo()
|
||||
.sudo_unchecked_weight(call, 0)
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let sudid = res.find_event::<sudo::events::Sudid>();
|
||||
assert_matches!(sudid, Ok(Some(_)))
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2019-2021 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/>.
|
||||
|
||||
use crate::{
|
||||
node_runtime::{
|
||||
system,
|
||||
DefaultConfig,
|
||||
},
|
||||
test_context,
|
||||
};
|
||||
use assert_matches::assert_matches;
|
||||
use sp_keyring::AccountKeyring;
|
||||
use subxt::extrinsic::{
|
||||
PairSigner,
|
||||
Signer,
|
||||
};
|
||||
|
||||
#[async_std::test]
|
||||
async fn storage_account() {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
|
||||
let cxt = test_context().await;
|
||||
let account_info = cxt
|
||||
.api
|
||||
.storage()
|
||||
.system()
|
||||
.account(alice.account_id().clone().into(), None)
|
||||
.await;
|
||||
assert_matches!(account_info, Ok(_))
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn tx_remark_with_event() {
|
||||
let alice = PairSigner::<DefaultConfig, _>::new(AccountKeyring::Alice.pair());
|
||||
let cxt = test_context().await;
|
||||
|
||||
let result = cxt
|
||||
.api
|
||||
.tx()
|
||||
.system()
|
||||
.remark_with_event(b"remarkable".to_vec())
|
||||
.sign_and_submit_then_watch(&alice)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let remarked = result.find_event::<system::events::Remarked>();
|
||||
assert_matches!(remarked, Ok(Some(_)));
|
||||
}
|
||||
Reference in New Issue
Block a user