difftreelog
Add test for vesting pallet presence, cleanup other tests
in: master
12 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1228,6 +1228,26 @@
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
+name = "enumflags2"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83c8d82922337cd23a15f88b70d8e4ef5f11da38dd7cdb55e84dd5de99695da0"
+dependencies = [
+ "enumflags2_derive",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3541,6 +3561,7 @@
"pallet-transaction-payment",
"pallet-transaction-payment-rpc-runtime-api",
"pallet-treasury",
+ "pallet-vesting",
"parity-scale-codec",
"serde",
"sp-api",
@@ -4020,6 +4041,20 @@
]
[[package]]
+name = "pallet-vesting"
+version = "2.0.0"
+source = "git+https://github.com/usetech-llc/substrate.git?branch=release_flexi#59646c902484d9c5e8933a80cbed551228b81274"
+dependencies = [
+ "enumflags2",
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "serde",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
name = "parity-db"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
node/src/chain_spec.rsdiffbeforeafterboth--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -154,7 +154,8 @@
.collect(),
}),
pallet_treasury: Some(Default::default()),
- pallet_sudo: Some(SudoConfig { key: root_key }),
+ pallet_sudo: Some(SudoConfig { key: root_key }),
+ pallet_vesting: Some(Default::default()),
pallet_nft: Some(NftConfig {
collection: vec![(
1,
runtime/Cargo.tomldiffbeforeafterboth--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -45,6 +45,8 @@
pallet-timestamp = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
pallet-transaction-payment = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
pallet-transaction-payment-rpc-runtime-api = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
+pallet-treasury = { version = "2.0.0", default-features = false, git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
+pallet-vesting = { version = "2.0.0", default-features = false, git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
sp-api = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
sp-block-builder = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
sp-consensus-aura = { default-features = false, version = '0.8.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
@@ -56,8 +58,6 @@
sp-std = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
sp-transaction-pool = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
sp-version = { default-features = false, version = '2.0.0' , git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
-
-pallet-treasury = { version = "2.0.0", default-features = false, git = 'https://github.com/usetech-llc/substrate.git', branch = 'release_flexi' }
[features]
default = ['std']
@@ -90,6 +90,9 @@
'pallet-timestamp/std',
'pallet-transaction-payment/std',
'pallet-transaction-payment-rpc-runtime-api/std',
+ 'pallet-treasury/std',
+ 'pallet-vesting/std',
+
'pallet-nft/std',
'sp-api/std',
'sp-block-builder/std',
@@ -103,5 +106,4 @@
'sp-transaction-pool/std',
'sp-version/std',
- 'pallet-treasury/std',
]
runtime/src/lib.rsdiffbeforeafterboth1//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.23#![cfg_attr(not(feature = "std"), no_std)]4// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.5#![recursion_limit = "256"]67// Make the WASM binary available.8#[cfg(feature = "std")]9include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));1011use pallet_contracts_rpc_runtime_api::ContractExecResult;12use pallet_grandpa::fg_primitives;13use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};14use sp_api::impl_runtime_apis;15use sp_consensus_aura::sr25519::AuthorityId as AuraId;16use sp_core::{ crypto::KeyTypeId, crypto::Public, OpaqueMetadata };17use sp_runtime::{18 create_runtime_str, generic, impl_opaque_keys,19 traits::{20 Convert, BlakeTwo256, Block as BlockT, IdentifyAccount, 21 IdentityLookup, NumberFor, Saturating, Verify,22 },23 transaction_validity::{TransactionSource, TransactionValidity},24 ApplyExtrinsicResult, MultiSignature,25};26use sp_std::prelude::*;27#[cfg(feature = "std")]28use sp_version::NativeVersion;29use sp_version::RuntimeVersion;3031// A few exports that help ease life for downstream crates.32pub use pallet_balances::Call as BalancesCall;33pub use pallet_contracts::Schedule as ContractsSchedule;34pub use frame_support::{35 construct_runtime,36 dispatch::DispatchResult,37 parameter_types,38 traits::{39 Currency, ExistenceRequirement, Get, KeyOwnerProofSystem, OnUnbalanced, Randomness,40 WithdrawReason, LockIdentifier,41 },42 weights::{43 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},44 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,45 WeightToFeePolynomial,46 },47 StorageValue,48};49#[cfg(any(feature = "std", test))]50pub use sp_runtime::BuildStorage;51use sp_runtime:: { Perbill, Permill, Percent, ModuleId };52use frame_system::{self as system, EnsureRoot };53use sp_std::{marker::PhantomData};5455pub use pallet_timestamp::Call as TimestampCall;5657/// Struct that handles the conversion of Balance -> `u64`. This is used for58/// staking's election calculation.59pub struct CurrencyToVoteHandler;6061impl CurrencyToVoteHandler {62 fn factor() -> Balance {63 (Balances::total_issuance() / u64::max_value() as Balance).max(1)64 }65}6667impl Convert<Balance, u64> for CurrencyToVoteHandler {68 fn convert(x: Balance) -> u64 {69 (x / Self::factor()) as u6470 }71}7273impl Convert<u128, Balance> for CurrencyToVoteHandler {74 fn convert(x: u128) -> Balance {75 x * Self::factor()76 }77}7879/// Re-export a nft pallet80/// TODO: Check this re-export. Is this safe and good style?81extern crate pallet_nft;82pub use pallet_nft::*;8384/// An index to a block.85pub type BlockNumber = u32;8687/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.88pub type Signature = MultiSignature;8990/// Some way of identifying an account on the chain. We intentionally make it equivalent91/// to the public key of our transaction signing scheme.92pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;9394/// The type for looking up accounts. We don't expect more than 4 billion of them, but you95/// never know...96pub type AccountIndex = u32;9798/// Balance of an account.99pub type Balance = u128;100101/// Index of a transaction in the chain.102pub type Index = u32;103104/// A hash of some data used by the chain.105pub type Hash = sp_core::H256;106107/// Digest item type.108pub type DigestItem = generic::DigestItem<Hash>;109110mod nft_weights;111112/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know113/// the specifics of the runtime. They can then be made to be agnostic over specific formats114/// of data like extrinsics, allowing for them to continue syncing the network through upgrades115/// to even the core data structures.116pub mod opaque {117 use super::*;118119 pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;120121 /// Opaque block header type.122 pub type Header = generic::Header<BlockNumber, BlakeTwo256>;123 /// Opaque block type.124 pub type Block = generic::Block<Header, UncheckedExtrinsic>;125 /// Opaque block identifier type.126 pub type BlockId = generic::BlockId<Block>;127128 impl_opaque_keys! {129 pub struct SessionKeys {130 pub aura: Aura,131 pub grandpa: Grandpa,132 }133 }134}135136/// This runtime version.137pub const VERSION: RuntimeVersion = RuntimeVersion {138 spec_name: create_runtime_str!("nft"),139 impl_name: create_runtime_str!("nft"),140 authoring_version: 1,141 spec_version: 2,142 impl_version: 1,143 apis: RUNTIME_API_VERSIONS,144 transaction_version: 1,145};146147pub const MILLISECS_PER_BLOCK: u64 = 6000;148149pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;150151// These time units are defined in number of blocks.152pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);153pub const HOURS: BlockNumber = MINUTES * 60;154pub const DAYS: BlockNumber = HOURS * 24;155156/// The version information used to identify this runtime when compiled natively.157#[cfg(feature = "std")]158pub fn native_version() -> NativeVersion {159 NativeVersion {160 runtime_version: VERSION,161 can_author_with: Default::default(),162 }163}164165/// Provides a membership set with only the configured aura users166pub struct ValiudatorsOnly<Runtime: pallet_aura::Trait>(PhantomData<Runtime>);167impl frame_support::traits::Contains<AccountId> for ValiudatorsOnly<Runtime> {168 fn contains(t: &AccountId) -> bool {169 let arr: [u8; 32] = *t.as_ref();170 let raw_key: Vec<u8> = Vec::from(arr);171172 match pallet_aura::Module::<Runtime>::authorities().iter().find(|auth| auth.to_raw_vec() == raw_key) {173 Some(_) => true,174 None => false,175 } 176 }177 fn sorted_members() -> Vec<AccountId> {178 let mut members: Vec<AccountId> = Vec::new();179 for auth in pallet_aura::Module::<Runtime>::authorities() {180 let mut arr: [u8; 32] = Default::default(); 181 let bor_arr = auth.clone().to_raw_vec();182 let slice = bor_arr.as_slice();183 arr.copy_from_slice(slice);184 members.push(AccountId::from(arr));185 }186 members 187 }188 fn count() -> usize {189 pallet_aura::Module::<Runtime>::authorities().len()190 }191}192193impl frame_support::traits::ContainsLengthBound for ValiudatorsOnly<Runtime> {194 fn min_len() -> usize {195 1196 }197 fn max_len() -> usize {198 100199 }200}201202parameter_types! {203 pub const BlockHashCount: BlockNumber = 2400;204 /// We allow for 2 seconds of compute with a 6 second average block time.205 pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND;206 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);207 /// Assume 10% of weight for average on_initialize calls.208 pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()209 .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();210 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;211 pub const Version: RuntimeVersion = VERSION;212}213214impl system::Trait for Runtime {215 /// The basic call filter to use in dispatchable.216 type BaseCallFilter = ();217 /// The identifier used to distinguish between accounts.218 type AccountId = AccountId;219 /// The aggregated dispatch type that is available for extrinsics.220 type Call = Call;221 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.222 type Lookup = IdentityLookup<AccountId>;223 /// The index type for storing how many extrinsics an account has signed.224 type Index = Index;225 /// The index type for blocks.226 type BlockNumber = BlockNumber;227 /// The type for hashing blocks and tries.228 type Hash = Hash;229 /// The hashing algorithm used.230 type Hashing = BlakeTwo256;231 /// The header type.232 type Header = generic::Header<BlockNumber, BlakeTwo256>;233 /// The ubiquitous event type.234 type Event = Event;235 /// The ubiquitous origin type.236 type Origin = Origin;237 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).238 type BlockHashCount = BlockHashCount;239 /// Maximum weight of each block.240 type MaximumBlockWeight = MaximumBlockWeight;241 /// The weight of database operations that the runtime can invoke.242 type DbWeight = RocksDbWeight;243 /// The weight of the overhead invoked on the block import process, independent of the244 /// extrinsics included in that block.245 type BlockExecutionWeight = BlockExecutionWeight;246 /// The base weight of any extrinsic processed by the runtime, independent of the247 /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...)248 type ExtrinsicBaseWeight = ExtrinsicBaseWeight;249 /// The maximum weight that a single extrinsic of `Normal` dispatch class can have,250 /// idependent of the logic of that extrinsics. (Roughly max block weight - average on251 /// initialize cost).252 type MaximumExtrinsicWeight = MaximumExtrinsicWeight;253 /// Maximum size of all encoded transactions (in bytes) that are allowed in one block.254 type MaximumBlockLength = MaximumBlockLength;255 /// Portion of the block weight that is available to all normal transactions.256 type AvailableBlockRatio = AvailableBlockRatio;257 /// Version of the runtime.258 type Version = Version;259 /// This type is being generated by `construct_runtime!`.260 type PalletInfo = PalletInfo;261 /// What to do if a new account is created.262 type OnNewAccount = ();263 /// What to do if an account is fully reaped from the system.264 type OnKilledAccount = ();265 /// The data to be stored in an account.266 type AccountData = pallet_balances::AccountData<Balance>;267 /// Weight information for the extrinsics of this pallet.268 type SystemWeightInfo = ();269}270271impl pallet_aura::Trait for Runtime {272 type AuthorityId = AuraId;273}274275impl pallet_grandpa::Trait for Runtime {276 type Event = Event;277 type Call = Call;278279 type KeyOwnerProofSystem = ();280281 type KeyOwnerProof =282 <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;283284 type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(285 KeyTypeId,286 GrandpaId,287 )>>::IdentificationTuple;288289 type HandleEquivocation = ();290291 type WeightInfo = ();292}293294parameter_types! {295 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;296}297298impl pallet_timestamp::Trait for Runtime {299 /// A timestamp: milliseconds since the unix epoch.300 type Moment = u64;301 type OnTimestampSet = Aura;302 type MinimumPeriod = MinimumPeriod;303 type WeightInfo = ();304}305306parameter_types! {307 // pub const ExistentialDeposit: u128 = 500;308 pub const ExistentialDeposit: u128 = 0;309 pub const MaxLocks: u32 = 50;310}311312impl pallet_balances::Trait for Runtime {313 type MaxLocks = MaxLocks;314 /// The type for recording an account's balance.315 type Balance = Balance;316 /// The ubiquitous event type.317 type Event = Event;318 type DustRemoval = Treasury;319 type ExistentialDeposit = ExistentialDeposit;320 type AccountStore = System;321 type WeightInfo = ();322}323324pub const MILLICENTS: Balance = 1_000_000_000;325pub const CENTS: Balance = 1_000 * MILLICENTS;326pub const DOLLARS: Balance = 100 * CENTS;327328parameter_types! {329 pub const TombstoneDeposit: Balance = 0;330 pub const RentByteFee: Balance = 4 * MILLICENTS;331 pub const RentDepositOffset: Balance = 1000 * MILLICENTS;332 pub const SurchargeReward: Balance = 150 * MILLICENTS;333}334335impl pallet_contracts::Trait for Runtime {336 type Time = Timestamp;337 type Randomness = RandomnessCollectiveFlip;338 type Currency = Balances;339 type Event = Event;340 type DetermineContractAddress = pallet_contracts::SimpleAddressDeterminer<Runtime>;341 type TrieIdGenerator = pallet_contracts::TrieIdFromParentCounter<Runtime>;342 type RentPayment = ();343 type SignedClaimHandicap = pallet_contracts::DefaultSignedClaimHandicap;344 type TombstoneDeposit = TombstoneDeposit;345 type StorageSizeOffset = pallet_contracts::DefaultStorageSizeOffset;346 type RentByteFee = RentByteFee;347 type RentDepositOffset = RentDepositOffset;348 type SurchargeReward = SurchargeReward;349 type MaxDepth = pallet_contracts::DefaultMaxDepth;350 type MaxValueSize = pallet_contracts::DefaultMaxValueSize;351 type WeightPrice = pallet_transaction_payment::Module<Self>;352}353354parameter_types! {355 pub const TransactionByteFee: Balance = 10 * MILLICENTS;356}357358impl pallet_transaction_payment::Trait for Runtime {359 type Currency = pallet_balances::Module<Runtime>;360 type OnTransactionPayment = Treasury;361 type TransactionByteFee = TransactionByteFee;362 type WeightToFee = IdentityFee<Balance>;363 type FeeMultiplierUpdate = ();364}365366parameter_types! {367 pub const ProposalBond: Permill = Permill::from_percent(5);368 pub const ProposalBondMinimum: Balance = 1 * DOLLARS;369 pub const SpendPeriod: BlockNumber = 5 * MINUTES;370 pub const Burn: Permill = Permill::from_percent(0);371 pub const TipCountdown: BlockNumber = 1 * DAYS;372 pub const TipFindersFee: Percent = Percent::from_percent(20);373 pub const TipReportDepositBase: Balance = 1 * DOLLARS;374 pub const DataDepositPerByte: Balance = 1 * CENTS;375 pub const BountyDepositBase: Balance = 1 * DOLLARS;376 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;377 pub const TreasuryModuleId: ModuleId = ModuleId(*b"py/trsry");378 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;379 pub const MaximumReasonLength: u32 = 16384;380 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);381 pub const BountyValueMinimum: Balance = 5 * DOLLARS;382}383384impl pallet_treasury::Trait for Runtime {385 type ModuleId = TreasuryModuleId;386 type Currency = Balances;387 type ApproveOrigin = EnsureRoot<AccountId>;388 type RejectOrigin = EnsureRoot<AccountId>;389 type Tippers = ValiudatorsOnly<Self>;390 type TipCountdown = TipCountdown;391 type TipFindersFee = TipFindersFee;392 type TipReportDepositBase = TipReportDepositBase;393 type DataDepositPerByte = DataDepositPerByte;394 type Event = Event;395 type OnSlash = ();396 type ProposalBond = ProposalBond;397 type ProposalBondMinimum = ProposalBondMinimum;398 type SpendPeriod = SpendPeriod;399 type Burn = Burn;400 type BountyDepositBase = BountyDepositBase;401 type BountyDepositPayoutDelay = BountyDepositPayoutDelay;402 type BountyUpdatePeriod = BountyUpdatePeriod;403 type BountyCuratorDeposit = BountyCuratorDeposit;404 type BountyValueMinimum = BountyValueMinimum;405 type MaximumReasonLength = MaximumReasonLength;406 type BurnDestination = ();407 type WeightInfo = ();408}409410impl pallet_sudo::Trait for Runtime {411 type Event = Event;412 type Call = Call;413}414415/// Used for the module nft in `./nft.rs`416impl pallet_nft::Trait for Runtime {417 type Event = Event;418 type WeightInfo = nft_weights::WeightInfo;419}420421construct_runtime!(422 pub enum Runtime where423 Block = Block,424 NodeBlock = opaque::Block,425 UncheckedExtrinsic = UncheckedExtrinsic426 {427 System: system::{Module, Call, Config, Storage, Event<T>},428 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},429 Contracts: pallet_contracts::{Module, Call, Config, Storage, Event<T>},430 Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},431 Aura: pallet_aura::{Module, Config<T>, Inherent},432 Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},433 Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},434 TransactionPayment: pallet_transaction_payment::{Module, Storage},435 Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},436 Nft: pallet_nft::{Module, Call, Config<T>, Storage, Event<T>},437 Treasury: pallet_treasury::{Module, Call, Storage, Config, Event<T>},438 }439);440441/// The address format for describing accounts.442pub type Address = AccountId;443/// Block header type as expected by this runtime.444pub type Header = generic::Header<BlockNumber, BlakeTwo256>;445/// Block type as expected by this runtime.446pub type Block = generic::Block<Header, UncheckedExtrinsic>;447/// A Block signed with a Justification448pub type SignedBlock = generic::SignedBlock<Block>;449/// BlockId type as expected by this runtime.450pub type BlockId = generic::BlockId<Block>;451/// The SignedExtension to the basic transaction logic.452pub type SignedExtra = (453 system::CheckSpecVersion<Runtime>,454 system::CheckTxVersion<Runtime>,455 system::CheckGenesis<Runtime>,456 system::CheckEra<Runtime>,457 system::CheckNonce<Runtime>,458 system::CheckWeight<Runtime>,459 pallet_nft::ChargeTransactionPayment<Runtime>,460);461/// Unchecked extrinsic type as expected by this runtime.462pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;463/// Extrinsic type that has already been checked.464pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;465/// Executive: handles dispatch to the various modules.466pub type Executive =467 frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;468469impl_runtime_apis! {470471 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>472 for Runtime473 {474 fn call(475 origin: AccountId,476 dest: AccountId,477 value: Balance,478 gas_limit: u64,479 input_data: Vec<u8>,480 ) -> ContractExecResult {481 let (exec_result, gas_consumed) =482 Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);483 match exec_result {484 Ok(v) => ContractExecResult::Success {485 flags: v.flags.bits(),486 data: v.data,487 gas_consumed: gas_consumed,488 },489 Err(_) => ContractExecResult::Error,490 }491 }492493 fn get_storage(494 address: AccountId,495 key: [u8; 32],496 ) -> pallet_contracts_primitives::GetStorageResult {497 Contracts::get_storage(address, key)498 }499500 fn rent_projection(501 address: AccountId,502 ) -> pallet_contracts_primitives::RentProjectionResult<BlockNumber> {503 Contracts::rent_projection(address)504 }505 }506507 impl sp_api::Core<Block> for Runtime {508 fn version() -> RuntimeVersion {509 VERSION510 }511512 fn execute_block(block: Block) {513 Executive::execute_block(block)514 }515516 fn initialize_block(header: &<Block as BlockT>::Header) {517 Executive::initialize_block(header)518 }519 }520521 impl sp_api::Metadata<Block> for Runtime {522 fn metadata() -> OpaqueMetadata {523 Runtime::metadata().into()524 }525 }526527 impl sp_block_builder::BlockBuilder<Block> for Runtime {528 fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {529 Executive::apply_extrinsic(extrinsic)530 }531532 fn finalize_block() -> <Block as BlockT>::Header {533 Executive::finalize_block()534 }535536 fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {537 data.create_extrinsics()538 }539540 fn check_inherents(541 block: Block,542 data: sp_inherents::InherentData,543 ) -> sp_inherents::CheckInherentsResult {544 data.check_extrinsics(&block)545 }546547 fn random_seed() -> <Block as BlockT>::Hash {548 RandomnessCollectiveFlip::random_seed()549 }550 }551552 impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {553 fn validate_transaction(554 source: TransactionSource,555 tx: <Block as BlockT>::Extrinsic,556 ) -> TransactionValidity {557 Executive::validate_transaction(source, tx)558 }559 }560561 impl sp_offchain::OffchainWorkerApi<Block> for Runtime {562 fn offchain_worker(header: &<Block as BlockT>::Header) {563 Executive::offchain_worker(header)564 }565 }566567 impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {568 fn slot_duration() -> u64 {569 Aura::slot_duration()570 }571572 fn authorities() -> Vec<AuraId> {573 Aura::authorities()574 }575 }576577 impl sp_session::SessionKeys<Block> for Runtime {578 fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {579 opaque::SessionKeys::generate(seed)580 }581582 fn decode_session_keys(583 encoded: Vec<u8>,584 ) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {585 opaque::SessionKeys::decode_into_raw_public_keys(&encoded)586 }587 }588589 impl fg_primitives::GrandpaApi<Block> for Runtime {590 fn grandpa_authorities() -> GrandpaAuthorityList {591 Grandpa::grandpa_authorities()592 }593594 fn submit_report_equivocation_unsigned_extrinsic(595 _equivocation_proof: fg_primitives::EquivocationProof<596 <Block as BlockT>::Hash,597 NumberFor<Block>,598 >,599 _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,600 ) -> Option<()> {601 None602 }603604 fn generate_key_ownership_proof(605 _set_id: fg_primitives::SetId,606 _authority_id: GrandpaId,607 ) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {608 // NOTE: this is the only implementation possible since we've609 // defined our key owner proof type as a bottom type (i.e. a type610 // with no values).611 None612 }613 }614 615 impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {616 fn account_nonce(account: AccountId) -> Index {617 System::account_nonce(account)618 }619 }620621 impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {622 fn query_info(623 uxt: <Block as BlockT>::Extrinsic,624 len: u32,625 ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {626 TransactionPayment::query_info(uxt, len)627 }628 }629630 #[cfg(feature = "runtime-benchmarks")]631 impl frame_benchmarking::Benchmark<Block> for Runtime {632 fn dispatch_benchmark(633 config: frame_benchmarking::BenchmarkConfig634 ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {635 use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};636637 let whitelist: Vec<TrackedStorageKey> = vec![638 // Alice account639 hex_literal::hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d").to_vec().into(),640 // // Total Issuance641 // hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),642 // // Execution Phase643 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),644 // // Event Count645 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),646 // // System Events647 // hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),648 ];649650 let mut batches = Vec::<BenchmarkBatch>::new();651 let params = (&config, &whitelist);652653 add_benchmark!(params, batches, pallet_nft, Nft);654655 if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }656 Ok(batches)657 }658 }659}tests/src/blocks-production.test.tsdiffbeforeafterboth--- a/tests/src/blocks-production.test.ts
+++ b/tests/src/blocks-production.test.ts
@@ -2,7 +2,7 @@
import promisifySubstrate from "./substrate/promisify-substrate";
import { expect } from "chai";
-describe('Blocks Production', () => {
+describe('Blocks Production smoke test', () => {
it('Node produces new blocks', async () => {
await usingApi(async api => {
const blocksPromise = promisifySubstrate(api, () => {
tests/src/connection.test.tsdiffbeforeafterboth--- a/tests/src/connection.test.ts
+++ b/tests/src/connection.test.ts
@@ -7,7 +7,7 @@
const expect = chai.expect;
-describe('Connection', () => {
+describe('Connection smoke test', () => {
it('Connection can be established', async () => {
await usingApi(async api => {
const health = await api.rpc.system.health();
@@ -16,11 +16,17 @@
});
it('Cannot connect to 255.255.255.255', async () => {
+ console.log = function () {};
+ console.error = function () {};
+
const neverConnectProvider = new WsProvider('ws://255.255.255.255:9944');
await expect((async () => {
await usingApi(async api => {
const health = await api.rpc.system.health();
}, { provider: neverConnectProvider });
})()).to.be.eventually.rejected;
+
+ delete console.log;
+ delete console.error;
});
});
\ No newline at end of file
tests/src/contracts.test.tsdiffbeforeafterboth--- a/tests/src/contracts.test.ts
+++ b/tests/src/contracts.test.ts
@@ -1,13 +1,17 @@
+import { ApiPromise } from "@polkadot/api";
import { expect } from "chai";
-import usingApi from "./substrate/substrate-api";
+import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api";
import fs from "fs";
import { Abi, BlueprintPromise, CodePromise } from "@polkadot/api-contract";
import { IKeyringPair } from "@polkadot/types/types";
import { Keyring } from "@polkadot/api";
import { ApiTypes, SubmittableExtrinsic } from "@polkadot/api/types";
+import { BigNumber } from 'bignumber.js';
+import { findUnusedAddress } from './util/helpers'
const value = 0;
const gasLimit = 3000n * 1000000n;
+const endowment = `1000000000000000`;
function deployBlueprint(alice: IKeyringPair, code: CodePromise): Promise<BlueprintPromise> {
return new Promise<BlueprintPromise>(async (resolve, reject) => {
@@ -25,7 +29,6 @@
function deployContract(alice: IKeyringPair, blueprint: BlueprintPromise) : Promise<any> {
return new Promise<any>(async (resolve, reject) => {
- const endowment = 1000000000000000n;
const initValue = true;
const unsub = await blueprint.tx
@@ -39,28 +42,25 @@
});
}
-function runTransaction(privateKey: IKeyringPair, extrinsic: SubmittableExtrinsic<ApiTypes>) {
- return new Promise<void>(async (resolve, reject) => {
- extrinsic.signAndSend(privateKey, async result => {
- if(!result.isInBlock) {
- return;
- }
+async function prepareDeployer(api: ApiPromise) {
+ // Find unused address
+ const deployer = await findUnusedAddress(api);
+
+ // Transfer balance to it
+ const keyring = new Keyring({ type: 'sr25519' });
+ const alice = keyring.addFromUri(`//Alice`);
+ let amount = new BigNumber(endowment);
+ amount = amount.plus(1e15);
+ const tx = api.tx.balances.transfer(deployer.address, amount.toFixed());
+ await submitTransactionAsync(alice, tx);
- if(result.findRecord('system', 'ExtrinsicSuccess')) {
- resolve();
- }
- else {
- reject('Failed to flip value.');
- }
- })
- });
+ return deployer;
}
-describe('Contracts', () => {
+describe('Contracts smoke test', () => {
it(`Can deploy smart contract Flipper, instantiate it and call it's get and flip messages.`, async () => {
await usingApi(async api => {
- const keyring = new Keyring({ type: 'sr25519' });
- const alice = keyring.addFromUri("//Alice");
+ const deployer = await prepareDeployer(api);
const wasm = fs.readFileSync('./src/flipper/flipper.wasm');
@@ -69,11 +69,11 @@
const code = new CodePromise(api, abi, wasm);
- const blueprint = await deployBlueprint(alice, code);
- const contract = (await deployContract(alice, blueprint))['contract'];
+ const blueprint = await deployBlueprint(deployer, code);
+ const contract = (await deployContract(deployer, blueprint))['contract'];
const getFlipValue = async () => {
- const result = await contract.query.get(alice.address, value, gasLimit);
+ const result = await contract.query.get(deployer.address, value, gasLimit);
if(!result.result.isSuccess) {
throw `Failed to get flipper value`;
@@ -85,7 +85,7 @@
expect(initialGetResponse).to.be.true;
const flip = contract.exec('flip', value, gasLimit);
- await runTransaction(alice, flip);
+ await submitTransactionAsync(deployer, flip);
const afterFlipGetResponse = await getFlipValue();
@@ -112,7 +112,7 @@
// const bob = new GenericAccountId(api.registry, bobsPublicKey);
// const transfer = contractInstance.exec('balance_transfer', 0, 1000000000000n, [bob, new u128(api.registry, 1000000)]);
- // await runTransaction(alicesPrivateKey, transfer);
+ // await submitTransactionAsync(alicesPrivateKey, transfer);
// const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);
tests/src/creditFeesToTreasury.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/creditFeesToTreasury.test.ts
@@ -0,0 +1,107 @@
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api";
+import { alicesPublicKey, bobsPublicKey } from "./accounts";
+import privateKey from "./substrate/privateKey";
+import { BigNumber } from 'bignumber.js';
+import { createCollectionExpectSuccess, getGenericResult } from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+const Treasury = "5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z";
+const saneMinimumFee = 0.0001;
+const saneMaximumFee = 0.01;
+
+describe('integration test: Fees must be credited to Treasury:', () => {
+ it('Total issuance does not change', async () => {
+ await usingApi(async (api) => {
+ const totalBefore = new BigNumber((await api.query.balances.totalIssuance()).toString());
+
+ const alicePrivateKey = privateKey('//Alice');
+ const amount = new BigNumber(1);
+ const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());
+
+ const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));
+
+ const totalAfter = new BigNumber((await api.query.balances.totalIssuance()).toString());
+
+ expect(result.success).to.be.true;
+ expect(totalAfter.toFixed()).to.be.equal(totalBefore.toFixed());
+ });
+ });
+
+ it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {
+ await usingApi(async (api) => {
+ const alicePrivateKey = privateKey('//Alice');
+ const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+
+ const amount = new BigNumber(1);
+ const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());
+ const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));
+
+ const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+ const fee = aliceBalanceBefore.minus(aliceBalanceAfter).minus(amount);
+ const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+ expect(result.success).to.be.true;
+ expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
+ });
+ });
+
+ it('Treasury balance increased by failed tx fee', async () => {
+ await usingApi(async (api) => {
+ const bobPrivateKey = privateKey('//Bob');
+ const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const bobBalanceBefore = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());
+
+ const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0);
+ const result = getGenericResult(await submitTransactionAsync(bobPrivateKey, badTx));
+
+ const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const bobBalanceAfter = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());
+ const fee = bobBalanceBefore.minus(bobBalanceAfter);
+ const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+ expect(result.success).to.be.false;
+ expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
+ });
+ });
+
+ it('NFT Transactions also send fees to Treasury', async () => {
+ await usingApi(async (api) => {
+ const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+
+ await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+
+ const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+ const fee = aliceBalanceBefore.minus(aliceBalanceAfter);
+ const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+ expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
+ });
+ });
+
+ it('Fees are sane', async () => {
+ await usingApi(async (api) => {
+ const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+
+ await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
+
+ const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
+ const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
+ const fee = aliceBalanceBefore.minus(aliceBalanceAfter);
+ const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
+
+ expect(fee.dividedBy(1e15).toNumber()).to.be.lessThan(0.01);
+ expect(fee.dividedBy(1e15).toNumber()).to.be.greaterThan(0.0001);
+ });
+ });
+
+});
+
tests/src/crefitFeesToTreasury.test.tsdiffbeforeafterboth--- a/tests/src/crefitFeesToTreasury.test.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import { default as usingApi, submitTransactionAsync } from "./substrate/substrate-api";
-import { alicesPublicKey, bobsPublicKey } from "./accounts";
-import privateKey from "./substrate/privateKey";
-import { BigNumber } from 'bignumber.js';
-import { createCollectionExpectSuccess, getGenericResult } from './util/helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-const Treasury = "5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z";
-const saneMinimumFee = 0.0001;
-const saneMaximumFee = 0.01;
-
-describe('integration test: Fees must be credited to Treasury:', () => {
- it('Total issuance does not change', async () => {
- await usingApi(async (api) => {
- const totalBefore = new BigNumber((await api.query.balances.totalIssuance()).toString());
-
- const alicePrivateKey = privateKey('//Alice');
- const amount = new BigNumber(1);
- const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());
-
- const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));
-
- const totalAfter = new BigNumber((await api.query.balances.totalIssuance()).toString());
-
- expect(result.success).to.be.true;
- expect(totalAfter.toFixed()).to.be.equal(totalBefore.toFixed());
- });
- });
-
- it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {
- await usingApi(async (api) => {
- const alicePrivateKey = privateKey('//Alice');
- const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
-
- const amount = new BigNumber(1);
- const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());
- const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));
-
- const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
- const fee = aliceBalanceBefore.minus(aliceBalanceAfter).minus(amount);
- const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
-
- expect(result.success).to.be.true;
- expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
- });
- });
-
- it('Treasury balance increased by failed tx fee', async () => {
- await usingApi(async (api) => {
- const bobPrivateKey = privateKey('//Bob');
- const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const bobBalanceBefore = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());
-
- const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0);
- const result = getGenericResult(await submitTransactionAsync(bobPrivateKey, badTx));
-
- const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const bobBalanceAfter = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());
- const fee = bobBalanceBefore.minus(bobBalanceAfter);
- const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
-
- expect(result.success).to.be.false;
- expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
- });
- });
-
- it('NFT Transactions also send fees to Treasury', async () => {
- await usingApi(async (api) => {
- const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
-
- await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
-
- const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
- const fee = aliceBalanceBefore.minus(aliceBalanceAfter);
- const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
-
- expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());
- });
- });
-
- it('Fees are sane', async () => {
- await usingApi(async (api) => {
- const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
-
- await createCollectionExpectSuccess('A', 'B', 'C', 'NFT');
-
- const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());
- const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());
- const fee = aliceBalanceBefore.minus(aliceBalanceAfter);
- const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);
-
- expect(fee.dividedBy(1e15).toNumber()).to.be.lessThan(0.01);
- expect(fee.dividedBy(1e15).toNumber()).to.be.greaterThan(0.0001);
- });
- });
-
-});
-
tests/src/pallet-presence.test.tsdiffbeforeafterboth--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -6,20 +6,34 @@
return api.runtimeMetadata.asLatest.modules.map(m => m.name.toString().toLowerCase());
}
-describe('Pallet presence.', () => {
- it('NFT pallet is present.', async () => {
+// Pallets that must always be present
+const requiredPallets = [
+ 'nft', 'balances', 'contracts', 'randomnesscollectiveflip', 'system', 'timestamp', 'transactionpayment', 'treasury', 'vesting'
+];
+
+// Pallets that depend on consensus and governance configuration
+const consensusPallets = [
+ 'sudo', 'grandpa', 'aura'
+];
+
+describe('Pallet presence', () => {
+ it('Required pallets are present', async () => {
await usingApi(async api => {
- expect(getModuleNames(api)).to.include('nft');
+ for (let i=0; i<requiredPallets.length; i++) {
+ expect(getModuleNames(api)).to.include(requiredPallets[i]);
+ }
});
});
- it('Balances pallet is present.', async () => {
+ it('Governance and consensus pallets are present', async () => {
await usingApi(async api => {
- expect(getModuleNames(api)).to.include('balances');
+ for (let i=0; i<consensusPallets.length; i++) {
+ expect(getModuleNames(api)).to.include(consensusPallets[i]);
+ }
});
});
- it('Contracts pallet is present.', async () => {
+ it('No extra pallets are included', async () => {
await usingApi(async api => {
- expect(getModuleNames(api)).to.include('contracts');
+ expect(getModuleNames(api).length).to.be.equal(requiredPallets.length + consensusPallets.length);
});
});
});
tests/src/transfer.test.tsdiffbeforeafterboth--- a/tests/src/transfer.test.ts
+++ b/tests/src/transfer.test.ts
@@ -3,6 +3,8 @@
import { alicesPublicKey, bobsPublicKey, ferdiesPublicKey } from "./accounts";
import privateKey from "./substrate/privateKey";
import getBalance from "./substrate/get-balance";
+import { BigNumber } from 'bignumber.js';
+import { findUnusedAddress } from './util/helpers'
describe('Transfer', () => {
it('Balance transfers', async () => {
@@ -23,7 +25,8 @@
it('Inability to pay fees error message is correct', async () => {
await usingApi(async api => {
- const pk = privateKey('//Ferdie');
+ // Find unused address
+ const pk = await findUnusedAddress(api);
console.log = function () {};
console.error = function () {};
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -1,10 +1,13 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
-import type { EventRecord } from '@polkadot/types/interfaces';
+import type { AccountId, EventRecord } from '@polkadot/types/interfaces';
+import { ApiPromise, Keyring } from "@polkadot/api";
import { default as usingApi, submitTransactionAsync } from "../substrate/substrate-api";
import privateKey from '../substrate/privateKey';
import { alicesPublicKey } from "../accounts";
import { strToUTF16, utf16ToStr, hexToStr } from '../util/util';
+import { IKeyringPair } from "@polkadot/types/types";
+import { BigNumber } from 'bignumber.js';
chai.use(chaiAsPromised);
const expect = chai.expect;
@@ -98,3 +101,14 @@
});
}
+export async function findUnusedAddress(api: ApiPromise): Promise<IKeyringPair> {
+ let bal = new BigNumber(0);
+ let unused;
+ do {
+ const randomSeed = 'seed' + Math.floor(Math.random() * Math.floor(10000));
+ const keyring = new Keyring({ type: 'sr25519' });
+ unused = keyring.addFromUri(`//${randomSeed}`);
+ bal = new BigNumber((await api.query.system.account(unused.address)).data.free.toString());
+ } while (bal.toFixed() != '0');
+ return unused;
+}
\ No newline at end of file