--- a/Cargo.lock +++ b/Cargo.lock @@ -113,6 +113,20 @@ checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8" [[package]] +name = "app-promotion-rpc" +version = "0.1.0" +dependencies = [ + "pallet-common", + "pallet-evm", + "parity-scale-codec 3.1.5", + "sp-api", + "sp-core", + "sp-runtime", + "sp-std", + "up-data-structs", +] + +[[package]] name = "approx" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5127,6 +5141,7 @@ name = "opal-runtime" version = "0.9.27" dependencies = [ + "app-promotion-rpc", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -5150,6 +5165,7 @@ "hex-literal", "log", "orml-vesting", + "pallet-app-promotion", "pallet-aura", "pallet-balances", "pallet-base-fee", @@ -5296,6 +5312,31 @@ ] [[package]] +name = "pallet-app-promotion" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "pallet-common", + "pallet-evm", + "pallet-evm-contract-helpers", + "pallet-evm-migration", + "pallet-randomness-collective-flip", + "pallet-timestamp", + "pallet-unique", + "parity-scale-codec 3.1.5", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "up-data-structs", +] + +[[package]] name = "pallet-aura" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.27#8eff668a42325aeb4433eace1604f4d286a6ec05" @@ -5694,6 +5735,7 @@ name = "pallet-evm-contract-helpers" version = "0.2.0" dependencies = [ + "ethereum", "evm-coder", "fp-evm-mapping", "frame-support", @@ -6432,7 +6474,7 @@ [[package]] name = "pallet-unique" -version = "0.1.3" +version = "0.1.4" dependencies = [ "ethereum", "evm-coder", @@ -8332,6 +8374,7 @@ name = "quartz-runtime" version = "0.9.27" dependencies = [ + "app-promotion-rpc", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -8355,6 +8398,7 @@ "hex-literal", "log", "orml-vesting", + "pallet-app-promotion", "pallet-aura", "pallet-balances", "pallet-base-fee", @@ -12103,9 +12147,10 @@ [[package]] name = "uc-rpc" -version = "0.1.3" +version = "0.1.4" dependencies = [ "anyhow", + "app-promotion-rpc", "jsonrpsee", "pallet-common", "pallet-evm", @@ -12184,6 +12229,7 @@ name = "unique-node" version = "0.9.27" dependencies = [ + "app-promotion-rpc", "clap", "cumulus-client-cli", "cumulus-client-collator", @@ -12272,6 +12318,7 @@ name = "unique-rpc" version = "0.1.1" dependencies = [ + "app-promotion-rpc", "fc-db", "fc-mapping-sync", "fc-rpc", @@ -12321,6 +12368,7 @@ name = "unique-runtime" version = "0.9.27" dependencies = [ + "app-promotion-rpc", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -12344,6 +12392,7 @@ "hex-literal", "log", "orml-vesting", + "pallet-app-promotion", "pallet-aura", "pallet-balances", "pallet-base-fee", --- a/Makefile +++ b/Makefile @@ -128,5 +128,9 @@ bench-rmrk-equip: make _bench PALLET=proxy-rmrk-equip +.PHONY: bench-app-promotion +bench-app-promotion: + make _bench PALLET=app-promotion PALLET_DIR=app-promotion + .PHONY: bench bench: bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-scheduler bench-rmrk-core bench-rmrk-equip --- a/client/rpc/CHANGELOG.md +++ b/client/rpc/CHANGELOG.md @@ -3,15 +3,21 @@ All notable changes to this project will be documented in this file. + +## [v0.1.4] 2022-09-08 + +### Added +- Support RPC for `AppPromotion` pallet. + ## [v0.1.3] 2022-08-16 ### Other changes -- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a +- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a -- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8 +- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8 -- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b +- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b ## [0.1.2] - 2022-08-12 --- a/client/rpc/Cargo.toml +++ b/client/rpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uc-rpc" -version = "0.1.3" +version = "0.1.4" license = "GPLv3" edition = "2021" @@ -8,6 +8,7 @@ pallet-common = { default-features = false, path = '../../pallets/common' } up-data-structs = { default-features = false, path = '../../primitives/data-structs' } up-rpc = { path = "../../primitives/rpc" } +app-promotion-rpc = { path = "../../primitives/app_promotion_rpc"} rmrk-rpc = { path = "../../primitives/rmrk-rpc" } codec = { package = "parity-scale-codec", version = "3.1.2" } jsonrpsee = { version = "0.14.0", features = ["server", "macros"] } --- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -23,6 +23,7 @@ proc_macros::rpc, }; use anyhow::anyhow; +use sp_runtime::traits::{AtLeast32BitUnsigned, Member}; use up_data_structs::{ RpcCollection, CollectionId, CollectionStats, CollectionLimits, TokenId, Property, PropertyKeyPermission, TokenData, TokenChild, @@ -30,6 +31,7 @@ use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt}; use sp_blockchain::HeaderBackend; use up_rpc::UniqueApi as UniqueRuntimeApi; +use app_promotion_rpc::AppPromotionApi as AppPromotionRuntimeApi; // RMRK use rmrk_rpc::RmrkApi as RmrkRuntimeApi; @@ -37,6 +39,7 @@ RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId, }; +pub use app_promotion_unique_rpc::AppPromotionApiServer; pub use rmrk_unique_rpc::RmrkApiServer; #[rpc(server)] @@ -245,6 +248,46 @@ ) -> Result>; } +mod app_promotion_unique_rpc { + use super::*; + + #[rpc(server)] + #[async_trait] + pub trait AppPromotionApi { + /// Returns the total amount of staked tokens. + #[method(name = "appPromotion_totalStaked")] + fn total_staked( + &self, + staker: Option, + at: Option, + ) -> Result; + + ///Returns the total amount of staked tokens per block when staked. + #[method(name = "appPromotion_totalStakedPerBlock")] + fn total_staked_per_block( + &self, + staker: CrossAccountId, + at: Option, + ) -> Result>; + + /// Returns the total amount of tokens pending withdrawal from staking. + #[method(name = "appPromotion_pendingUnstake")] + fn pending_unstake( + &self, + staker: Option, + at: Option, + ) -> Result; + + /// Returns the total amount of tokens pending withdrawal from staking per block. + #[method(name = "appPromotion_pendingUnstakePerBlock")] + fn pending_unstake_per_block( + &self, + staker: CrossAccountId, + at: Option, + ) -> Result>; + } +} + mod rmrk_unique_rpc { use super::*; @@ -367,34 +410,28 @@ } } -pub struct Unique { - client: Arc, - _marker: std::marker::PhantomData

, -} +macro_rules! define_struct_for_server_api { + ($name:ident) => { + pub struct $name { + client: Arc, + _marker: std::marker::PhantomData

, + } -impl Unique { - pub fn new(client: Arc) -> Self { - Self { - client, - _marker: Default::default(), + impl $name { + pub fn new(client: Arc) -> Self { + Self { + client, + _marker: Default::default(), + } + } } - } + }; } -pub struct Rmrk { - client: Arc, - _marker: std::marker::PhantomData

, -} +define_struct_for_server_api!(Unique); +define_struct_for_server_api!(AppPromotion); +define_struct_for_server_api!(Rmrk); -impl Rmrk { - pub fn new(client: Arc) -> Self { - Self { - client, - _marker: Default::default(), - } - } -} - macro_rules! pass_method { ( $method_name:ident( @@ -440,6 +477,12 @@ }; } +macro_rules! app_promotion_api { + () => { + dyn AppPromotionRuntimeApi + }; +} + macro_rules! rmrk_api { () => { dyn RmrkRuntimeApi @@ -522,6 +565,35 @@ pass_method!(token_owners(collection: CollectionId, token: TokenId) -> Vec, unique_api); } +impl + app_promotion_unique_rpc::AppPromotionApiServer< + ::Hash, + BlockNumber, + CrossAccountId, + AccountId, + > for AppPromotion +where + Block: BlockT, + BlockNumber: Decode + Member + AtLeast32BitUnsigned, + AccountId: Decode, + C: 'static + ProvideRuntimeApi + HeaderBackend, + C::Api: AppPromotionRuntimeApi, + CrossAccountId: pallet_evm::account::CrossAccountId, +{ + pass_method!(total_staked(staker: Option) -> String => |v| v.to_string(), app_promotion_api); + pass_method!(total_staked_per_block(staker: CrossAccountId) -> Vec<(BlockNumber, String)> => + |v| v + .into_iter() + .map(|(b, a)| (b, a.to_string())) + .collect::>(), app_promotion_api); + pass_method!(pending_unstake(staker: Option) -> String => |v| v.to_string(), app_promotion_api); + pass_method!(pending_unstake_per_block(staker: CrossAccountId) -> Vec<(BlockNumber, String)> => + |v| v + .into_iter() + .map(|(b, a)| (b, a.to_string())) + .collect::>(), app_promotion_api); +} + #[allow(deprecated)] impl< C, --- /dev/null +++ b/doc/separate_rpc.md @@ -0,0 +1,123 @@ +1. Create, in the `primitives` folder, a crate with a trait for RPC generation. + ```rust + sp_api::decl_runtime_apis! { + #[api_version(2)] + pub trait ModuleNameApi + where + CrossAccountId: pallet_evm::account::CrossAccountId, + { + fn method_name(user: Option) -> Result; + } + } + ``` + +2. client/rpc/src/lib.rs + * Add a trait with the required methods. Mark it with `#[rpc(server)]` and `#[async_trait]` directives. + ```rust + #[rpc(server)] + #[async_trait] + pub trait ModuleNameApi { + #[method(name = "moduleName_methodName")] + fn method_name(&self, user: Option, at: Option) + -> Result; + } + ``` + * Don't forget to write the correct method identifier in the form `moduleName_methodName`. + * Add a structure for which the server API interface will be implemented. + ```rust + define_struct_for_server_api!(ModuleName); + ``` + * Define a macro to be used in the implementation of the server API interface. + ```rust + macro_rules! module_api { + () => { + dyn ModuleNameRuntimeApi + }; + } + ``` + * Implement a server API interface. + ```rust + impl + ModuleNameApiServer<::Hash, CrossAccountId> for ModuleName + where + Block: BlockT, + C: 'static + ProvideRuntimeApi + HeaderBackend, + C::Api: AppPromotionRuntimeApi, + CrossAccountId: pallet_evm::account::CrossAccountId, + { + pass_method!(method_name(user: Option) -> String => |v| v.to_string(), app_promotion_api); + } + ``` + +3. runtime/common/runtime_apis.rs + * Implement the `ModuleNameApi` interface for `Runtime`. Optionally, you can mark a feature flag to disable the functionality. + ```rust + impl MethodApi for Runtime { + fn method_name(user: Option) -> Result { + #[cfg(not(feature = "module"))] + return unsupported!(); + + #[cfg(feature = "module")] + return Ok(0); + } + } + ``` + +4. node/cli/src/service.rs + * Set the `MethodApi` bound in the `start_node_impl`, `start_node`, `start_dev_node` methods. + +5. node/rpc/src/lib.rs + * Add `MethodApi` bound to `create_full` method. + * Enable RPC in the `create_full` method by adding `io.merge(ModuleName::new(client.clone()).into_rpc())?;` + +6. Add a new crate (see point 1) into dependencies. + * client/rpc/Cargo.toml + * node/rpc/Cargo.toml + * runtime/opal/Cargo.toml + * runtime/quartz/Cargo.toml + * runtime/unique/Cargo.toml + +7. Create tests/src/interfaces/ModuleName/definitions.ts and describe the necessary methods in it. + ```ts + type RpcParam = { + name: string; + type: string; + isOptional?: true; + }; + + const CROSS_ACCOUNT_ID_TYPE = 'PalletEvmAccountBasicCrossAccountIdRepr'; + + const fun = (description: string, params: RpcParam[], type: string) => ({ + description, + params: [...params, atParam], + type, + }); + + export default { + types: {}, + rpc: { + methodName: fun( + 'Documentation for method', + [{name: 'user', type: CROSS_ACCOUNT_ID_TYPE, isOptional: true}], + 'u128', + ), + }, + }; + ``` + +8. Describe definitions from paragraph 7 in tests/src/interfaces/definitions.ts. + ```ts + export {default as ModuleName} from './module/definitions'; + ``` + +9. tests/src/substrate/substrate-api.ts + * Set the RPC interface in the `defaultApiOptions` function, add an entry in the `rpc` parameter + ```ts + module: defs.module.rpc, + ``` + +10. tests/src/util/playgrounds/unique.dev.ts + * Specify RPC interface in `connect` function, add entry in `rpc` parameter + ```ts + module: defs.module.rpc, + ``` \ No newline at end of file --- a/node/cli/Cargo.toml +++ b/node/cli/Cargo.toml @@ -318,6 +318,7 @@ pallet-ethereum = { git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" } unique-rpc = { default-features = false, path = "../rpc" } +app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false} rmrk-rpc = { path = "../../primitives/rmrk-rpc" } [features] --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -63,7 +63,9 @@ use fc_rpc_core::types::FilterPool; use fc_mapping_sync::{MappingSyncWorker, SyncStrategy}; -use up_common::types::opaque::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block}; +use up_common::types::opaque::{ + AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block, BlockNumber, +}; // RMRK use up_data_structs::{ @@ -362,6 +364,7 @@ + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + sp_api::ApiExt> + up_rpc::UniqueApi + + app_promotion_rpc::AppPromotionApi + rmrk_rpc::RmrkApi< Block, AccountId, @@ -663,6 +666,7 @@ + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + sp_api::ApiExt> + up_rpc::UniqueApi + + app_promotion_rpc::AppPromotionApi + rmrk_rpc::RmrkApi< Block, AccountId, @@ -807,6 +811,7 @@ + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi + sp_api::ApiExt> + up_rpc::UniqueApi + + app_promotion_rpc::AppPromotionApi + rmrk_rpc::RmrkApi< Block, AccountId, --- a/node/rpc/Cargo.toml +++ b/node/rpc/Cargo.toml @@ -53,6 +53,7 @@ pallet-unique = { path = "../../pallets/unique" } uc-rpc = { path = "../../client/rpc" } up-rpc = { path = "../../primitives/rpc" } +app-promotion-rpc = { path = "../../primitives/app_promotion_rpc"} rmrk-rpc = { path = "../../primitives/rmrk-rpc" } up-data-structs = { default-features = false, path = "../../primitives/data-structs" } --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -145,6 +145,12 @@ C::Api: fp_rpc::EthereumRuntimeRPCApi, C::Api: fp_rpc::ConvertTransactionRuntimeApi, C::Api: up_rpc::UniqueApi::CrossAccountId, AccountId>, + C::Api: app_promotion_rpc::AppPromotionApi< + Block, + BlockNumber, + ::CrossAccountId, + AccountId, + >, C::Api: rmrk_rpc::RmrkApi< Block, AccountId, @@ -169,6 +175,7 @@ EthPubSubApiServer, EthSigner, Net, NetApiServer, Web3, Web3ApiServer, }; use uc_rpc::{UniqueApiServer, Unique}; + use uc_rpc::{AppPromotionApiServer, AppPromotion}; #[cfg(not(feature = "unique-runtime"))] use uc_rpc::{RmrkApiServer, Rmrk}; @@ -227,6 +234,9 @@ io.merge(Unique::new(client.clone()).into_rpc())?; + #[cfg(not(any(feature = "unique-runtime", feature = "quartz-runtime")))] + io.merge(AppPromotion::new(client.clone()).into_rpc())?; + #[cfg(not(feature = "unique-runtime"))] io.merge(Rmrk::new(client.clone()).into_rpc())?; --- /dev/null +++ b/pallets/app-promotion/Cargo.toml @@ -0,0 +1,73 @@ +################################################################################ +# Package + +[package] +authors = ['Unique Network '] +description = 'Unique App Promotion Pallet' +edition = '2021' +homepage = 'https://unique.network' +license = 'GPLv3' +name = 'pallet-app-promotion' +repository = 'https://github.com/UniqueNetwork/unique-chain' +version = '0.1.0' + +[package.metadata.docs.rs] +targets = ['x86_64-unknown-linux-gnu'] + +[features] +default = ['std'] +runtime-benchmarks = [ + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system/runtime-benchmarks', + # 'pallet-unique/runtime-benchmarks', +] +std = [ + 'codec/std', + 'frame-benchmarking/std', + 'frame-support/std', + 'frame-system/std', + 'pallet-balances/std', + 'pallet-timestamp/std', + 'pallet-randomness-collective-flip/std', + 'pallet-evm/std', + 'sp-io/std', + 'sp-std/std', + 'sp-runtime/std', + 'sp-core/std', + 'serde/std', + +] +[dependencies] +scale-info = { version = "2.0.1", default-features = false, features = [ + "derive", +] } +################################################################################ +# Substrate Dependencies + +codec = { default-features = false, features = ['derive'], package = 'parity-scale-codec', version = '3.1.2' } +frame-benchmarking = {default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +frame-system ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-balances ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-timestamp ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-randomness-collective-flip ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-evm ={ default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" } +sp-std ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-io ={ default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +serde = { default-features = false, features = ['derive'], version = '1.0.130' } + +################################################################################ +# local dependencies + +up-data-structs ={ default-features = false, path = "../../primitives/data-structs" } +pallet-common ={ default-features = false, path = "../common" } +pallet-unique ={ default-features = false, path = "../unique" } +pallet-evm-contract-helpers ={ default-features = false, path = "../evm-contract-helpers" } + +[dev-dependencies] +pallet-evm-migration ={ default-features = false, path = "../evm-migration" } + +################################################################################ --- /dev/null +++ b/pallets/app-promotion/src/benchmarking.rs @@ -0,0 +1,162 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use crate::Pallet as PromototionPallet; + +use sp_runtime::traits::Bounded; +use sp_std::vec; + +use frame_benchmarking::{benchmarks, account}; +use frame_support::traits::OnInitialize; +use frame_system::{Origin, RawOrigin}; +use pallet_unique::benchmarking::create_nft_collection; +use pallet_evm_migration::Pallet as EvmMigrationPallet; + +const SEED: u32 = 0; + +fn set_admin() -> Result +where + T: Config + pallet_unique::Config + pallet_evm_migration::Config, + T::BlockNumber: From + Into, + <::Currency as Currency>::Balance: Sum + From, +{ + let pallet_admin = account::("admin", 0, SEED); + + ::Currency::make_free_balance_be( + &pallet_admin, + Perbill::from_rational(1u32, 2) * BalanceOf::::max_value(), + ); + + PromototionPallet::::set_admin_address( + RawOrigin::Root.into(), + T::CrossAccountId::from_sub(pallet_admin.clone()), + )?; + + Ok(pallet_admin) +} + +benchmarks! { + where_clause{ + where T: Config + pallet_unique::Config + pallet_evm_migration::Config , + T::BlockNumber: From + Into, + <::Currency as Currency>::Balance: Sum + From + } + + on_initialize { + let b in 0..PENDING_LIMIT_PER_BLOCK; + set_admin::()?; + + (0..b).try_for_each(|index| { + let staker = account::("staker", index, SEED); + ::Currency::make_free_balance_be(&staker, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + PromototionPallet::::stake(RawOrigin::Signed(staker.clone()).into(), Into::>::into(100u128) * T::Nominal::get())?; + PromototionPallet::::unstake(RawOrigin::Signed(staker.clone()).into()).map_err(|e| e.error)?; + Result::<(), sp_runtime::DispatchError>::Ok(()) + })?; + let block_number = >::current_block_number() + T::PendingInterval::get(); + }: {PromototionPallet::::on_initialize(block_number)} + + set_admin_address { + let pallet_admin = account::("admin", 0, SEED); + let _ = ::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + } : _(RawOrigin::Root, T::CrossAccountId::from_sub(pallet_admin)) + + payout_stakers{ + let b in 1..101; + + let pallet_admin = account::("admin", 1, SEED); + let share = Perbill::from_rational(1u32, 20); + PromototionPallet::::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?; + ::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + + let staker: T::AccountId = account("caller", 0, SEED); + ::Currency::make_free_balance_be(&staker, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + let stakers: Vec = (0..b).map(|index| account("staker", index, SEED)).collect(); + stakers.iter().for_each(|staker| { + ::Currency::make_free_balance_be(&staker, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + }); + (0..10).try_for_each(|_| { + stakers.iter() + .map(|staker| { + PromototionPallet::::stake(RawOrigin::Signed(staker.clone()).into(), Into::>::into(100u128) * T::Nominal::get()) + }).collect::, _>>()?; + >::finalize(); + Result::<(), sp_runtime::DispatchError>::Ok(()) + })?; + } : _(RawOrigin::Signed(pallet_admin.clone()), Some(b as u8)) + + stake { + let caller = account::("caller", 0, SEED); + let share = Perbill::from_rational(1u32, 10); + let _ = ::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + } : _(RawOrigin::Signed(caller.clone()), share * ::Currency::total_balance(&caller)) + + unstake { + let caller = account::("caller", 0, SEED); + let share = Perbill::from_rational(1u32, 20); + let _ = ::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + (0..10).map(|_| { + >::finalize(); + PromototionPallet::::stake(RawOrigin::Signed(caller.clone()).into(), share * ::Currency::total_balance(&caller)) + }).collect::, _>>()?; + + } : _(RawOrigin::Signed(caller.clone())) + + sponsor_collection { + let pallet_admin = account::("admin", 0, SEED); + PromototionPallet::::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?; + let _ = ::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + let caller: T::AccountId = account("caller", 0, SEED); + let _ = ::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + let collection = create_nft_collection::(caller.clone())?; + } : _(RawOrigin::Signed(pallet_admin.clone()), collection) + + stop_sponsoring_collection { + let pallet_admin = account::("admin", 0, SEED); + PromototionPallet::::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?; + let _ = ::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + let caller: T::AccountId = account("caller", 0, SEED); + let _ = ::Currency::make_free_balance_be(&caller, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + let collection = create_nft_collection::(caller.clone())?; + PromototionPallet::::sponsor_collection(RawOrigin::Signed(pallet_admin.clone()).into(), collection)?; + } : _(RawOrigin::Signed(pallet_admin.clone()), collection) + + sponsor_contract { + let pallet_admin = account::("admin", 0, SEED); + PromototionPallet::::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?; + + let _ = ::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + let address = H160::from_low_u64_be(SEED as u64); + let data: Vec = (0..20 as u8).collect(); + >::begin(RawOrigin::Root.into(), address)?; + >::finish(RawOrigin::Root.into(), address, data)?; + } : _(RawOrigin::Signed(pallet_admin.clone()), address) + + stop_sponsoring_contract { + let pallet_admin = account::("admin", 0, SEED); + PromototionPallet::::set_admin_address(RawOrigin::Root.into(), T::CrossAccountId::from_sub(pallet_admin.clone()))?; + + let _ = ::Currency::make_free_balance_be(&pallet_admin, Perbill::from_rational(1u32, 2) * BalanceOf::::max_value()); + let address = H160::from_low_u64_be(SEED as u64); + let data: Vec = (0..20 as u8).collect(); + >::begin(RawOrigin::Root.into(), address)?; + >::finish(RawOrigin::Root.into(), address, data)?; + PromototionPallet::::sponsor_contract(RawOrigin::Signed(pallet_admin.clone()).into(), address)?; + } : _(RawOrigin::Signed(pallet_admin.clone()), address) +} --- /dev/null +++ b/pallets/app-promotion/src/lib.rs @@ -0,0 +1,758 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +//! # App promotion +//! +//! The app promotion pallet is designed to ... . +//! +//! ## Interface +//! +//! ### Dispatchable Functions +//! + +// #![recursion_limit = "1024"] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +pub mod types; +pub mod weights; + +use sp_std::{ + vec::{Vec}, + vec, + iter::Sum, + borrow::ToOwned, + cell::RefCell, +}; +use sp_core::H160; +use codec::EncodeLike; +use pallet_balances::BalanceLock; +pub use types::*; + +use up_data_structs::CollectionId; + +use frame_support::{ + dispatch::{DispatchResult}, + traits::{ + Currency, Get, LockableCurrency, WithdrawReasons, tokens::Balance, ExistenceRequirement, + }, + ensure, +}; + +use weights::WeightInfo; + +pub use pallet::*; +use pallet_evm::account::CrossAccountId; +use sp_runtime::{ + Perbill, + traits::{BlockNumberProvider, CheckedAdd, CheckedSub, AccountIdConversion, Zero}, + ArithmeticError, +}; + +pub const LOCK_IDENTIFIER: [u8; 8] = *b"appstake"; + +const PENDING_LIMIT_PER_BLOCK: u32 = 3; + +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::{ + Blake2_128Concat, Twox64Concat, pallet_prelude::*, storage::Key, PalletId, + traits::ReservableCurrency, + }; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config + pallet_evm::account::Config { + /// Type to interact with the native token + type Currency: ExtendedLockableCurrency + + ReservableCurrency; + + /// Type for interacting with collections + type CollectionHandler: CollectionHandler< + AccountId = Self::AccountId, + CollectionId = CollectionId, + >; + + /// Type for interacting with conrtacts + type ContractHandler: ContractHandler; + + /// ID for treasury + type TreasuryAccountId: Get; + + /// The app's pallet id, used for deriving its sovereign account ID. + #[pallet::constant] + type PalletId: Get; + + /// In relay blocks. + #[pallet::constant] + type RecalculationInterval: Get; + + /// In parachain blocks. + #[pallet::constant] + type PendingInterval: Get; + + /// Rate of return for interval in blocks defined in `RecalculationInterval`. + #[pallet::constant] + type IntervalIncome: Get; + + /// Decimals for the `Currency`. + #[pallet::constant] + type Nominal: Get>; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + + // The relay block number provider + type RelayBlockNumberProvider: BlockNumberProvider; + + /// Events compatible with [`frame_system::Config::Event`]. + type Event: IsType<::Event> + From>; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::event] + #[pallet::generate_deposit(fn deposit_event)] + pub enum Event { + /// Staking recalculation was performed + /// + /// # Arguments + /// * AccountId: ID of the staker. + /// * Balance : recalculation base + /// * Balance : total income + StakingRecalculation( + /// An recalculated staker + T::AccountId, + /// Base on which interest is calculated + BalanceOf, + /// Amount of accrued interest + BalanceOf, + ), + + /// Staking was performed + /// + /// # Arguments + /// * AccountId: ID of the staker + /// * Balance : staking amount + Stake(T::AccountId, BalanceOf), + + /// Unstaking was performed + /// + /// # Arguments + /// * AccountId: ID of the staker + /// * Balance : unstaking amount + Unstake(T::AccountId, BalanceOf), + + /// The admin was set + /// + /// # Arguments + /// * AccountId: ID of the admin + SetAdmin(T::AccountId), + } + + #[pallet::error] + pub enum Error { + /// Error due to action requiring admin to be set. + AdminNotSet, + /// No permission to perform an action. + NoPermission, + /// Insufficient funds to perform an action. + NotSufficientFunds, + /// Occurs when a pending unstake cannot be added in this block. PENDING_LIMIT_PER_BLOCK` limits exceeded. + PendingForBlockOverflow, + /// The error is due to the fact that the collection/contract must already be sponsored in order to perform the action. + SponsorNotSet, + /// Errors caused by incorrect actions with a locked balance. + IncorrectLockedBalanceOperation, + } + + #[pallet::storage] + pub type TotalStaked = StorageValue, QueryKind = ValueQuery>; + + #[pallet::storage] + pub type Admin = StorageValue; + + /// Amount of tokens staked by account in the blocknumber. + #[pallet::storage] + pub type Staked = StorageNMap< + Key = ( + Key, + Key, + ), + Value = (BalanceOf, T::BlockNumber), + QueryKind = ValueQuery, + >; + /// Amount of stakes for an Account + #[pallet::storage] + pub type StakesPerAccount = + StorageMap<_, Blake2_128Concat, T::AccountId, u8, ValueQuery>; + + #[pallet::storage] + pub type PendingUnstake = StorageMap< + _, + Twox64Concat, + T::BlockNumber, + BoundedVec<(T::AccountId, BalanceOf), ConstU32>, + ValueQuery, + >; + + /// Stores a key for record for which the next revenue recalculation would be performed. + /// If `None`, then recalculation has not yet been performed or calculations have been completed for all stakers. + #[pallet::storage] + #[pallet::getter(fn get_next_calculated_record)] + pub type NextCalculatedRecord = + StorageValue; + + #[pallet::hooks] + impl Hooks> for Pallet { + /// Block overflow is impossible due to the fact that the unstake algorithm in on_initialize + /// implies the execution of a strictly limited number of relatively lightweight operations. + /// A separate benchmark has been implemented to scale the weight depending on the number of pendings. + fn on_initialize(current_block_number: T::BlockNumber) -> Weight + where + ::BlockNumber: From, + { + let block_pending = PendingUnstake::::take(current_block_number); + let counter = block_pending.len() as u32; + + if !block_pending.is_empty() { + block_pending.into_iter().for_each(|(staker, amount)| { + >::unreserve(&staker, amount); + }); + } + + T::WeightInfo::on_initialize(counter) + } + } + + #[pallet::call] + impl Pallet + where + T::BlockNumber: From + Into, + <::Currency as Currency>::Balance: Sum + From, + { + #[pallet::weight(T::WeightInfo::set_admin_address())] + pub fn set_admin_address(origin: OriginFor, admin: T::CrossAccountId) -> DispatchResult { + ensure_root(origin)?; + + >::set(Some(admin.as_sub().to_owned())); + + Self::deposit_event(Event::SetAdmin(admin.as_sub().to_owned())); + + Ok(()) + } + + #[pallet::weight(T::WeightInfo::stake())] + pub fn stake(staker: OriginFor, amount: BalanceOf) -> DispatchResult { + let staker_id = ensure_signed(staker)?; + + ensure!( + StakesPerAccount::::get(&staker_id) < 10, + Error::::NoPermission + ); + + ensure!( + amount >= >::from(100u128) * T::Nominal::get(), + ArithmeticError::Underflow + ); + + let balance = + <::Currency as Currency>::free_balance(&staker_id); + + <::Currency as Currency>::ensure_can_withdraw( + &staker_id, + amount, + WithdrawReasons::all(), + balance + .checked_sub(&amount) + .ok_or(ArithmeticError::Underflow)?, + )?; + + Self::add_lock_balance(&staker_id, amount)?; + + let block_number = T::RelayBlockNumberProvider::current_block_number(); + + let recalculate_after_interval: T::BlockNumber = + if block_number % T::RecalculationInterval::get() == 0u32.into() { + 1u32.into() + } else { + 2u32.into() + }; + + let recalc_block = (block_number / T::RecalculationInterval::get() + + recalculate_after_interval) + * T::RecalculationInterval::get(); + + >::insert((&staker_id, block_number), { + let mut balance_and_recalc_block = >::get((&staker_id, block_number)); + balance_and_recalc_block.0 = balance_and_recalc_block + .0 + .checked_add(&amount) + .ok_or(ArithmeticError::Overflow)?; + balance_and_recalc_block.1 = recalc_block; + balance_and_recalc_block + }); + + >::set( + >::get() + .checked_add(&amount) + .ok_or(ArithmeticError::Overflow)?, + ); + + StakesPerAccount::::mutate(&staker_id, |stakes| *stakes += 1); + + Self::deposit_event(Event::Stake(staker_id, amount)); + + Ok(()) + } + + #[pallet::weight(T::WeightInfo::unstake())] + pub fn unstake(staker: OriginFor) -> DispatchResultWithPostInfo { + let staker_id = ensure_signed(staker)?; + let block = >::block_number() + T::PendingInterval::get(); + let mut pendings = >::get(block); + + ensure!(!pendings.is_full(), Error::::PendingForBlockOverflow); + + let mut total_stakes = 0u64; + + let total_staked: BalanceOf = Staked::::drain_prefix((&staker_id,)) + .map(|(_, (amount, _))| { + total_stakes += 1; + amount + }) + .sum(); + + if total_staked.is_zero() { + return Ok(None.into()); // TO-DO + } + + pendings + .try_push((staker_id.clone(), total_staked)) + .map_err(|_| Error::::PendingForBlockOverflow)?; + + >::insert(block, pendings); + + Self::unlock_balance(&staker_id, total_staked)?; + + >::reserve(&staker_id, total_staked)?; + + TotalStaked::::set( + TotalStaked::::get() + .checked_sub(&total_staked) + .ok_or(ArithmeticError::Underflow)?, + ); + + StakesPerAccount::::remove(&staker_id); + + Self::deposit_event(Event::Unstake(staker_id, total_staked)); + + Ok(None.into()) + } + + #[pallet::weight(T::WeightInfo::sponsor_collection())] + pub fn sponsor_collection( + admin: OriginFor, + collection_id: CollectionId, + ) -> DispatchResult { + let admin_id = ensure_signed(admin)?; + ensure!( + admin_id == Admin::::get().ok_or(Error::::AdminNotSet)?, + Error::::NoPermission + ); + + T::CollectionHandler::set_sponsor(Self::account_id(), collection_id) + } + #[pallet::weight(T::WeightInfo::stop_sponsoring_collection())] + pub fn stop_sponsoring_collection( + admin: OriginFor, + collection_id: CollectionId, + ) -> DispatchResult { + let admin_id = ensure_signed(admin)?; + + ensure!( + admin_id == Admin::::get().ok_or(Error::::AdminNotSet)?, + Error::::NoPermission + ); + + ensure!( + T::CollectionHandler::sponsor(collection_id)?.ok_or(>::SponsorNotSet)? + == Self::account_id(), + >::NoPermission + ); + T::CollectionHandler::remove_collection_sponsor(collection_id) + } + + #[pallet::weight(T::WeightInfo::sponsor_contract())] + pub fn sponsor_contract(admin: OriginFor, contract_id: H160) -> DispatchResult { + let admin_id = ensure_signed(admin)?; + + ensure!( + admin_id == Admin::::get().ok_or(Error::::AdminNotSet)?, + Error::::NoPermission + ); + + T::ContractHandler::set_sponsor( + T::CrossAccountId::from_sub(Self::account_id()), + contract_id, + ) + } + + #[pallet::weight(T::WeightInfo::stop_sponsoring_contract())] + pub fn stop_sponsoring_contract(admin: OriginFor, contract_id: H160) -> DispatchResult { + let admin_id = ensure_signed(admin)?; + + ensure!( + admin_id == Admin::::get().ok_or(Error::::AdminNotSet)?, + Error::::NoPermission + ); + + ensure!( + T::ContractHandler::sponsor(contract_id)? + .ok_or(>::SponsorNotSet)? + .as_sub() == &Self::account_id(), + >::NoPermission + ); + T::ContractHandler::remove_contract_sponsor(contract_id) + } + + #[pallet::weight(T::WeightInfo::payout_stakers(stakers_number.unwrap_or(20) as u32))] + pub fn payout_stakers(admin: OriginFor, stakers_number: Option) -> DispatchResult { + let admin_id = ensure_signed(admin)?; + + ensure!( + admin_id == Admin::::get().ok_or(Error::::AdminNotSet)?, + Error::::NoPermission + ); + + let current_recalc_block = + Self::get_current_recalc_block(T::RelayBlockNumberProvider::current_block_number()); + let next_recalc_block = current_recalc_block + T::RecalculationInterval::get(); + + let mut storage_iterator = Self::get_next_calculated_key() + .map_or(Staked::::iter(), |key| Staked::::iter_from(key)); + + NextCalculatedRecord::::set(None); + + // { + // let mut stakers_number = stakers_number.unwrap_or(20); + // let mut last_id = admin_id; + // let mut income_acc = BalanceOf::::default(); + // let mut amount_acc = BalanceOf::::default(); + + // while let Some(( + // (current_id, staked_block), + // (amount, next_recalc_block_for_stake), + // )) = storage_iterator.next() + // { + // if last_id != current_id { + // if income_acc != BalanceOf::::default() { + // >::transfer( + // &T::TreasuryAccountId::get(), + // &last_id, + // income_acc, + // ExistenceRequirement::KeepAlive, + // ) + // .and_then(|_| Self::add_lock_balance(&last_id, income_acc))?; + + // Self::deposit_event(Event::StakingRecalculation( + // last_id, amount, income_acc, + // )); + // } + + // if stakers_number == 0 { + // NextCalculatedRecord::::set(Some((current_id, staked_block))); + // break; + // } + // stakers_number -= 1; + // income_acc = BalanceOf::::default(); + // last_id = current_id; + // }; + // if current_recalc_block >= next_recalc_block_for_stake { + // Self::recalculate_and_insert_stake( + // &last_id, + // staked_block, + // next_recalc_block, + // amount, + // ((current_recalc_block - next_recalc_block_for_stake) + // / T::RecalculationInterval::get()) + // .into() + 1, + // &mut income_acc, + // ); + // } + // } + // } + + { + let mut stakers_number = stakers_number.unwrap_or(20); + let last_id = RefCell::new(None); + let income_acc = RefCell::new(BalanceOf::::default()); + let amount_acc = RefCell::new(BalanceOf::::default()); + + let flush_stake = || -> DispatchResult { + if let Some(last_id) = &*last_id.borrow() { + if !income_acc.borrow().is_zero() { + >::transfer( + &T::TreasuryAccountId::get(), + last_id, + *income_acc.borrow(), + ExistenceRequirement::KeepAlive, + ) + .and_then(|_| { + Self::add_lock_balance(last_id, *income_acc.borrow())?; + >::try_mutate(|staked| { + staked + .checked_add(&*income_acc.borrow()) + .ok_or(ArithmeticError::Overflow.into()) + }) + })?; + + Self::deposit_event(Event::StakingRecalculation( + last_id.clone(), + *amount_acc.borrow(), + *income_acc.borrow(), + )); + } + + *income_acc.borrow_mut() = BalanceOf::::default(); + *amount_acc.borrow_mut() = BalanceOf::::default(); + } + Ok(()) + }; + + while let Some(( + (current_id, staked_block), + (amount, next_recalc_block_for_stake), + )) = storage_iterator.next() + { + if stakers_number == 0 { + NextCalculatedRecord::::set(Some((current_id, staked_block))); + break; + } + if last_id.borrow().as_ref() != Some(¤t_id) { + flush_stake()?; + *last_id.borrow_mut() = Some(current_id.clone()); + stakers_number -= 1; + }; + if current_recalc_block >= next_recalc_block_for_stake { + *amount_acc.borrow_mut() += amount; + Self::recalculate_and_insert_stake( + ¤t_id, + staked_block, + next_recalc_block, + amount, + ((current_recalc_block - next_recalc_block_for_stake) + / T::RecalculationInterval::get()) + .into() + 1, + &mut *income_acc.borrow_mut(), + ); + } + } + flush_stake()?; + } + + Ok(()) + } + } +} + +impl Pallet { + pub fn account_id() -> T::AccountId { + T::PalletId::get().into_account_truncating() + } + + fn unlock_balance(staker: &T::AccountId, amount: BalanceOf) -> DispatchResult { + let locked_balance = Self::get_locked_balance(staker) + .map(|l| l.amount) + .ok_or(>::IncorrectLockedBalanceOperation)?; + + // It is understood that we cannot unlock more funds than were locked by staking. + // Therefore, if implemented correctly, this error should not occur. + Self::set_lock_unchecked( + staker, + locked_balance + .checked_sub(&amount) + .ok_or(ArithmeticError::Underflow)?, + ); + Ok(()) + } + + fn add_lock_balance(staker: &T::AccountId, amount: BalanceOf) -> DispatchResult { + Self::get_locked_balance(staker) + .map_or(>::default(), |l| l.amount) + .checked_add(&amount) + .map(|new_lock| Self::set_lock_unchecked(staker, new_lock)) + .ok_or(ArithmeticError::Overflow.into()) + } + + fn set_lock_unchecked(staker: &T::AccountId, amount: BalanceOf) { + if amount.is_zero() { + >::remove_lock(LOCK_IDENTIFIER, &staker); + } else { + >::set_lock( + LOCK_IDENTIFIER, + staker, + amount, + WithdrawReasons::all(), + ) + } + } + + pub fn get_locked_balance( + staker: impl EncodeLike, + ) -> Option>> { + >::locks(staker) + .into_iter() + .find(|l| l.id == LOCK_IDENTIFIER) + } + + pub fn total_staked_by_id(staker: impl EncodeLike) -> Option> { + let staked = Staked::::iter_prefix((staker,)) + .into_iter() + .fold(>::default(), |acc, (_, (amount, _))| { + acc + amount + }); + if staked != >::default() { + Some(staked) + } else { + None + } + } + + pub fn total_staked_by_id_per_block( + staker: impl EncodeLike, + ) -> Option)>> { + let mut staked = Staked::::iter_prefix((staker,)) + .into_iter() + .map(|(block, (amount, _))| (block, amount)) + .collect::>(); + staked.sort_by_key(|(block, _)| *block); + if !staked.is_empty() { + Some(staked) + } else { + None + } + } + + pub fn cross_id_total_staked(staker: Option) -> Option> { + staker.map_or(Some(>::get()), |s| { + Self::total_staked_by_id(s.as_sub()) + }) + } + + // pub fn cross_id_locked_balance(staker: T::CrossAccountId) -> BalanceOf { + // Self::get_locked_balance(staker.as_sub()) + // .map(|l| l.amount) + // .unwrap_or_default() + // } + + pub fn cross_id_total_staked_per_block( + staker: T::CrossAccountId, + ) -> Vec<(T::BlockNumber, BalanceOf)> { + Self::total_staked_by_id_per_block(staker.as_sub()).unwrap_or_default() + } + + fn recalculate_and_insert_stake( + staker: &T::AccountId, + staked_block: T::BlockNumber, + next_recalc_block: T::BlockNumber, + base: BalanceOf, + iters: u32, + income_acc: &mut BalanceOf, + ) { + let income = Self::calculate_income(base, iters); + + base.checked_add(&income).map(|res| { + >::insert((staker, staked_block), (res, next_recalc_block)); + *income_acc += income; + }); + } + + fn calculate_income(base: I, iters: u32) -> I + where + I: EncodeLike> + Balance, + { + let mut income = base; + + (0..iters).for_each(|_| income += T::IntervalIncome::get() * income); + + income - base + } + + fn get_current_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber { + (current_relay_block / T::RecalculationInterval::get()) * T::RecalculationInterval::get() + } + + // fn get_next_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber { + // Self::get_current_recalc_block(current_relay_block) + T::RecalculationInterval::get() + // } + + fn get_next_calculated_key() -> Option> { + Self::get_next_calculated_record().map(|key| Staked::::hashed_key_for(key)) + } +} + +impl Pallet +where + <::Currency as Currency>::Balance: Sum, +{ + /// Since user funds are not transferred anywhere by staking, overflow protection is provided + /// at the level of the associated type `Balance` of `Currency` trait. In order to overflow, + /// the staker must have more funds on his account than the maximum set for `Balance` type. + pub fn cross_id_pending_unstake(staker: Option) -> BalanceOf { + staker.map_or( + PendingUnstake::::iter_values() + .flat_map(|pendings| pendings.into_iter().map(|(_, amount)| amount)) + .sum(), + |s| { + PendingUnstake::::iter_values() + .flatten() + .filter_map(|(id, amount)| { + if id == *s.as_sub() { + Some(amount) + } else { + None + } + }) + .sum() + }, + ) + } + + pub fn cross_id_pending_unstake_per_block( + staker: T::CrossAccountId, + ) -> Vec<(T::BlockNumber, BalanceOf)> { + let mut unsorted_res = vec![]; + PendingUnstake::::iter().for_each(|(block, pendings)| { + pendings.into_iter().for_each(|(id, amount)| { + if id == *staker.as_sub() { + unsorted_res.push((block, amount)); + }; + }) + }); + + unsorted_res.sort_by_key(|(block, _)| *block); + unsorted_res + } +} --- /dev/null +++ b/pallets/app-promotion/src/types.rs @@ -0,0 +1,107 @@ +use codec::EncodeLike; +use frame_support::{traits::LockableCurrency, WeakBoundedVec, Parameter, dispatch::DispatchResult}; + +use pallet_balances::{BalanceLock, Config as BalancesConfig, Pallet as PalletBalances}; +use pallet_common::CollectionHandle; + +use sp_runtime::DispatchError; +use up_data_structs::{CollectionId}; +use sp_std::borrow::ToOwned; +use pallet_evm_contract_helpers::{Pallet as EvmHelpersPallet, Config as EvmHelpersConfig}; + +pub trait ExtendedLockableCurrency: LockableCurrency { + fn locks(who: KArg) -> WeakBoundedVec, Self::MaxLocks> + where + KArg: EncodeLike; +} + +impl, I: 'static> ExtendedLockableCurrency + for PalletBalances +{ + fn locks(who: KArg) -> WeakBoundedVec, Self::MaxLocks> + where + KArg: EncodeLike, + { + Self::locks(who) + } +} + +pub trait CollectionHandler { + type CollectionId; + type AccountId; + + fn set_sponsor( + sponsor_id: Self::AccountId, + collection_id: Self::CollectionId, + ) -> DispatchResult; + + fn remove_collection_sponsor(collection_id: Self::CollectionId) -> DispatchResult; + + fn sponsor(collection_id: Self::CollectionId) + -> Result, DispatchError>; +} + +impl CollectionHandler for pallet_unique::Pallet { + type CollectionId = CollectionId; + + type AccountId = T::AccountId; + + fn set_sponsor( + sponsor_id: Self::AccountId, + collection_id: Self::CollectionId, + ) -> DispatchResult { + Self::force_set_sponsor(sponsor_id, collection_id) + } + + fn remove_collection_sponsor(collection_id: Self::CollectionId) -> DispatchResult { + Self::force_remove_collection_sponsor(collection_id) + } + + fn sponsor( + collection_id: Self::CollectionId, + ) -> Result, DispatchError> { + Ok(>::try_get(collection_id)? + .sponsorship + .sponsor() + .map(|acc| acc.to_owned())) + } +} + +pub trait ContractHandler { + type ContractId; + type AccountId; + + fn set_sponsor( + sponsor_id: Self::AccountId, + contract_address: Self::ContractId, + ) -> DispatchResult; + + fn remove_contract_sponsor(contract_address: Self::ContractId) -> DispatchResult; + + fn sponsor( + contract_address: Self::ContractId, + ) -> Result, DispatchError>; +} + +impl ContractHandler for EvmHelpersPallet { + type ContractId = sp_core::H160; + + type AccountId = T::CrossAccountId; + + fn set_sponsor( + sponsor_id: Self::AccountId, + contract_address: Self::ContractId, + ) -> DispatchResult { + Self::force_set_sponsor(contract_address, &sponsor_id) + } + + fn remove_contract_sponsor(contract_address: Self::ContractId) -> DispatchResult { + Self::force_remove_sponsor(contract_address) + } + + fn sponsor( + contract_address: Self::ContractId, + ) -> Result, DispatchError> { + Ok(Self::get_sponsor(contract_address)) + } +} --- /dev/null +++ b/pallets/app-promotion/src/weights.rs @@ -0,0 +1,209 @@ +// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs + +//! Autogenerated weights for pallet_app_promotion +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-09-07, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// target/release/unique-collator +// benchmark +// pallet +// --pallet +// pallet-app-promotion +// --wasm-execution +// compiled +// --extrinsic +// * +// --template +// .maintain/frame-weight-template.hbs +// --steps=50 +// --repeat=80 +// --heap-pages=4096 +// --output=./pallets/app-promotion/src/weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_app_promotion. +pub trait WeightInfo { + fn on_initialize(b: u32, ) -> Weight; + fn set_admin_address() -> Weight; + fn payout_stakers(b: u32, ) -> Weight; + fn stake() -> Weight; + fn unstake() -> Weight; + fn sponsor_collection() -> Weight; + fn stop_sponsoring_collection() -> Weight; + fn sponsor_contract() -> Weight; + fn stop_sponsoring_contract() -> Weight; +} + +/// Weights for pallet_app_promotion using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: AppPromotion PendingUnstake (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn on_initialize(b: u32, ) -> Weight { + (2_651_000 as Weight) + // Standard Error: 103_000 + .saturating_add((6_024_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) + .saturating_add(T::DbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) + } + // Storage: AppPromotion Admin (r:0 w:1) + fn set_admin_address() -> Weight { + (7_117_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AppPromotion NextCalculatedRecord (r:1 w:1) + // Storage: AppPromotion Staked (r:2 w:0) + fn payout_stakers(b: u32, ) -> Weight { + (9_958_000 as Weight) + // Standard Error: 8_000 + .saturating_add((4_406_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(T::DbWeight::get().reads(4 as Weight)) + .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion StakesPerAccount (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AppPromotion Staked (r:1 w:1) + // Storage: AppPromotion TotalStaked (r:1 w:1) + fn stake() -> Weight { + (20_574_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(5 as Weight)) + } + // Storage: AppPromotion PendingUnstake (r:1 w:1) + // Storage: AppPromotion Staked (r:2 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AppPromotion TotalStaked (r:1 w:1) + // Storage: AppPromotion StakesPerAccount (r:0 w:1) + fn unstake() -> Weight { + (31_703_000 as Weight) + .saturating_add(T::DbWeight::get().reads(6 as Weight)) + .saturating_add(T::DbWeight::get().writes(6 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: Common CollectionById (r:1 w:1) + fn sponsor_collection() -> Weight { + (12_932_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: Common CollectionById (r:1 w:1) + fn stop_sponsoring_collection() -> Weight { + (12_453_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: EvmContractHelpers Sponsoring (r:0 w:1) + fn sponsor_contract() -> Weight { + (11_952_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: EvmContractHelpers Sponsoring (r:1 w:1) + fn stop_sponsoring_contract() -> Weight { + (12_538_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: AppPromotion PendingUnstake (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn on_initialize(b: u32, ) -> Weight { + (2_651_000 as Weight) + // Standard Error: 103_000 + .saturating_add((6_024_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) + .saturating_add(RocksDbWeight::get().writes((1 as Weight).saturating_mul(b as Weight))) + } + // Storage: AppPromotion Admin (r:0 w:1) + fn set_admin_address() -> Weight { + (7_117_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AppPromotion NextCalculatedRecord (r:1 w:1) + // Storage: AppPromotion Staked (r:2 w:0) + fn payout_stakers(b: u32, ) -> Weight { + (9_958_000 as Weight) + // Standard Error: 8_000 + .saturating_add((4_406_000 as Weight).saturating_mul(b as Weight)) + .saturating_add(RocksDbWeight::get().reads(4 as Weight)) + .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight))) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion StakesPerAccount (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainSystem ValidationData (r:1 w:0) + // Storage: AppPromotion Staked (r:1 w:1) + // Storage: AppPromotion TotalStaked (r:1 w:1) + fn stake() -> Weight { + (20_574_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(5 as Weight)) + } + // Storage: AppPromotion PendingUnstake (r:1 w:1) + // Storage: AppPromotion Staked (r:2 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: AppPromotion TotalStaked (r:1 w:1) + // Storage: AppPromotion StakesPerAccount (r:0 w:1) + fn unstake() -> Weight { + (31_703_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(6 as Weight)) + .saturating_add(RocksDbWeight::get().writes(6 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: Common CollectionById (r:1 w:1) + fn sponsor_collection() -> Weight { + (12_932_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: Common CollectionById (r:1 w:1) + fn stop_sponsoring_collection() -> Weight { + (12_453_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: EvmContractHelpers Sponsoring (r:0 w:1) + fn sponsor_contract() -> Weight { + (11_952_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: AppPromotion Admin (r:1 w:0) + // Storage: EvmContractHelpers Sponsoring (r:1 w:1) + fn stop_sponsoring_contract() -> Weight { + (12_538_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } +} --- a/pallets/common/Cargo.toml +++ b/pallets/common/Cargo.toml @@ -40,4 +40,7 @@ "up-data-structs/std", "pallet-evm/std", ] -runtime-benchmarks = ["frame-benchmarking"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "up-data-structs/runtime-benchmarks", +] --- a/pallets/evm-contract-helpers/Cargo.toml +++ b/pallets/evm-contract-helpers/Cargo.toml @@ -9,6 +9,7 @@ "derive", ] } log = { default-features = false, version = "0.4.14" } +ethereum = { version = "0.12.0", default-features = false } # Substrate frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } --- a/pallets/evm-contract-helpers/src/eth.rs +++ b/pallets/evm-contract-helpers/src/eth.rs @@ -17,7 +17,9 @@ //! Implementation of magic contract use core::marker::PhantomData; -use evm_coder::{abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*}; +use evm_coder::{ + abi::AbiWriter, execution::Result, generate_stubgen, solidity_interface, types::*, ToLog, +}; use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm}; use pallet_evm::{ ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle, @@ -33,6 +35,35 @@ use up_sponsorship::SponsorshipHandler; use sp_std::vec::Vec; +/// Pallet events. +#[derive(ToLog)] +pub enum ContractHelpersEvents { + /// Contract sponsor was set. + ContractSponsorSet { + /// Contract address of the affected collection. + #[indexed] + contract_address: address, + /// New sponsor address. + sponsor: address, + }, + + /// New sponsor was confirm. + ContractSponsorshipConfirmed { + /// Contract address of the affected collection. + #[indexed] + contract_address: address, + /// New sponsor address. + sponsor: address, + }, + + /// Collection sponsor was removed. + ContractSponsorRemoved { + /// Contract address of the affected collection. + #[indexed] + contract_address: address, + }, +} + /// See [`ContractHelpersCall`] pub struct ContractHelpers(SubstrateRecorder); impl WithRecorder for ContractHelpers { @@ -46,7 +77,7 @@ } /// @title Magic contract, which allows users to reconfigure other contracts -#[solidity_interface(name = ContractHelpers)] +#[solidity_interface(name = ContractHelpers, events(ContractHelpersEvents))] impl ContractHelpers where T::AccountId: AsRef<[u8; 32]>, @@ -91,9 +122,17 @@ self.recorder().consume_sload()?; self.recorder().consume_sstore()?; - Pallet::::self_sponsored_enable(&T::CrossAccountId::from_eth(caller), contract_address) + let caller = T::CrossAccountId::from_eth(caller); + + Pallet::::ensure_owner(contract_address, *caller.as_eth()) .map_err(dispatch_to_evm::)?; + Pallet::::force_set_sponsor( + contract_address, + &T::CrossAccountId::from_eth(contract_address), + ) + .map_err(dispatch_to_evm::)?; + Ok(()) } --- a/pallets/evm-contract-helpers/src/lib.rs +++ b/pallets/evm-contract-helpers/src/lib.rs @@ -16,7 +16,7 @@ #![doc = include_str!("../README.md")] #![cfg_attr(not(feature = "std"), no_std)] -#![deny(missing_docs)] +#![warn(missing_docs)] use codec::{Decode, Encode, MaxEncodedLen}; pub use pallet::*; @@ -27,18 +27,24 @@ #[frame_support::pallet] pub mod pallet { pub use super::*; + use crate::eth::ContractHelpersEvents; use frame_support::pallet_prelude::*; use pallet_evm_coder_substrate::DispatchResult; use sp_core::H160; - use pallet_evm::account::CrossAccountId; + use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm}; use up_data_structs::SponsorshipState; + use evm_coder::ToLog; #[pallet::config] pub trait Config: frame_system::Config + pallet_evm_coder_substrate::Config + pallet_evm::account::Config { + /// Overarching event type. + type Event: IsType<::Event> + From>; + /// Address, under which magic contract will be available type ContractAddress: Get; + /// In case of enabled sponsoring, but no sponsoring rate limit set, /// this value will be used implicitly type DefaultSponsoringRateLimit: Get; @@ -150,6 +156,32 @@ QueryKind = ValueQuery, >; + #[pallet::event] + #[pallet::generate_deposit(pub fn deposit_event)] + pub enum Event { + /// Contract sponsor was set. + ContractSponsorSet( + /// Contract address of the affected collection. + H160, + /// New sponsor address. + T::AccountId, + ), + + /// New sponsor was confirm. + ContractSponsorshipConfirmed( + /// Contract address of the affected collection. + H160, + /// New sponsor address. + T::AccountId, + ), + + /// Collection sponsor was removed. + ContractSponsorRemoved( + /// Contract address of the affected collection. + H160, + ), + } + impl Pallet { /// Get contract owner. pub fn contract_owner(contract: H160) -> H160 { @@ -169,43 +201,118 @@ contract, SponsorshipState::::Unconfirmed(sponsor.clone()), ); + + >::deposit_event(Event::::ContractSponsorSet( + contract, + sponsor.as_sub().clone(), + )); + >::deposit_log( + ContractHelpersEvents::ContractSponsorSet { + contract_address: contract, + sponsor: *sponsor.as_eth(), + } + .to_log(contract), + ); Ok(()) } - /// Set `contract` as self sponsored. + /// TO-DO /// - /// `sender` must be owner of contract. - pub fn self_sponsored_enable(sender: &T::CrossAccountId, contract: H160) -> DispatchResult { - Pallet::::ensure_owner(contract, *sender.as_eth())?; + /// + pub fn force_set_sponsor( + contract_address: H160, + sponsor: &T::CrossAccountId, + ) -> DispatchResult { Sponsoring::::insert( - contract, - SponsorshipState::::Confirmed(T::CrossAccountId::from_eth( - contract, - )), + contract_address, + SponsorshipState::::Confirmed(sponsor.clone()), ); + + let eth_sponsor = *sponsor.as_eth(); + let sub_sponsor = sponsor.as_sub().clone(); + + >::deposit_event(Event::::ContractSponsorSet( + contract_address, + sub_sponsor.clone(), + )); + >::deposit_log( + ContractHelpersEvents::ContractSponsorSet { + contract_address, + sponsor: eth_sponsor, + } + .to_log(contract_address), + ); + + >::deposit_event(Event::::ContractSponsorshipConfirmed( + contract_address, + sub_sponsor, + )); + >::deposit_log( + ContractHelpersEvents::ContractSponsorshipConfirmed { + contract_address, + sponsor: eth_sponsor, + } + .to_log(contract_address), + ); + Ok(()) } /// Remove sponsor for `contract`. /// /// `sender` must be owner of contract. - pub fn remove_sponsor(sender: &T::CrossAccountId, contract: H160) -> DispatchResult { - Pallet::::ensure_owner(contract, *sender.as_eth())?; - Sponsoring::::remove(contract); + pub fn remove_sponsor( + sender: &T::CrossAccountId, + contract_address: H160, + ) -> DispatchResult { + Self::ensure_owner(contract_address, *sender.as_eth())?; + Self::force_remove_sponsor(contract_address) + } + + /// TO-DO + /// + /// + pub fn force_remove_sponsor(contract_address: H160) -> DispatchResult { + Sponsoring::::remove(contract_address); + + Self::deposit_event(Event::::ContractSponsorRemoved(contract_address)); + >::deposit_log( + ContractHelpersEvents::ContractSponsorRemoved { contract_address } + .to_log(contract_address), + ); + Ok(()) } /// Confirm sponsorship. /// /// `sender` must be same that set via [`set_sponsor`]. - pub fn confirm_sponsorship(sender: &T::CrossAccountId, contract: H160) -> DispatchResult { - match Sponsoring::::get(contract) { + pub fn confirm_sponsorship( + sender: &T::CrossAccountId, + contract_address: H160, + ) -> DispatchResult { + match Sponsoring::::get(contract_address) { SponsorshipState::Unconfirmed(sponsor) => { ensure!(sponsor == *sender, Error::::NoPermission); + let eth_sponsor = *sponsor.as_eth(); + let sub_sponsor = sponsor.as_sub().clone(); Sponsoring::::insert( - contract, + contract_address, SponsorshipState::::Confirmed(sponsor), ); + + >::deposit_event(Event::::ContractSponsorshipConfirmed( + contract_address, + sub_sponsor, + )); + >::deposit_log( + ContractHelpersEvents::ContractSponsorshipConfirmed { + contract_address, + sponsor: eth_sponsor, + } + .to_log(contract_address), + ); + Ok(()) } SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => { --- a/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol +++ b/pallets/evm-contract-helpers/src/stubs/ContractHelpers.sol @@ -21,9 +21,19 @@ } } +/// @dev inlined interface +contract ContractHelpersEvents { + event ContractSponsorSet(address indexed contractAddress, address sponsor); + event ContractSponsorshipConfirmed( + address indexed contractAddress, + address sponsor + ); + event ContractSponsorRemoved(address indexed contractAddress); +} + /// @title Magic contract, which allows users to reconfigure other contracts /// @dev the ERC-165 identifier for this interface is 0xd77fab70 -contract ContractHelpers is Dummy, ERC165 { +contract ContractHelpers is Dummy, ERC165, ContractHelpersEvents { /// Get user, which deployed specified contract /// @dev May return zero address in case if contract is deployed /// using uniquenetwork evm-migration pallet, or using other terms not --- a/pallets/unique/CHANGELOG.md +++ b/pallets/unique/CHANGELOG.md @@ -3,22 +3,29 @@ All notable changes to this project will be documented in this file. + +## [v0.1.4] 2022-09-5 + +### Added + +- Methods `force_set_sponsor` , `force_remove_collection_sponsor` to be able to administer sponsorships with other pallets. Added to implement `AppPromotion` pallet logic. + ## [v0.1.3] 2022-08-16 ### Other changes -- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a +- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a -- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8 +- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8 -- refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd31 +- refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd31 Every extrinsic now runs in transaction implicitly, and `#[transactional]` on pallet dispatchable is now meaningless Upstream-Change: https://github.com/paritytech/substrate/issues/10806 -- refactor: Switch to new prefix removal methods 26734e9567589d75cdd99e404eabf11d5a97d975 +- refactor: Switch to new prefix removal methods 26734e9567589d75cdd99e404eabf11d5a97d975 New methods allows to call `remove_prefix` with limit multiple times in the same block @@ -27,10 +34,12 @@ Upstream-Change: https://github.com/paritytech/substrate/pull/11490 -- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b +- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b ## [v0.1.1] - 2022-07-25 + ### Added -- Method for creating `ERC721Metadata` compatible NFT collection. -- Method for creating `ERC721Metadata` compatible ReFungible collection. -- Method for creating ReFungible collection. + +- Method for creating `ERC721Metadata` compatible NFT collection. +- Method for creating `ERC721Metadata` compatible ReFungible collection. +- Method for creating ReFungible collection. --- a/pallets/unique/Cargo.toml +++ b/pallets/unique/Cargo.toml @@ -9,7 +9,7 @@ license = 'GPLv3' name = 'pallet-unique' repository = 'https://github.com/UniqueNetwork/unique-chain' -version = "0.1.3" +version = "0.1.4" [package.metadata.docs.rs] targets = ['x86_64-unknown-linux-gnu'] --- a/pallets/unique/src/benchmarking.rs +++ b/pallets/unique/src/benchmarking.rs @@ -46,7 +46,9 @@ )?; Ok(>::get()) } -fn create_nft_collection(owner: T::AccountId) -> Result { +pub fn create_nft_collection( + owner: T::AccountId, +) -> Result { create_collection_helper::(owner, CollectionMode::NFT) } --- a/pallets/unique/src/lib.rs +++ b/pallets/unique/src/lib.rs @@ -98,7 +98,7 @@ pub mod eth; #[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +pub mod benchmarking; pub mod weights; use weights::WeightInfo; @@ -277,7 +277,7 @@ { type Error = Error; - fn deposit_event() = default; + pub fn deposit_event() = default; fn on_initialize(_now: T::BlockNumber) -> Weight { 0 @@ -1103,3 +1103,35 @@ } } } + +impl Pallet { + pub fn force_set_sponsor(sponsor: T::AccountId, collection_id: CollectionId) -> DispatchResult { + let mut target_collection = >::try_get(collection_id)?; + target_collection.check_is_internal()?; + target_collection.set_sponsor(sponsor.clone())?; + + Self::deposit_event(Event::::CollectionSponsorSet( + collection_id, + sponsor.clone(), + )); + + ensure!( + target_collection.confirm_sponsorship(&sponsor)?, + Error::::ConfirmUnsetSponsorFail + ); + + Self::deposit_event(Event::::SponsorshipConfirmed(collection_id, sponsor)); + + target_collection.save() + } + + pub fn force_remove_collection_sponsor(collection_id: CollectionId) -> DispatchResult { + let mut target_collection = >::try_get(collection_id)?; + target_collection.check_is_internal()?; + target_collection.sponsorship = SponsorshipState::Disabled; + + Self::deposit_event(Event::::CollectionSponsorRemoved(collection_id)); + + target_collection.save() + } +} --- /dev/null +++ b/primitives/app_promotion_rpc/CHANGELOG.md @@ -0,0 +1,5 @@ +# Change Log + +All notable changes to this project will be documented in this file. + + --- /dev/null +++ b/primitives/app_promotion_rpc/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "app-promotion-rpc" +version = "0.1.0" +license = "GPLv3" +edition = "2021" + +[dependencies] +pallet-common = { default-features = false, path = '../../pallets/common' } +up-data-structs = { default-features = false, path = '../data-structs' } +codec = { package = "parity-scale-codec", version = "3.1.2", default-features = false, features = [ + "derive", +] } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-core/std", + "sp-std/std", + "sp-api/std", + "sp-runtime/std", + "pallet-common/std", + "up-data-structs/std", +] --- /dev/null +++ b/primitives/app_promotion_rpc/src/lib.rs @@ -0,0 +1,41 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::vec::Vec; +use codec::Decode; +use sp_runtime::{ + DispatchError, + traits::{AtLeast32BitUnsigned, Member}, +}; + +type Result = core::result::Result; + +sp_api::decl_runtime_apis! { + #[api_version(2)] + /// Trait for generate rpc. + pub trait AppPromotionApi where + BlockNumber: Decode + Member + AtLeast32BitUnsigned, + AccountId: Decode, + CrossAccountId: pallet_evm::account::CrossAccountId, + { + fn total_staked(staker: Option) -> Result; + fn total_staked_per_block(staker: CrossAccountId) -> Result>; + fn pending_unstake(staker: Option) -> Result; + fn pending_unstake_per_block(staker: CrossAccountId) -> Result>; + } +} --- a/primitives/common/src/constants.rs +++ b/primitives/common/src/constants.rs @@ -22,6 +22,7 @@ use crate::types::{BlockNumber, Balance}; pub const MILLISECS_PER_BLOCK: u64 = 12000; +pub const MILLISECS_PER_RELAY_BLOCK: u64 = 6000; pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; @@ -30,6 +31,11 @@ pub const HOURS: BlockNumber = MINUTES * 60; pub const DAYS: BlockNumber = HOURS * 24; +// These time units are defined in number of relay blocks. +pub const RELAY_MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_RELAY_BLOCK as BlockNumber); +pub const RELAY_HOURS: BlockNumber = RELAY_MINUTES * 60; +pub const RELAY_DAYS: BlockNumber = RELAY_HOURS * 24; + pub const MICROUNIQUE: Balance = 1_000_000_000_000; pub const MILLIUNIQUE: Balance = 1_000 * MICROUNIQUE; pub const CENTIUNIQUE: Balance = 10 * MILLIUNIQUE; --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -20,9 +20,13 @@ CollectionId, TokenId, RpcCollection, CollectionStats, CollectionLimits, Property, PropertyKeyPermission, TokenData, TokenChild, }; + use sp_std::vec::Vec; use codec::Decode; -use sp_runtime::DispatchError; +use sp_runtime::{ + DispatchError, + traits::{AtLeast32BitUnsigned, Member}, +}; type Result = core::result::Result; @@ -120,6 +124,7 @@ /// Get total pieces of token. fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Result>; + fn token_owners(collection: CollectionId, token: TokenId) -> Result>; } } --- a/runtime/common/config/ethereum.rs +++ b/runtime/common/config/ethereum.rs @@ -112,6 +112,7 @@ } impl pallet_evm_contract_helpers::Config for Runtime { + type Event = Event; type ContractAddress = HelpersContractAddress; type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit; } --- /dev/null +++ b/runtime/common/config/pallets/app_promotion.rs @@ -0,0 +1,63 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +use crate::{ + runtime_common::config::pallets::{TreasuryAccountId, RelayChainBlockNumberProvider}, + Runtime, Balances, BlockNumber, Unique, Event, EvmContractHelpers, +}; + +use frame_support::{parameter_types, PalletId}; +use sp_arithmetic::Perbill; +use up_common::{ + constants::{UNIQUE, RELAY_DAYS}, + types::Balance, +}; + +#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))] +parameter_types! { + pub const AppPromotionId: PalletId = PalletId(*b"appstake"); + pub const RecalculationInterval: BlockNumber = 20; + pub const PendingInterval: BlockNumber = 10; + pub const Nominal: Balance = UNIQUE; + // pub const Day: BlockNumber = DAYS; + pub IntervalIncome: Perbill = Perbill::from_rational(RecalculationInterval::get(), RELAY_DAYS) * Perbill::from_rational(5u32, 10_000); +} + +#[cfg(any(feature = "unique-runtime", feature = "quartz-runtime"))] +parameter_types! { + pub const AppPromotionId: PalletId = PalletId(*b"appstake"); + pub const RecalculationInterval: BlockNumber = RELAY_DAYS; + pub const PendingInterval: BlockNumber = 7 * RELAY_DAYS; + pub const Nominal: Balance = UNIQUE; + // pub const Day: BlockNumber = RELAY_DAYS; + pub IntervalIncome: Perbill = Perbill::from_rational(5u32, 10_000); +} + +impl pallet_app_promotion::Config for Runtime { + type PalletId = AppPromotionId; + type CollectionHandler = Unique; + type ContractHandler = EvmContractHelpers; + type Currency = Balances; + type WeightInfo = pallet_app_promotion::weights::SubstrateWeight; + type TreasuryAccountId = TreasuryAccountId; + type RelayBlockNumberProvider = RelayChainBlockNumberProvider; + type RecalculationInterval = RecalculationInterval; + type PendingInterval = PendingInterval; + // type Day = Day; + type Nominal = Nominal; + type IntervalIncome = IntervalIncome; + type Event = Event; +} --- a/runtime/common/config/pallets/mod.rs +++ b/runtime/common/config/pallets/mod.rs @@ -40,6 +40,9 @@ #[cfg(feature = "scheduler")] pub mod scheduler; +#[cfg(feature = "app-promotion")] +pub mod app_promotion; + parameter_types! { pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating(); pub const CollectionCreationPrice: Balance = 2 * UNIQUE; --- a/runtime/common/construct_runtime/mod.rs +++ b/runtime/common/construct_runtime/mod.rs @@ -77,12 +77,15 @@ #[runtimes(opal)] RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event} = 72, + #[runtimes(opal)] + AppPromotion: pallet_app_promotion::{Pallet, Call, Storage, Event} = 73, + // Frontier EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 100, Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101, EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150, - EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151, + EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage, Event} = 151, EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152, EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153, } --- a/runtime/common/runtime_apis.rs +++ b/runtime/common/runtime_apis.rs @@ -189,6 +189,40 @@ } } + impl app_promotion_rpc::AppPromotionApi for Runtime { + fn total_staked(staker: Option) -> Result { + #[cfg(not(feature = "app-promotion"))] + return unsupported!(); + + #[cfg(feature = "app-promotion")] + return Ok(>::cross_id_total_staked(staker).unwrap_or_default()); + } + + fn total_staked_per_block(staker: CrossAccountId) -> Result, DispatchError> { + #[cfg(not(feature = "app-promotion"))] + return unsupported!(); + + #[cfg(feature = "app-promotion")] + return Ok(>::cross_id_total_staked_per_block(staker)); + } + + fn pending_unstake(staker: Option) -> Result { + #[cfg(not(feature = "app-promotion"))] + return unsupported!(); + + #[cfg(feature = "app-promotion")] + return Ok(>::cross_id_pending_unstake(staker)); + } + + fn pending_unstake_per_block(staker: CrossAccountId) -> Result, DispatchError> { + #[cfg(not(feature = "app-promotion"))] + return unsupported!(); + + #[cfg(feature = "app-promotion")] + return Ok(>::cross_id_pending_unstake_per_block(staker)) + } + } + impl rmrk_rpc::RmrkApi< Block, AccountId, @@ -638,6 +672,7 @@ list_benchmark!(list, extra, pallet_unique, Unique); list_benchmark!(list, extra, pallet_structure, Structure); list_benchmark!(list, extra, pallet_inflation, Inflation); + list_benchmark!(list, extra, pallet_app_promotion, AppPromotion); list_benchmark!(list, extra, pallet_fungible, Fungible); list_benchmark!(list, extra, pallet_nonfungible, Nonfungible); @@ -693,6 +728,7 @@ add_benchmark!(params, batches, pallet_unique, Unique); add_benchmark!(params, batches, pallet_structure, Structure); add_benchmark!(params, batches, pallet_inflation, Inflation); + add_benchmark!(params, batches, pallet_app_promotion, AppPromotion); add_benchmark!(params, batches, pallet_fungible, Fungible); add_benchmark!(params, batches, pallet_nonfungible, Nonfungible); --- a/runtime/opal/Cargo.toml +++ b/runtime/opal/Cargo.toml @@ -37,6 +37,7 @@ 'pallet-proxy-rmrk-equip/runtime-benchmarks', 'pallet-unique/runtime-benchmarks', 'pallet-inflation/runtime-benchmarks', + 'pallet-app-promotion/runtime-benchmarks', 'pallet-unique-scheduler/runtime-benchmarks', 'pallet-xcm/runtime-benchmarks', 'sp-runtime/runtime-benchmarks', @@ -82,12 +83,14 @@ 'pallet-base-fee/std', 'fp-rpc/std', 'up-rpc/std', + 'app-promotion-rpc/std', 'fp-evm-mapping/std', 'fp-self-contained/std', 'parachain-info/std', 'serde', 'pallet-inflation/std', 'pallet-configuration/std', + 'pallet-app-promotion/std', 'pallet-common/std', 'pallet-structure/std', 'pallet-fungible/std', @@ -122,11 +125,12 @@ "orml-vesting/std", ] limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing'] -opal-runtime = ['refungible', 'scheduler', 'rmrk'] +opal-runtime = ['refungible', 'scheduler', 'rmrk', 'app-promotion'] refungible = [] scheduler = [] rmrk = [] +app-promotion = [] ################################################################################ # Substrate Dependencies @@ -411,9 +415,11 @@ derivative = "2.2.0" pallet-unique = { path = '../../pallets/unique', default-features = false } up-rpc = { path = "../../primitives/rpc", default-features = false } +app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false} rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false } fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" } pallet-inflation = { path = '../../pallets/inflation', default-features = false } +pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false } up-data-structs = { path = '../../primitives/data-structs', default-features = false } pallet-configuration = { default-features = false, path = "../../pallets/configuration" } pallet-common = { default-features = false, path = "../../pallets/common" } --- a/runtime/quartz/Cargo.toml +++ b/runtime/quartz/Cargo.toml @@ -82,6 +82,7 @@ 'pallet-base-fee/std', 'fp-rpc/std', 'up-rpc/std', + 'app-promotion-rpc/std', 'fp-evm-mapping/std', 'fp-self-contained/std', 'parachain-info/std', @@ -416,8 +417,10 @@ derivative = "2.2.0" pallet-unique = { path = '../../pallets/unique', default-features = false } up-rpc = { path = "../../primitives/rpc", default-features = false } +app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false} fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.27" } pallet-inflation = { path = '../../pallets/inflation', default-features = false } +pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false } up-data-structs = { path = '../../primitives/data-structs', default-features = false } pallet-configuration = { default-features = false, path = "../../pallets/configuration" } pallet-common = { default-features = false, path = "../../pallets/common" } --- a/runtime/unique/Cargo.toml +++ b/runtime/unique/Cargo.toml @@ -83,6 +83,7 @@ 'pallet-base-fee/std', 'fp-rpc/std', 'up-rpc/std', + 'app-promotion-rpc/std', 'fp-evm-mapping/std', 'fp-self-contained/std', 'parachain-info/std', @@ -409,8 +410,10 @@ derivative = "2.2.0" pallet-unique = { path = '../../pallets/unique', default-features = false } up-rpc = { path = "../../primitives/rpc", default-features = false } +app-promotion-rpc = { path = "../../primitives/app_promotion_rpc", default-features = false} rmrk-rpc = { path = "../../primitives/rmrk-rpc", default-features = false } pallet-inflation = { path = '../../pallets/inflation', default-features = false } +pallet-app-promotion = { path = '../../pallets/app-promotion', default-features = false } up-data-structs = { path = '../../primitives/data-structs', default-features = false } pallet-configuration = { default-features = false, path = "../../pallets/configuration" } pallet-common = { default-features = false, path = "../../pallets/common" } --- a/tests/package.json +++ b/tests/package.json @@ -85,6 +85,7 @@ "testRFT": "mocha --timeout 9999999 -r ts-node/register ./**/refungible.test.ts", "testFT": "mocha --timeout 9999999 -r ts-node/register ./**/fungible.test.ts", "testRPC": "mocha --timeout 9999999 -r ts-node/register ./**/rpc.test.ts", + "testPromotion": "mocha --timeout 9999999 -r ts-node/register ./**/app-promotion.test.ts", "polkadot-types-fetch-metadata": "curl -H 'Content-Type: application/json' -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9933 > src/interfaces/metadata.json", "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --endpoint src/interfaces/metadata.json --input src/interfaces/ --package .", "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint src/interfaces/metadata.json --output src/interfaces/ --package .", --- /dev/null +++ b/tests/src/app-promotion.test.ts @@ -0,0 +1,800 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +import {IKeyringPair} from '@polkadot/types/types'; +import { + normalizeAccountId, + getModuleNames, + Pallets, +} from './util/helpers'; + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import {usingPlaygrounds} from './util/playgrounds'; + +import {encodeAddress} from '@polkadot/util-crypto'; +import {stringToU8a} from '@polkadot/util'; +import {SponsoringMode, contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3, transferBalanceToEth} from './eth/util/helpers'; +import {DevUniqueHelper} from './util/playgrounds/unique.dev'; +chai.use(chaiAsPromised); +const expect = chai.expect; + +let alice: IKeyringPair; +let palletAdmin: IKeyringPair; +let nominal: bigint; +const palletAddress = calculatePalleteAddress('appstake'); +let accounts: IKeyringPair[] = []; +const LOCKING_PERIOD = 20n; // 20 blocks of relay +const UNLOCKING_PERIOD = 10n; // 20 blocks of parachain +const rewardAvailableInBlock = (stakedInBlock: bigint) => (stakedInBlock - stakedInBlock % LOCKING_PERIOD) + (LOCKING_PERIOD * 2n); + +const beforeEach = async (context: Mocha.Context) => { + await usingPlaygrounds(async (helper, privateKey) => { + if (!getModuleNames(helper.api!).includes(Pallets.AppPromotion)) context.skip(); + alice = privateKey('//Alice'); + palletAdmin = privateKey('//Charlie'); // TODO use custom address + await helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address}))); + nominal = helper.balance.getOneTokenNominal(); + await helper.balance.transferToSubstrate(alice, palletAdmin.address, 1000n * nominal); + await helper.balance.transferToSubstrate(alice, palletAddress, 1000n * nominal); + accounts = await helper.arrange.createCrowd(100, 1000n, alice); // create accounts-pool to speed up tests + }); +}; + +describe('app-promotions.stake extrinsic', () => { + before(async function () { + await beforeEach(this); + }); + + it('should "lock" staking balance, add it to "staked" map, and increase "totalStaked" amount', async () => { + await usingPlaygrounds(async (helper) => { + const [staker, recepient] = [accounts.pop()!, accounts.pop()!]; + const totalStakedBefore = await helper.staking.getTotalStaked(); + + // Minimum stake amount is 100: + await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.eventually.rejected; + await helper.staking.stake(staker, 100n * nominal); + + // Staker balance is: miscFrozen: 100, feeFrozen: 100, reserved: 0n... + // ...so he can not transfer 900 + expect (await helper.balance.getSubstrateFull(staker.address)).to.contain({miscFrozen: 100n * nominal, feeFrozen: 100n * nominal, reserved: 0n}); + await expect(helper.balance.transferToSubstrate(staker, recepient.address, 900n * nominal)).to.be.rejected; + + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(100n * nominal); + expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); + // it is potentially flaky test. Promotion can credited some tokens. Maybe we need to use closeTo? + expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore + 100n * nominal); // total tokens amount staked in app-promotion increased + + + await helper.staking.stake(staker, 200n * nominal); + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(300n * nominal); + expect((await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map((x) => x[1])).to.be.deep.equal([100n * nominal, 200n * nominal]); + }); + }); + + it('should allow to create maximum 10 stakes for account', async () => { + await usingPlaygrounds(async (helper) => { + const [staker] = await helper.arrange.createAccounts([2000n], alice); + for (let i = 0; i < 10; i++) { + await helper.staking.stake(staker, 100n * nominal); + } + + // can have 10 stakes + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(1000n * nominal); + expect(await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).to.have.length(10); + + await expect(helper.staking.stake(staker, 100n * nominal)).to.be.rejected; + + // After unstake can stake again + await helper.staking.unstake(staker); + await helper.staking.stake(staker, 100n * nominal); + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.equal(100n * nominal); + }); + }); + + it('should reject transaction if stake amount is more than total free balance minus frozen', async () => { + await usingPlaygrounds(async helper => { + const staker = accounts.pop()!; + + // Can't stake full balance because Alice needs to pay some fee + await expect(helper.staking.stake(staker, 1000n * nominal)).to.be.eventually.rejected; + await helper.staking.stake(staker, 500n * nominal); + + // Can't stake 500 tkn because Alice has Less than 500 transferable; + await expect(helper.staking.stake(staker, 500n * nominal)).to.be.eventually.rejected; + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(500n * nominal); + }); + }); + + it('for different accounts in one block is possible', async () => { + await usingPlaygrounds(async helper => { + const crowd = [accounts.pop()!, accounts.pop()!, accounts.pop()!, accounts.pop()!]; + + const crowdStartsToStake = crowd.map(user => helper.staking.stake(user, 100n * nominal)); + await expect(Promise.all(crowdStartsToStake)).to.be.eventually.fulfilled; + + const crowdStakes = await Promise.all(crowd.map(address => helper.staking.getTotalStaked({Substrate: address.address}))); + expect(crowdStakes).to.deep.equal([100n * nominal, 100n * nominal, 100n * nominal, 100n * nominal]); + }); + }); +}); + +describe('unstake balance extrinsic', () => { + before(async function () { + await beforeEach(this); + }); + + it('should change balance state from "frozen" to "reserved", add it to "pendingUnstake" map, and subtract it from totalStaked', async () => { + await usingPlaygrounds(async helper => { + const [staker, recepient] = [accounts.pop()!, accounts.pop()!]; + const totalStakedBefore = await helper.staking.getTotalStaked(); + await helper.staking.stake(staker, 900n * nominal); + await helper.staking.unstake(staker); + + // Right after unstake balance is reserved + // Staker can not transfer + expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 900n * nominal, miscFrozen: 0n, feeFrozen: 0n}); + await expect(helper.balance.transferToSubstrate(staker, recepient.address, 100n * nominal)).to.be.rejected; + expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(900n * nominal); + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n); + expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore); + }); + }); + + it('should unlock balance after unlocking period ends and remove it from "pendingUnstake"', async () => { + await usingPlaygrounds(async (helper) => { + const staker = accounts.pop()!; + await helper.staking.stake(staker, 100n * nominal); + await helper.staking.unstake(staker); + const unstakedInBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}))[0][0]; + + // Wait for unstaking period. Balance now free ~1000; reserved, frozen, miscFrozeb: 0n + await helper.wait.forParachainBlockNumber(unstakedInBlock); + expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: 0n, feeFrozen: 0n}); + expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); + + // staker can transfer: + await helper.balance.transferToSubstrate(staker, alice.address, 998n * nominal); + expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(1n); + }); + }); + + it('should successfully unstake multiple stakes', async () => { + await usingPlaygrounds(async helper => { + const staker = accounts.pop()!; + await helper.staking.stake(staker, 100n * nominal); + await helper.staking.stake(staker, 200n * nominal); + await helper.staking.stake(staker, 300n * nominal); + + // staked: [100, 200, 300]; unstaked: 0 + let pendingUnstake = await helper.staking.getPendingUnstake({Substrate: staker.address}); + let unstakedPerBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address})).map(stake => stake[1]); + let stakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(stake => stake[1]); + expect(pendingUnstake).to.be.deep.equal(0n); + expect(unstakedPerBlock).to.be.deep.equal([]); + expect(stakedPerBlock).to.be.deep.equal([100n * nominal, 200n * nominal, 300n * nominal]); + + // Can unstake multiple stakes + await helper.staking.unstake(staker); + const unstakingBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}))[0][0]; + pendingUnstake = await helper.staking.getPendingUnstake({Substrate: staker.address}); + unstakedPerBlock = (await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address})).map(stake => stake[1]); + stakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(stake => stake[1]); + expect(pendingUnstake).to.be.equal(600n * nominal); + expect(stakedPerBlock).to.be.deep.equal([]); + expect(unstakedPerBlock).to.be.deep.equal([600n * nominal]); + + expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 600n * nominal, feeFrozen: 0n, miscFrozen: 0n}); + await helper.wait.forParachainBlockNumber(unstakingBlock); + expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, feeFrozen: 0n, miscFrozen: 0n}); + expect (await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); + }); + }); + + it('should not have any effects if no active stakes', async () => { + await usingPlaygrounds(async (helper) => { + const staker = accounts.pop()!; + + // unstake has no effect if no stakes at all + await helper.staking.unstake(staker); + expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(0n); + expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n); // TODO bigint closeTo helper + + // TODO stake() unstake() waitUnstaked() unstake(); + + // can't unstake if there are only pendingUnstakes + await helper.staking.stake(staker, 100n * nominal); + await helper.staking.unstake(staker); + await helper.staking.unstake(staker); + + expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(100n * nominal); + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n); + }); + }); + + it('should keep different unlocking block for each unlocking stake', async () => { + await usingPlaygrounds(async (helper) => { + const staker = accounts.pop()!; + await helper.staking.stake(staker, 100n * nominal); + await helper.staking.unstake(staker); + await helper.staking.stake(staker, 120n * nominal); + await helper.staking.unstake(staker); + + const unstakingPerBlock = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address}); + expect(unstakingPerBlock).has.length(2); + expect(unstakingPerBlock[0][1]).to.equal(100n * nominal); + expect(unstakingPerBlock[1][1]).to.equal(120n * nominal); + }); + }); + + it('should be possible for different accounts in one block', async () => { + await usingPlaygrounds(async (helper) => { + const stakers = [accounts.pop()!, accounts.pop()!, accounts.pop()!]; + + await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal))); + await Promise.all(stakers.map(staker => helper.staking.unstake(staker))); + + await Promise.all(stakers.map(async (staker) => { + expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(100n * nominal); + expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n); + })); + }); + }); +}); + +describe('Admin adress', () => { + before(async function () { + await beforeEach(this); + }); + + it('can be set by sudo only', async () => { + await usingPlaygrounds(async (helper) => { + const nonAdmin = accounts.pop()!; + // nonAdmin can not set admin not from himself nor as a sudo + await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address}))).to.be.eventually.rejected; + await expect(helper.signTransaction(nonAdmin, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address})))).to.be.eventually.rejected; + + // Alice can + await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.eventually.fulfilled; + }); + }); + + it('can be any valid CrossAccountId', async () => { + // We are not going to set an eth address as a sponsor, + // but we do want to check, it doesn't break anything; + await usingPlaygrounds(async (helper) => { + const account = accounts.pop()!; + const ethAccount = helper.address.substrateToEth(account.address); + // Alice sets Ethereum address as a sudo. Then Substrate address back... + await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Ethereum: ethAccount})))).to.be.eventually.fulfilled; + await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.eventually.fulfilled; + + // ...It doesn't break anything; + const collection = await helper.nft.mintCollection(account, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); + await expect(helper.signTransaction(account, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected; + }); + }); + + it('can be reassigned', async () => { + await usingPlaygrounds(async (helper) => { + const [oldAdmin, newAdmin, collectionOwner] = [accounts.pop()!, accounts.pop()!, accounts.pop()!]; + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); + + await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress(normalizeAccountId(oldAdmin))))).to.be.eventually.fulfilled; + await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress(normalizeAccountId(newAdmin))))).to.be.eventually.fulfilled; + await expect(helper.signTransaction(oldAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected; + + await expect(helper.signTransaction(newAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.fulfilled; + }); + }); +}); + +describe('App-promotion collection sponsoring', () => { + before(async function () { + await beforeEach(this); + await usingPlaygrounds(async (helper) => { + const tx = helper.api!.tx.sudo.sudo(helper.api!.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})); + await helper.signTransaction(alice, tx); + }); + }); + + it('should actually sponsor transactions', async () => { + await usingPlaygrounds(async (helper) => { + const [collectionOwner, tokenSender, receiver] = [accounts.pop()!, accounts.pop()!, accounts.pop()!]; + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'Name', description: 'Description', tokenPrefix: 'Prefix', limits: {sponsorTransferTimeout: 0}}); + const token = await collection.mintToken(collectionOwner, {Substrate: tokenSender.address}); + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId)); + const palletBalanceBefore = await helper.balance.getSubstrate(palletAddress); + + await token.transfer(tokenSender, {Substrate: receiver.address}); + expect (await token.getOwner()).to.be.deep.equal({Substrate: receiver.address}); + const palletBalanceAfter = await helper.balance.getSubstrate(palletAddress); + + // senders balance the same, transaction has sponsored + expect (await helper.balance.getSubstrate(tokenSender.address)).to.be.equal(1000n * nominal); + expect (palletBalanceBefore > palletBalanceAfter).to.be.true; + }); + }); + + it('can not be set by non admin', async () => { + await usingPlaygrounds(async (helper) => { + const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!]; + + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); + + await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected; + expect((await collection.getData())?.raw.sponsorship).to.equal('Disabled'); + }); + }); + + it('should set pallet address as confirmed admin', async () => { + await usingPlaygrounds(async (helper) => { + const [collectionOwner, oldSponsor] = [accounts.pop()!, accounts.pop()!]; + + // Can set sponsoring for collection without sponsor + const collectionWithoutSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'No-sponsor', description: 'New Collection', tokenPrefix: 'Promotion'}); + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithoutSponsor.collectionId))).to.be.eventually.fulfilled; + expect((await collectionWithoutSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); + + // Can set sponsoring for collection with unconfirmed sponsor + const collectionWithUnconfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Unconfirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address}); + expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: oldSponsor.address}); + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithUnconfirmedSponsor.collectionId))).to.be.eventually.fulfilled; + expect((await collectionWithUnconfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); + + // Can set sponsoring for collection with confirmed sponsor + const collectionWithConfirmedSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'Confirmed', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: oldSponsor.address}); + await collectionWithConfirmedSponsor.confirmSponsorship(oldSponsor); + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithConfirmedSponsor.collectionId))).to.be.eventually.fulfilled; + expect((await collectionWithConfirmedSponsor.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); + }); + }); + + it('can be overwritten by collection owner', async () => { + await usingPlaygrounds(async (helper) => { + const [collectionOwner, newSponsor] = [accounts.pop()!, accounts.pop()!]; + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); + const collectionId = collection.collectionId; + + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionId))).to.be.eventually.fulfilled; + + // Collection limits still can be changed by the owner + expect(await collection.setLimits(collectionOwner, {sponsorTransferTimeout: 0})).to.be.true; + expect((await collection.getData())?.raw.limits.sponsorTransferTimeout).to.be.equal(0); + expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); + + // Collection sponsor can be changed too + expect((await collection.setSponsor(collectionOwner, newSponsor.address))).to.be.true; + expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Unconfirmed: newSponsor.address}); + }); + }); + + it('should not overwrite collection limits set by the owner earlier', async () => { + await usingPlaygrounds(async (helper) => { + const limits = {ownerCanDestroy: true, ownerCanTransfer: true, sponsorTransferTimeout: 0}; + const collectionWithLimits = await helper.nft.mintCollection(alice, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits}); + + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collectionWithLimits.collectionId))).to.be.eventually.fulfilled; + expect((await collectionWithLimits.getData())?.raw.limits).to.be.deep.contain(limits); + }); + }); + + it('should reject transaction if collection doesn\'t exist', async () => { + await usingPlaygrounds(async (helper) => { + const collectionOwner = accounts.pop()!; + + // collection has never existed + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(999999999))).to.be.eventually.rejected; + // collection has been burned + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); + await collection.burn(collectionOwner); + + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.rejected; + }); + }); +}); + +describe('app-promotion stopSponsoringCollection', () => { + before(async function () { + await beforeEach(this); + }); + + it('can not be called by non-admin', async () => { + await usingPlaygrounds(async (helper) => { + const [collectionOwner, nonAdmin] = [accounts.pop()!, accounts.pop()!]; + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); + + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.eventually.fulfilled; + + await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.eventually.rejected; + expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: palletAddress}); + }); + }); + + it('should set sponsoring as disabled', async () => { + await usingPlaygrounds(async (helper) => { + const [collectionOwner, recepient] = [accounts.pop()!, accounts.pop()!]; + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits: {sponsorTransferTimeout: 0}}); + const token = await collection.mintToken(collectionOwner, {Substrate: collectionOwner.address}); + + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.sponsorCollection(collection.collectionId)); + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId)); + + expect((await collection.getData())?.raw.sponsorship).to.be.equal('Disabled'); + + // Transactions are not sponsored anymore: + const ownerBalanceBefore = await helper.balance.getSubstrate(collectionOwner.address); + await token.transfer(collectionOwner, {Substrate: recepient.address}); + const ownerBalanceAfter = await helper.balance.getSubstrate(collectionOwner.address); + expect(ownerBalanceAfter < ownerBalanceBefore).to.be.equal(true); + }); + }); + + it('should not affect collection which is not sponsored by pallete', async () => { + await usingPlaygrounds(async (helper) => { + const collectionOwner = accounts.pop()!; + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: collectionOwner.address}); + await collection.confirmSponsorship(collectionOwner); + + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.eventually.rejected; + + expect((await collection.getData())?.raw.sponsorship).to.be.deep.equal({Confirmed: collectionOwner.address}); + }); + }); + + it('should reject transaction if collection does not exist', async () => { + await usingPlaygrounds(async (helper) => { + const collectionOwner = accounts.pop()!; + const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); + + await collection.burn(collectionOwner); + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(collection.collectionId))).to.be.eventually.rejected; + await expect(helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.stopSponsoringCollection(999999999))).to.be.eventually.rejected; + }); + }); +}); + +describe('app-promotion contract sponsoring', () => { + before(async function () { + await beforeEach(this); + }); + + itWeb3('should set palletes address as a sponsor', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + const contractMethods = contractHelpers(web3, contractOwner); + + await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address)); + + expect(await contractMethods.methods.hasSponsor(flipper.options.address).call()).to.be.true; + expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner); + expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({ + confirmed: { + substrate: palletAddress, + }, + }); + }); + }); + + itWeb3('should overwrite sponsoring mode and existed sponsor', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + const contractMethods = contractHelpers(web3, contractOwner); + + await expect(contractMethods.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected; + + // Contract is self sponsored + expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.be.deep.equal({ + confirmed: { + ethereum: flipper.options.address.toLowerCase(), + }, + }); + + // set promotion sponsoring + await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address)); + + // new sponsor is pallet address + expect(await contractMethods.methods.hasSponsor(flipper.options.address).call()).to.be.true; + expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner); + expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({ + confirmed: { + substrate: palletAddress, + }, + }); + }); + }); + + itWeb3('can be overwritten by contract owner', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + const contractMethods = contractHelpers(web3, contractOwner); + + // contract sponsored by pallet + await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address)); + + // owner sets self sponsoring + await expect(contractMethods.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected; + + expect(await contractMethods.methods.hasSponsor(flipper.options.address).call()).to.be.true; + expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner); + expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({ + confirmed: { + ethereum: flipper.options.address.toLowerCase(), + }, + }); + }); + }); + + itWeb3('can not be set by non admin', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const nonAdmin = accounts.pop()!; + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + const contractMethods = contractHelpers(web3, contractOwner); + + await expect(contractMethods.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected; + + // nonAdmin calls sponsorContract + await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address))).to.be.rejected; + + // contract still self-sponsored + expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({ + confirmed: { + ethereum: flipper.options.address.toLowerCase(), + }, + }); + }); + + itWeb3('should be rejected for non-contract address', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + + }); + }); + }); + + itWeb3('should actually sponsor transactions', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + const contractHelper = contractHelpers(web3, contractOwner); + await contractHelper.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: contractOwner}); + await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner}); + await transferBalanceToEth(api, alice, flipper.options.address, 1000n); + + await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address)); + await flipper.methods.flip().send({from: caller}); + expect(await flipper.methods.getValue().call()).to.be.true; + + const callerBalance = await helper.balance.getEthereum(caller); + const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address); + + expect(callerBalance).to.be.equal(1000n * nominal); + expect(1000n * nominal > contractBalanceAfter).to.be.true; + }); + }); +}); + +describe('app-promotion stopSponsoringContract', () => { + before(async function () { + await beforeEach(this); + }); + + itWeb3('should remove pallet address from contract sponsors', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + await transferBalanceToEth(api, alice, flipper.options.address); + const contractHelper = contractHelpers(web3, contractOwner); + await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner}); + await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address)); + await helper.signTransaction(palletAdmin, api.tx.appPromotion.stopSponsoringContract(flipper.options.address)); + + expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.false; + expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner); + expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({ + disabled: null, + }); + + await flipper.methods.flip().send({from: caller}); + expect(await flipper.methods.getValue().call()).to.be.true; + + const callerBalance = await helper.balance.getEthereum(caller); + const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address); + + // caller payed for call + expect(1000n * nominal > callerBalance).to.be.true; + expect(contractBalanceAfter).to.be.equal(1000n * nominal); + }); + }); + + itWeb3('can not be called by non-admin', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const nonAdmin = accounts.pop()!; + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + + await helper.signTransaction(palletAdmin, api.tx.appPromotion.sponsorContract(flipper.options.address)); + await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.stopSponsoringContract(flipper.options.address))).to.be.rejected; + }); + }); + + itWeb3('should not affect a contract which is not sponsored by pallete', async ({api, web3, privateKeyWrapper}) => { + await usingPlaygrounds(async (helper) => { + const nonAdmin = accounts.pop()!; + const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase(); + const flipper = await deployFlipper(web3, contractOwner); + const contractHelper = contractHelpers(web3, contractOwner); + await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected; + + await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.stopSponsoringContract(flipper.options.address))).to.be.rejected; + }); + }); +}); + +describe('app-promotion rewards', () => { + before(async function () { + await beforeEach(this); + }); + + it('can not be called by non admin', async () => { + await usingPlaygrounds(async (helper) => { + const nonAdmin = accounts.pop()!; + await expect(helper.signTransaction(nonAdmin, helper.api!.tx.appPromotion.payoutStakers(100))).to.be.rejected; + }); + }); + + it('should credit 0.05% for staking period', async () => { + await usingPlaygrounds(async helper => { + const staker = accounts.pop()!; + + await waitPromotionPeriodDoesntEnd(helper); + + await helper.staking.stake(staker, 100n * nominal); + await helper.staking.stake(staker, 200n * nominal); + + // wait rewards are available: + const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[1][0]; + await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock)); + + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100)); + + const totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]); + expect(totalStakedPerBlock).to.be.deep.equal([calculateIncome(100n * nominal, 10n), calculateIncome(200n * nominal, 10n)]); + }); + }); + + it('shoud be paid for more than one period if payments was missed', async () => { + await usingPlaygrounds(async (helper) => { + const staker = accounts.pop()!; + + await helper.staking.stake(staker, 100n * nominal); + // wait for two rewards are available: + const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[0][0]; + await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock) + LOCKING_PERIOD); + + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100)); + const stakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}); + const frozenBalanceShouldBe = calculateIncome(100n * nominal, 10n, 2); + expect(stakedPerBlock[0][1]).to.be.equal(frozenBalanceShouldBe); + + const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address); + + expect(stakerFullBalance).to.contain({reserved: 0n, feeFrozen: frozenBalanceShouldBe, miscFrozen: frozenBalanceShouldBe}); + }); + }); + + it('should not be credited for unstaked (reserved) balance', async () => { + await usingPlaygrounds(async helper => { + // staker unstakes before rewards has been payed + const staker = accounts.pop()!; + await helper.staking.stake(staker, 100n * nominal); + const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[0][0]; + await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock) + LOCKING_PERIOD); + await helper.staking.unstake(staker); + + // so he did not receive any rewards + const totalBalanceBefore = await helper.balance.getSubstrate(staker.address); + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100)); + const totalBalanceAfter = await helper.balance.getSubstrate(staker.address); + + expect(totalBalanceBefore).to.be.equal(totalBalanceAfter); + }); + }); + + it('should bring compound interest', async () => { + await usingPlaygrounds(async helper => { + const staker = accounts.pop()!; + + await helper.staking.stake(staker, 100n * nominal); + + const stakedInBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address}))[0][0]; + await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock)); + + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100)); + let totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]); + expect(totalStakedPerBlock).to.deep.equal([calculateIncome(100n * nominal, 10n)]); + + await helper.wait.forRelayBlockNumber(rewardAvailableInBlock(stakedInBlock) + LOCKING_PERIOD); + await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100)); + totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]); + expect(totalStakedPerBlock).to.deep.equal([calculateIncome(100n * nominal, 10n, 2)]); + }); + }); + + it.skip('can be paid 1000 rewards in a time', async () => { + // all other stakes should be unstaked + await usingPlaygrounds(async (helper) => { + const oneHundredStakers = await helper.arrange.createCrowd(100, 1050n, alice); + + // stakers stakes 10 times each + for (let i = 0; i < 10; i++) { + await Promise.all(oneHundredStakers.map(staker => helper.staking.stake(staker, 100n * nominal))); + } + await helper.wait.newBlocks(40); + const result = await helper.signTransaction(palletAdmin, helper.api!.tx.appPromotion.payoutStakers(100)); + }); + }); + + it.skip('can handle 40.000 rewards', async () => { + await usingPlaygrounds(async (helper) => { + const [donor] = await helper.arrange.createAccounts([7_000_000n], alice); + const crowdStakes = async () => { + // each account in the crowd stakes 2 times + const crowd = await helper.arrange.createCrowd(500, 300n, donor); + await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal))); + await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal))); + // + }; + + for (let i = 0; i < 40; i++) { + await crowdStakes(); + } + + // TODO pay rewards for some period + }); + }); +}); + +function calculatePalleteAddress(palletId: any) { + const address = stringToU8a(('modl' + palletId).padEnd(32, '\0')); + return encodeAddress(address); +} + +function calculateIncome(base: bigint, calcPeriod: bigint, iter = 0): bigint { + const DAY = 7200n; + const ACCURACY = 1_000_000_000n; + const income = base + base * (ACCURACY * (calcPeriod * 5n) / (10_000n * DAY)) / ACCURACY ; + + if (iter > 1) { + return calculateIncome(income, calcPeriod, iter - 1); + } else return income; +} + +// Wait while promotion period less than specified block, to avoid boundary cases +// 0 if this should be the beginning of the period. +async function waitPromotionPeriodDoesntEnd(helper: DevUniqueHelper, waitBlockLessThan = LOCKING_PERIOD / 3n) { + const relayBlockNumber = (await helper.api!.query.parachainSystem.validationData()).value.relayParentNumber.toNumber(); // await helper.chain.getLatestBlockNumber(); + const currentPeriodBlock = BigInt(relayBlockNumber) % LOCKING_PERIOD; + + if (currentPeriodBlock > waitBlockLessThan) { + await helper.wait.forRelayBlockNumber(BigInt(relayBlockNumber) + LOCKING_PERIOD - currentPeriodBlock); + } +} --- a/tests/src/eth/api/ContractHelpers.sol +++ b/tests/src/eth/api/ContractHelpers.sol @@ -12,9 +12,19 @@ function supportsInterface(bytes4 interfaceID) external view returns (bool); } +/// @dev inlined interface +interface ContractHelpersEvents { + event ContractSponsorSet(address indexed contractAddress, address sponsor); + event ContractSponsorshipConfirmed( + address indexed contractAddress, + address sponsor + ); + event ContractSponsorRemoved(address indexed contractAddress); +} + /// @title Magic contract, which allows users to reconfigure other contracts /// @dev the ERC-165 identifier for this interface is 0xd77fab70 -interface ContractHelpers is Dummy, ERC165 { +interface ContractHelpers is Dummy, ERC165, ContractHelpersEvents { /// Get user, which deployed specified contract /// @dev May return zero address in case if contract is deployed /// using uniquenetwork evm-migration pallet, or using other terms not --- a/tests/src/eth/contractSponsoring.test.ts +++ b/tests/src/eth/contractSponsoring.test.ts @@ -15,6 +15,7 @@ // along with Unique Network. If not, see . import {expect} from 'chai'; +import { expectSubstrateEventsAtBlock } from '../util/helpers'; import { contractHelpers, createEthAccountWithBalance, @@ -24,6 +25,7 @@ SponsoringMode, createEthAccount, ethBalanceViaSub, + normalizeEvents, } from './util/helpers'; describe('Sponsoring EVM contracts', () => { @@ -36,6 +38,41 @@ expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true; }); + itWeb3('Set self sponsored events', async ({api, web3, privateKeyWrapper}) => { + const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const flipper = await deployFlipper(web3, owner); + const helpers = contractHelpers(web3, owner); + + const result = await helpers.methods.selfSponsoredEnable(flipper.options.address).send(); + // console.log(result); + const ethEvents = normalizeEvents(result.events); + expect(ethEvents).to.be.deep.equal([ + { + address: flipper.options.address, + event: 'ContractSponsorSet', + args: { + contractAddress: flipper.options.address, + sponsor: flipper.options.address, + }, + }, + { + address: flipper.options.address, + event: 'ContractSponsorshipConfirmed', + args: { + contractAddress: flipper.options.address, + sponsor: flipper.options.address, + }, + }, + ]); + + await expectSubstrateEventsAtBlock( + api, + result.blockNumber, + 'evmContractHelpers', + ['ContractSponsorSet','ContractSponsorshipConfirmed'], + ); + }); + itWeb3('Self sponsored can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => { const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); @@ -75,6 +112,33 @@ expect(await helpers.methods.hasPendingSponsor(flipper.options.address).call()).to.be.true; }); + itWeb3('Set sponsor event', async ({api, web3, privateKeyWrapper}) => { + const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const flipper = await deployFlipper(web3, owner); + const helpers = contractHelpers(web3, owner); + + const result = await helpers.methods.setSponsor(flipper.options.address, sponsor).send(); + const events = normalizeEvents(result.events); + expect(events).to.be.deep.equal([ + { + address: flipper.options.address, + event: 'ContractSponsorSet', + args: { + contractAddress: flipper.options.address, + sponsor: sponsor, + }, + }, + ]); + + await expectSubstrateEventsAtBlock( + api, + result.blockNumber, + 'evmContractHelpers', + ['ContractSponsorSet'], + ); + }); + itWeb3('Sponsor can not be set by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => { const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper); @@ -97,6 +161,33 @@ expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.true; }); + itWeb3('Confirm sponsorship event', async ({api, web3, privateKeyWrapper}) => { + const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const flipper = await deployFlipper(web3, owner); + const helpers = contractHelpers(web3, owner); + await expect(helpers.methods.setSponsor(flipper.options.address, sponsor).send()).to.be.not.rejected; + const result = await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor}); + const events = normalizeEvents(result.events); + expect(events).to.be.deep.equal([ + { + address: flipper.options.address, + event: 'ContractSponsorshipConfirmed', + args: { + contractAddress: flipper.options.address, + sponsor: sponsor, + }, + }, + ]); + + await expectSubstrateEventsAtBlock( + api, + result.blockNumber, + 'evmContractHelpers', + ['ContractSponsorshipConfirmed'], + ); + }); + itWeb3('Sponsorship can not be confirmed by the address that not pending as sponsor', async ({api, web3, privateKeyWrapper}) => { const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper); @@ -160,6 +251,35 @@ expect(await helpers.methods.hasSponsor(flipper.options.address).call()).to.be.false; }); + itWeb3('Remove sponsor event', async ({api, web3, privateKeyWrapper}) => { + const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const sponsor = await createEthAccountWithBalance(api, web3, privateKeyWrapper); + const flipper = await deployFlipper(web3, owner); + const helpers = contractHelpers(web3, owner); + + await helpers.methods.setSponsor(flipper.options.address, sponsor).send(); + await helpers.methods.confirmSponsorship(flipper.options.address).send({from: sponsor}); + + const result = await helpers.methods.removeSponsor(flipper.options.address).send(); + const events = normalizeEvents(result.events); + expect(events).to.be.deep.equal([ + { + address: flipper.options.address, + event: 'ContractSponsorRemoved', + args: { + contractAddress: flipper.options.address, + }, + }, + ]); + + await expectSubstrateEventsAtBlock( + api, + result.blockNumber, + 'evmContractHelpers', + ['ContractSponsorRemoved'], + ); + }); + itWeb3('Sponsor can not be removed by the address that did not deployed the contract', async ({api, web3, privateKeyWrapper}) => { const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); const notOwner = await createEthAccountWithBalance(api, web3, privateKeyWrapper); --- a/tests/src/eth/util/contractHelpersAbi.json +++ b/tests/src/eth/util/contractHelpersAbi.json @@ -1,5 +1,56 @@ [ { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractSponsorRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sponsor", + "type": "address" + } + ], + "name": "ContractSponsorSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sponsor", + "type": "address" + } + ], + "name": "ContractSponsorshipConfirmed", + "type": "event" + }, + { "inputs": [ { "internalType": "address", --- /dev/null +++ b/tests/src/interfaces/appPromotion/definitions.ts @@ -0,0 +1,58 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network 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. + +// Unique Network 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 Unique Network. If not, see . + +type RpcParam = { + name: string; + type: string; + isOptional?: true; +}; + +const CROSS_ACCOUNT_ID_TYPE = 'PalletEvmAccountBasicCrossAccountIdRepr'; + +const crossAccountParam = (name = 'account') => ({name, type: CROSS_ACCOUNT_ID_TYPE}); +const atParam = {name: 'at', type: 'Hash', isOptional: true}; + +const fun = (description: string, params: RpcParam[], type: string) => ({ + description, + params: [...params, atParam], + type, +}); + +export default { + types: {}, + rpc: { + totalStaked: fun( + 'Returns the total amount of staked tokens', + [{name: 'staker', type: CROSS_ACCOUNT_ID_TYPE, isOptional: true}], + 'u128', + ), + totalStakedPerBlock: fun( + 'Returns the total amount of staked tokens per block when staked', + [crossAccountParam('staker')], + 'Vec<(u32, u128)>', + ), + pendingUnstake: fun( + 'Returns the total amount of unstaked tokens', + [{name: 'staker', type: CROSS_ACCOUNT_ID_TYPE, isOptional: true}], + 'u128', + ), + pendingUnstakePerBlock: fun( + 'Returns the total amount of unstaked tokens per block', + [crossAccountParam('staker')], + 'Vec<(u32, u128)>', + ), + }, +}; --- /dev/null +++ b/tests/src/interfaces/appPromotion/index.ts @@ -0,0 +1,4 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +export * from './types'; --- /dev/null +++ b/tests/src/interfaces/appPromotion/types.ts @@ -0,0 +1,4 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +export type PHANTOM_APPPROMOTION = 'appPromotion'; --- a/tests/src/interfaces/augment-api-consts.ts +++ b/tests/src/interfaces/augment-api-consts.ts @@ -8,13 +8,39 @@ import type { ApiTypes, AugmentedConst } from '@polkadot/api-base/types'; import type { Option, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { Codec } from '@polkadot/types-codec/types'; -import type { Permill } from '@polkadot/types/interfaces/runtime'; +import type { Perbill, Permill } from '@polkadot/types/interfaces/runtime'; import type { FrameSupportPalletId, FrameSupportWeightsRuntimeDbWeight, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion } from '@polkadot/types/lookup'; export type __AugmentedConst = AugmentedConst; declare module '@polkadot/api-base/types/consts' { interface AugmentedConsts { + appPromotion: { + /** + * Rate of return for interval in blocks defined in `RecalculationInterval`. + **/ + intervalIncome: Perbill & AugmentedConst; + /** + * Decimals for the `Currency`. + **/ + nominal: u128 & AugmentedConst; + /** + * The app's pallet id, used for deriving its sovereign account ID. + **/ + palletId: FrameSupportPalletId & AugmentedConst; + /** + * In parachain blocks. + **/ + pendingInterval: u32 & AugmentedConst; + /** + * In relay blocks. + **/ + recalculationInterval: u32 & AugmentedConst; + /** + * Generic const + **/ + [key: string]: Codec; + }; balances: { /** * The minimum amount required to keep an account open. --- a/tests/src/interfaces/augment-api-errors.ts +++ b/tests/src/interfaces/augment-api-errors.ts @@ -11,6 +11,36 @@ declare module '@polkadot/api-base/types/errors' { interface AugmentedErrors { + appPromotion: { + /** + * Error due to action requiring admin to be set. + **/ + AdminNotSet: AugmentedError; + /** + * Errors caused by incorrect actions with a locked balance. + **/ + IncorrectLockedBalanceOperation: AugmentedError; + /** + * No permission to perform an action. + **/ + NoPermission: AugmentedError; + /** + * Insufficient funds to perform an action. + **/ + NotSufficientFunds: AugmentedError; + /** + * Occurs when a pending unstake cannot be added in this block. PENDING_LIMIT_PER_BLOCK` limits exceeded. + **/ + PendingForBlockOverflow: AugmentedError; + /** + * The error is due to the fact that the collection/contract must already be sponsored in order to perform the action. + **/ + SponsorNotSet: AugmentedError; + /** + * Generic error + **/ + [key: string]: AugmentedError; + }; balances: { /** * Beneficiary account must pre-exist @@ -265,8 +295,12 @@ }; evmContractHelpers: { /** - * This method is only executable by owner + * No pending sponsor for contract. **/ + NoPendingSponsor: AugmentedError; + /** + * This method is only executable by contract owner + **/ NoPermission: AugmentedError; /** * Generic error @@ -274,7 +308,13 @@ [key: string]: AugmentedError; }; evmMigration: { + /** + * Migration of this account is not yet started, or already finished. + **/ AccountIsNotMigrating: AugmentedError; + /** + * Can only migrate to empty address. + **/ AccountNotEmpty: AugmentedError; /** * Generic error --- a/tests/src/interfaces/augment-api-events.ts +++ b/tests/src/interfaces/augment-api-events.ts @@ -15,6 +15,44 @@ declare module '@polkadot/api-base/types/events' { interface AugmentedEvents { + appPromotion: { + /** + * The admin was set + * + * # Arguments + * * AccountId: ID of the admin + **/ + SetAdmin: AugmentedEvent; + /** + * Staking was performed + * + * # Arguments + * * AccountId: ID of the staker + * * Balance : staking amount + **/ + Stake: AugmentedEvent; + /** + * Staking recalculation was performed + * + * # Arguments + * * AccountId: ID of the staker. + * * Balance : recalculation base + * * Balance : total income + **/ + StakingRecalculation: AugmentedEvent; + /** + * Unstaking was performed + * + * # Arguments + * * AccountId: ID of the staker + * * Balance : unstaking amount + **/ + Unstake: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; balances: { /** * A balance was set by root. @@ -208,6 +246,24 @@ **/ [key: string]: AugmentedEvent; }; + evmContractHelpers: { + /** + * Collection sponsor was removed. + **/ + ContractSponsorRemoved: AugmentedEvent; + /** + * Contract sponsor was set. + **/ + ContractSponsorSet: AugmentedEvent; + /** + * New sponsor was confirm. + **/ + ContractSponsorshipConfirmed: AugmentedEvent; + /** + * Generic event + **/ + [key: string]: AugmentedEvent; + }; parachainSystem: { /** * Downward messages were processed using the given weight. --- a/tests/src/interfaces/augment-api-query.ts +++ b/tests/src/interfaces/augment-api-query.ts @@ -6,10 +6,10 @@ import '@polkadot/api-base/types/storage'; import type { ApiTypes, AugmentedQuery, QueryableStorageEntry } from '@polkadot/api-base/types'; -import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types-codec'; +import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec'; import type { AnyNumber, ITuple } from '@polkadot/types-codec/types'; import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime'; -import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsTokenChild } from '@polkadot/types/lookup'; +import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild } from '@polkadot/types/lookup'; import type { Observable } from '@polkadot/types/types'; export type __AugmentedQuery = AugmentedQuery unknown>; @@ -17,6 +17,28 @@ declare module '@polkadot/api-base/types/storage' { interface AugmentedQueries { + appPromotion: { + admin: AugmentedQuery Observable>, []> & QueryableStorageEntry; + /** + * Stores a key for record for which the next revenue recalculation would be performed. + * If `None`, then recalculation has not yet been performed or calculations have been completed for all stakers. + **/ + nextCalculatedRecord: AugmentedQuery Observable>>, []> & QueryableStorageEntry; + pendingUnstake: AugmentedQuery Observable>>, [u32]> & QueryableStorageEntry; + /** + * Amount of tokens staked by account in the blocknumber. + **/ + staked: AugmentedQuery Observable>, [AccountId32, u32]> & QueryableStorageEntry; + /** + * Amount of stakes for an Account + **/ + stakesPerAccount: AugmentedQuery Observable, [AccountId32]> & QueryableStorageEntry; + totalStaked: AugmentedQuery Observable, []> & QueryableStorageEntry; + /** + * Generic query + **/ + [key: string]: QueryableStorageEntry; + }; balances: { /** * The Balances pallet example of storing the balance of an account. @@ -194,12 +216,66 @@ [key: string]: QueryableStorageEntry; }; evmContractHelpers: { + /** + * Storage for users that allowed for sponsorship. + * + * ### Usage + * Prefer to delete record from storage if user no more allowed for sponsorship. + * + * * **Key1** - contract address. + * * **Key2** - user that allowed for sponsorship. + * * **Value** - allowance for sponsorship. + **/ allowlist: AugmentedQuery Observable, [H160, H160]> & QueryableStorageEntry; + /** + * Storege for contracts with [`Allowlisted`](SponsoringModeT::Allowlisted) sponsoring mode. + * + * ### Usage + * Prefer to delete collection from storage if mode chaged to non `Allowlisted`, than set **Value** to **false**. + * + * * **Key** - contract address. + * * **Value** - is contract in [`Allowlisted`](SponsoringModeT::Allowlisted) mode. + **/ allowlistEnabled: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; + /** + * Store owner for contract. + * + * * **Key** - contract address. + * * **Value** - owner for contract. + **/ owner: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; selfSponsoring: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; + /** + * Storage for last sponsored block. + * + * * **Key1** - contract address. + * * **Key2** - sponsored user address. + * * **Value** - last sponsored block number. + **/ sponsorBasket: AugmentedQuery Observable>, [H160, H160]> & QueryableStorageEntry; + /** + * Store for contract sponsorship state. + * + * * **Key** - contract address. + * * **Value** - sponsorship state. + **/ + sponsoring: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; + /** + * Store for sponsoring mode. + * + * ### Usage + * Prefer to delete collection from storage if mode chaged to [`Disabled`](SponsoringModeT::Disabled). + * + * * **Key** - contract address. + * * **Value** - [`sponsoring mode`](SponsoringModeT). + **/ sponsoringMode: AugmentedQuery Observable>, [H160]> & QueryableStorageEntry; + /** + * Storage for sponsoring rate limit in blocks. + * + * * **Key** - contract address. + * * **Value** - amount of sponsored blocks. + **/ sponsoringRateLimit: AugmentedQuery Observable, [H160]> & QueryableStorageEntry; /** * Generic query @@ -281,7 +357,7 @@ * * Currently used to store RMRK data. **/ - tokenAuxProperties: AugmentedQuery Observable>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry; + tokenAuxProperties: AugmentedQuery Observable>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry; /** * Used to enumerate token's children. **/ --- a/tests/src/interfaces/augment-api-rpc.ts +++ b/tests/src/interfaces/augment-api-rpc.ts @@ -9,7 +9,7 @@ import type { AugmentedRpc } from '@polkadot/rpc-core/types'; import type { Metadata, StorageKey } from '@polkadot/types'; import type { Bytes, HashMap, Json, Null, Option, Text, U256, U64, Vec, bool, f64, u128, u32, u64 } from '@polkadot/types-codec'; -import type { AnyNumber, Codec } from '@polkadot/types-codec/types'; +import type { AnyNumber, Codec, ITuple } from '@polkadot/types-codec/types'; import type { ExtrinsicOrHash, ExtrinsicStatus } from '@polkadot/types/interfaces/author'; import type { EpochAuthorship } from '@polkadot/types/interfaces/babe'; import type { BeefySignedCommitment } from '@polkadot/types/interfaces/beefy'; @@ -35,6 +35,24 @@ declare module '@polkadot/rpc-core/types/jsonrpc' { interface RpcInterface { + appPromotion: { + /** + * Returns the total amount of unstaked tokens + **/ + pendingUnstake: AugmentedRpc<(staker?: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>; + /** + * Returns the total amount of unstaked tokens per block + **/ + pendingUnstakePerBlock: AugmentedRpc<(staker: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>>>; + /** + * Returns the total amount of staked tokens + **/ + totalStaked: AugmentedRpc<(staker?: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>; + /** + * Returns the total amount of staked tokens per block when staked + **/ + totalStakedPerBlock: AugmentedRpc<(staker: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>>>; + }; author: { /** * Returns true if the keystore has private keys for the given public key and key type. --- a/tests/src/interfaces/augment-api-tx.ts +++ b/tests/src/interfaces/augment-api-tx.ts @@ -17,6 +17,20 @@ declare module '@polkadot/api-base/types/submittable' { interface AugmentedSubmittables { + appPromotion: { + payoutStakers: AugmentedSubmittable<(stakersNumber: Option | null | Uint8Array | u8 | AnyNumber) => SubmittableExtrinsic, [Option]>; + setAdminAddress: AugmentedSubmittable<(admin: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic, [PalletEvmAccountBasicCrossAccountIdRepr]>; + sponsorCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + sponsorContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic, [H160]>; + stake: AugmentedSubmittable<(amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u128]>; + stopSponsoringCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic, [u32]>; + stopSponsoringContract: AugmentedSubmittable<(contractId: H160 | string | Uint8Array) => SubmittableExtrinsic, [H160]>; + unstake: AugmentedSubmittable<() => SubmittableExtrinsic, []>; + /** + * Generic tx + **/ + [key: string]: SubmittableExtrinsicFunction; + }; balances: { /** * Exactly as `transfer`, except the origin must be root and the source account may be @@ -181,8 +195,21 @@ [key: string]: SubmittableExtrinsicFunction; }; evmMigration: { + /** + * Start contract migration, inserts contract stub at target address, + * and marks account as pending, allowing to insert storage + **/ begin: AugmentedSubmittable<(address: H160 | string | Uint8Array) => SubmittableExtrinsic, [H160]>; + /** + * Finish contract migration, allows it to be called. + * It is not possible to alter contract storage via [`Self::set_data`] + * after this call. + **/ finish: AugmentedSubmittable<(address: H160 | string | Uint8Array, code: Bytes | string | Uint8Array) => SubmittableExtrinsic, [H160, Bytes]>; + /** + * Insert items into contract storage, this method can be called + * multiple times + **/ setData: AugmentedSubmittable<(address: H160 | string | Uint8Array, data: Vec> | ([H256 | string | Uint8Array, H256 | string | Uint8Array])[]) => SubmittableExtrinsic, [H160, Vec>]>; /** * Generic tx --- a/tests/src/interfaces/augment-types.ts +++ b/tests/src/interfaces/augment-types.ts @@ -5,7 +5,7 @@ // this is required to allow for ambient/previous definitions import '@polkadot/types/types/registry'; -import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default'; +import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default'; import type { Data, StorageKey } from '@polkadot/types'; import type { BitVec, Bool, Bytes, F32, F64, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, f32, f64, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec'; import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets'; @@ -804,6 +804,9 @@ Owner: Owner; PageCounter: PageCounter; PageIndexData: PageIndexData; + PalletAppPromotionCall: PalletAppPromotionCall; + PalletAppPromotionError: PalletAppPromotionError; + PalletAppPromotionEvent: PalletAppPromotionEvent; PalletBalancesAccountData: PalletBalancesAccountData; PalletBalancesBalanceLock: PalletBalancesBalanceLock; PalletBalancesCall: PalletBalancesCall; @@ -832,6 +835,7 @@ PalletEvmCall: PalletEvmCall; PalletEvmCoderSubstrateError: PalletEvmCoderSubstrateError; PalletEvmContractHelpersError: PalletEvmContractHelpersError; + PalletEvmContractHelpersEvent: PalletEvmContractHelpersEvent; PalletEvmContractHelpersSponsoringModeT: PalletEvmContractHelpersSponsoringModeT; PalletEvmError: PalletEvmError; PalletEvmEvent: PalletEvmEvent; @@ -1295,7 +1299,8 @@ UpDataStructsPropertyScope: UpDataStructsPropertyScope; UpDataStructsRpcCollection: UpDataStructsRpcCollection; UpDataStructsSponsoringRateLimit: UpDataStructsSponsoringRateLimit; - UpDataStructsSponsorshipState: UpDataStructsSponsorshipState; + UpDataStructsSponsorshipStateAccountId32: UpDataStructsSponsorshipStateAccountId32; + UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: UpDataStructsSponsorshipStateBasicCrossAccountIdRepr; UpDataStructsTokenChild: UpDataStructsTokenChild; UpDataStructsTokenData: UpDataStructsTokenData; UpgradeGoAhead: UpgradeGoAhead; --- a/tests/src/interfaces/default/types.ts +++ b/tests/src/interfaces/default/types.ts @@ -806,6 +806,64 @@ readonly perPeriod: Compact; } +/** @name PalletAppPromotionCall */ +export interface PalletAppPromotionCall extends Enum { + readonly isSetAdminAddress: boolean; + readonly asSetAdminAddress: { + readonly admin: PalletEvmAccountBasicCrossAccountIdRepr; + } & Struct; + readonly isStake: boolean; + readonly asStake: { + readonly amount: u128; + } & Struct; + readonly isUnstake: boolean; + readonly isSponsorCollection: boolean; + readonly asSponsorCollection: { + readonly collectionId: u32; + } & Struct; + readonly isStopSponsoringCollection: boolean; + readonly asStopSponsoringCollection: { + readonly collectionId: u32; + } & Struct; + readonly isSponsorContract: boolean; + readonly asSponsorContract: { + readonly contractId: H160; + } & Struct; + readonly isStopSponsoringContract: boolean; + readonly asStopSponsoringContract: { + readonly contractId: H160; + } & Struct; + readonly isPayoutStakers: boolean; + readonly asPayoutStakers: { + readonly stakersNumber: Option; + } & Struct; + readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers'; +} + +/** @name PalletAppPromotionError */ +export interface PalletAppPromotionError extends Enum { + readonly isAdminNotSet: boolean; + readonly isNoPermission: boolean; + readonly isNotSufficientFunds: boolean; + readonly isPendingForBlockOverflow: boolean; + readonly isSponsorNotSet: boolean; + readonly isIncorrectLockedBalanceOperation: boolean; + readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation'; +} + +/** @name PalletAppPromotionEvent */ +export interface PalletAppPromotionEvent extends Enum { + readonly isStakingRecalculation: boolean; + readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>; + readonly isStake: boolean; + readonly asStake: ITuple<[AccountId32, u128]>; + readonly isUnstake: boolean; + readonly asUnstake: ITuple<[AccountId32, u128]>; + readonly isSetAdmin: boolean; + readonly asSetAdmin: AccountId32; + readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin'; +} + /** @name PalletBalancesAccountData */ export interface PalletBalancesAccountData extends Struct { readonly free: u128; @@ -1127,7 +1185,19 @@ /** @name PalletEvmContractHelpersError */ export interface PalletEvmContractHelpersError extends Enum { readonly isNoPermission: boolean; - readonly type: 'NoPermission'; + readonly isNoPendingSponsor: boolean; + readonly type: 'NoPermission' | 'NoPendingSponsor'; +} + +/** @name PalletEvmContractHelpersEvent */ +export interface PalletEvmContractHelpersEvent extends Enum { + readonly isContractSponsorSet: boolean; + readonly asContractSponsorSet: ITuple<[H160, AccountId32]>; + readonly isContractSponsorshipConfirmed: boolean; + readonly asContractSponsorshipConfirmed: ITuple<[H160, AccountId32]>; + readonly isContractSponsorRemoved: boolean; + readonly asContractSponsorRemoved: H160; + readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved'; } /** @name PalletEvmContractHelpersSponsoringModeT */ @@ -2419,7 +2489,7 @@ readonly name: Vec; readonly description: Vec; readonly tokenPrefix: Bytes; - readonly sponsorship: UpDataStructsSponsorshipState; + readonly sponsorship: UpDataStructsSponsorshipStateAccountId32; readonly limits: UpDataStructsCollectionLimits; readonly permissions: UpDataStructsCollectionPermissions; readonly externalCollection: bool; @@ -2580,8 +2650,7 @@ export interface UpDataStructsPropertyScope extends Enum { readonly isNone: boolean; readonly isRmrk: boolean; - readonly isEth: boolean; - readonly type: 'None' | 'Rmrk' | 'Eth'; + readonly type: 'None' | 'Rmrk'; } /** @name UpDataStructsRpcCollection */ @@ -2591,7 +2660,7 @@ readonly name: Vec; readonly description: Vec; readonly tokenPrefix: Bytes; - readonly sponsorship: UpDataStructsSponsorshipState; + readonly sponsorship: UpDataStructsSponsorshipStateAccountId32; readonly limits: UpDataStructsCollectionLimits; readonly permissions: UpDataStructsCollectionPermissions; readonly tokenPropertyPermissions: Vec; @@ -2607,8 +2676,8 @@ readonly type: 'SponsoringDisabled' | 'Blocks'; } -/** @name UpDataStructsSponsorshipState */ -export interface UpDataStructsSponsorshipState extends Enum { +/** @name UpDataStructsSponsorshipStateAccountId32 */ +export interface UpDataStructsSponsorshipStateAccountId32 extends Enum { readonly isDisabled: boolean; readonly isUnconfirmed: boolean; readonly asUnconfirmed: AccountId32; @@ -2617,6 +2686,16 @@ readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; } +/** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr */ +export interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum { + readonly isDisabled: boolean; + readonly isUnconfirmed: boolean; + readonly asUnconfirmed: PalletEvmAccountBasicCrossAccountIdRepr; + readonly isConfirmed: boolean; + readonly asConfirmed: PalletEvmAccountBasicCrossAccountIdRepr; + readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; +} + /** @name UpDataStructsTokenChild */ export interface UpDataStructsTokenChild extends Struct { readonly token: u32; --- a/tests/src/interfaces/definitions.ts +++ b/tests/src/interfaces/definitions.ts @@ -15,5 +15,6 @@ // along with Unique Network. If not, see . export {default as unique} from './unique/definitions'; +export {default as appPromotion} from './appPromotion/definitions'; export {default as rmrk} from './rmrk/definitions'; export {default as default} from './default/definitions'; \ No newline at end of file --- a/tests/src/interfaces/lookup.ts +++ b/tests/src/interfaces/lookup.ts @@ -1057,7 +1057,18 @@ } }, /** - * Lookup103: pallet_evm::pallet::Event + * Lookup103: pallet_app_promotion::pallet::Event + **/ + PalletAppPromotionEvent: { + _enum: { + StakingRecalculation: '(AccountId32,u128,u128)', + Stake: '(AccountId32,u128)', + Unstake: '(AccountId32,u128)', + SetAdmin: 'AccountId32' + } + }, + /** + * Lookup104: pallet_evm::pallet::Event **/ PalletEvmEvent: { _enum: { @@ -1071,7 +1082,7 @@ } }, /** - * Lookup104: ethereum::log::Log + * Lookup105: ethereum::log::Log **/ EthereumLog: { address: 'H160', @@ -1079,7 +1090,7 @@ data: 'Bytes' }, /** - * Lookup108: pallet_ethereum::pallet::Event + * Lookup109: pallet_ethereum::pallet::Event **/ PalletEthereumEvent: { _enum: { @@ -1087,7 +1098,7 @@ } }, /** - * Lookup109: evm_core::error::ExitReason + * Lookup110: evm_core::error::ExitReason **/ EvmCoreErrorExitReason: { _enum: { @@ -1098,13 +1109,13 @@ } }, /** - * Lookup110: evm_core::error::ExitSucceed + * Lookup111: evm_core::error::ExitSucceed **/ EvmCoreErrorExitSucceed: { _enum: ['Stopped', 'Returned', 'Suicided'] }, /** - * Lookup111: evm_core::error::ExitError + * Lookup112: evm_core::error::ExitError **/ EvmCoreErrorExitError: { _enum: { @@ -1126,13 +1137,13 @@ } }, /** - * Lookup114: evm_core::error::ExitRevert + * Lookup115: evm_core::error::ExitRevert **/ EvmCoreErrorExitRevert: { _enum: ['Reverted'] }, /** - * Lookup115: evm_core::error::ExitFatal + * Lookup116: evm_core::error::ExitFatal **/ EvmCoreErrorExitFatal: { _enum: { @@ -1143,7 +1154,17 @@ } }, /** - * Lookup116: frame_system::Phase + * Lookup117: pallet_evm_contract_helpers::pallet::Event + **/ + PalletEvmContractHelpersEvent: { + _enum: { + ContractSponsorSet: '(H160,AccountId32)', + ContractSponsorshipConfirmed: '(H160,AccountId32)', + ContractSponsorRemoved: 'H160' + } + }, + /** + * Lookup118: frame_system::Phase **/ FrameSystemPhase: { _enum: { @@ -1153,14 +1174,14 @@ } }, /** - * Lookup118: frame_system::LastRuntimeUpgradeInfo + * Lookup120: frame_system::LastRuntimeUpgradeInfo **/ FrameSystemLastRuntimeUpgradeInfo: { specVersion: 'Compact', specName: 'Text' }, /** - * Lookup119: frame_system::pallet::Call + * Lookup121: frame_system::pallet::Call **/ FrameSystemCall: { _enum: { @@ -1198,7 +1219,7 @@ } }, /** - * Lookup124: frame_system::limits::BlockWeights + * Lookup126: frame_system::limits::BlockWeights **/ FrameSystemLimitsBlockWeights: { baseBlock: 'u64', @@ -1206,7 +1227,7 @@ perClass: 'FrameSupportWeightsPerDispatchClassWeightsPerClass' }, /** - * Lookup125: frame_support::weights::PerDispatchClass + * Lookup127: frame_support::weights::PerDispatchClass **/ FrameSupportWeightsPerDispatchClassWeightsPerClass: { normal: 'FrameSystemLimitsWeightsPerClass', @@ -1214,7 +1235,7 @@ mandatory: 'FrameSystemLimitsWeightsPerClass' }, /** - * Lookup126: frame_system::limits::WeightsPerClass + * Lookup128: frame_system::limits::WeightsPerClass **/ FrameSystemLimitsWeightsPerClass: { baseExtrinsic: 'u64', @@ -1223,13 +1244,13 @@ reserved: 'Option' }, /** - * Lookup128: frame_system::limits::BlockLength + * Lookup130: frame_system::limits::BlockLength **/ FrameSystemLimitsBlockLength: { max: 'FrameSupportWeightsPerDispatchClassU32' }, /** - * Lookup129: frame_support::weights::PerDispatchClass + * Lookup131: frame_support::weights::PerDispatchClass **/ FrameSupportWeightsPerDispatchClassU32: { normal: 'u32', @@ -1237,14 +1258,14 @@ mandatory: 'u32' }, /** - * Lookup130: frame_support::weights::RuntimeDbWeight + * Lookup132: frame_support::weights::RuntimeDbWeight **/ FrameSupportWeightsRuntimeDbWeight: { read: 'u64', write: 'u64' }, /** - * Lookup131: sp_version::RuntimeVersion + * Lookup133: sp_version::RuntimeVersion **/ SpVersionRuntimeVersion: { specName: 'Text', @@ -1257,13 +1278,13 @@ stateVersion: 'u8' }, /** - * Lookup136: frame_system::pallet::Error + * Lookup138: frame_system::pallet::Error **/ FrameSystemError: { _enum: ['InvalidSpecName', 'SpecVersionNeedsToIncrease', 'FailedToExtractRuntimeVersion', 'NonDefaultComposite', 'NonZeroRefCount', 'CallFiltered'] }, /** - * Lookup137: polkadot_primitives::v2::PersistedValidationData + * Lookup139: polkadot_primitives::v2::PersistedValidationData **/ PolkadotPrimitivesV2PersistedValidationData: { parentHead: 'Bytes', @@ -1272,19 +1293,19 @@ maxPovSize: 'u32' }, /** - * Lookup140: polkadot_primitives::v2::UpgradeRestriction + * Lookup142: polkadot_primitives::v2::UpgradeRestriction **/ PolkadotPrimitivesV2UpgradeRestriction: { _enum: ['Present'] }, /** - * Lookup141: sp_trie::storage_proof::StorageProof + * Lookup143: sp_trie::storage_proof::StorageProof **/ SpTrieStorageProof: { trieNodes: 'BTreeSet' }, /** - * Lookup143: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot + * Lookup145: cumulus_pallet_parachain_system::relay_state_snapshot::MessagingStateSnapshot **/ CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot: { dmqMqcHead: 'H256', @@ -1293,7 +1314,7 @@ egressChannels: 'Vec<(u32,PolkadotPrimitivesV2AbridgedHrmpChannel)>' }, /** - * Lookup146: polkadot_primitives::v2::AbridgedHrmpChannel + * Lookup148: polkadot_primitives::v2::AbridgedHrmpChannel **/ PolkadotPrimitivesV2AbridgedHrmpChannel: { maxCapacity: 'u32', @@ -1304,7 +1325,7 @@ mqcHead: 'Option' }, /** - * Lookup147: polkadot_primitives::v2::AbridgedHostConfiguration + * Lookup149: polkadot_primitives::v2::AbridgedHostConfiguration **/ PolkadotPrimitivesV2AbridgedHostConfiguration: { maxCodeSize: 'u32', @@ -1318,14 +1339,14 @@ validationUpgradeDelay: 'u32' }, /** - * Lookup153: polkadot_core_primitives::OutboundHrmpMessage + * Lookup155: polkadot_core_primitives::OutboundHrmpMessage **/ PolkadotCorePrimitivesOutboundHrmpMessage: { recipient: 'u32', data: 'Bytes' }, /** - * Lookup154: cumulus_pallet_parachain_system::pallet::Call + * Lookup156: cumulus_pallet_parachain_system::pallet::Call **/ CumulusPalletParachainSystemCall: { _enum: { @@ -1344,7 +1365,7 @@ } }, /** - * Lookup155: cumulus_primitives_parachain_inherent::ParachainInherentData + * Lookup157: cumulus_primitives_parachain_inherent::ParachainInherentData **/ CumulusPrimitivesParachainInherentParachainInherentData: { validationData: 'PolkadotPrimitivesV2PersistedValidationData', @@ -1353,27 +1374,27 @@ horizontalMessages: 'BTreeMap>' }, /** - * Lookup157: polkadot_core_primitives::InboundDownwardMessage + * Lookup159: polkadot_core_primitives::InboundDownwardMessage **/ PolkadotCorePrimitivesInboundDownwardMessage: { sentAt: 'u32', msg: 'Bytes' }, /** - * Lookup160: polkadot_core_primitives::InboundHrmpMessage + * Lookup162: polkadot_core_primitives::InboundHrmpMessage **/ PolkadotCorePrimitivesInboundHrmpMessage: { sentAt: 'u32', data: 'Bytes' }, /** - * Lookup163: cumulus_pallet_parachain_system::pallet::Error + * Lookup165: cumulus_pallet_parachain_system::pallet::Error **/ CumulusPalletParachainSystemError: { _enum: ['OverlappingUpgrades', 'ProhibitedByPolkadot', 'TooBig', 'ValidationDataNotAvailable', 'HostConfigurationNotAvailable', 'NotScheduled', 'NothingAuthorized', 'Unauthorized'] }, /** - * Lookup165: pallet_balances::BalanceLock + * Lookup167: pallet_balances::BalanceLock **/ PalletBalancesBalanceLock: { id: '[u8;8]', @@ -1381,26 +1402,26 @@ reasons: 'PalletBalancesReasons' }, /** - * Lookup166: pallet_balances::Reasons + * Lookup168: pallet_balances::Reasons **/ PalletBalancesReasons: { _enum: ['Fee', 'Misc', 'All'] }, /** - * Lookup169: pallet_balances::ReserveData + * Lookup171: pallet_balances::ReserveData **/ PalletBalancesReserveData: { id: '[u8;16]', amount: 'u128' }, /** - * Lookup171: pallet_balances::Releases + * Lookup173: pallet_balances::Releases **/ PalletBalancesReleases: { _enum: ['V1_0_0', 'V2_0_0'] }, /** - * Lookup172: pallet_balances::pallet::Call + * Lookup174: pallet_balances::pallet::Call **/ PalletBalancesCall: { _enum: { @@ -1433,13 +1454,13 @@ } }, /** - * Lookup175: pallet_balances::pallet::Error + * Lookup177: pallet_balances::pallet::Error **/ PalletBalancesError: { _enum: ['VestingBalance', 'LiquidityRestrictions', 'InsufficientBalance', 'ExistentialDeposit', 'KeepAlive', 'ExistingVestingSchedule', 'DeadAccount', 'TooManyReserves'] }, /** - * Lookup177: pallet_timestamp::pallet::Call + * Lookup179: pallet_timestamp::pallet::Call **/ PalletTimestampCall: { _enum: { @@ -1449,13 +1470,13 @@ } }, /** - * Lookup179: pallet_transaction_payment::Releases + * Lookup181: pallet_transaction_payment::Releases **/ PalletTransactionPaymentReleases: { _enum: ['V1Ancient', 'V2'] }, /** - * Lookup180: pallet_treasury::Proposal + * Lookup182: pallet_treasury::Proposal **/ PalletTreasuryProposal: { proposer: 'AccountId32', @@ -1464,7 +1485,7 @@ bond: 'u128' }, /** - * Lookup183: pallet_treasury::pallet::Call + * Lookup185: pallet_treasury::pallet::Call **/ PalletTreasuryCall: { _enum: { @@ -1488,17 +1509,17 @@ } }, /** - * Lookup186: frame_support::PalletId + * Lookup188: frame_support::PalletId **/ FrameSupportPalletId: '[u8;8]', /** - * Lookup187: pallet_treasury::pallet::Error + * Lookup189: pallet_treasury::pallet::Error **/ PalletTreasuryError: { _enum: ['InsufficientProposersBalance', 'InvalidIndex', 'TooManyApprovals', 'InsufficientPermission', 'ProposalNotApproved'] }, /** - * Lookup188: pallet_sudo::pallet::Call + * Lookup190: pallet_sudo::pallet::Call **/ PalletSudoCall: { _enum: { @@ -1522,7 +1543,7 @@ } }, /** - * Lookup190: orml_vesting::module::Call + * Lookup192: orml_vesting::module::Call **/ OrmlVestingModuleCall: { _enum: { @@ -1541,7 +1562,7 @@ } }, /** - * Lookup192: cumulus_pallet_xcmp_queue::pallet::Call + * Lookup194: cumulus_pallet_xcmp_queue::pallet::Call **/ CumulusPalletXcmpQueueCall: { _enum: { @@ -1590,7 +1611,7 @@ } }, /** - * Lookup193: pallet_xcm::pallet::Call + * Lookup195: pallet_xcm::pallet::Call **/ PalletXcmCall: { _enum: { @@ -1644,7 +1665,7 @@ } }, /** - * Lookup194: xcm::VersionedXcm + * Lookup196: xcm::VersionedXcm **/ XcmVersionedXcm: { _enum: { @@ -1654,7 +1675,7 @@ } }, /** - * Lookup195: xcm::v0::Xcm + * Lookup197: xcm::v0::Xcm **/ XcmV0Xcm: { _enum: { @@ -1708,7 +1729,7 @@ } }, /** - * Lookup197: xcm::v0::order::Order + * Lookup199: xcm::v0::order::Order **/ XcmV0Order: { _enum: { @@ -1751,7 +1772,7 @@ } }, /** - * Lookup199: xcm::v0::Response + * Lookup201: xcm::v0::Response **/ XcmV0Response: { _enum: { @@ -1759,7 +1780,7 @@ } }, /** - * Lookup200: xcm::v1::Xcm + * Lookup202: xcm::v1::Xcm **/ XcmV1Xcm: { _enum: { @@ -1818,7 +1839,7 @@ } }, /** - * Lookup202: xcm::v1::order::Order + * Lookup204: xcm::v1::order::Order **/ XcmV1Order: { _enum: { @@ -1863,7 +1884,7 @@ } }, /** - * Lookup204: xcm::v1::Response + * Lookup206: xcm::v1::Response **/ XcmV1Response: { _enum: { @@ -1872,11 +1893,11 @@ } }, /** - * Lookup218: cumulus_pallet_xcm::pallet::Call + * Lookup220: cumulus_pallet_xcm::pallet::Call **/ CumulusPalletXcmCall: 'Null', /** - * Lookup219: cumulus_pallet_dmp_queue::pallet::Call + * Lookup221: cumulus_pallet_dmp_queue::pallet::Call **/ CumulusPalletDmpQueueCall: { _enum: { @@ -1887,7 +1908,7 @@ } }, /** - * Lookup220: pallet_inflation::pallet::Call + * Lookup222: pallet_inflation::pallet::Call **/ PalletInflationCall: { _enum: { @@ -1897,7 +1918,7 @@ } }, /** - * Lookup221: pallet_unique::Call + * Lookup223: pallet_unique::Call **/ PalletUniqueCall: { _enum: { @@ -2029,7 +2050,7 @@ } }, /** - * Lookup226: up_data_structs::CollectionMode + * Lookup228: up_data_structs::CollectionMode **/ UpDataStructsCollectionMode: { _enum: { @@ -2039,7 +2060,7 @@ } }, /** - * Lookup227: up_data_structs::CreateCollectionData + * Lookup229: up_data_structs::CreateCollectionData **/ UpDataStructsCreateCollectionData: { mode: 'UpDataStructsCollectionMode', @@ -2054,13 +2075,13 @@ properties: 'Vec' }, /** - * Lookup229: up_data_structs::AccessMode + * Lookup231: up_data_structs::AccessMode **/ UpDataStructsAccessMode: { _enum: ['Normal', 'AllowList'] }, /** - * Lookup231: up_data_structs::CollectionLimits + * Lookup233: up_data_structs::CollectionLimits **/ UpDataStructsCollectionLimits: { accountTokenOwnershipLimit: 'Option', @@ -2074,7 +2095,7 @@ transfersEnabled: 'Option' }, /** - * Lookup233: up_data_structs::SponsoringRateLimit + * Lookup235: up_data_structs::SponsoringRateLimit **/ UpDataStructsSponsoringRateLimit: { _enum: { @@ -2083,7 +2104,7 @@ } }, /** - * Lookup236: up_data_structs::CollectionPermissions + * Lookup238: up_data_structs::CollectionPermissions **/ UpDataStructsCollectionPermissions: { access: 'Option', @@ -2091,7 +2112,7 @@ nesting: 'Option' }, /** - * Lookup238: up_data_structs::NestingPermissions + * Lookup240: up_data_structs::NestingPermissions **/ UpDataStructsNestingPermissions: { tokenOwner: 'bool', @@ -2099,18 +2120,18 @@ restricted: 'Option' }, /** - * Lookup240: up_data_structs::OwnerRestrictedSet + * Lookup242: up_data_structs::OwnerRestrictedSet **/ UpDataStructsOwnerRestrictedSet: 'BTreeSet', /** - * Lookup245: up_data_structs::PropertyKeyPermission + * Lookup247: up_data_structs::PropertyKeyPermission **/ UpDataStructsPropertyKeyPermission: { key: 'Bytes', permission: 'UpDataStructsPropertyPermission' }, /** - * Lookup246: up_data_structs::PropertyPermission + * Lookup248: up_data_structs::PropertyPermission **/ UpDataStructsPropertyPermission: { mutable: 'bool', @@ -2118,14 +2139,14 @@ tokenOwner: 'bool' }, /** - * Lookup249: up_data_structs::Property + * Lookup251: up_data_structs::Property **/ UpDataStructsProperty: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup252: up_data_structs::CreateItemData + * Lookup254: up_data_structs::CreateItemData **/ UpDataStructsCreateItemData: { _enum: { @@ -2135,26 +2156,26 @@ } }, /** - * Lookup253: up_data_structs::CreateNftData + * Lookup255: up_data_structs::CreateNftData **/ UpDataStructsCreateNftData: { properties: 'Vec' }, /** - * Lookup254: up_data_structs::CreateFungibleData + * Lookup256: up_data_structs::CreateFungibleData **/ UpDataStructsCreateFungibleData: { value: 'u128' }, /** - * Lookup255: up_data_structs::CreateReFungibleData + * Lookup257: up_data_structs::CreateReFungibleData **/ UpDataStructsCreateReFungibleData: { pieces: 'u128', properties: 'Vec' }, /** - * Lookup258: up_data_structs::CreateItemExData> + * Lookup260: up_data_structs::CreateItemExData> **/ UpDataStructsCreateItemExData: { _enum: { @@ -2165,14 +2186,14 @@ } }, /** - * Lookup260: up_data_structs::CreateNftExData> + * Lookup262: up_data_structs::CreateNftExData> **/ UpDataStructsCreateNftExData: { properties: 'Vec', owner: 'PalletEvmAccountBasicCrossAccountIdRepr' }, /** - * Lookup267: up_data_structs::CreateRefungibleExSingleOwner> + * Lookup269: up_data_structs::CreateRefungibleExSingleOwner> **/ UpDataStructsCreateRefungibleExSingleOwner: { user: 'PalletEvmAccountBasicCrossAccountIdRepr', @@ -2180,14 +2201,14 @@ properties: 'Vec' }, /** - * Lookup269: up_data_structs::CreateRefungibleExMultipleOwners> + * Lookup271: up_data_structs::CreateRefungibleExMultipleOwners> **/ UpDataStructsCreateRefungibleExMultipleOwners: { users: 'BTreeMap', properties: 'Vec' }, /** - * Lookup270: pallet_unique_scheduler::pallet::Call + * Lookup272: pallet_unique_scheduler::pallet::Call **/ PalletUniqueSchedulerCall: { _enum: { @@ -2211,7 +2232,7 @@ } }, /** - * Lookup272: frame_support::traits::schedule::MaybeHashed + * Lookup274: frame_support::traits::schedule::MaybeHashed **/ FrameSupportScheduleMaybeHashed: { _enum: { @@ -2220,7 +2241,7 @@ } }, /** - * Lookup273: pallet_configuration::pallet::Call + * Lookup275: pallet_configuration::pallet::Call **/ PalletConfigurationCall: { _enum: { @@ -2233,15 +2254,15 @@ } }, /** - * Lookup274: pallet_template_transaction_payment::Call + * Lookup276: pallet_template_transaction_payment::Call **/ PalletTemplateTransactionPaymentCall: 'Null', /** - * Lookup275: pallet_structure::pallet::Call + * Lookup277: pallet_structure::pallet::Call **/ PalletStructureCall: 'Null', /** - * Lookup276: pallet_rmrk_core::pallet::Call + * Lookup278: pallet_rmrk_core::pallet::Call **/ PalletRmrkCoreCall: { _enum: { @@ -2332,7 +2353,7 @@ } }, /** - * Lookup282: rmrk_traits::resource::ResourceTypes, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup284: rmrk_traits::resource::ResourceTypes, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceResourceTypes: { _enum: { @@ -2342,7 +2363,7 @@ } }, /** - * Lookup284: rmrk_traits::resource::BasicResource> + * Lookup286: rmrk_traits::resource::BasicResource> **/ RmrkTraitsResourceBasicResource: { src: 'Option', @@ -2351,7 +2372,7 @@ thumb: 'Option' }, /** - * Lookup286: rmrk_traits::resource::ComposableResource, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup288: rmrk_traits::resource::ComposableResource, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceComposableResource: { parts: 'Vec', @@ -2362,7 +2383,7 @@ thumb: 'Option' }, /** - * Lookup287: rmrk_traits::resource::SlotResource> + * Lookup289: rmrk_traits::resource::SlotResource> **/ RmrkTraitsResourceSlotResource: { base: 'u32', @@ -2373,7 +2394,7 @@ thumb: 'Option' }, /** - * Lookup290: pallet_rmrk_equip::pallet::Call + * Lookup292: pallet_rmrk_equip::pallet::Call **/ PalletRmrkEquipCall: { _enum: { @@ -2394,7 +2415,7 @@ } }, /** - * Lookup293: rmrk_traits::part::PartType, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup295: rmrk_traits::part::PartType, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPartPartType: { _enum: { @@ -2403,7 +2424,7 @@ } }, /** - * Lookup295: rmrk_traits::part::FixedPart> + * Lookup297: rmrk_traits::part::FixedPart> **/ RmrkTraitsPartFixedPart: { id: 'u32', @@ -2411,7 +2432,7 @@ src: 'Bytes' }, /** - * Lookup296: rmrk_traits::part::SlotPart, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup298: rmrk_traits::part::SlotPart, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPartSlotPart: { id: 'u32', @@ -2420,7 +2441,7 @@ z: 'u32' }, /** - * Lookup297: rmrk_traits::part::EquippableList> + * Lookup299: rmrk_traits::part::EquippableList> **/ RmrkTraitsPartEquippableList: { _enum: { @@ -2430,7 +2451,7 @@ } }, /** - * Lookup299: rmrk_traits::theme::Theme, sp_runtime::bounded::bounded_vec::BoundedVec>, S>> + * Lookup301: rmrk_traits::theme::Theme, sp_runtime::bounded::bounded_vec::BoundedVec>, S>> **/ RmrkTraitsTheme: { name: 'Bytes', @@ -2438,14 +2459,43 @@ inherit: 'bool' }, /** - * Lookup301: rmrk_traits::theme::ThemeProperty> + * Lookup303: rmrk_traits::theme::ThemeProperty> **/ RmrkTraitsThemeThemeProperty: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup303: pallet_evm::pallet::Call + * Lookup305: pallet_app_promotion::pallet::Call + **/ + PalletAppPromotionCall: { + _enum: { + set_admin_address: { + admin: 'PalletEvmAccountBasicCrossAccountIdRepr', + }, + stake: { + amount: 'u128', + }, + unstake: 'Null', + sponsor_collection: { + collectionId: 'u32', + }, + stop_sponsoring_collection: { + collectionId: 'u32', + }, + sponsor_contract: { + contractId: 'H160', + }, + stop_sponsoring_contract: { + contractId: 'H160', + }, + payout_stakers: { + stakersNumber: 'Option' + } + } + }, + /** + * Lookup307: pallet_evm::pallet::Call **/ PalletEvmCall: { _enum: { @@ -2488,7 +2538,7 @@ } }, /** - * Lookup307: pallet_ethereum::pallet::Call + * Lookup311: pallet_ethereum::pallet::Call **/ PalletEthereumCall: { _enum: { @@ -2498,7 +2548,7 @@ } }, /** - * Lookup308: ethereum::transaction::TransactionV2 + * Lookup312: ethereum::transaction::TransactionV2 **/ EthereumTransactionTransactionV2: { _enum: { @@ -2508,7 +2558,7 @@ } }, /** - * Lookup309: ethereum::transaction::LegacyTransaction + * Lookup313: ethereum::transaction::LegacyTransaction **/ EthereumTransactionLegacyTransaction: { nonce: 'U256', @@ -2520,7 +2570,7 @@ signature: 'EthereumTransactionTransactionSignature' }, /** - * Lookup310: ethereum::transaction::TransactionAction + * Lookup314: ethereum::transaction::TransactionAction **/ EthereumTransactionTransactionAction: { _enum: { @@ -2529,7 +2579,7 @@ } }, /** - * Lookup311: ethereum::transaction::TransactionSignature + * Lookup315: ethereum::transaction::TransactionSignature **/ EthereumTransactionTransactionSignature: { v: 'u64', @@ -2537,7 +2587,7 @@ s: 'H256' }, /** - * Lookup313: ethereum::transaction::EIP2930Transaction + * Lookup317: ethereum::transaction::EIP2930Transaction **/ EthereumTransactionEip2930Transaction: { chainId: 'u64', @@ -2553,14 +2603,14 @@ s: 'H256' }, /** - * Lookup315: ethereum::transaction::AccessListItem + * Lookup319: ethereum::transaction::AccessListItem **/ EthereumTransactionAccessListItem: { address: 'H160', storageKeys: 'Vec' }, /** - * Lookup316: ethereum::transaction::EIP1559Transaction + * Lookup320: ethereum::transaction::EIP1559Transaction **/ EthereumTransactionEip1559Transaction: { chainId: 'u64', @@ -2577,7 +2627,7 @@ s: 'H256' }, /** - * Lookup317: pallet_evm_migration::pallet::Call + * Lookup321: pallet_evm_migration::pallet::Call **/ PalletEvmMigrationCall: { _enum: { @@ -2595,19 +2645,19 @@ } }, /** - * Lookup320: pallet_sudo::pallet::Error + * Lookup324: pallet_sudo::pallet::Error **/ PalletSudoError: { _enum: ['RequireSudo'] }, /** - * Lookup322: orml_vesting::module::Error + * Lookup326: orml_vesting::module::Error **/ OrmlVestingModuleError: { _enum: ['ZeroVestingPeriod', 'ZeroVestingPeriodCount', 'InsufficientBalanceToLock', 'TooManyVestingSchedules', 'AmountLow', 'MaxVestingSchedulesExceeded'] }, /** - * Lookup324: cumulus_pallet_xcmp_queue::InboundChannelDetails + * Lookup328: cumulus_pallet_xcmp_queue::InboundChannelDetails **/ CumulusPalletXcmpQueueInboundChannelDetails: { sender: 'u32', @@ -2615,19 +2665,19 @@ messageMetadata: 'Vec<(u32,PolkadotParachainPrimitivesXcmpMessageFormat)>' }, /** - * Lookup325: cumulus_pallet_xcmp_queue::InboundState + * Lookup329: cumulus_pallet_xcmp_queue::InboundState **/ CumulusPalletXcmpQueueInboundState: { _enum: ['Ok', 'Suspended'] }, /** - * Lookup328: polkadot_parachain::primitives::XcmpMessageFormat + * Lookup332: polkadot_parachain::primitives::XcmpMessageFormat **/ PolkadotParachainPrimitivesXcmpMessageFormat: { _enum: ['ConcatenatedVersionedXcm', 'ConcatenatedEncodedBlob', 'Signals'] }, /** - * Lookup331: cumulus_pallet_xcmp_queue::OutboundChannelDetails + * Lookup335: cumulus_pallet_xcmp_queue::OutboundChannelDetails **/ CumulusPalletXcmpQueueOutboundChannelDetails: { recipient: 'u32', @@ -2637,13 +2687,13 @@ lastIndex: 'u16' }, /** - * Lookup332: cumulus_pallet_xcmp_queue::OutboundState + * Lookup336: cumulus_pallet_xcmp_queue::OutboundState **/ CumulusPalletXcmpQueueOutboundState: { _enum: ['Ok', 'Suspended'] }, /** - * Lookup334: cumulus_pallet_xcmp_queue::QueueConfigData + * Lookup338: cumulus_pallet_xcmp_queue::QueueConfigData **/ CumulusPalletXcmpQueueQueueConfigData: { suspendThreshold: 'u32', @@ -2654,29 +2704,29 @@ xcmpMaxIndividualWeight: 'u64' }, /** - * Lookup336: cumulus_pallet_xcmp_queue::pallet::Error + * Lookup340: cumulus_pallet_xcmp_queue::pallet::Error **/ CumulusPalletXcmpQueueError: { _enum: ['FailedToSend', 'BadXcmOrigin', 'BadXcm', 'BadOverweightIndex', 'WeightOverLimit'] }, /** - * Lookup337: pallet_xcm::pallet::Error + * Lookup341: pallet_xcm::pallet::Error **/ PalletXcmError: { _enum: ['Unreachable', 'SendFailure', 'Filtered', 'UnweighableMessage', 'DestinationNotInvertible', 'Empty', 'CannotReanchor', 'TooManyAssets', 'InvalidOrigin', 'BadVersion', 'BadLocation', 'NoSubscription', 'AlreadySubscribed'] }, /** - * Lookup338: cumulus_pallet_xcm::pallet::Error + * Lookup342: cumulus_pallet_xcm::pallet::Error **/ CumulusPalletXcmError: 'Null', /** - * Lookup339: cumulus_pallet_dmp_queue::ConfigData + * Lookup343: cumulus_pallet_dmp_queue::ConfigData **/ CumulusPalletDmpQueueConfigData: { maxIndividual: 'u64' }, /** - * Lookup340: cumulus_pallet_dmp_queue::PageIndexData + * Lookup344: cumulus_pallet_dmp_queue::PageIndexData **/ CumulusPalletDmpQueuePageIndexData: { beginUsed: 'u32', @@ -2684,19 +2734,19 @@ overweightCount: 'u64' }, /** - * Lookup343: cumulus_pallet_dmp_queue::pallet::Error + * Lookup347: cumulus_pallet_dmp_queue::pallet::Error **/ CumulusPalletDmpQueueError: { _enum: ['Unknown', 'OverLimit'] }, /** - * Lookup347: pallet_unique::Error + * Lookup351: pallet_unique::Error **/ PalletUniqueError: { _enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument', 'RepartitionCalledOnNonRefungibleCollection'] }, /** - * Lookup350: pallet_unique_scheduler::ScheduledV3, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32> + * Lookup354: pallet_unique_scheduler::ScheduledV3, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32> **/ PalletUniqueSchedulerScheduledV3: { maybeId: 'Option<[u8;16]>', @@ -2706,7 +2756,7 @@ origin: 'OpalRuntimeOriginCaller' }, /** - * Lookup351: opal_runtime::OriginCaller + * Lookup355: opal_runtime::OriginCaller **/ OpalRuntimeOriginCaller: { _enum: { @@ -2815,7 +2865,7 @@ } }, /** - * Lookup352: frame_support::dispatch::RawOrigin + * Lookup356: frame_support::dispatch::RawOrigin **/ FrameSupportDispatchRawOrigin: { _enum: { @@ -2825,7 +2875,7 @@ } }, /** - * Lookup353: pallet_xcm::pallet::Origin + * Lookup357: pallet_xcm::pallet::Origin **/ PalletXcmOrigin: { _enum: { @@ -2834,7 +2884,7 @@ } }, /** - * Lookup354: cumulus_pallet_xcm::pallet::Origin + * Lookup358: cumulus_pallet_xcm::pallet::Origin **/ CumulusPalletXcmOrigin: { _enum: { @@ -2843,7 +2893,7 @@ } }, /** - * Lookup355: pallet_ethereum::RawOrigin + * Lookup359: pallet_ethereum::RawOrigin **/ PalletEthereumRawOrigin: { _enum: { @@ -2851,17 +2901,17 @@ } }, /** - * Lookup356: sp_core::Void + * Lookup360: sp_core::Void **/ SpCoreVoid: 'Null', /** - * Lookup357: pallet_unique_scheduler::pallet::Error + * Lookup361: pallet_unique_scheduler::pallet::Error **/ PalletUniqueSchedulerError: { _enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange'] }, /** - * Lookup358: up_data_structs::Collection + * Lookup362: up_data_structs::Collection **/ UpDataStructsCollection: { owner: 'AccountId32', @@ -2869,15 +2919,15 @@ name: 'Vec', description: 'Vec', tokenPrefix: 'Bytes', - sponsorship: 'UpDataStructsSponsorshipState', + sponsorship: 'UpDataStructsSponsorshipStateAccountId32', limits: 'UpDataStructsCollectionLimits', permissions: 'UpDataStructsCollectionPermissions', externalCollection: 'bool' }, /** - * Lookup359: up_data_structs::SponsorshipState + * Lookup363: up_data_structs::SponsorshipState **/ - UpDataStructsSponsorshipState: { + UpDataStructsSponsorshipStateAccountId32: { _enum: { Disabled: 'Null', Unconfirmed: 'AccountId32', @@ -2885,7 +2935,7 @@ } }, /** - * Lookup360: up_data_structs::Properties + * Lookup364: up_data_structs::Properties **/ UpDataStructsProperties: { map: 'UpDataStructsPropertiesMapBoundedVec', @@ -2893,15 +2943,15 @@ spaceLimit: 'u32' }, /** - * Lookup361: up_data_structs::PropertiesMap> + * Lookup365: up_data_structs::PropertiesMap> **/ UpDataStructsPropertiesMapBoundedVec: 'BTreeMap', /** - * Lookup366: up_data_structs::PropertiesMap + * Lookup370: up_data_structs::PropertiesMap **/ UpDataStructsPropertiesMapPropertyPermission: 'BTreeMap', /** - * Lookup373: up_data_structs::CollectionStats + * Lookup377: up_data_structs::CollectionStats **/ UpDataStructsCollectionStats: { created: 'u32', @@ -2909,18 +2959,18 @@ alive: 'u32' }, /** - * Lookup374: up_data_structs::TokenChild + * Lookup378: up_data_structs::TokenChild **/ UpDataStructsTokenChild: { token: 'u32', collection: 'u32' }, /** - * Lookup375: PhantomType::up_data_structs + * Lookup379: PhantomType::up_data_structs **/ PhantomTypeUpDataStructs: '[(UpDataStructsTokenData,UpDataStructsRpcCollection,RmrkTraitsCollectionCollectionInfo,RmrkTraitsNftNftInfo,RmrkTraitsResourceResourceInfo,RmrkTraitsPropertyPropertyInfo,RmrkTraitsBaseBaseInfo,RmrkTraitsPartPartType,RmrkTraitsTheme,RmrkTraitsNftNftChild);0]', /** - * Lookup377: up_data_structs::TokenData> + * Lookup381: up_data_structs::TokenData> **/ UpDataStructsTokenData: { properties: 'Vec', @@ -2928,7 +2978,7 @@ pieces: 'u128' }, /** - * Lookup379: up_data_structs::RpcCollection + * Lookup383: up_data_structs::RpcCollection **/ UpDataStructsRpcCollection: { owner: 'AccountId32', @@ -2936,7 +2986,7 @@ name: 'Vec', description: 'Vec', tokenPrefix: 'Bytes', - sponsorship: 'UpDataStructsSponsorshipState', + sponsorship: 'UpDataStructsSponsorshipStateAccountId32', limits: 'UpDataStructsCollectionLimits', permissions: 'UpDataStructsCollectionPermissions', tokenPropertyPermissions: 'Vec', @@ -2944,7 +2994,7 @@ readOnly: 'bool' }, /** - * Lookup380: rmrk_traits::collection::CollectionInfo, sp_runtime::bounded::bounded_vec::BoundedVec, sp_core::crypto::AccountId32> + * Lookup384: rmrk_traits::collection::CollectionInfo, sp_runtime::bounded::bounded_vec::BoundedVec, sp_core::crypto::AccountId32> **/ RmrkTraitsCollectionCollectionInfo: { issuer: 'AccountId32', @@ -2954,7 +3004,7 @@ nftsCount: 'u32' }, /** - * Lookup381: rmrk_traits::nft::NftInfo> + * Lookup385: rmrk_traits::nft::NftInfo> **/ RmrkTraitsNftNftInfo: { owner: 'RmrkTraitsNftAccountIdOrCollectionNftTuple', @@ -2964,14 +3014,14 @@ pending: 'bool' }, /** - * Lookup383: rmrk_traits::nft::RoyaltyInfo + * Lookup387: rmrk_traits::nft::RoyaltyInfo **/ RmrkTraitsNftRoyaltyInfo: { recipient: 'AccountId32', amount: 'Permill' }, /** - * Lookup384: rmrk_traits::resource::ResourceInfo, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup388: rmrk_traits::resource::ResourceInfo, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsResourceResourceInfo: { id: 'u32', @@ -2980,14 +3030,14 @@ pendingRemoval: 'bool' }, /** - * Lookup385: rmrk_traits::property::PropertyInfo, sp_runtime::bounded::bounded_vec::BoundedVec> + * Lookup389: rmrk_traits::property::PropertyInfo, sp_runtime::bounded::bounded_vec::BoundedVec> **/ RmrkTraitsPropertyPropertyInfo: { key: 'Bytes', value: 'Bytes' }, /** - * Lookup386: rmrk_traits::base::BaseInfo> + * Lookup390: rmrk_traits::base::BaseInfo> **/ RmrkTraitsBaseBaseInfo: { issuer: 'AccountId32', @@ -2995,80 +3045,86 @@ symbol: 'Bytes' }, /** - * Lookup387: rmrk_traits::nft::NftChild + * Lookup391: rmrk_traits::nft::NftChild **/ RmrkTraitsNftNftChild: { collectionId: 'u32', nftId: 'u32' }, /** - * Lookup389: pallet_common::pallet::Error + * Lookup393: pallet_common::pallet::Error **/ PalletCommonError: { _enum: ['CollectionNotFound', 'MustBeTokenOwner', 'NoPermission', 'CantDestroyNotEmptyCollection', 'PublicMintingNotAllowed', 'AddressNotInAllowlist', 'CollectionNameLimitExceeded', 'CollectionDescriptionLimitExceeded', 'CollectionTokenPrefixLimitExceeded', 'TotalCollectionsLimitExceeded', 'CollectionAdminCountExceeded', 'CollectionLimitBoundsExceeded', 'OwnerPermissionsCantBeReverted', 'TransferNotAllowed', 'AccountTokenLimitExceeded', 'CollectionTokenLimitExceeded', 'MetadataFlagFrozen', 'TokenNotFound', 'TokenValueTooLow', 'ApprovedValueTooLow', 'CantApproveMoreThanOwned', 'AddressIsZero', 'UnsupportedOperation', 'NotSufficientFounds', 'UserIsNotAllowedToNest', 'SourceCollectionIsNotAllowedToNest', 'CollectionFieldSizeExceeded', 'NoSpaceForProperty', 'PropertyLimitReached', 'PropertyKeyIsTooLong', 'InvalidCharacterInPropertyKey', 'EmptyPropertyKey', 'CollectionIsExternal', 'CollectionIsInternal'] }, /** - * Lookup391: pallet_fungible::pallet::Error + * Lookup395: pallet_fungible::pallet::Error **/ PalletFungibleError: { _enum: ['NotFungibleDataUsedToMintFungibleCollectionToken', 'FungibleItemsHaveNoId', 'FungibleItemsDontHaveData', 'FungibleDisallowsNesting', 'SettingPropertiesNotAllowed'] }, /** - * Lookup392: pallet_refungible::ItemData + * Lookup396: pallet_refungible::ItemData **/ PalletRefungibleItemData: { constData: 'Bytes' }, /** - * Lookup397: pallet_refungible::pallet::Error + * Lookup401: pallet_refungible::pallet::Error **/ PalletRefungibleError: { _enum: ['NotRefungibleDataUsedToMintFungibleCollectionToken', 'WrongRefungiblePieces', 'RepartitionWhileNotOwningAllPieces', 'RefungibleDisallowsNesting', 'SettingPropertiesNotAllowed'] }, /** - * Lookup398: pallet_nonfungible::ItemData> + * Lookup402: pallet_nonfungible::ItemData> **/ PalletNonfungibleItemData: { owner: 'PalletEvmAccountBasicCrossAccountIdRepr' }, /** - * Lookup400: up_data_structs::PropertyScope + * Lookup404: up_data_structs::PropertyScope **/ UpDataStructsPropertyScope: { - _enum: ['None', 'Rmrk', 'Eth'] + _enum: ['None', 'Rmrk'] }, /** - * Lookup402: pallet_nonfungible::pallet::Error + * Lookup406: pallet_nonfungible::pallet::Error **/ PalletNonfungibleError: { _enum: ['NotNonfungibleDataUsedToMintFungibleCollectionToken', 'NonfungibleItemsHaveNoAmount', 'CantBurnNftWithChildren'] }, /** - * Lookup403: pallet_structure::pallet::Error + * Lookup407: pallet_structure::pallet::Error **/ PalletStructureError: { _enum: ['OuroborosDetected', 'DepthLimit', 'BreadthLimit', 'TokenNotFound'] }, /** - * Lookup404: pallet_rmrk_core::pallet::Error + * Lookup408: pallet_rmrk_core::pallet::Error **/ PalletRmrkCoreError: { _enum: ['CorruptedCollectionType', 'RmrkPropertyKeyIsTooLong', 'RmrkPropertyValueIsTooLong', 'RmrkPropertyIsNotFound', 'UnableToDecodeRmrkData', 'CollectionNotEmpty', 'NoAvailableCollectionId', 'NoAvailableNftId', 'CollectionUnknown', 'NoPermission', 'NonTransferable', 'CollectionFullOrLocked', 'ResourceDoesntExist', 'CannotSendToDescendentOrSelf', 'CannotAcceptNonOwnedNft', 'CannotRejectNonOwnedNft', 'CannotRejectNonPendingNft', 'ResourceNotPending', 'NoAvailableResourceId'] }, /** - * Lookup406: pallet_rmrk_equip::pallet::Error + * Lookup410: pallet_rmrk_equip::pallet::Error **/ PalletRmrkEquipError: { _enum: ['PermissionError', 'NoAvailableBaseId', 'NoAvailablePartId', 'BaseDoesntExist', 'NeedsDefaultThemeFirst', 'PartDoesntExist', 'NoEquippableOnFixedPart'] }, /** - * Lookup409: pallet_evm::pallet::Error + * Lookup416: pallet_app_promotion::pallet::Error **/ + PalletAppPromotionError: { + _enum: ['AdminNotSet', 'NoPermission', 'NotSufficientFunds', 'PendingForBlockOverflow', 'SponsorNotSet', 'IncorrectLockedBalanceOperation'] + }, + /** + * Lookup419: pallet_evm::pallet::Error + **/ PalletEvmError: { _enum: ['BalanceLow', 'FeeOverflow', 'PaymentOverflow', 'WithdrawFailed', 'GasPriceTooLow', 'InvalidNonce'] }, /** - * Lookup412: fp_rpc::TransactionStatus + * Lookup422: fp_rpc::TransactionStatus **/ FpRpcTransactionStatus: { transactionHash: 'H256', @@ -3080,11 +3136,11 @@ logsBloom: 'EthbloomBloom' }, /** - * Lookup414: ethbloom::Bloom + * Lookup424: ethbloom::Bloom **/ EthbloomBloom: '[u8;256]', /** - * Lookup416: ethereum::receipt::ReceiptV3 + * Lookup426: ethereum::receipt::ReceiptV3 **/ EthereumReceiptReceiptV3: { _enum: { @@ -3094,7 +3150,7 @@ } }, /** - * Lookup417: ethereum::receipt::EIP658ReceiptData + * Lookup427: ethereum::receipt::EIP658ReceiptData **/ EthereumReceiptEip658ReceiptData: { statusCode: 'u8', @@ -3103,7 +3159,7 @@ logs: 'Vec' }, /** - * Lookup418: ethereum::block::Block + * Lookup428: ethereum::block::Block **/ EthereumBlock: { header: 'EthereumHeader', @@ -3111,7 +3167,7 @@ ommers: 'Vec' }, /** - * Lookup419: ethereum::header::Header + * Lookup429: ethereum::header::Header **/ EthereumHeader: { parentHash: 'H256', @@ -3131,41 +3187,51 @@ nonce: 'EthereumTypesHashH64' }, /** - * Lookup420: ethereum_types::hash::H64 + * Lookup430: ethereum_types::hash::H64 **/ EthereumTypesHashH64: '[u8;8]', /** - * Lookup425: pallet_ethereum::pallet::Error + * Lookup435: pallet_ethereum::pallet::Error **/ PalletEthereumError: { _enum: ['InvalidSignature', 'PreLogExists'] }, /** - * Lookup426: pallet_evm_coder_substrate::pallet::Error + * Lookup436: pallet_evm_coder_substrate::pallet::Error **/ PalletEvmCoderSubstrateError: { _enum: ['OutOfGas', 'OutOfFund'] }, /** - * Lookup427: pallet_evm_contract_helpers::SponsoringModeT + * Lookup437: up_data_structs::SponsorshipState> **/ + UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: { + _enum: { + Disabled: 'Null', + Unconfirmed: 'PalletEvmAccountBasicCrossAccountIdRepr', + Confirmed: 'PalletEvmAccountBasicCrossAccountIdRepr' + } + }, + /** + * Lookup438: pallet_evm_contract_helpers::SponsoringModeT + **/ PalletEvmContractHelpersSponsoringModeT: { _enum: ['Disabled', 'Allowlisted', 'Generous'] }, /** - * Lookup429: pallet_evm_contract_helpers::pallet::Error + * Lookup440: pallet_evm_contract_helpers::pallet::Error **/ PalletEvmContractHelpersError: { - _enum: ['NoPermission'] + _enum: ['NoPermission', 'NoPendingSponsor'] }, /** - * Lookup430: pallet_evm_migration::pallet::Error + * Lookup441: pallet_evm_migration::pallet::Error **/ PalletEvmMigrationError: { _enum: ['AccountNotEmpty', 'AccountIsNotMigrating'] }, /** - * Lookup432: sp_runtime::MultiSignature + * Lookup443: sp_runtime::MultiSignature **/ SpRuntimeMultiSignature: { _enum: { @@ -3175,43 +3241,43 @@ } }, /** - * Lookup433: sp_core::ed25519::Signature + * Lookup444: sp_core::ed25519::Signature **/ SpCoreEd25519Signature: '[u8;64]', /** - * Lookup435: sp_core::sr25519::Signature + * Lookup446: sp_core::sr25519::Signature **/ SpCoreSr25519Signature: '[u8;64]', /** - * Lookup436: sp_core::ecdsa::Signature + * Lookup447: sp_core::ecdsa::Signature **/ SpCoreEcdsaSignature: '[u8;65]', /** - * Lookup439: frame_system::extensions::check_spec_version::CheckSpecVersion + * Lookup450: frame_system::extensions::check_spec_version::CheckSpecVersion **/ FrameSystemExtensionsCheckSpecVersion: 'Null', /** - * Lookup440: frame_system::extensions::check_genesis::CheckGenesis + * Lookup451: frame_system::extensions::check_genesis::CheckGenesis **/ FrameSystemExtensionsCheckGenesis: 'Null', /** - * Lookup443: frame_system::extensions::check_nonce::CheckNonce + * Lookup454: frame_system::extensions::check_nonce::CheckNonce **/ FrameSystemExtensionsCheckNonce: 'Compact', /** - * Lookup444: frame_system::extensions::check_weight::CheckWeight + * Lookup455: frame_system::extensions::check_weight::CheckWeight **/ FrameSystemExtensionsCheckWeight: 'Null', /** - * Lookup445: pallet_template_transaction_payment::ChargeTransactionPayment + * Lookup456: pallet_template_transaction_payment::ChargeTransactionPayment **/ PalletTemplateTransactionPaymentChargeTransactionPayment: 'Compact', /** - * Lookup446: opal_runtime::Runtime + * Lookup457: opal_runtime::Runtime **/ OpalRuntimeRuntime: 'Null', /** - * Lookup447: pallet_ethereum::FakeTransactionFinalizer + * Lookup458: pallet_ethereum::FakeTransactionFinalizer **/ PalletEthereumFakeTransactionFinalizer: 'Null' }; --- a/tests/src/interfaces/registry.ts +++ b/tests/src/interfaces/registry.ts @@ -5,7 +5,7 @@ // this is required to allow for ambient/previous definitions import '@polkadot/types/types/registry'; -import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; +import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletAppPromotionCall, PalletAppPromotionError, PalletAppPromotionEvent, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletConfigurationCall, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersEvent, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentEvent, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExMultipleOwners, UpDataStructsCreateRefungibleExSingleOwner, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipStateAccountId32, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup'; declare module '@polkadot/types/types/registry' { interface InterfaceTypes { @@ -83,6 +83,9 @@ OrmlVestingModuleError: OrmlVestingModuleError; OrmlVestingModuleEvent: OrmlVestingModuleEvent; OrmlVestingVestingSchedule: OrmlVestingVestingSchedule; + PalletAppPromotionCall: PalletAppPromotionCall; + PalletAppPromotionError: PalletAppPromotionError; + PalletAppPromotionEvent: PalletAppPromotionEvent; PalletBalancesAccountData: PalletBalancesAccountData; PalletBalancesBalanceLock: PalletBalancesBalanceLock; PalletBalancesCall: PalletBalancesCall; @@ -103,6 +106,7 @@ PalletEvmCall: PalletEvmCall; PalletEvmCoderSubstrateError: PalletEvmCoderSubstrateError; PalletEvmContractHelpersError: PalletEvmContractHelpersError; + PalletEvmContractHelpersEvent: PalletEvmContractHelpersEvent; PalletEvmContractHelpersSponsoringModeT: PalletEvmContractHelpersSponsoringModeT; PalletEvmError: PalletEvmError; PalletEvmEvent: PalletEvmEvent; @@ -213,7 +217,8 @@ UpDataStructsPropertyScope: UpDataStructsPropertyScope; UpDataStructsRpcCollection: UpDataStructsRpcCollection; UpDataStructsSponsoringRateLimit: UpDataStructsSponsoringRateLimit; - UpDataStructsSponsorshipState: UpDataStructsSponsorshipState; + UpDataStructsSponsorshipStateAccountId32: UpDataStructsSponsorshipStateAccountId32; + UpDataStructsSponsorshipStateBasicCrossAccountIdRepr: UpDataStructsSponsorshipStateBasicCrossAccountIdRepr; UpDataStructsTokenChild: UpDataStructsTokenChild; UpDataStructsTokenData: UpDataStructsTokenData; XcmDoubleEncoded: XcmDoubleEncoded; --- a/tests/src/interfaces/types-lookup.ts +++ b/tests/src/interfaces/types-lookup.ts @@ -1198,7 +1198,20 @@ readonly type: 'BaseCreated' | 'EquippablesUpdated'; } - /** @name PalletEvmEvent (103) */ + /** @name PalletAppPromotionEvent (103) */ + interface PalletAppPromotionEvent extends Enum { + readonly isStakingRecalculation: boolean; + readonly asStakingRecalculation: ITuple<[AccountId32, u128, u128]>; + readonly isStake: boolean; + readonly asStake: ITuple<[AccountId32, u128]>; + readonly isUnstake: boolean; + readonly asUnstake: ITuple<[AccountId32, u128]>; + readonly isSetAdmin: boolean; + readonly asSetAdmin: AccountId32; + readonly type: 'StakingRecalculation' | 'Stake' | 'Unstake' | 'SetAdmin'; + } + + /** @name PalletEvmEvent (104) */ interface PalletEvmEvent extends Enum { readonly isLog: boolean; readonly asLog: EthereumLog; @@ -1217,21 +1230,21 @@ readonly type: 'Log' | 'Created' | 'CreatedFailed' | 'Executed' | 'ExecutedFailed' | 'BalanceDeposit' | 'BalanceWithdraw'; } - /** @name EthereumLog (104) */ + /** @name EthereumLog (105) */ interface EthereumLog extends Struct { readonly address: H160; readonly topics: Vec; readonly data: Bytes; } - /** @name PalletEthereumEvent (108) */ + /** @name PalletEthereumEvent (109) */ interface PalletEthereumEvent extends Enum { readonly isExecuted: boolean; readonly asExecuted: ITuple<[H160, H160, H256, EvmCoreErrorExitReason]>; readonly type: 'Executed'; } - /** @name EvmCoreErrorExitReason (109) */ + /** @name EvmCoreErrorExitReason (110) */ interface EvmCoreErrorExitReason extends Enum { readonly isSucceed: boolean; readonly asSucceed: EvmCoreErrorExitSucceed; @@ -1244,7 +1257,7 @@ readonly type: 'Succeed' | 'Error' | 'Revert' | 'Fatal'; } - /** @name EvmCoreErrorExitSucceed (110) */ + /** @name EvmCoreErrorExitSucceed (111) */ interface EvmCoreErrorExitSucceed extends Enum { readonly isStopped: boolean; readonly isReturned: boolean; @@ -1252,7 +1265,7 @@ readonly type: 'Stopped' | 'Returned' | 'Suicided'; } - /** @name EvmCoreErrorExitError (111) */ + /** @name EvmCoreErrorExitError (112) */ interface EvmCoreErrorExitError extends Enum { readonly isStackUnderflow: boolean; readonly isStackOverflow: boolean; @@ -1273,13 +1286,13 @@ readonly type: 'StackUnderflow' | 'StackOverflow' | 'InvalidJump' | 'InvalidRange' | 'DesignatedInvalid' | 'CallTooDeep' | 'CreateCollision' | 'CreateContractLimit' | 'OutOfOffset' | 'OutOfGas' | 'OutOfFund' | 'PcUnderflow' | 'CreateEmpty' | 'Other' | 'InvalidCode'; } - /** @name EvmCoreErrorExitRevert (114) */ + /** @name EvmCoreErrorExitRevert (115) */ interface EvmCoreErrorExitRevert extends Enum { readonly isReverted: boolean; readonly type: 'Reverted'; } - /** @name EvmCoreErrorExitFatal (115) */ + /** @name EvmCoreErrorExitFatal (116) */ interface EvmCoreErrorExitFatal extends Enum { readonly isNotSupported: boolean; readonly isUnhandledInterrupt: boolean; @@ -1290,7 +1303,18 @@ readonly type: 'NotSupported' | 'UnhandledInterrupt' | 'CallErrorAsFatal' | 'Other'; } - /** @name FrameSystemPhase (116) */ + /** @name PalletEvmContractHelpersEvent (117) */ + interface PalletEvmContractHelpersEvent extends Enum { + readonly isContractSponsorSet: boolean; + readonly asContractSponsorSet: ITuple<[H160, AccountId32]>; + readonly isContractSponsorshipConfirmed: boolean; + readonly asContractSponsorshipConfirmed: ITuple<[H160, AccountId32]>; + readonly isContractSponsorRemoved: boolean; + readonly asContractSponsorRemoved: H160; + readonly type: 'ContractSponsorSet' | 'ContractSponsorshipConfirmed' | 'ContractSponsorRemoved'; + } + + /** @name FrameSystemPhase (118) */ interface FrameSystemPhase extends Enum { readonly isApplyExtrinsic: boolean; readonly asApplyExtrinsic: u32; @@ -1299,13 +1323,13 @@ readonly type: 'ApplyExtrinsic' | 'Finalization' | 'Initialization'; } - /** @name FrameSystemLastRuntimeUpgradeInfo (118) */ + /** @name FrameSystemLastRuntimeUpgradeInfo (120) */ interface FrameSystemLastRuntimeUpgradeInfo extends Struct { readonly specVersion: Compact; readonly specName: Text; } - /** @name FrameSystemCall (119) */ + /** @name FrameSystemCall (121) */ interface FrameSystemCall extends Enum { readonly isFillBlock: boolean; readonly asFillBlock: { @@ -1347,21 +1371,21 @@ readonly type: 'FillBlock' | 'Remark' | 'SetHeapPages' | 'SetCode' | 'SetCodeWithoutChecks' | 'SetStorage' | 'KillStorage' | 'KillPrefix' | 'RemarkWithEvent'; } - /** @name FrameSystemLimitsBlockWeights (124) */ + /** @name FrameSystemLimitsBlockWeights (126) */ interface FrameSystemLimitsBlockWeights extends Struct { readonly baseBlock: u64; readonly maxBlock: u64; readonly perClass: FrameSupportWeightsPerDispatchClassWeightsPerClass; } - /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (125) */ + /** @name FrameSupportWeightsPerDispatchClassWeightsPerClass (127) */ interface FrameSupportWeightsPerDispatchClassWeightsPerClass extends Struct { readonly normal: FrameSystemLimitsWeightsPerClass; readonly operational: FrameSystemLimitsWeightsPerClass; readonly mandatory: FrameSystemLimitsWeightsPerClass; } - /** @name FrameSystemLimitsWeightsPerClass (126) */ + /** @name FrameSystemLimitsWeightsPerClass (128) */ interface FrameSystemLimitsWeightsPerClass extends Struct { readonly baseExtrinsic: u64; readonly maxExtrinsic: Option; @@ -1369,25 +1393,25 @@ readonly reserved: Option; } - /** @name FrameSystemLimitsBlockLength (128) */ + /** @name FrameSystemLimitsBlockLength (130) */ interface FrameSystemLimitsBlockLength extends Struct { readonly max: FrameSupportWeightsPerDispatchClassU32; } - /** @name FrameSupportWeightsPerDispatchClassU32 (129) */ + /** @name FrameSupportWeightsPerDispatchClassU32 (131) */ interface FrameSupportWeightsPerDispatchClassU32 extends Struct { readonly normal: u32; readonly operational: u32; readonly mandatory: u32; } - /** @name FrameSupportWeightsRuntimeDbWeight (130) */ + /** @name FrameSupportWeightsRuntimeDbWeight (132) */ interface FrameSupportWeightsRuntimeDbWeight extends Struct { readonly read: u64; readonly write: u64; } - /** @name SpVersionRuntimeVersion (131) */ + /** @name SpVersionRuntimeVersion (133) */ interface SpVersionRuntimeVersion extends Struct { readonly specName: Text; readonly implName: Text; @@ -1399,7 +1423,7 @@ readonly stateVersion: u8; } - /** @name FrameSystemError (136) */ + /** @name FrameSystemError (138) */ interface FrameSystemError extends Enum { readonly isInvalidSpecName: boolean; readonly isSpecVersionNeedsToIncrease: boolean; @@ -1410,7 +1434,7 @@ readonly type: 'InvalidSpecName' | 'SpecVersionNeedsToIncrease' | 'FailedToExtractRuntimeVersion' | 'NonDefaultComposite' | 'NonZeroRefCount' | 'CallFiltered'; } - /** @name PolkadotPrimitivesV2PersistedValidationData (137) */ + /** @name PolkadotPrimitivesV2PersistedValidationData (139) */ interface PolkadotPrimitivesV2PersistedValidationData extends Struct { readonly parentHead: Bytes; readonly relayParentNumber: u32; @@ -1418,18 +1442,18 @@ readonly maxPovSize: u32; } - /** @name PolkadotPrimitivesV2UpgradeRestriction (140) */ + /** @name PolkadotPrimitivesV2UpgradeRestriction (142) */ interface PolkadotPrimitivesV2UpgradeRestriction extends Enum { readonly isPresent: boolean; readonly type: 'Present'; } - /** @name SpTrieStorageProof (141) */ + /** @name SpTrieStorageProof (143) */ interface SpTrieStorageProof extends Struct { readonly trieNodes: BTreeSet; } - /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (143) */ + /** @name CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot (145) */ interface CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot extends Struct { readonly dmqMqcHead: H256; readonly relayDispatchQueueSize: ITuple<[u32, u32]>; @@ -1437,7 +1461,7 @@ readonly egressChannels: Vec>; } - /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (146) */ + /** @name PolkadotPrimitivesV2AbridgedHrmpChannel (148) */ interface PolkadotPrimitivesV2AbridgedHrmpChannel extends Struct { readonly maxCapacity: u32; readonly maxTotalSize: u32; @@ -1447,7 +1471,7 @@ readonly mqcHead: Option; } - /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (147) */ + /** @name PolkadotPrimitivesV2AbridgedHostConfiguration (149) */ interface PolkadotPrimitivesV2AbridgedHostConfiguration extends Struct { readonly maxCodeSize: u32; readonly maxHeadDataSize: u32; @@ -1460,13 +1484,13 @@ readonly validationUpgradeDelay: u32; } - /** @name PolkadotCorePrimitivesOutboundHrmpMessage (153) */ + /** @name PolkadotCorePrimitivesOutboundHrmpMessage (155) */ interface PolkadotCorePrimitivesOutboundHrmpMessage extends Struct { readonly recipient: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemCall (154) */ + /** @name CumulusPalletParachainSystemCall (156) */ interface CumulusPalletParachainSystemCall extends Enum { readonly isSetValidationData: boolean; readonly asSetValidationData: { @@ -1487,7 +1511,7 @@ readonly type: 'SetValidationData' | 'SudoSendUpwardMessage' | 'AuthorizeUpgrade' | 'EnactAuthorizedUpgrade'; } - /** @name CumulusPrimitivesParachainInherentParachainInherentData (155) */ + /** @name CumulusPrimitivesParachainInherentParachainInherentData (157) */ interface CumulusPrimitivesParachainInherentParachainInherentData extends Struct { readonly validationData: PolkadotPrimitivesV2PersistedValidationData; readonly relayChainState: SpTrieStorageProof; @@ -1495,19 +1519,19 @@ readonly horizontalMessages: BTreeMap>; } - /** @name PolkadotCorePrimitivesInboundDownwardMessage (157) */ + /** @name PolkadotCorePrimitivesInboundDownwardMessage (159) */ interface PolkadotCorePrimitivesInboundDownwardMessage extends Struct { readonly sentAt: u32; readonly msg: Bytes; } - /** @name PolkadotCorePrimitivesInboundHrmpMessage (160) */ + /** @name PolkadotCorePrimitivesInboundHrmpMessage (162) */ interface PolkadotCorePrimitivesInboundHrmpMessage extends Struct { readonly sentAt: u32; readonly data: Bytes; } - /** @name CumulusPalletParachainSystemError (163) */ + /** @name CumulusPalletParachainSystemError (165) */ interface CumulusPalletParachainSystemError extends Enum { readonly isOverlappingUpgrades: boolean; readonly isProhibitedByPolkadot: boolean; @@ -1520,14 +1544,14 @@ readonly type: 'OverlappingUpgrades' | 'ProhibitedByPolkadot' | 'TooBig' | 'ValidationDataNotAvailable' | 'HostConfigurationNotAvailable' | 'NotScheduled' | 'NothingAuthorized' | 'Unauthorized'; } - /** @name PalletBalancesBalanceLock (165) */ + /** @name PalletBalancesBalanceLock (167) */ interface PalletBalancesBalanceLock extends Struct { readonly id: U8aFixed; readonly amount: u128; readonly reasons: PalletBalancesReasons; } - /** @name PalletBalancesReasons (166) */ + /** @name PalletBalancesReasons (168) */ interface PalletBalancesReasons extends Enum { readonly isFee: boolean; readonly isMisc: boolean; @@ -1535,20 +1559,20 @@ readonly type: 'Fee' | 'Misc' | 'All'; } - /** @name PalletBalancesReserveData (169) */ + /** @name PalletBalancesReserveData (171) */ interface PalletBalancesReserveData extends Struct { readonly id: U8aFixed; readonly amount: u128; } - /** @name PalletBalancesReleases (171) */ + /** @name PalletBalancesReleases (173) */ interface PalletBalancesReleases extends Enum { readonly isV100: boolean; readonly isV200: boolean; readonly type: 'V100' | 'V200'; } - /** @name PalletBalancesCall (172) */ + /** @name PalletBalancesCall (174) */ interface PalletBalancesCall extends Enum { readonly isTransfer: boolean; readonly asTransfer: { @@ -1585,7 +1609,7 @@ readonly type: 'Transfer' | 'SetBalance' | 'ForceTransfer' | 'TransferKeepAlive' | 'TransferAll' | 'ForceUnreserve'; } - /** @name PalletBalancesError (175) */ + /** @name PalletBalancesError (177) */ interface PalletBalancesError extends Enum { readonly isVestingBalance: boolean; readonly isLiquidityRestrictions: boolean; @@ -1598,7 +1622,7 @@ readonly type: 'VestingBalance' | 'LiquidityRestrictions' | 'InsufficientBalance' | 'ExistentialDeposit' | 'KeepAlive' | 'ExistingVestingSchedule' | 'DeadAccount' | 'TooManyReserves'; } - /** @name PalletTimestampCall (177) */ + /** @name PalletTimestampCall (179) */ interface PalletTimestampCall extends Enum { readonly isSet: boolean; readonly asSet: { @@ -1607,14 +1631,14 @@ readonly type: 'Set'; } - /** @name PalletTransactionPaymentReleases (179) */ + /** @name PalletTransactionPaymentReleases (181) */ interface PalletTransactionPaymentReleases extends Enum { readonly isV1Ancient: boolean; readonly isV2: boolean; readonly type: 'V1Ancient' | 'V2'; } - /** @name PalletTreasuryProposal (180) */ + /** @name PalletTreasuryProposal (182) */ interface PalletTreasuryProposal extends Struct { readonly proposer: AccountId32; readonly value: u128; @@ -1622,7 +1646,7 @@ readonly bond: u128; } - /** @name PalletTreasuryCall (183) */ + /** @name PalletTreasuryCall (185) */ interface PalletTreasuryCall extends Enum { readonly isProposeSpend: boolean; readonly asProposeSpend: { @@ -1649,10 +1673,10 @@ readonly type: 'ProposeSpend' | 'RejectProposal' | 'ApproveProposal' | 'Spend' | 'RemoveApproval'; } - /** @name FrameSupportPalletId (186) */ + /** @name FrameSupportPalletId (188) */ interface FrameSupportPalletId extends U8aFixed {} - /** @name PalletTreasuryError (187) */ + /** @name PalletTreasuryError (189) */ interface PalletTreasuryError extends Enum { readonly isInsufficientProposersBalance: boolean; readonly isInvalidIndex: boolean; @@ -1662,7 +1686,7 @@ readonly type: 'InsufficientProposersBalance' | 'InvalidIndex' | 'TooManyApprovals' | 'InsufficientPermission' | 'ProposalNotApproved'; } - /** @name PalletSudoCall (188) */ + /** @name PalletSudoCall (190) */ interface PalletSudoCall extends Enum { readonly isSudo: boolean; readonly asSudo: { @@ -1685,7 +1709,7 @@ readonly type: 'Sudo' | 'SudoUncheckedWeight' | 'SetKey' | 'SudoAs'; } - /** @name OrmlVestingModuleCall (190) */ + /** @name OrmlVestingModuleCall (192) */ interface OrmlVestingModuleCall extends Enum { readonly isClaim: boolean; readonly isVestedTransfer: boolean; @@ -1705,7 +1729,7 @@ readonly type: 'Claim' | 'VestedTransfer' | 'UpdateVestingSchedules' | 'ClaimFor'; } - /** @name CumulusPalletXcmpQueueCall (192) */ + /** @name CumulusPalletXcmpQueueCall (194) */ interface CumulusPalletXcmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -1741,7 +1765,7 @@ readonly type: 'ServiceOverweight' | 'SuspendXcmExecution' | 'ResumeXcmExecution' | 'UpdateSuspendThreshold' | 'UpdateDropThreshold' | 'UpdateResumeThreshold' | 'UpdateThresholdWeight' | 'UpdateWeightRestrictDecay' | 'UpdateXcmpMaxIndividualWeight'; } - /** @name PalletXcmCall (193) */ + /** @name PalletXcmCall (195) */ interface PalletXcmCall extends Enum { readonly isSend: boolean; readonly asSend: { @@ -1803,7 +1827,7 @@ readonly type: 'Send' | 'TeleportAssets' | 'ReserveTransferAssets' | 'Execute' | 'ForceXcmVersion' | 'ForceDefaultXcmVersion' | 'ForceSubscribeVersionNotify' | 'ForceUnsubscribeVersionNotify' | 'LimitedReserveTransferAssets' | 'LimitedTeleportAssets'; } - /** @name XcmVersionedXcm (194) */ + /** @name XcmVersionedXcm (196) */ interface XcmVersionedXcm extends Enum { readonly isV0: boolean; readonly asV0: XcmV0Xcm; @@ -1814,7 +1838,7 @@ readonly type: 'V0' | 'V1' | 'V2'; } - /** @name XcmV0Xcm (195) */ + /** @name XcmV0Xcm (197) */ interface XcmV0Xcm extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: { @@ -1877,7 +1901,7 @@ readonly type: 'WithdrawAsset' | 'ReserveAssetDeposit' | 'TeleportAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom'; } - /** @name XcmV0Order (197) */ + /** @name XcmV0Order (199) */ interface XcmV0Order extends Enum { readonly isNull: boolean; readonly isDepositAsset: boolean; @@ -1925,14 +1949,14 @@ readonly type: 'Null' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution'; } - /** @name XcmV0Response (199) */ + /** @name XcmV0Response (201) */ interface XcmV0Response extends Enum { readonly isAssets: boolean; readonly asAssets: Vec; readonly type: 'Assets'; } - /** @name XcmV1Xcm (200) */ + /** @name XcmV1Xcm (202) */ interface XcmV1Xcm extends Enum { readonly isWithdrawAsset: boolean; readonly asWithdrawAsset: { @@ -2001,7 +2025,7 @@ readonly type: 'WithdrawAsset' | 'ReserveAssetDeposited' | 'ReceiveTeleportedAsset' | 'QueryResponse' | 'TransferAsset' | 'TransferReserveAsset' | 'Transact' | 'HrmpNewChannelOpenRequest' | 'HrmpChannelAccepted' | 'HrmpChannelClosing' | 'RelayedFrom' | 'SubscribeVersion' | 'UnsubscribeVersion'; } - /** @name XcmV1Order (202) */ + /** @name XcmV1Order (204) */ interface XcmV1Order extends Enum { readonly isNoop: boolean; readonly isDepositAsset: boolean; @@ -2051,7 +2075,7 @@ readonly type: 'Noop' | 'DepositAsset' | 'DepositReserveAsset' | 'ExchangeAsset' | 'InitiateReserveWithdraw' | 'InitiateTeleport' | 'QueryHolding' | 'BuyExecution'; } - /** @name XcmV1Response (204) */ + /** @name XcmV1Response (206) */ interface XcmV1Response extends Enum { readonly isAssets: boolean; readonly asAssets: XcmV1MultiassetMultiAssets; @@ -2060,10 +2084,10 @@ readonly type: 'Assets' | 'Version'; } - /** @name CumulusPalletXcmCall (218) */ + /** @name CumulusPalletXcmCall (220) */ type CumulusPalletXcmCall = Null; - /** @name CumulusPalletDmpQueueCall (219) */ + /** @name CumulusPalletDmpQueueCall (221) */ interface CumulusPalletDmpQueueCall extends Enum { readonly isServiceOverweight: boolean; readonly asServiceOverweight: { @@ -2073,7 +2097,7 @@ readonly type: 'ServiceOverweight'; } - /** @name PalletInflationCall (220) */ + /** @name PalletInflationCall (222) */ interface PalletInflationCall extends Enum { readonly isStartInflation: boolean; readonly asStartInflation: { @@ -2082,7 +2106,7 @@ readonly type: 'StartInflation'; } - /** @name PalletUniqueCall (221) */ + /** @name PalletUniqueCall (223) */ interface PalletUniqueCall extends Enum { readonly isCreateCollection: boolean; readonly asCreateCollection: { @@ -2240,7 +2264,7 @@ readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition'; } - /** @name UpDataStructsCollectionMode (226) */ + /** @name UpDataStructsCollectionMode (228) */ interface UpDataStructsCollectionMode extends Enum { readonly isNft: boolean; readonly isFungible: boolean; @@ -2249,7 +2273,7 @@ readonly type: 'Nft' | 'Fungible' | 'ReFungible'; } - /** @name UpDataStructsCreateCollectionData (227) */ + /** @name UpDataStructsCreateCollectionData (229) */ interface UpDataStructsCreateCollectionData extends Struct { readonly mode: UpDataStructsCollectionMode; readonly access: Option; @@ -2263,14 +2287,14 @@ readonly properties: Vec; } - /** @name UpDataStructsAccessMode (229) */ + /** @name UpDataStructsAccessMode (231) */ interface UpDataStructsAccessMode extends Enum { readonly isNormal: boolean; readonly isAllowList: boolean; readonly type: 'Normal' | 'AllowList'; } - /** @name UpDataStructsCollectionLimits (231) */ + /** @name UpDataStructsCollectionLimits (233) */ interface UpDataStructsCollectionLimits extends Struct { readonly accountTokenOwnershipLimit: Option; readonly sponsoredDataSize: Option; @@ -2283,7 +2307,7 @@ readonly transfersEnabled: Option; } - /** @name UpDataStructsSponsoringRateLimit (233) */ + /** @name UpDataStructsSponsoringRateLimit (235) */ interface UpDataStructsSponsoringRateLimit extends Enum { readonly isSponsoringDisabled: boolean; readonly isBlocks: boolean; @@ -2291,43 +2315,43 @@ readonly type: 'SponsoringDisabled' | 'Blocks'; } - /** @name UpDataStructsCollectionPermissions (236) */ + /** @name UpDataStructsCollectionPermissions (238) */ interface UpDataStructsCollectionPermissions extends Struct { readonly access: Option; readonly mintMode: Option; readonly nesting: Option; } - /** @name UpDataStructsNestingPermissions (238) */ + /** @name UpDataStructsNestingPermissions (240) */ interface UpDataStructsNestingPermissions extends Struct { readonly tokenOwner: bool; readonly collectionAdmin: bool; readonly restricted: Option; } - /** @name UpDataStructsOwnerRestrictedSet (240) */ + /** @name UpDataStructsOwnerRestrictedSet (242) */ interface UpDataStructsOwnerRestrictedSet extends BTreeSet {} - /** @name UpDataStructsPropertyKeyPermission (245) */ + /** @name UpDataStructsPropertyKeyPermission (247) */ interface UpDataStructsPropertyKeyPermission extends Struct { readonly key: Bytes; readonly permission: UpDataStructsPropertyPermission; } - /** @name UpDataStructsPropertyPermission (246) */ + /** @name UpDataStructsPropertyPermission (248) */ interface UpDataStructsPropertyPermission extends Struct { readonly mutable: bool; readonly collectionAdmin: bool; readonly tokenOwner: bool; } - /** @name UpDataStructsProperty (249) */ + /** @name UpDataStructsProperty (251) */ interface UpDataStructsProperty extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name UpDataStructsCreateItemData (252) */ + /** @name UpDataStructsCreateItemData (254) */ interface UpDataStructsCreateItemData extends Enum { readonly isNft: boolean; readonly asNft: UpDataStructsCreateNftData; @@ -2338,23 +2362,23 @@ readonly type: 'Nft' | 'Fungible' | 'ReFungible'; } - /** @name UpDataStructsCreateNftData (253) */ + /** @name UpDataStructsCreateNftData (255) */ interface UpDataStructsCreateNftData extends Struct { readonly properties: Vec; } - /** @name UpDataStructsCreateFungibleData (254) */ + /** @name UpDataStructsCreateFungibleData (256) */ interface UpDataStructsCreateFungibleData extends Struct { readonly value: u128; } - /** @name UpDataStructsCreateReFungibleData (255) */ + /** @name UpDataStructsCreateReFungibleData (257) */ interface UpDataStructsCreateReFungibleData extends Struct { readonly pieces: u128; readonly properties: Vec; } - /** @name UpDataStructsCreateItemExData (258) */ + /** @name UpDataStructsCreateItemExData (260) */ interface UpDataStructsCreateItemExData extends Enum { readonly isNft: boolean; readonly asNft: Vec; @@ -2367,26 +2391,26 @@ readonly type: 'Nft' | 'Fungible' | 'RefungibleMultipleItems' | 'RefungibleMultipleOwners'; } - /** @name UpDataStructsCreateNftExData (260) */ + /** @name UpDataStructsCreateNftExData (262) */ interface UpDataStructsCreateNftExData extends Struct { readonly properties: Vec; readonly owner: PalletEvmAccountBasicCrossAccountIdRepr; } - /** @name UpDataStructsCreateRefungibleExSingleOwner (267) */ + /** @name UpDataStructsCreateRefungibleExSingleOwner (269) */ interface UpDataStructsCreateRefungibleExSingleOwner extends Struct { readonly user: PalletEvmAccountBasicCrossAccountIdRepr; readonly pieces: u128; readonly properties: Vec; } - /** @name UpDataStructsCreateRefungibleExMultipleOwners (269) */ + /** @name UpDataStructsCreateRefungibleExMultipleOwners (271) */ interface UpDataStructsCreateRefungibleExMultipleOwners extends Struct { readonly users: BTreeMap; readonly properties: Vec; } - /** @name PalletUniqueSchedulerCall (270) */ + /** @name PalletUniqueSchedulerCall (272) */ interface PalletUniqueSchedulerCall extends Enum { readonly isScheduleNamed: boolean; readonly asScheduleNamed: { @@ -2411,7 +2435,7 @@ readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter'; } - /** @name FrameSupportScheduleMaybeHashed (272) */ + /** @name FrameSupportScheduleMaybeHashed (274) */ interface FrameSupportScheduleMaybeHashed extends Enum { readonly isValue: boolean; readonly asValue: Call; @@ -2420,7 +2444,7 @@ readonly type: 'Value' | 'Hash'; } - /** @name PalletConfigurationCall (273) */ + /** @name PalletConfigurationCall (275) */ interface PalletConfigurationCall extends Enum { readonly isSetWeightToFeeCoefficientOverride: boolean; readonly asSetWeightToFeeCoefficientOverride: { @@ -2433,13 +2457,13 @@ readonly type: 'SetWeightToFeeCoefficientOverride' | 'SetMinGasPriceOverride'; } - /** @name PalletTemplateTransactionPaymentCall (274) */ + /** @name PalletTemplateTransactionPaymentCall (276) */ type PalletTemplateTransactionPaymentCall = Null; - /** @name PalletStructureCall (275) */ + /** @name PalletStructureCall (277) */ type PalletStructureCall = Null; - /** @name PalletRmrkCoreCall (276) */ + /** @name PalletRmrkCoreCall (278) */ interface PalletRmrkCoreCall extends Enum { readonly isCreateCollection: boolean; readonly asCreateCollection: { @@ -2545,7 +2569,7 @@ readonly type: 'CreateCollection' | 'DestroyCollection' | 'ChangeCollectionIssuer' | 'LockCollection' | 'MintNft' | 'BurnNft' | 'Send' | 'AcceptNft' | 'RejectNft' | 'AcceptResource' | 'AcceptResourceRemoval' | 'SetProperty' | 'SetPriority' | 'AddBasicResource' | 'AddComposableResource' | 'AddSlotResource' | 'RemoveResource'; } - /** @name RmrkTraitsResourceResourceTypes (282) */ + /** @name RmrkTraitsResourceResourceTypes (284) */ interface RmrkTraitsResourceResourceTypes extends Enum { readonly isBasic: boolean; readonly asBasic: RmrkTraitsResourceBasicResource; @@ -2556,7 +2580,7 @@ readonly type: 'Basic' | 'Composable' | 'Slot'; } - /** @name RmrkTraitsResourceBasicResource (284) */ + /** @name RmrkTraitsResourceBasicResource (286) */ interface RmrkTraitsResourceBasicResource extends Struct { readonly src: Option; readonly metadata: Option; @@ -2564,7 +2588,7 @@ readonly thumb: Option; } - /** @name RmrkTraitsResourceComposableResource (286) */ + /** @name RmrkTraitsResourceComposableResource (288) */ interface RmrkTraitsResourceComposableResource extends Struct { readonly parts: Vec; readonly base: u32; @@ -2574,7 +2598,7 @@ readonly thumb: Option; } - /** @name RmrkTraitsResourceSlotResource (287) */ + /** @name RmrkTraitsResourceSlotResource (289) */ interface RmrkTraitsResourceSlotResource extends Struct { readonly base: u32; readonly src: Option; @@ -2584,7 +2608,7 @@ readonly thumb: Option; } - /** @name PalletRmrkEquipCall (290) */ + /** @name PalletRmrkEquipCall (292) */ interface PalletRmrkEquipCall extends Enum { readonly isCreateBase: boolean; readonly asCreateBase: { @@ -2606,7 +2630,7 @@ readonly type: 'CreateBase' | 'ThemeAdd' | 'Equippable'; } - /** @name RmrkTraitsPartPartType (293) */ + /** @name RmrkTraitsPartPartType (295) */ interface RmrkTraitsPartPartType extends Enum { readonly isFixedPart: boolean; readonly asFixedPart: RmrkTraitsPartFixedPart; @@ -2615,14 +2639,14 @@ readonly type: 'FixedPart' | 'SlotPart'; } - /** @name RmrkTraitsPartFixedPart (295) */ + /** @name RmrkTraitsPartFixedPart (297) */ interface RmrkTraitsPartFixedPart extends Struct { readonly id: u32; readonly z: u32; readonly src: Bytes; } - /** @name RmrkTraitsPartSlotPart (296) */ + /** @name RmrkTraitsPartSlotPart (298) */ interface RmrkTraitsPartSlotPart extends Struct { readonly id: u32; readonly equippable: RmrkTraitsPartEquippableList; @@ -2630,7 +2654,7 @@ readonly z: u32; } - /** @name RmrkTraitsPartEquippableList (297) */ + /** @name RmrkTraitsPartEquippableList (299) */ interface RmrkTraitsPartEquippableList extends Enum { readonly isAll: boolean; readonly isEmpty: boolean; @@ -2639,20 +2663,54 @@ readonly type: 'All' | 'Empty' | 'Custom'; } - /** @name RmrkTraitsTheme (299) */ + /** @name RmrkTraitsTheme (301) */ interface RmrkTraitsTheme extends Struct { readonly name: Bytes; readonly properties: Vec; readonly inherit: bool; } - /** @name RmrkTraitsThemeThemeProperty (301) */ + /** @name RmrkTraitsThemeThemeProperty (303) */ interface RmrkTraitsThemeThemeProperty extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name PalletEvmCall (303) */ + /** @name PalletAppPromotionCall (305) */ + interface PalletAppPromotionCall extends Enum { + readonly isSetAdminAddress: boolean; + readonly asSetAdminAddress: { + readonly admin: PalletEvmAccountBasicCrossAccountIdRepr; + } & Struct; + readonly isStake: boolean; + readonly asStake: { + readonly amount: u128; + } & Struct; + readonly isUnstake: boolean; + readonly isSponsorCollection: boolean; + readonly asSponsorCollection: { + readonly collectionId: u32; + } & Struct; + readonly isStopSponsoringCollection: boolean; + readonly asStopSponsoringCollection: { + readonly collectionId: u32; + } & Struct; + readonly isSponsorContract: boolean; + readonly asSponsorContract: { + readonly contractId: H160; + } & Struct; + readonly isStopSponsoringContract: boolean; + readonly asStopSponsoringContract: { + readonly contractId: H160; + } & Struct; + readonly isPayoutStakers: boolean; + readonly asPayoutStakers: { + readonly stakersNumber: Option; + } & Struct; + readonly type: 'SetAdminAddress' | 'Stake' | 'Unstake' | 'SponsorCollection' | 'StopSponsoringCollection' | 'SponsorContract' | 'StopSponsoringContract' | 'PayoutStakers'; + } + + /** @name PalletEvmCall (307) */ interface PalletEvmCall extends Enum { readonly isWithdraw: boolean; readonly asWithdraw: { @@ -2697,7 +2755,7 @@ readonly type: 'Withdraw' | 'Call' | 'Create' | 'Create2'; } - /** @name PalletEthereumCall (307) */ + /** @name PalletEthereumCall (311) */ interface PalletEthereumCall extends Enum { readonly isTransact: boolean; readonly asTransact: { @@ -2706,7 +2764,7 @@ readonly type: 'Transact'; } - /** @name EthereumTransactionTransactionV2 (308) */ + /** @name EthereumTransactionTransactionV2 (312) */ interface EthereumTransactionTransactionV2 extends Enum { readonly isLegacy: boolean; readonly asLegacy: EthereumTransactionLegacyTransaction; @@ -2717,7 +2775,7 @@ readonly type: 'Legacy' | 'Eip2930' | 'Eip1559'; } - /** @name EthereumTransactionLegacyTransaction (309) */ + /** @name EthereumTransactionLegacyTransaction (313) */ interface EthereumTransactionLegacyTransaction extends Struct { readonly nonce: U256; readonly gasPrice: U256; @@ -2728,7 +2786,7 @@ readonly signature: EthereumTransactionTransactionSignature; } - /** @name EthereumTransactionTransactionAction (310) */ + /** @name EthereumTransactionTransactionAction (314) */ interface EthereumTransactionTransactionAction extends Enum { readonly isCall: boolean; readonly asCall: H160; @@ -2736,14 +2794,14 @@ readonly type: 'Call' | 'Create'; } - /** @name EthereumTransactionTransactionSignature (311) */ + /** @name EthereumTransactionTransactionSignature (315) */ interface EthereumTransactionTransactionSignature extends Struct { readonly v: u64; readonly r: H256; readonly s: H256; } - /** @name EthereumTransactionEip2930Transaction (313) */ + /** @name EthereumTransactionEip2930Transaction (317) */ interface EthereumTransactionEip2930Transaction extends Struct { readonly chainId: u64; readonly nonce: U256; @@ -2758,13 +2816,13 @@ readonly s: H256; } - /** @name EthereumTransactionAccessListItem (315) */ + /** @name EthereumTransactionAccessListItem (319) */ interface EthereumTransactionAccessListItem extends Struct { readonly address: H160; readonly storageKeys: Vec; } - /** @name EthereumTransactionEip1559Transaction (316) */ + /** @name EthereumTransactionEip1559Transaction (320) */ interface EthereumTransactionEip1559Transaction extends Struct { readonly chainId: u64; readonly nonce: U256; @@ -2780,7 +2838,7 @@ readonly s: H256; } - /** @name PalletEvmMigrationCall (317) */ + /** @name PalletEvmMigrationCall (321) */ interface PalletEvmMigrationCall extends Enum { readonly isBegin: boolean; readonly asBegin: { @@ -2799,13 +2857,13 @@ readonly type: 'Begin' | 'SetData' | 'Finish'; } - /** @name PalletSudoError (320) */ + /** @name PalletSudoError (324) */ interface PalletSudoError extends Enum { readonly isRequireSudo: boolean; readonly type: 'RequireSudo'; } - /** @name OrmlVestingModuleError (322) */ + /** @name OrmlVestingModuleError (326) */ interface OrmlVestingModuleError extends Enum { readonly isZeroVestingPeriod: boolean; readonly isZeroVestingPeriodCount: boolean; @@ -2816,21 +2874,21 @@ readonly type: 'ZeroVestingPeriod' | 'ZeroVestingPeriodCount' | 'InsufficientBalanceToLock' | 'TooManyVestingSchedules' | 'AmountLow' | 'MaxVestingSchedulesExceeded'; } - /** @name CumulusPalletXcmpQueueInboundChannelDetails (324) */ + /** @name CumulusPalletXcmpQueueInboundChannelDetails (328) */ interface CumulusPalletXcmpQueueInboundChannelDetails extends Struct { readonly sender: u32; readonly state: CumulusPalletXcmpQueueInboundState; readonly messageMetadata: Vec>; } - /** @name CumulusPalletXcmpQueueInboundState (325) */ + /** @name CumulusPalletXcmpQueueInboundState (329) */ interface CumulusPalletXcmpQueueInboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: 'Ok' | 'Suspended'; } - /** @name PolkadotParachainPrimitivesXcmpMessageFormat (328) */ + /** @name PolkadotParachainPrimitivesXcmpMessageFormat (332) */ interface PolkadotParachainPrimitivesXcmpMessageFormat extends Enum { readonly isConcatenatedVersionedXcm: boolean; readonly isConcatenatedEncodedBlob: boolean; @@ -2838,7 +2896,7 @@ readonly type: 'ConcatenatedVersionedXcm' | 'ConcatenatedEncodedBlob' | 'Signals'; } - /** @name CumulusPalletXcmpQueueOutboundChannelDetails (331) */ + /** @name CumulusPalletXcmpQueueOutboundChannelDetails (335) */ interface CumulusPalletXcmpQueueOutboundChannelDetails extends Struct { readonly recipient: u32; readonly state: CumulusPalletXcmpQueueOutboundState; @@ -2847,14 +2905,14 @@ readonly lastIndex: u16; } - /** @name CumulusPalletXcmpQueueOutboundState (332) */ + /** @name CumulusPalletXcmpQueueOutboundState (336) */ interface CumulusPalletXcmpQueueOutboundState extends Enum { readonly isOk: boolean; readonly isSuspended: boolean; readonly type: 'Ok' | 'Suspended'; } - /** @name CumulusPalletXcmpQueueQueueConfigData (334) */ + /** @name CumulusPalletXcmpQueueQueueConfigData (338) */ interface CumulusPalletXcmpQueueQueueConfigData extends Struct { readonly suspendThreshold: u32; readonly dropThreshold: u32; @@ -2864,7 +2922,7 @@ readonly xcmpMaxIndividualWeight: u64; } - /** @name CumulusPalletXcmpQueueError (336) */ + /** @name CumulusPalletXcmpQueueError (340) */ interface CumulusPalletXcmpQueueError extends Enum { readonly isFailedToSend: boolean; readonly isBadXcmOrigin: boolean; @@ -2874,7 +2932,7 @@ readonly type: 'FailedToSend' | 'BadXcmOrigin' | 'BadXcm' | 'BadOverweightIndex' | 'WeightOverLimit'; } - /** @name PalletXcmError (337) */ + /** @name PalletXcmError (341) */ interface PalletXcmError extends Enum { readonly isUnreachable: boolean; readonly isSendFailure: boolean; @@ -2892,29 +2950,29 @@ readonly type: 'Unreachable' | 'SendFailure' | 'Filtered' | 'UnweighableMessage' | 'DestinationNotInvertible' | 'Empty' | 'CannotReanchor' | 'TooManyAssets' | 'InvalidOrigin' | 'BadVersion' | 'BadLocation' | 'NoSubscription' | 'AlreadySubscribed'; } - /** @name CumulusPalletXcmError (338) */ + /** @name CumulusPalletXcmError (342) */ type CumulusPalletXcmError = Null; - /** @name CumulusPalletDmpQueueConfigData (339) */ + /** @name CumulusPalletDmpQueueConfigData (343) */ interface CumulusPalletDmpQueueConfigData extends Struct { readonly maxIndividual: u64; } - /** @name CumulusPalletDmpQueuePageIndexData (340) */ + /** @name CumulusPalletDmpQueuePageIndexData (344) */ interface CumulusPalletDmpQueuePageIndexData extends Struct { readonly beginUsed: u32; readonly endUsed: u32; readonly overweightCount: u64; } - /** @name CumulusPalletDmpQueueError (343) */ + /** @name CumulusPalletDmpQueueError (347) */ interface CumulusPalletDmpQueueError extends Enum { readonly isUnknown: boolean; readonly isOverLimit: boolean; readonly type: 'Unknown' | 'OverLimit'; } - /** @name PalletUniqueError (347) */ + /** @name PalletUniqueError (351) */ interface PalletUniqueError extends Enum { readonly isCollectionDecimalPointLimitExceeded: boolean; readonly isConfirmUnsetSponsorFail: boolean; @@ -2923,7 +2981,7 @@ readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument' | 'RepartitionCalledOnNonRefungibleCollection'; } - /** @name PalletUniqueSchedulerScheduledV3 (350) */ + /** @name PalletUniqueSchedulerScheduledV3 (354) */ interface PalletUniqueSchedulerScheduledV3 extends Struct { readonly maybeId: Option; readonly priority: u8; @@ -2932,7 +2990,7 @@ readonly origin: OpalRuntimeOriginCaller; } - /** @name OpalRuntimeOriginCaller (351) */ + /** @name OpalRuntimeOriginCaller (355) */ interface OpalRuntimeOriginCaller extends Enum { readonly isSystem: boolean; readonly asSystem: FrameSupportDispatchRawOrigin; @@ -2946,7 +3004,7 @@ readonly type: 'System' | 'Void' | 'PolkadotXcm' | 'CumulusXcm' | 'Ethereum'; } - /** @name FrameSupportDispatchRawOrigin (352) */ + /** @name FrameSupportDispatchRawOrigin (356) */ interface FrameSupportDispatchRawOrigin extends Enum { readonly isRoot: boolean; readonly isSigned: boolean; @@ -2955,7 +3013,7 @@ readonly type: 'Root' | 'Signed' | 'None'; } - /** @name PalletXcmOrigin (353) */ + /** @name PalletXcmOrigin (357) */ interface PalletXcmOrigin extends Enum { readonly isXcm: boolean; readonly asXcm: XcmV1MultiLocation; @@ -2964,7 +3022,7 @@ readonly type: 'Xcm' | 'Response'; } - /** @name CumulusPalletXcmOrigin (354) */ + /** @name CumulusPalletXcmOrigin (358) */ interface CumulusPalletXcmOrigin extends Enum { readonly isRelay: boolean; readonly isSiblingParachain: boolean; @@ -2972,17 +3030,17 @@ readonly type: 'Relay' | 'SiblingParachain'; } - /** @name PalletEthereumRawOrigin (355) */ + /** @name PalletEthereumRawOrigin (359) */ interface PalletEthereumRawOrigin extends Enum { readonly isEthereumTransaction: boolean; readonly asEthereumTransaction: H160; readonly type: 'EthereumTransaction'; } - /** @name SpCoreVoid (356) */ + /** @name SpCoreVoid (360) */ type SpCoreVoid = Null; - /** @name PalletUniqueSchedulerError (357) */ + /** @name PalletUniqueSchedulerError (361) */ interface PalletUniqueSchedulerError extends Enum { readonly isFailedToSchedule: boolean; readonly isNotFound: boolean; @@ -2991,21 +3049,21 @@ readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange'; } - /** @name UpDataStructsCollection (358) */ + /** @name UpDataStructsCollection (362) */ interface UpDataStructsCollection extends Struct { readonly owner: AccountId32; readonly mode: UpDataStructsCollectionMode; readonly name: Vec; readonly description: Vec; readonly tokenPrefix: Bytes; - readonly sponsorship: UpDataStructsSponsorshipState; + readonly sponsorship: UpDataStructsSponsorshipStateAccountId32; readonly limits: UpDataStructsCollectionLimits; readonly permissions: UpDataStructsCollectionPermissions; readonly externalCollection: bool; } - /** @name UpDataStructsSponsorshipState (359) */ - interface UpDataStructsSponsorshipState extends Enum { + /** @name UpDataStructsSponsorshipStateAccountId32 (363) */ + interface UpDataStructsSponsorshipStateAccountId32 extends Enum { readonly isDisabled: boolean; readonly isUnconfirmed: boolean; readonly asUnconfirmed: AccountId32; @@ -3014,50 +3072,50 @@ readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; } - /** @name UpDataStructsProperties (360) */ + /** @name UpDataStructsProperties (364) */ interface UpDataStructsProperties extends Struct { readonly map: UpDataStructsPropertiesMapBoundedVec; readonly consumedSpace: u32; readonly spaceLimit: u32; } - /** @name UpDataStructsPropertiesMapBoundedVec (361) */ + /** @name UpDataStructsPropertiesMapBoundedVec (365) */ interface UpDataStructsPropertiesMapBoundedVec extends BTreeMap {} - /** @name UpDataStructsPropertiesMapPropertyPermission (366) */ + /** @name UpDataStructsPropertiesMapPropertyPermission (370) */ interface UpDataStructsPropertiesMapPropertyPermission extends BTreeMap {} - /** @name UpDataStructsCollectionStats (373) */ + /** @name UpDataStructsCollectionStats (377) */ interface UpDataStructsCollectionStats extends Struct { readonly created: u32; readonly destroyed: u32; readonly alive: u32; } - /** @name UpDataStructsTokenChild (374) */ + /** @name UpDataStructsTokenChild (378) */ interface UpDataStructsTokenChild extends Struct { readonly token: u32; readonly collection: u32; } - /** @name PhantomTypeUpDataStructs (375) */ + /** @name PhantomTypeUpDataStructs (379) */ interface PhantomTypeUpDataStructs extends Vec> {} - /** @name UpDataStructsTokenData (377) */ + /** @name UpDataStructsTokenData (381) */ interface UpDataStructsTokenData extends Struct { readonly properties: Vec; readonly owner: Option; readonly pieces: u128; } - /** @name UpDataStructsRpcCollection (379) */ + /** @name UpDataStructsRpcCollection (383) */ interface UpDataStructsRpcCollection extends Struct { readonly owner: AccountId32; readonly mode: UpDataStructsCollectionMode; readonly name: Vec; readonly description: Vec; readonly tokenPrefix: Bytes; - readonly sponsorship: UpDataStructsSponsorshipState; + readonly sponsorship: UpDataStructsSponsorshipStateAccountId32; readonly limits: UpDataStructsCollectionLimits; readonly permissions: UpDataStructsCollectionPermissions; readonly tokenPropertyPermissions: Vec; @@ -3065,7 +3123,7 @@ readonly readOnly: bool; } - /** @name RmrkTraitsCollectionCollectionInfo (380) */ + /** @name RmrkTraitsCollectionCollectionInfo (384) */ interface RmrkTraitsCollectionCollectionInfo extends Struct { readonly issuer: AccountId32; readonly metadata: Bytes; @@ -3074,7 +3132,7 @@ readonly nftsCount: u32; } - /** @name RmrkTraitsNftNftInfo (381) */ + /** @name RmrkTraitsNftNftInfo (385) */ interface RmrkTraitsNftNftInfo extends Struct { readonly owner: RmrkTraitsNftAccountIdOrCollectionNftTuple; readonly royalty: Option; @@ -3083,13 +3141,13 @@ readonly pending: bool; } - /** @name RmrkTraitsNftRoyaltyInfo (383) */ + /** @name RmrkTraitsNftRoyaltyInfo (387) */ interface RmrkTraitsNftRoyaltyInfo extends Struct { readonly recipient: AccountId32; readonly amount: Permill; } - /** @name RmrkTraitsResourceResourceInfo (384) */ + /** @name RmrkTraitsResourceResourceInfo (388) */ interface RmrkTraitsResourceResourceInfo extends Struct { readonly id: u32; readonly resource: RmrkTraitsResourceResourceTypes; @@ -3097,26 +3155,26 @@ readonly pendingRemoval: bool; } - /** @name RmrkTraitsPropertyPropertyInfo (385) */ + /** @name RmrkTraitsPropertyPropertyInfo (389) */ interface RmrkTraitsPropertyPropertyInfo extends Struct { readonly key: Bytes; readonly value: Bytes; } - /** @name RmrkTraitsBaseBaseInfo (386) */ + /** @name RmrkTraitsBaseBaseInfo (390) */ interface RmrkTraitsBaseBaseInfo extends Struct { readonly issuer: AccountId32; readonly baseType: Bytes; readonly symbol: Bytes; } - /** @name RmrkTraitsNftNftChild (387) */ + /** @name RmrkTraitsNftNftChild (391) */ interface RmrkTraitsNftNftChild extends Struct { readonly collectionId: u32; readonly nftId: u32; } - /** @name PalletCommonError (389) */ + /** @name PalletCommonError (393) */ interface PalletCommonError extends Enum { readonly isCollectionNotFound: boolean; readonly isMustBeTokenOwner: boolean; @@ -3155,7 +3213,7 @@ readonly type: 'CollectionNotFound' | 'MustBeTokenOwner' | 'NoPermission' | 'CantDestroyNotEmptyCollection' | 'PublicMintingNotAllowed' | 'AddressNotInAllowlist' | 'CollectionNameLimitExceeded' | 'CollectionDescriptionLimitExceeded' | 'CollectionTokenPrefixLimitExceeded' | 'TotalCollectionsLimitExceeded' | 'CollectionAdminCountExceeded' | 'CollectionLimitBoundsExceeded' | 'OwnerPermissionsCantBeReverted' | 'TransferNotAllowed' | 'AccountTokenLimitExceeded' | 'CollectionTokenLimitExceeded' | 'MetadataFlagFrozen' | 'TokenNotFound' | 'TokenValueTooLow' | 'ApprovedValueTooLow' | 'CantApproveMoreThanOwned' | 'AddressIsZero' | 'UnsupportedOperation' | 'NotSufficientFounds' | 'UserIsNotAllowedToNest' | 'SourceCollectionIsNotAllowedToNest' | 'CollectionFieldSizeExceeded' | 'NoSpaceForProperty' | 'PropertyLimitReached' | 'PropertyKeyIsTooLong' | 'InvalidCharacterInPropertyKey' | 'EmptyPropertyKey' | 'CollectionIsExternal' | 'CollectionIsInternal'; } - /** @name PalletFungibleError (391) */ + /** @name PalletFungibleError (395) */ interface PalletFungibleError extends Enum { readonly isNotFungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isFungibleItemsHaveNoId: boolean; @@ -3165,12 +3223,12 @@ readonly type: 'NotFungibleDataUsedToMintFungibleCollectionToken' | 'FungibleItemsHaveNoId' | 'FungibleItemsDontHaveData' | 'FungibleDisallowsNesting' | 'SettingPropertiesNotAllowed'; } - /** @name PalletRefungibleItemData (392) */ + /** @name PalletRefungibleItemData (396) */ interface PalletRefungibleItemData extends Struct { readonly constData: Bytes; } - /** @name PalletRefungibleError (397) */ + /** @name PalletRefungibleError (401) */ interface PalletRefungibleError extends Enum { readonly isNotRefungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isWrongRefungiblePieces: boolean; @@ -3180,20 +3238,19 @@ readonly type: 'NotRefungibleDataUsedToMintFungibleCollectionToken' | 'WrongRefungiblePieces' | 'RepartitionWhileNotOwningAllPieces' | 'RefungibleDisallowsNesting' | 'SettingPropertiesNotAllowed'; } - /** @name PalletNonfungibleItemData (398) */ + /** @name PalletNonfungibleItemData (402) */ interface PalletNonfungibleItemData extends Struct { readonly owner: PalletEvmAccountBasicCrossAccountIdRepr; } - /** @name UpDataStructsPropertyScope (400) */ + /** @name UpDataStructsPropertyScope (404) */ interface UpDataStructsPropertyScope extends Enum { readonly isNone: boolean; readonly isRmrk: boolean; - readonly isEth: boolean; - readonly type: 'None' | 'Rmrk' | 'Eth'; + readonly type: 'None' | 'Rmrk'; } - /** @name PalletNonfungibleError (402) */ + /** @name PalletNonfungibleError (406) */ interface PalletNonfungibleError extends Enum { readonly isNotNonfungibleDataUsedToMintFungibleCollectionToken: boolean; readonly isNonfungibleItemsHaveNoAmount: boolean; @@ -3201,7 +3258,7 @@ readonly type: 'NotNonfungibleDataUsedToMintFungibleCollectionToken' | 'NonfungibleItemsHaveNoAmount' | 'CantBurnNftWithChildren'; } - /** @name PalletStructureError (403) */ + /** @name PalletStructureError (407) */ interface PalletStructureError extends Enum { readonly isOuroborosDetected: boolean; readonly isDepthLimit: boolean; @@ -3210,7 +3267,7 @@ readonly type: 'OuroborosDetected' | 'DepthLimit' | 'BreadthLimit' | 'TokenNotFound'; } - /** @name PalletRmrkCoreError (404) */ + /** @name PalletRmrkCoreError (408) */ interface PalletRmrkCoreError extends Enum { readonly isCorruptedCollectionType: boolean; readonly isRmrkPropertyKeyIsTooLong: boolean; @@ -3234,7 +3291,7 @@ readonly type: 'CorruptedCollectionType' | 'RmrkPropertyKeyIsTooLong' | 'RmrkPropertyValueIsTooLong' | 'RmrkPropertyIsNotFound' | 'UnableToDecodeRmrkData' | 'CollectionNotEmpty' | 'NoAvailableCollectionId' | 'NoAvailableNftId' | 'CollectionUnknown' | 'NoPermission' | 'NonTransferable' | 'CollectionFullOrLocked' | 'ResourceDoesntExist' | 'CannotSendToDescendentOrSelf' | 'CannotAcceptNonOwnedNft' | 'CannotRejectNonOwnedNft' | 'CannotRejectNonPendingNft' | 'ResourceNotPending' | 'NoAvailableResourceId'; } - /** @name PalletRmrkEquipError (406) */ + /** @name PalletRmrkEquipError (410) */ interface PalletRmrkEquipError extends Enum { readonly isPermissionError: boolean; readonly isNoAvailableBaseId: boolean; @@ -3246,7 +3303,18 @@ readonly type: 'PermissionError' | 'NoAvailableBaseId' | 'NoAvailablePartId' | 'BaseDoesntExist' | 'NeedsDefaultThemeFirst' | 'PartDoesntExist' | 'NoEquippableOnFixedPart'; } - /** @name PalletEvmError (409) */ + /** @name PalletAppPromotionError (416) */ + interface PalletAppPromotionError extends Enum { + readonly isAdminNotSet: boolean; + readonly isNoPermission: boolean; + readonly isNotSufficientFunds: boolean; + readonly isPendingForBlockOverflow: boolean; + readonly isSponsorNotSet: boolean; + readonly isIncorrectLockedBalanceOperation: boolean; + readonly type: 'AdminNotSet' | 'NoPermission' | 'NotSufficientFunds' | 'PendingForBlockOverflow' | 'SponsorNotSet' | 'IncorrectLockedBalanceOperation'; + } + + /** @name PalletEvmError (419) */ interface PalletEvmError extends Enum { readonly isBalanceLow: boolean; readonly isFeeOverflow: boolean; @@ -3257,7 +3325,7 @@ readonly type: 'BalanceLow' | 'FeeOverflow' | 'PaymentOverflow' | 'WithdrawFailed' | 'GasPriceTooLow' | 'InvalidNonce'; } - /** @name FpRpcTransactionStatus (412) */ + /** @name FpRpcTransactionStatus (422) */ interface FpRpcTransactionStatus extends Struct { readonly transactionHash: H256; readonly transactionIndex: u32; @@ -3268,10 +3336,10 @@ readonly logsBloom: EthbloomBloom; } - /** @name EthbloomBloom (414) */ + /** @name EthbloomBloom (424) */ interface EthbloomBloom extends U8aFixed {} - /** @name EthereumReceiptReceiptV3 (416) */ + /** @name EthereumReceiptReceiptV3 (426) */ interface EthereumReceiptReceiptV3 extends Enum { readonly isLegacy: boolean; readonly asLegacy: EthereumReceiptEip658ReceiptData; @@ -3282,7 +3350,7 @@ readonly type: 'Legacy' | 'Eip2930' | 'Eip1559'; } - /** @name EthereumReceiptEip658ReceiptData (417) */ + /** @name EthereumReceiptEip658ReceiptData (427) */ interface EthereumReceiptEip658ReceiptData extends Struct { readonly statusCode: u8; readonly usedGas: U256; @@ -3290,14 +3358,14 @@ readonly logs: Vec; } - /** @name EthereumBlock (418) */ + /** @name EthereumBlock (428) */ interface EthereumBlock extends Struct { readonly header: EthereumHeader; readonly transactions: Vec; readonly ommers: Vec; } - /** @name EthereumHeader (419) */ + /** @name EthereumHeader (429) */ interface EthereumHeader extends Struct { readonly parentHash: H256; readonly ommersHash: H256; @@ -3316,24 +3384,34 @@ readonly nonce: EthereumTypesHashH64; } - /** @name EthereumTypesHashH64 (420) */ + /** @name EthereumTypesHashH64 (430) */ interface EthereumTypesHashH64 extends U8aFixed {} - /** @name PalletEthereumError (425) */ + /** @name PalletEthereumError (435) */ interface PalletEthereumError extends Enum { readonly isInvalidSignature: boolean; readonly isPreLogExists: boolean; readonly type: 'InvalidSignature' | 'PreLogExists'; } - /** @name PalletEvmCoderSubstrateError (426) */ + /** @name PalletEvmCoderSubstrateError (436) */ interface PalletEvmCoderSubstrateError extends Enum { readonly isOutOfGas: boolean; readonly isOutOfFund: boolean; readonly type: 'OutOfGas' | 'OutOfFund'; } - /** @name PalletEvmContractHelpersSponsoringModeT (427) */ + /** @name UpDataStructsSponsorshipStateBasicCrossAccountIdRepr (437) */ + interface UpDataStructsSponsorshipStateBasicCrossAccountIdRepr extends Enum { + readonly isDisabled: boolean; + readonly isUnconfirmed: boolean; + readonly asUnconfirmed: PalletEvmAccountBasicCrossAccountIdRepr; + readonly isConfirmed: boolean; + readonly asConfirmed: PalletEvmAccountBasicCrossAccountIdRepr; + readonly type: 'Disabled' | 'Unconfirmed' | 'Confirmed'; + } + + /** @name PalletEvmContractHelpersSponsoringModeT (438) */ interface PalletEvmContractHelpersSponsoringModeT extends Enum { readonly isDisabled: boolean; readonly isAllowlisted: boolean; @@ -3341,20 +3419,21 @@ readonly type: 'Disabled' | 'Allowlisted' | 'Generous'; } - /** @name PalletEvmContractHelpersError (429) */ + /** @name PalletEvmContractHelpersError (440) */ interface PalletEvmContractHelpersError extends Enum { readonly isNoPermission: boolean; - readonly type: 'NoPermission'; + readonly isNoPendingSponsor: boolean; + readonly type: 'NoPermission' | 'NoPendingSponsor'; } - /** @name PalletEvmMigrationError (430) */ + /** @name PalletEvmMigrationError (441) */ interface PalletEvmMigrationError extends Enum { readonly isAccountNotEmpty: boolean; readonly isAccountIsNotMigrating: boolean; readonly type: 'AccountNotEmpty' | 'AccountIsNotMigrating'; } - /** @name SpRuntimeMultiSignature (432) */ + /** @name SpRuntimeMultiSignature (443) */ interface SpRuntimeMultiSignature extends Enum { readonly isEd25519: boolean; readonly asEd25519: SpCoreEd25519Signature; @@ -3365,34 +3444,34 @@ readonly type: 'Ed25519' | 'Sr25519' | 'Ecdsa'; } - /** @name SpCoreEd25519Signature (433) */ + /** @name SpCoreEd25519Signature (444) */ interface SpCoreEd25519Signature extends U8aFixed {} - /** @name SpCoreSr25519Signature (435) */ + /** @name SpCoreSr25519Signature (446) */ interface SpCoreSr25519Signature extends U8aFixed {} - /** @name SpCoreEcdsaSignature (436) */ + /** @name SpCoreEcdsaSignature (447) */ interface SpCoreEcdsaSignature extends U8aFixed {} - /** @name FrameSystemExtensionsCheckSpecVersion (439) */ + /** @name FrameSystemExtensionsCheckSpecVersion (450) */ type FrameSystemExtensionsCheckSpecVersion = Null; - /** @name FrameSystemExtensionsCheckGenesis (440) */ + /** @name FrameSystemExtensionsCheckGenesis (451) */ type FrameSystemExtensionsCheckGenesis = Null; - /** @name FrameSystemExtensionsCheckNonce (443) */ + /** @name FrameSystemExtensionsCheckNonce (454) */ interface FrameSystemExtensionsCheckNonce extends Compact {} - /** @name FrameSystemExtensionsCheckWeight (444) */ + /** @name FrameSystemExtensionsCheckWeight (455) */ type FrameSystemExtensionsCheckWeight = Null; - /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (445) */ + /** @name PalletTemplateTransactionPaymentChargeTransactionPayment (456) */ interface PalletTemplateTransactionPaymentChargeTransactionPayment extends Compact {} - /** @name OpalRuntimeRuntime (446) */ + /** @name OpalRuntimeRuntime (457) */ type OpalRuntimeRuntime = Null; - /** @name PalletEthereumFakeTransactionFinalizer (447) */ + /** @name PalletEthereumFakeTransactionFinalizer (458) */ type PalletEthereumFakeTransactionFinalizer = Null; } // declare module --- a/tests/src/interfaces/types.ts +++ b/tests/src/interfaces/types.ts @@ -2,5 +2,6 @@ /* eslint-disable */ export * from './unique/types'; +export * from './appPromotion/types'; export * from './rmrk/types'; export * from './default/types'; --- a/tests/src/pallet-presence.test.ts +++ b/tests/src/pallet-presence.test.ts @@ -68,9 +68,10 @@ const refungible = 'refungible'; const scheduler = 'scheduler'; const rmrkPallets = ['rmrkcore', 'rmrkequip']; + const appPromotion = 'apppromotion'; if (chain.eq('OPAL by UNIQUE')) { - requiredPallets.push(refungible, scheduler, ...rmrkPallets); + requiredPallets.push(refungible, scheduler, appPromotion, ...rmrkPallets); } else if (chain.eq('QUARTZ by UNIQUE')) { // Insert Quartz additional pallets here } else if (chain.eq('UNIQUE')) { --- a/tests/src/refungible.test.ts +++ b/tests/src/refungible.test.ts @@ -245,8 +245,8 @@ section: 'common', index: '0x4202', data: [ - collection.collectionId.toString(), - token.tokenId.toString(), + helper.api!.createType('u32', collection.collectionId).toHuman(), + helper.api!.createType('u32', token.tokenId).toHuman(), {Substrate: alice.address}, '100', ], @@ -265,8 +265,8 @@ section: 'common', index: '0x4203', data: [ - collection.collectionId.toString(), - token.tokenId.toString(), + helper.api!.createType('u32', collection.collectionId).toHuman(), + helper.api!.createType('u32', token.tokenId).toHuman(), {Substrate: alice.address}, '50', ], --- a/tests/src/removeCollectionAdmin.test.ts +++ b/tests/src/removeCollectionAdmin.test.ts @@ -27,6 +27,7 @@ const alice = privateKey('//Alice'); const bob = privateKey('//Bob'); const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const collectionInfo = await collection.getData(); expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address); // first - add collection admin Bob --- a/tests/src/substrate/substrate-api.ts +++ b/tests/src/substrate/substrate-api.ts @@ -44,6 +44,7 @@ }, rpc: { unique: defs.unique.rpc, + appPromotion: defs.appPromotion.rpc, rmrk: defs.rmrk.rpc, eth: { feeHistory: { --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -17,10 +17,11 @@ import '../interfaces/augment-api-rpc'; import '../interfaces/augment-api-query'; import {ApiPromise} from '@polkadot/api'; -import type {AccountId, EventRecord, Event} from '@polkadot/types/interfaces'; +import type {AccountId, EventRecord, Event, BlockNumber} from '@polkadot/types/interfaces'; import type {GenericEventData} from '@polkadot/types'; import {AnyTuple, IEvent, IKeyringPair} from '@polkadot/types/types'; import {evmToAddress} from '@polkadot/util-crypto'; +import {AnyNumber} from '@polkadot/types-codec/types'; import BN from 'bn.js'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; @@ -48,6 +49,7 @@ Fungible = 'fungible', NFT = 'nonfungible', Scheduler = 'scheduler', + AppPromotion = 'apppromotion', } export async function isUnique(): Promise { @@ -1779,3 +1781,23 @@ itApi.only = (name: string, cb: (apis: { api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any) => itApi(name, cb, {only: true}); itApi.skip = (name: string, cb: (apis: { api: ApiPromise, privateKeyWrapper: (account: string) => IKeyringPair }) => any) => itApi(name, cb, {skip: true}); + + +export async function expectSubstrateEventsAtBlock(api: ApiPromise, blockNumber: AnyNumber | BlockNumber, section: string, methods: string[], dryRun = false) { + const blockHash = await api.rpc.chain.getBlockHash(blockNumber); + const subEvents = (await api.query.system.events.at(blockHash)) + .filter(x => x.event.section === section) + .map((x) => x.toHuman()); + const events = methods.map((m) => { + return { + event: { + method: m, + section, + }, + }; + }); + if (!dryRun) { + expect(subEvents).to.be.like(events); + } + return subEvents; +} \ No newline at end of file --- a/tests/src/util/playgrounds/types.ts +++ b/tests/src/util/playgrounds/types.ts @@ -101,6 +101,23 @@ tokenId: number; } +export interface IBlock { + extrinsics: IExtrinsic[] + header: { + parentHash: string, + number: number, + }; +} + +export interface IExtrinsic { + isSigned: boolean, + method: { + method: string, + section: string, + args: any[] + } +} + export interface ICollectionCreationOptions { name?: string | number[]; description?: string | number[]; @@ -123,8 +140,15 @@ tokenSymbol: string[] } +export interface ISubstrateBalance { + free: bigint, + reserved: bigint, + miscFrozen: bigint, + feeFrozen: bigint +} + export type TSubstrateAccount = string; export type TEthereumAccount = string; export type TApiAllowedListeners = 'connected' | 'disconnected' | 'error' | 'ready' | 'decorated'; export type TUniqueNetworks = 'opal' | 'quartz' | 'unique'; -export type TSigner = IKeyringPair; // | 'string' \ No newline at end of file +export type TSigner = IKeyringPair; // | 'string' --- a/tests/src/util/playgrounds/unique.dev.ts +++ b/tests/src/util/playgrounds/unique.dev.ts @@ -17,7 +17,6 @@ }; } - export class SilentConsole { // TODO: Remove, this is temporary: Filter unneeded API output // (Jaco promised it will be removed in the next version) @@ -36,7 +35,7 @@ for (const arg of args) { if (typeof arg !== 'string') continue; - if (arg.includes('1000:: Normal connection closure') || arg.includes('Not decorating unknown runtime apis: UniqueApi/2, RmrkApi/1') || arg.includes('RPC methods not decorated:') || arg === 'Normal connection closure') + if (arg.includes('1000:: Normal connection closure') || arg.includes('Not decorating unknown runtime apis:') || arg.includes('RPC methods not decorated:') || arg === 'Normal connection closure') return; } printer(...args); @@ -60,10 +59,12 @@ * Arrange methods for tests */ arrange: ArrangeGroup; + wait: WaitGroup; constructor(logger: { log: (msg: any, level: any) => void, level: any }) { super(logger); this.arrange = new ArrangeGroup(this); + this.wait = new WaitGroup(this); } async connect(wsEndpoint: string, _listeners?: any): Promise { @@ -82,6 +83,7 @@ }, rpc: { unique: defs.unique.rpc, + appPromotion: defs.appPromotion.rpc, rmrk: defs.rmrk.rpc, eth: { feeHistory: { @@ -152,7 +154,7 @@ for (let index = 0; index < 5; index++) { accountsCreated = await checkBalances(); if(accountsCreated) break; - await this.waitNewBlocks(1); + } if (!accountsCreated) throw Error('Accounts generation failed'); @@ -160,13 +162,86 @@ return accounts; }; - + + // TODO combine this method and createAccounts into one + createCrowd = async (accountsToCreate: number, withBalance: bigint, donor: IKeyringPair): Promise => { + const createAsManyAsCan = async () => { + let transactions: any = []; + const accounts: IKeyringPair[] = []; + let nonce = await this.helper.chain.getNonce(donor.address); + const tokenNominal = this.helper.balance.getOneTokenNominal(); + for (let i = 0; i < accountsToCreate; i++) { + if (i === 500) { // if there are too many accounts to create + await Promise.allSettled(transactions); // wait while first 500 (should be 100 for devnode) tx will be settled + transactions = []; // + nonce = await this.helper.chain.getNonce(donor.address); // update nonce + } + const recepient = this.helper.util.fromSeed(mnemonicGenerate()); + accounts.push(recepient); + if (withBalance !== 0n) { + const tx = this.helper.constructApiCall('api.tx.balances.transfer', [{Id: recepient.address}, withBalance * tokenNominal]); + transactions.push(this.helper.signTransaction(donor, tx, 'account generation', {nonce})); + nonce++; + } + } + + const fullfilledAccounts = []; + await Promise.allSettled(transactions); + for (const account of accounts) { + const accountBalance = await this.helper.balance.getSubstrate(account.address); + if (accountBalance === withBalance * tokenNominal) { + fullfilledAccounts.push(account); + } + } + return fullfilledAccounts; + }; + + + const crowd: IKeyringPair[] = []; + // do up to 5 retries + for (let index = 0; index < 5 && accountsToCreate !== 0; index++) { + const asManyAsCan = await createAsManyAsCan(); + crowd.push(...asManyAsCan); + accountsToCreate -= asManyAsCan.length; + } + + if (accountsToCreate !== 0) throw Error(`Crowd generation failed: ${accountsToCreate} accounts left`); + + return crowd; + }; + + isDevNode = async () => { + const block1 = await this.helper.api?.rpc.chain.getBlock(await this.helper.api?.rpc.chain.getBlockHash(1)); + const block2 = await this.helper.api?.rpc.chain.getBlock(await this.helper.api?.rpc.chain.getBlockHash(2)); + const findCreationDate = async (block: any) => { + const humanBlock = block.toHuman(); + let date; + humanBlock.block.extrinsics.forEach((ext: any) => { + if(ext.method.section === 'timestamp') { + date = Number(ext.method.args.now.replaceAll(',', '')); + } + }); + return date; + }; + const block1date = await findCreationDate(block1); + const block2date = await findCreationDate(block2); + if(block2date! - block1date! < 9000) return true; + }; +} + +class WaitGroup { + helper: UniqueHelper; + + constructor(helper: UniqueHelper) { + this.helper = helper; + } + /** * Wait for specified bnumber of blocks * @param blocksCount number of blocks to wait * @returns */ - async waitNewBlocks(blocksCount = 1): Promise { + async newBlocks(blocksCount = 1): Promise { // eslint-disable-next-line no-async-promise-executor const promise = new Promise(async (resolve) => { const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(() => { @@ -180,4 +255,27 @@ }); return promise; } -} \ No newline at end of file + + async forParachainBlockNumber(blockNumber: bigint) { + return new Promise(async (resolve) => { + const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(async (data: any) => { + if (data.number.toNumber() >= blockNumber) { + unsubscribe(); + resolve(); + } + }); + }); + } + + async forRelayBlockNumber(blockNumber: bigint) { + return new Promise(async (resolve) => { + const unsubscribe = await this.helper.api!.query.parachainSystem.validationData(async (data: any) => { + if (data.value.relayParentNumber.toNumber() >= blockNumber) { + // @ts-ignore + unsubscribe(); + resolve(); + } + }); + }); + } +} --- a/tests/src/util/playgrounds/unique.ts +++ b/tests/src/util/playgrounds/unique.ts @@ -9,7 +9,7 @@ import {ApiInterfaceEvents} from '@polkadot/api/types'; import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto'; import {IKeyringPair} from '@polkadot/types/types'; -import {IApiListeners, IChainEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types'; +import {IApiListeners, IBlock, IChainEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types'; export const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => { const address = {} as ICrossAccountId; @@ -1858,6 +1858,13 @@ return blockHash; } + // TODO add docs + async getBlock(blockHashOrNumber: string | number): Promise { + const blockHash = typeof blockHashOrNumber === 'string' ? blockHashOrNumber : await this.getBlockHashByNumber(blockHashOrNumber); + if (!blockHash) return null; + return (await this.helper.callRpc('api.rpc.chain.getBlock', [blockHash])).toHuman().block; + } + /** * Get account nonce * @param address substrate address @@ -1892,6 +1899,16 @@ } /** + * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved + * @param address substrate address + * @returns + */ + async getSubstrateFull(address: TSubstrateAccount): Promise { + const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data; + return {free: accountInfo.free.toBigInt(), miscFrozen: accountInfo.miscFrozen.toBigInt(), feeFrozen: accountInfo.feeFrozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()}; + } + + /** * Get ethereum address balance * @param address ethereum address * @example getEthereum("0x9F0583DbB855d...") @@ -1977,7 +1994,59 @@ } } +class StakingGroup extends HelperGroup { + /** + * Stake tokens for App Promotion + * @param signer keyring of signer + * @param amountToStake amount of tokens to stake + * @param label extra label for log + * @returns + */ + async stake(signer: TSigner, amountToStake: bigint, label?: string): Promise { + if(typeof label === 'undefined') label = `${signer.address} amount: ${amountToStake}`; + const stakeResult = await this.helper.executeExtrinsic( + signer, 'api.tx.appPromotion.stake', + [amountToStake], true, + ); + // TODO extract info from stakeResult + return true; + } + /** + * Unstake tokens for App Promotion + * @param signer keyring of signer + * @param amountToUnstake amount of tokens to unstake + * @param label extra label for log + * @returns block number where balances will be unlocked + */ + async unstake(signer: TSigner, label?: string): Promise { + if(typeof label === 'undefined') label = `${signer.address}`; + const unstakeResult = await this.helper.executeExtrinsic( + signer, 'api.tx.appPromotion.unstake', + [], true, + ); + // TODO extract block number fron events + return 1; + } + + async getTotalStaked(address?: ICrossAccountId): Promise { + if (address) return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked', [address])).toBigInt(); + return (await this.helper.callRpc('api.rpc.appPromotion.totalStaked')).toBigInt(); + } + + async getTotalStakedPerBlock(address: ICrossAccountId): Promise { + return (await this.helper.callRpc('api.rpc.appPromotion.totalStakedPerBlock', [address])).map(([block, amount]: any[]) => [block.toBigInt(), amount.toBigInt()]); + } + + async getPendingUnstake(address: ICrossAccountId): Promise { + return (await this.helper.callRpc('api.rpc.appPromotion.pendingUnstake', [address])).toBigInt(); + } + + async getPendingUnstakePerBlock(address: ICrossAccountId): Promise { + return (await this.helper.callRpc('api.rpc.appPromotion.pendingUnstakePerBlock', [address])).map(([block, amount]: any[]) => [block.toBigInt(), amount.toBigInt()]); + } +} + export class UniqueHelper extends ChainHelperBase { chain: ChainGroup; balance: BalanceGroup; @@ -1986,6 +2055,7 @@ nft: NFTGroup; rft: RFTGroup; ft: FTGroup; + staking: StakingGroup; constructor(logger?: ILogger) { super(logger); @@ -1996,6 +2066,7 @@ this.nft = new NFTGroup(this); this.rft = new RFTGroup(this); this.ft = new FTGroup(this); + this.staking = new StakingGroup(this); } } @@ -2413,4 +2484,4 @@ async burn(signer: TSigner, amount=1n) { return await this.collection.burnToken(signer, this.tokenId, amount); } -} \ No newline at end of file +}