git.delta.rocks / unique-network / refs/commits / 282c701e6ebe

difftreelog

Merge pull request #462 from UniqueNetwork/fix/pallets_disabled

Yaroslav Bolyukin2022-08-11parents: #54cf093 #fcb85ee.patch.diff
in: master

98 files changed

modifiedCargo.lockdiffbeforeafterboth
5291 "cumulus-primitives-timestamp",5291 "cumulus-primitives-timestamp",
5292 "cumulus-primitives-utility",5292 "cumulus-primitives-utility",
5293 "derivative",5293 "derivative",
5294 "evm-coder",
5294 "fp-evm-mapping",5295 "fp-evm-mapping",
5295 "fp-rpc",5296 "fp-rpc",
5296 "fp-self-contained",5297 "fp-self-contained",
5352 "sp-transaction-pool",5353 "sp-transaction-pool",
5353 "sp-version",5354 "sp-version",
5354 "substrate-wasm-builder",5355 "substrate-wasm-builder",
5355 "unique-runtime-common",5356 "up-common",
5356 "up-data-structs",5357 "up-data-structs",
5357 "up-rpc",5358 "up-rpc",
5359 "up-sponsorship",
5358 "xcm",5360 "xcm",
5359 "xcm-builder",5361 "xcm-builder",
5360 "xcm-executor",5362 "xcm-executor",
8605 "cumulus-primitives-timestamp",8607 "cumulus-primitives-timestamp",
8606 "cumulus-primitives-utility",8608 "cumulus-primitives-utility",
8607 "derivative",8609 "derivative",
8610 "evm-coder",
8608 "fp-evm-mapping",8611 "fp-evm-mapping",
8609 "fp-rpc",8612 "fp-rpc",
8610 "fp-self-contained",8613 "fp-self-contained",
8666 "sp-transaction-pool",8669 "sp-transaction-pool",
8667 "sp-version",8670 "sp-version",
8668 "substrate-wasm-builder",8671 "substrate-wasm-builder",
8669 "unique-runtime-common",8672 "up-common",
8670 "up-data-structs",8673 "up-data-structs",
8671 "up-rpc",8674 "up-rpc",
8675 "up-sponsorship",
8672 "xcm",8676 "xcm",
8673 "xcm-builder",8677 "xcm-builder",
8674 "xcm-executor",8678 "xcm-executor",
11881name = "tests"11885name = "tests"
11882version = "0.1.0"11886version = "0.1.0"
11883dependencies = [11887dependencies = [
11888 "evm-coder",
11884 "fp-evm-mapping",11889 "fp-evm-mapping",
11885 "frame-support",11890 "frame-support",
11886 "frame-system",11891 "frame-system",
11902 "sp-io",11907 "sp-io",
11903 "sp-runtime",11908 "sp-runtime",
11904 "sp-std",11909 "sp-std",
11905 "unique-runtime-common",
11906 "up-data-structs",11910 "up-data-structs",
11911 "up-sponsorship",
11907]11912]
1190811913
11909[[package]]11914[[package]]
12387 "sp-core",12392 "sp-core",
12388 "sp-rpc",12393 "sp-rpc",
12389 "sp-runtime",12394 "sp-runtime",
12390 "unique-runtime-common",
12391 "up-data-structs",12395 "up-data-structs",
12392 "up-rpc",12396 "up-rpc",
12393]12397]
12541 "try-runtime-cli",12545 "try-runtime-cli",
12542 "unique-rpc",12546 "unique-rpc",
12543 "unique-runtime",12547 "unique-runtime",
12544 "unique-runtime-common",12548 "up-common",
12545 "up-data-structs",12549 "up-data-structs",
12546 "up-rpc",12550 "up-rpc",
12547]12551]
12590 "substrate-frame-rpc-system",12594 "substrate-frame-rpc-system",
12591 "tokio 0.2.25",12595 "tokio 0.2.25",
12592 "uc-rpc",12596 "uc-rpc",
12593 "unique-runtime-common",12597 "up-common",
12594 "up-data-structs",12598 "up-data-structs",
12595 "up-rpc",12599 "up-rpc",
12596]12600]
12608 "cumulus-primitives-timestamp",12612 "cumulus-primitives-timestamp",
12609 "cumulus-primitives-utility",12613 "cumulus-primitives-utility",
12610 "derivative",12614 "derivative",
12615 "evm-coder",
12611 "fp-evm-mapping",12616 "fp-evm-mapping",
12612 "fp-rpc",12617 "fp-rpc",
12613 "fp-self-contained",12618 "fp-self-contained",
12669 "sp-transaction-pool",12674 "sp-transaction-pool",
12670 "sp-version",12675 "sp-version",
12671 "substrate-wasm-builder",12676 "substrate-wasm-builder",
12672 "unique-runtime-common",12677 "up-common",
12673 "up-data-structs",12678 "up-data-structs",
12674 "up-rpc",12679 "up-rpc",
12680 "up-sponsorship",
12675 "xcm",12681 "xcm",
12676 "xcm-builder",12682 "xcm-builder",
12677 "xcm-executor",12683 "xcm-executor",
12678]12684]
12679
12680[[package]]
12681name = "unique-runtime-common"
12682version = "0.9.24"
12683dependencies = [
12684 "evm-coder",
12685 "fp-rpc",
12686 "frame-support",
12687 "frame-system",
12688 "pallet-common",
12689 "pallet-evm",
12690 "pallet-fungible",
12691 "pallet-nonfungible",
12692 "pallet-refungible",
12693 "pallet-unique",
12694 "pallet-unique-scheduler",
12695 "parity-scale-codec 3.1.5",
12696 "rmrk-rpc",
12697 "scale-info",
12698 "sp-consensus-aura",
12699 "sp-core",
12700 "sp-runtime",
12701 "sp-std",
12702 "up-data-structs",
12703 "up-sponsorship",
12704]
1270512685
12706[[package]]12686[[package]]
12707name = "universal-hash"12687name = "universal-hash"
12731source = "registry+https://github.com/rust-lang/crates.io-index"12711source = "registry+https://github.com/rust-lang/crates.io-index"
12732checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"12712checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
12713
12714[[package]]
12715name = "up-common"
12716version = "0.9.24"
12717dependencies = [
12718 "fp-rpc",
12719 "frame-support",
12720 "pallet-evm",
12721 "sp-consensus-aura",
12722 "sp-core",
12723 "sp-runtime",
12724 "sp-std",
12725]
1273312726
12734[[package]]12727[[package]]
12735name = "up-data-structs"12728name = "up-data-structs"
modifiedclient/rpc/Cargo.tomldiffbeforeafterboth
5edition = "2021"5edition = "2021"
66
7[dependencies]7[dependencies]
8unique-runtime-common = { default-features = false, path = "../../runtime/common" }
9pallet-common = { default-features = false, path = '../../pallets/common' }8pallet-common = { default-features = false, path = '../../pallets/common' }
10up-data-structs = { default-features = false, path = '../../primitives/data-structs' }9up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
11up-rpc = { path = "../../primitives/rpc" }10up-rpc = { path = "../../primitives/rpc" }
modifiednode/cli/Cargo.tomldiffbeforeafterboth
253################################################################################253################################################################################
254# Local dependencies254# Local dependencies
255255
256[dependencies.unique-runtime-common]256[dependencies.up-common]
257default-features = false
258path = "../../runtime/common"257path = "../../primitives/common"
259258
260[dependencies.unique-runtime]259[dependencies.unique-runtime]
261path = '../../runtime/unique'260path = '../../runtime/unique'
modifiednode/cli/src/chain_spec.rsdiffbeforeafterboth
23use serde::{Deserialize, Serialize};23use serde::{Deserialize, Serialize};
24use serde_json::map::Map;24use serde_json::map::Map;
2525
26use unique_runtime_common::types::*;26use up_common::types::opaque::*;
2727
28#[cfg(feature = "unique-runtime")]28#[cfg(feature = "unique-runtime")]
29pub use unique_runtime as default_runtime;29pub use unique_runtime as default_runtime;
modifiednode/cli/src/command.rsdiffbeforeafterboth
64use sp_runtime::traits::{AccountIdConversion, Block as BlockT};64use sp_runtime::traits::{AccountIdConversion, Block as BlockT};
65use std::{io::Write, net::SocketAddr, time::Duration};65use std::{io::Write, net::SocketAddr, time::Duration};
6666
67use unique_runtime_common::types::Block;67use up_common::types::opaque::Block;
6868
69macro_rules! no_runtime_err {69macro_rules! no_runtime_err {
70 ($chain_name:expr) => {70 ($chain_name:expr) => {
modifiednode/cli/src/service.rsdiffbeforeafterboth
63use fc_rpc_core::types::FilterPool;63use fc_rpc_core::types::FilterPool;
64use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};64use fc_mapping_sync::{MappingSyncWorker, SyncStrategy};
6565
66use unique_runtime_common::types::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};66use up_common::types::opaque::{AuraId, RuntimeInstance, AccountId, Balance, Index, Hash, Block};
6767
68// RMRK68// RMRK
69use up_data_structs::{69use up_data_structs::{
modifiednode/rpc/Cargo.tomldiffbeforeafterboth
49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }49fc-mapping-sync = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
5050
51pallet-common = { default-features = false, path = "../../pallets/common" }51pallet-common = { default-features = false, path = "../../pallets/common" }
52unique-runtime-common = { default-features = false, path = "../../runtime/common" }52up-common = { path = "../../primitives/common" }
53pallet-unique = { path = "../../pallets/unique" }53pallet-unique = { path = "../../pallets/unique" }
54uc-rpc = { path = "../../client/rpc" }54uc-rpc = { path = "../../client/rpc" }
55up-rpc = { path = "../../primitives/rpc" }55up-rpc = { path = "../../primitives/rpc" }
modifiednode/rpc/src/lib.rsdiffbeforeafterboth
40use sc_service::TransactionPool;40use sc_service::TransactionPool;
41use std::{collections::BTreeMap, sync::Arc};41use std::{collections::BTreeMap, sync::Arc};
4242
43use unique_runtime_common::types::{43use up_common::types::opaque::{Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance};
44 Hash, AccountId, RuntimeInstance, Index, Block, BlockNumber, Balance,44
45};
46// RMRK45// RMRK
47use up_data_structs::{46use up_data_structs::{
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
535535
536 /// Can't transfer tokens to ethereum zero address536 /// Can't transfer tokens to ethereum zero address
537 AddressIsZero,537 AddressIsZero,
538 /// Target collection doesn't support this operation538
539 /// The oprtation is not supported
539 UnsupportedOperation,540 UnsupportedOperation,
540541
541 /// Insufficient funds to perform an action542 /// Insufficient funds to perform an action
1353/// Indicates unsupported methods by returning [Error::UnsupportedOperation].1354/// Indicates unsupported methods by returning [Error::UnsupportedOperation].
1354#[macro_export]1355#[macro_export]
1355macro_rules! unsupported {1356macro_rules! unsupported {
1356 () => {1357 ($runtime:path) => {
1357 Err(<Error<T>>::UnsupportedOperation.into())1358 Err($crate::Error::<$runtime>::UnsupportedOperation.into())
1358 };1359 };
1359}1360}
13601361
addedprimitives/common/Cargo.tomldiffbeforeafterboth

no changes

addedprimitives/common/src/constants.rsdiffbeforeafterboth

no changes

addedprimitives/common/src/lib.rsdiffbeforeafterboth

no changes

addedprimitives/common/src/types.rsdiffbeforeafterboth

no changes

deletedruntime/common/Cargo.tomldiffbeforeafterboth

no changes

addedruntime/common/config/ethereum.rsdiffbeforeafterboth

no changes

addedruntime/common/config/mod.rsdiffbeforeafterboth

no changes

addedruntime/common/config/orml.rsdiffbeforeafterboth

no changes

addedruntime/common/config/pallets/mod.rsdiffbeforeafterboth

no changes

addedruntime/common/config/pallets/rmrk.rsdiffbeforeafterboth

no changes

addedruntime/common/config/pallets/scheduler.rsdiffbeforeafterboth

no changes

addedruntime/common/config/parachain.rsdiffbeforeafterboth

no changes

addedruntime/common/config/sponsoring.rsdiffbeforeafterboth

no changes

addedruntime/common/config/substrate.rsdiffbeforeafterboth

no changes

addedruntime/common/config/xcm.rsdiffbeforeafterboth

no changes

addedruntime/common/constants.rsdiffbeforeafterboth

no changes

addedruntime/common/construct_runtime/mod.rsdiffbeforeafterboth

no changes

addedruntime/common/construct_runtime/util.rsdiffbeforeafterboth

no changes

addedruntime/common/dispatch.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/mod.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/self_contained_call.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/sponsoring.rsdiffbeforeafterboth

no changes

addedruntime/common/ethereum/transaction_converter.rsdiffbeforeafterboth

no changes

addedruntime/common/instance.rsdiffbeforeafterboth

no changes

addedruntime/common/mod.rsdiffbeforeafterboth

no changes

addedruntime/common/runtime_apis.rsdiffbeforeafterboth

no changes

addedruntime/common/scheduler.rsdiffbeforeafterboth

no changes

addedruntime/common/sponsoring.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/constants.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/dispatch.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/eth_sponsoring.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/lib.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/runtime_apis.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/sponsoring.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/types.rsdiffbeforeafterboth

no changes

deletedruntime/common/src/weights.rsdiffbeforeafterboth

no changes

addedruntime/common/weights.rsdiffbeforeafterboth

no changes

modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
16targets = ['x86_64-unknown-linux-gnu']16targets = ['x86_64-unknown-linux-gnu']
1717
18[features]18[features]
19default = ['std']19default = ['std', 'opal-runtime']
20runtime-benchmarks = [20runtime-benchmarks = [
21 'hex-literal',21 'hex-literal',
22 'frame-benchmarking',22 'frame-benchmarking',
113 'xcm/std',113 'xcm/std',
114 'xcm-builder/std',114 'xcm-builder/std',
115 'xcm-executor/std',115 'xcm-executor/std',
116 'unique-runtime-common/std',116 'up-common/std',
117 'rmrk-rpc/std',117 'rmrk-rpc/std',
118 'evm-coder/std',
119 'up-sponsorship/std',
118120
119 "orml-vesting/std",121 "orml-vesting/std",
120]122]
121limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']123limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
124opal-runtime = ['refungible', 'scheduler', 'rmrk']
125
126refungible = []
127scheduler = []
128rmrk = []
122129
123################################################################################130################################################################################
124# Substrate Dependencies131# Substrate Dependencies
396403
397[dependencies]404[dependencies]
398log = { version = "0.4.16", default-features = false }405log = { version = "0.4.16", default-features = false }
399unique-runtime-common = { path = "../common", default-features = false }406up-common = { path = "../../primitives/common", default-features = false }
400scale-info = { version = "2.0.1", default-features = false, features = [407scale-info = { version = "2.0.1", default-features = false, features = [
401 "derive",408 "derive",
402] }409] }
426pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }433pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
427fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }434fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
428fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }435fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
436evm-coder = { default-features = false, path = '../../crates/evm-coder' }
437up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }
429438
430################################################################################439################################################################################
431# Build Dependencies440# Build Dependencies
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
25#[cfg(feature = "std")]25#[cfg(feature = "std")]
26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
2727
28use sp_api::impl_runtime_apis;28use frame_support::parameter_types;
29
29use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_version::RuntimeVersion;
30use sp_runtime::DispatchError;
31use fp_self_contained::*;
32// #[cfg(any(feature = "std", test))]
33// pub use sp_runtime::BuildStorage;
34
35use sp_runtime::{31use sp_runtime::create_runtime_str;
36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},
38 transaction_validity::{TransactionSource, TransactionValidity},
39 ApplyExtrinsicResult, RuntimeAppPublic,
40};
4132
42use sp_std::prelude::*;33use up_common::types::*;
4334
44#[cfg(feature = "std")]35#[path = "../../common/mod.rs"]
45use sp_version::NativeVersion;36mod runtime_common;
46use sp_version::RuntimeVersion;37
47pub use pallet_transaction_payment::{38pub use runtime_common::*;
48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,
49};
50// A few exports that help ease life for downstream crates.
51pub use pallet_balances::Call as BalancesCall;
52pub use pallet_evm::{
53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,
54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,
55};
56pub use frame_support::{
57 construct_runtime, match_types,
58 dispatch::DispatchResult,
59 PalletId, parameter_types, StorageValue, ConsensusEngineId,
60 traits::{
61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,
62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,
63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,
64 },
65 weights::{
66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,
69 WeightToFee,
70 },
71};
72use pallet_unique_scheduler::DispatchCall;
73use up_data_structs::{
74 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,
75 CollectionStats, RpcCollection,
76 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
77 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,
78 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,
79 RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,
80};
81
82// use pallet_contracts::weights::WeightInfo;
83// #[cfg(any(feature = "std", test))]
84use frame_system::{
85 self as frame_system, EnsureRoot, EnsureSigned,
86 limits::{BlockWeights, BlockLength},
87};
88use sp_arithmetic::{
89 traits::{BaseArithmetic, Unsigned},
90};
91use smallvec::smallvec;
92// use scale_info::TypeInfo;
93use codec::{Encode, Decode};
94use fp_rpc::TransactionStatus;
95use sp_runtime::{
96 traits::{
97 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,
98 Saturating, CheckedConversion,
99 },
100 generic::Era,
101 transaction_validity::TransactionValidityError,
102 DispatchErrorWithPostInfo, SaturatedConversion,
103};
104
105// pub use pallet_timestamp::Call as TimestampCall;
106pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
107
108// Polkadot imports
109use pallet_xcm::XcmPassthrough;
110use polkadot_parachain::primitives::Sibling;
111use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
112use xcm_builder::{
113 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
114 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,
115 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
116 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
117 ParentIsPreset,
118};
119use xcm_executor::{Config, XcmExecutor, Assets};
120use sp_std::{cmp::Ordering, marker::PhantomData};
121
122use xcm::latest::{
123 // Xcm,
124 AssetId::{Concrete},
125 Fungibility::Fungible as XcmFungible,
126 MultiAsset,
127 Error as XcmError,
128};
129use xcm_executor::traits::{MatchesFungible, WeightTrader};
130//use xcm_executor::traits::MatchesFungible;
131
132use unique_runtime_common::{
133 impl_common_runtime_apis,
134 types::*,
135 constants::*,
136 dispatch::{CollectionDispatchT, CollectionDispatch},
137 sponsoring::UniqueSponsorshipHandler,
138 eth_sponsoring::UniqueEthSponsorshipHandler,
139 weights::CommonWeights,
140};
14139
142pub const RUNTIME_NAME: &str = "opal";40pub const RUNTIME_NAME: &str = "opal";
143pub const TOKEN_SYMBOL: &str = "OPL";41pub const TOKEN_SYMBOL: &str = "OPL";
144
145type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
146
147impl RuntimeInstance for Runtime {
148 type CrossAccountId = self::CrossAccountId;
149 type TransactionConverter = self::TransactionConverter;
150
151 fn get_transaction_converter() -> TransactionConverter {
152 TransactionConverter
153 }
154}
155
156/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
157/// never know...
158pub type AccountIndex = u32;
159
160/// Balance of an account.
161pub type Balance = u128;
162
163/// Index of a transaction in the chain.
164pub type Index = u32;
165
166/// A hash of some data used by the chain.
167pub type Hash = sp_core::H256;
168
169/// Digest item type.
170pub type DigestItem = generic::DigestItem;
171
172/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
173/// the specifics of the runtime. They can then be made to be agnostic over specific formats
174/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
175/// to even the core data structures.
176pub mod opaque {
177 use sp_std::prelude::*;
178 use sp_runtime::impl_opaque_keys;
179 use super::Aura;
180
181 pub use unique_runtime_common::types::*;
182
183 impl_opaque_keys! {
184 pub struct SessionKeys {
185 pub aura: Aura,
186 }
187 }
188}
18942
190/// This runtime version.43/// This runtime version.
191pub const VERSION: RuntimeVersion = RuntimeVersion {44pub const VERSION: RuntimeVersion = RuntimeVersion {
199 state_version: 0,52 state_version: 0,
200};53};
201
202#[derive(codec::Encode, codec::Decode)]
203pub enum XCMPMessage<XAccountId, XBalance> {
204 /// Transfer tokens to the given account from the Parachain account.
205 TransferToken(XAccountId, XBalance),
206}
207
208/// The version information used to identify this runtime when compiled natively.
209#[cfg(feature = "std")]
210pub fn native_version() -> NativeVersion {
211 NativeVersion {
212 runtime_version: VERSION,
213 can_author_with: Default::default(),
214 }
215}
216
217type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
218
219pub struct DealWithFees;
220impl OnUnbalanced<NegativeImbalance> for DealWithFees {
221 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
222 if let Some(fees) = fees_then_tips.next() {
223 // for fees, 100% to treasury
224 let mut split = fees.ration(100, 0);
225 if let Some(tips) = fees_then_tips.next() {
226 // for tips, if any, 100% to treasury
227 tips.ration_merge_into(100, 0, &mut split);
228 }
229 Treasury::on_unbalanced(split.0);
230 // Author::on_unbalanced(split.1);
231 }
232 }
233}
23454
235parameter_types! {55parameter_types! {
236 pub const BlockHashCount: BlockNumber = 2400;
237 pub RuntimeBlockLength: BlockLength =
238 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
239 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
240 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
241 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
242 .base_block(BlockExecutionWeight::get())
243 .for_class(DispatchClass::all(), |weights| {
244 weights.base_extrinsic = ExtrinsicBaseWeight::get();
245 })
246 .for_class(DispatchClass::Normal, |weights| {
247 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
248 })
249 .for_class(DispatchClass::Operational, |weights| {
250 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
251 // Operational transactions have some extra reserved space, so that they
252 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
253 weights.reserved = Some(
254 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
255 );
256 })
257 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
258 .build_or_panic();
259 pub const Version: RuntimeVersion = VERSION;56 pub const Version: RuntimeVersion = VERSION;
260 pub const SS58Prefix: u8 = 42;57 pub const SS58Prefix: u8 = 42;
261}
262
263parameter_types! {
264 pub const ChainId: u64 = 8882;58 pub const ChainId: u64 = 8882;
265}59}
266
267pub struct FixedFee;
268impl FeeCalculator for FixedFee {
269 fn min_gas_price() -> (U256, u64) {
270 (MIN_GAS_PRICE.into(), 0)
271 }
272}
273
274// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
275// (contract, which only writes a lot of data),
276// approximating on top of our real store write weight
277parameter_types! {
278 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
279 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
280 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
281}
282
283/// Limiting EVM execution to 50% of block for substrate users and management tasks
284/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
285/// scheduled fairly
286const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
287parameter_types! {
288 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
289}
290
291pub enum FixedGasWeightMapping {}
292impl GasWeightMapping for FixedGasWeightMapping {
293 fn gas_to_weight(gas: u64) -> Weight {
294 gas.saturating_mul(WeightPerGas::get())
295 }
296 fn weight_to_gas(weight: Weight) -> u64 {
297 weight / WeightPerGas::get()
298 }
299}
300
301impl pallet_evm::account::Config for Runtime {
302 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;
303 type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;
304 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
305}
306
307impl pallet_evm::Config for Runtime {
308 type BlockGasLimit = BlockGasLimit;
309 type FeeCalculator = FixedFee;
310 type GasWeightMapping = FixedGasWeightMapping;
311 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
312 type CallOrigin = EnsureAddressTruncated<Self>;
313 type WithdrawOrigin = EnsureAddressTruncated<Self>;
314 type AddressMapping = HashedAddressMapping<Self::Hashing>;
315 type PrecompilesType = ();
316 type PrecompilesValue = ();
317 type Currency = Balances;
318 type Event = Event;
319 type OnMethodCall = (
320 pallet_evm_migration::OnMethodCall<Self>,
321 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
322 CollectionDispatchT<Self>,
323 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
324 );
325 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
326 type ChainId = ChainId;
327 type Runner = pallet_evm::runner::stack::Runner<Self>;
328 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
329 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
330 type FindAuthor = EthereumFindAuthor<Aura>;
331}
332
333impl pallet_evm_migration::Config for Runtime {
334 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
335}
336
337pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
338impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {
339 fn find_author<'a, I>(digests: I) -> Option<H160>
340 where
341 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
342 {
343 if let Some(author_index) = F::find_author(digests) {
344 let authority_id = Aura::authorities()[author_index as usize].clone();
345 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
346 }
347 None
348 }
349}
350
351impl pallet_ethereum::Config for Runtime {
352 type Event = Event;
353 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
354}
355
356impl pallet_randomness_collective_flip::Config for Runtime {}
357
358impl frame_system::Config for Runtime {
359 /// The data to be stored in an account.
360 type AccountData = pallet_balances::AccountData<Balance>;
361 /// The identifier used to distinguish between accounts.
362 type AccountId = AccountId;
363 /// The basic call filter to use in dispatchable.
364 type BaseCallFilter = Everything;
365 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
366 type BlockHashCount = BlockHashCount;
367 /// The maximum length of a block (in bytes).
368 type BlockLength = RuntimeBlockLength;
369 /// The index type for blocks.
370 type BlockNumber = BlockNumber;
371 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.
372 type BlockWeights = RuntimeBlockWeights;
373 /// The aggregated dispatch type that is available for extrinsics.
374 type Call = Call;
375 /// The weight of database operations that the runtime can invoke.
376 type DbWeight = RocksDbWeight;
377 /// The ubiquitous event type.
378 type Event = Event;
379 /// The type for hashing blocks and tries.
380 type Hash = Hash;
381 /// The hashing algorithm used.
382 type Hashing = BlakeTwo256;
383 /// The header type.
384 type Header = generic::Header<BlockNumber, BlakeTwo256>;
385 /// The index type for storing how many extrinsics an account has signed.
386 type Index = Index;
387 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
388 type Lookup = AccountIdLookup<AccountId, ()>;
389 /// What to do if an account is fully reaped from the system.
390 type OnKilledAccount = ();
391 /// What to do if a new account is created.
392 type OnNewAccount = ();
393 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
394 /// The ubiquitous origin type.
395 type Origin = Origin;
396 /// This type is being generated by `construct_runtime!`.
397 type PalletInfo = PalletInfo;
398 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
399 type SS58Prefix = SS58Prefix;
400 /// Weight information for the extrinsics of this pallet.
401 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;
402 /// Version of the runtime.
403 type Version = Version;
404 type MaxConsumers = ConstU32<16>;
405}
406
407parameter_types! {
408 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
409}
410
411impl pallet_timestamp::Config for Runtime {
412 /// A timestamp: milliseconds since the unix epoch.
413 type Moment = u64;
414 type OnTimestampSet = ();
415 type MinimumPeriod = MinimumPeriod;
416 type WeightInfo = ();
417}
418
419parameter_types! {
420 // pub const ExistentialDeposit: u128 = 500;
421 pub const ExistentialDeposit: u128 = 0;
422 pub const MaxLocks: u32 = 50;
423 pub const MaxReserves: u32 = 50;
424}
425
426impl pallet_balances::Config for Runtime {
427 type MaxLocks = MaxLocks;
428 type MaxReserves = MaxReserves;
429 type ReserveIdentifier = [u8; 16];
430 /// The type for recording an account's balance.
431 type Balance = Balance;
432 /// The ubiquitous event type.
433 type Event = Event;
434 type DustRemoval = Treasury;
435 type ExistentialDeposit = ExistentialDeposit;
436 type AccountStore = System;
437 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
438}
439
440pub const fn deposit(items: u32, bytes: u32) -> Balance {
441 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE
442}
443
444/*
445parameter_types! {
446 pub TombstoneDeposit: Balance = deposit(
447 1,
448 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,
449 );
450 pub DepositPerContract: Balance = TombstoneDeposit::get();
451 pub const DepositPerStorageByte: Balance = deposit(0, 1);
452 pub const DepositPerStorageItem: Balance = deposit(1, 0);
453 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
454 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;
455 pub const SignedClaimHandicap: u32 = 2;
456 pub const MaxDepth: u32 = 32;
457 pub const MaxValueSize: u32 = 16 * 1024;
458 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb
459 // The lazy deletion runs inside on_initialize.
460 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
461 RuntimeBlockWeights::get().max_block;
462 // The weight needed for decoding the queue should be less or equal than a fifth
463 // of the overall weight dedicated to the lazy deletion.
464 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
465 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
466 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
467 )) / 5) as u32;
468 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
469}
470
471impl pallet_contracts::Config for Runtime {
472 type Time = Timestamp;
473 type Randomness = RandomnessCollectiveFlip;
474 type Currency = Balances;
475 type Event = Event;
476 type RentPayment = ();
477 type SignedClaimHandicap = SignedClaimHandicap;
478 type TombstoneDeposit = TombstoneDeposit;
479 type DepositPerContract = DepositPerContract;
480 type DepositPerStorageByte = DepositPerStorageByte;
481 type DepositPerStorageItem = DepositPerStorageItem;
482 type RentFraction = RentFraction;
483 type SurchargeReward = SurchargeReward;
484 type WeightPrice = pallet_transaction_payment::Pallet<Self>;
485 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
486 type ChainExtension = NFTExtension;
487 type DeletionQueueDepth = DeletionQueueDepth;
488 type DeletionWeightLimit = DeletionWeightLimit;
489 type Schedule = Schedule;
490 type CallStack = [pallet_contracts::Frame<Self>; 31];
491}
492*/
493
494parameter_types! {
495 /// This value increases the priority of `Operational` transactions by adding
496 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
497 pub const OperationalFeeMultiplier: u8 = 5;
498}
499
500/// Linear implementor of `WeightToFeePolynomial`
501pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);
502
503impl<T> WeightToFeePolynomial for LinearFee<T>
504where
505 T: BaseArithmetic + From<u32> + Copy + Unsigned,
506{
507 type Balance = T;
508
509 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
510 smallvec!(WeightToFeeCoefficient {
511 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),
512 coeff_frac: Perbill::zero(),
513 negative: false,
514 degree: 1,
515 })
516 }
517}
518
519impl pallet_transaction_payment::Config for Runtime {
520 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;
521 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
522 type OperationalFeeMultiplier = OperationalFeeMultiplier;
523 type WeightToFee = LinearFee<Balance>;
524 type FeeMultiplierUpdate = ();
525}
526
527parameter_types! {
528 pub const ProposalBond: Permill = Permill::from_percent(5);
529 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;
530 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;
531 pub const SpendPeriod: BlockNumber = 5 * MINUTES;
532 pub const Burn: Permill = Permill::from_percent(0);
533 pub const TipCountdown: BlockNumber = 1 * DAYS;
534 pub const TipFindersFee: Percent = Percent::from_percent(20);
535 pub const TipReportDepositBase: Balance = 1 * UNIQUE;
536 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;
537 pub const BountyDepositBase: Balance = 1 * UNIQUE;
538 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
539 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");
540 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
541 pub const MaximumReasonLength: u32 = 16384;
542 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
543 pub const BountyValueMinimum: Balance = 5 * UNIQUE;
544 pub const MaxApprovals: u32 = 100;
545}
546
547impl pallet_treasury::Config for Runtime {
548 type PalletId = TreasuryModuleId;
549 type Currency = Balances;
550 type ApproveOrigin = EnsureRoot<AccountId>;
551 type RejectOrigin = EnsureRoot<AccountId>;
552 type Event = Event;
553 type OnSlash = ();
554 type ProposalBond = ProposalBond;
555 type ProposalBondMinimum = ProposalBondMinimum;
556 type ProposalBondMaximum = ProposalBondMaximum;
557 type SpendPeriod = SpendPeriod;
558 type Burn = Burn;
559 type BurnDestination = ();
560 type SpendFunds = ();
561 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
562 type MaxApprovals = MaxApprovals;
563}
564
565impl pallet_sudo::Config for Runtime {
566 type Event = Event;
567 type Call = Call;
568}
569
570pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);
571
572impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider
573 for RelayChainBlockNumberProvider<T>
574{
575 type BlockNumber = BlockNumber;
576
577 fn current_block_number() -> Self::BlockNumber {
578 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()
579 .map(|d| d.relay_parent_number)
580 .unwrap_or_default()
581 }
582}
583
584parameter_types! {
585 pub const MinVestedTransfer: Balance = 10 * UNIQUE;
586 pub const MaxVestingSchedules: u32 = 28;
587}
588
589impl orml_vesting::Config for Runtime {
590 type Event = Event;
591 type Currency = pallet_balances::Pallet<Runtime>;
592 type MinVestedTransfer = MinVestedTransfer;
593 type VestedTransferOrigin = EnsureSigned<AccountId>;
594 type WeightInfo = ();
595 type MaxVestingSchedules = MaxVestingSchedules;
596 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
597}
598
599parameter_types! {
600 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
601 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
602}
603
604impl cumulus_pallet_parachain_system::Config for Runtime {
605 type Event = Event;
606 type SelfParaId = parachain_info::Pallet<Self>;
607 type OnSystemEvent = ();
608 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
609 // MaxDownwardMessageWeight,
610 // XcmExecutor<XcmConfig>,
611 // Call,
612 // >;
613 type OutboundXcmpMessageSource = XcmpQueue;
614 type DmpMessageHandler = DmpQueue;
615 type ReservedDmpWeight = ReservedDmpWeight;
616 type ReservedXcmpWeight = ReservedXcmpWeight;
617 type XcmpMessageHandler = XcmpQueue;
618}
619
620impl parachain_info::Config for Runtime {}
621
622impl cumulus_pallet_aura_ext::Config for Runtime {}
623
624parameter_types! {
625 pub const RelayLocation: MultiLocation = MultiLocation::parent();
626 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
627 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
628 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
629}
630
631/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
632/// when determining ownership of accounts for asset transacting and when attempting to use XCM
633/// `Transact` in order to determine the dispatch Origin.
634pub type LocationToAccountId = (
635 // The parent (Relay-chain) origin converts to the default `AccountId`.
636 ParentIsPreset<AccountId>,
637 // Sibling parachain origins convert to AccountId via the `ParaId::into`.
638 SiblingParachainConvertsVia<Sibling, AccountId>,
639 // Straight up local `AccountId32` origins just alias directly to `AccountId`.
640 AccountId32Aliases<RelayNetwork, AccountId>,
641);
642
643pub struct OnlySelfCurrency;
644impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
645 fn matches_fungible(a: &MultiAsset) -> Option<B> {
646 match (&a.id, &a.fun) {
647 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
648 _ => None,
649 }
650 }
651}
652
653/// Means for transacting assets on this chain.
654pub type LocalAssetTransactor = CurrencyAdapter<
655 // Use this currency:
656 Balances,
657 // Use this currency when it is a fungible asset matching the given location or name:
658 OnlySelfCurrency,
659 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
660 LocationToAccountId,
661 // Our chain's account ID type (we can't get away without mentioning it explicitly):
662 AccountId,
663 // We don't track any teleports.
664 (),
665>;
666
667/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
668/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
669/// biases the kind of local `Origin` it will become.
670pub type XcmOriginToTransactDispatchOrigin = (
671 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
672 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
673 // foreign chains who want to have a local sovereign account on this chain which they control.
674 SovereignSignedViaLocation<LocationToAccountId, Origin>,
675 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
676 // recognised.
677 RelayChainAsNative<RelayOrigin, Origin>,
678 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
679 // recognised.
680 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
681 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
682 // transaction from the Root origin.
683 ParentAsSuperuser<Origin>,
684 // Native signed account converter; this just converts an `AccountId32` origin into a normal
685 // `Origin::Signed` origin of the same 32-byte value.
686 SignedAccountId32AsNative<RelayNetwork, Origin>,
687 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
688 XcmPassthrough<Origin>,
689);
690
691parameter_types! {
692 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
693 pub UnitWeightCost: Weight = 1_000_000;
694 // 1200 UNIQUEs buy 1 second of weight.
695 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);
696 pub const MaxInstructions: u32 = 100;
697 pub const MaxAuthorities: u32 = 100_000;
698}
699
700match_types! {
701 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
702 MultiLocation { parents: 1, interior: Here } |
703 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
704 };
705}
706
707pub type Barrier = (
708 TakeWeightCredit,
709 AllowTopLevelPaidExecutionFrom<Everything>,
710 // ^^^ Parent & its unit plurality gets free execution
711);
712
713pub struct UsingOnlySelfCurrencyComponents<
714 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
715 AssetId: Get<MultiLocation>,
716 AccountId,
717 Currency: CurrencyT<AccountId>,
718 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
719>(
720 Weight,
721 Currency::Balance,
722 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
723);
724impl<
725 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
726 AssetId: Get<MultiLocation>,
727 AccountId,
728 Currency: CurrencyT<AccountId>,
729 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
730 > WeightTrader
731 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
732{
733 fn new() -> Self {
734 Self(0, Zero::zero(), PhantomData)
735 }
736
737 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
738 let amount = WeightToFee::weight_to_fee(&weight);
739 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
740
741 // location to this parachain through relay chain
742 let option1: xcm::v1::AssetId = Concrete(MultiLocation {
743 parents: 1,
744 interior: X1(Parachain(ParachainInfo::parachain_id().into())),
745 });
746 // direct location
747 let option2: xcm::v1::AssetId = Concrete(MultiLocation {
748 parents: 0,
749 interior: Here,
750 });
751
752 let required = if payment.fungible.contains_key(&option1) {
753 (option1, u128_amount).into()
754 } else if payment.fungible.contains_key(&option2) {
755 (option2, u128_amount).into()
756 } else {
757 (Concrete(MultiLocation::default()), u128_amount).into()
758 };
759
760 let unused = payment
761 .checked_sub(required)
762 .map_err(|_| XcmError::TooExpensive)?;
763 self.0 = self.0.saturating_add(weight);
764 self.1 = self.1.saturating_add(amount);
765 Ok(unused)
766 }
767
768 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
769 let weight = weight.min(self.0);
770 let amount = WeightToFee::weight_to_fee(&weight);
771 self.0 -= weight;
772 self.1 = self.1.saturating_sub(amount);
773 let amount: u128 = amount.saturated_into();
774 if amount > 0 {
775 Some((AssetId::get(), amount).into())
776 } else {
777 None
778 }
779 }
780}
781impl<
782 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
783 AssetId: Get<MultiLocation>,
784 AccountId,
785 Currency: CurrencyT<AccountId>,
786 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
787 > Drop
788 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
789{
790 fn drop(&mut self) {
791 OnUnbalanced::on_unbalanced(Currency::issue(self.1));
792 }
793}
794
795pub struct XcmConfig;
796impl Config for XcmConfig {
797 type Call = Call;
798 type XcmSender = XcmRouter;
799 // How to withdraw and deposit an asset.
800 type AssetTransactor = LocalAssetTransactor;
801 type OriginConverter = XcmOriginToTransactDispatchOrigin;
802 type IsReserve = NativeAsset;
803 type IsTeleporter = (); // Teleportation is disabled
804 type LocationInverter = LocationInverter<Ancestry>;
805 type Barrier = Barrier;
806 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
807 type Trader =
808 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;
809 type ResponseHandler = (); // Don't handle responses for now.
810 type SubscriptionService = PolkadotXcm;
811
812 type AssetTrap = PolkadotXcm;
813 type AssetClaims = PolkadotXcm;
814}
815
816// parameter_types! {
817// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
818// }
819
820/// No local origins on this chain are allowed to dispatch XCM sends/executions.
821pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);
822
823/// The means for routing XCM messages which are not for local execution into the right message
824/// queues.
825pub type XcmRouter = (
826 // Two routers - use UMP to communicate with the relay chain:
827 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
828 // ..and XCMP to communicate with the sibling chains.
829 XcmpQueue,
830);
831
832impl pallet_evm_coder_substrate::Config for Runtime {}
833
834impl pallet_xcm::Config for Runtime {
835 type Event = Event;
836 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
837 type XcmRouter = XcmRouter;
838 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
839 type XcmExecuteFilter = Everything;
840 type XcmExecutor = XcmExecutor<XcmConfig>;
841 type XcmTeleportFilter = Everything;
842 type XcmReserveTransferFilter = Everything;
843 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
844 type LocationInverter = LocationInverter<Ancestry>;
845 type Origin = Origin;
846 type Call = Call;
847 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
848 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
849}
850
851impl cumulus_pallet_xcm::Config for Runtime {
852 type Event = Event;
853 type XcmExecutor = XcmExecutor<XcmConfig>;
854}
855
856impl cumulus_pallet_xcmp_queue::Config for Runtime {
857 type WeightInfo = ();
858 type Event = Event;
859 type XcmExecutor = XcmExecutor<XcmConfig>;
860 type ChannelInfo = ParachainSystem;
861 type VersionWrapper = ();
862 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
863 type ControllerOrigin = EnsureRoot<AccountId>;
864 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
865}
866
867impl cumulus_pallet_dmp_queue::Config for Runtime {
868 type Event = Event;
869 type XcmExecutor = XcmExecutor<XcmConfig>;
870 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
871}
872
873impl pallet_aura::Config for Runtime {
874 type AuthorityId = AuraId;
875 type DisabledValidators = ();
876 type MaxAuthorities = MaxAuthorities;
877}
878
879parameter_types! {
880 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
881 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
882}
883
884impl pallet_common::Config for Runtime {
885 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;
886 type Event = Event;
887 type Currency = Balances;
888 type CollectionCreationPrice = CollectionCreationPrice;
889 type TreasuryAccountId = TreasuryAccountId;
890 type CollectionDispatch = CollectionDispatchT<Self>;
891
892 type EvmTokenAddressMapping = EvmTokenAddressMapping;
893 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
894 type ContractAddress = EvmCollectionHelpersAddress;
895}
896
897impl pallet_structure::Config for Runtime {
898 type Event = Event;
899 type Call = Call;
900 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;
901}
902
903impl pallet_fungible::Config for Runtime {
904 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;
905}
906impl pallet_refungible::Config for Runtime {
907 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;
908}
909impl pallet_nonfungible::Config for Runtime {
910 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
911}
912
913impl pallet_proxy_rmrk_core::Config for Runtime {
914 type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
915 type Event = Event;
916}
917
918impl pallet_proxy_rmrk_equip::Config for Runtime {
919 type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;
920 type Event = Event;
921}
922
923impl pallet_unique::Config for Runtime {
924 type Event = Event;
925 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
926 type CommonWeightInfo = CommonWeights<Self>;
927 type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
928}
929
930parameter_types! {
931 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied
932}
933
934/// Used for the pallet inflation
935impl pallet_inflation::Config for Runtime {
936 type Currency = Balances;
937 type TreasuryAccountId = TreasuryAccountId;
938 type InflationBlockInterval = InflationBlockInterval;
939 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
940}
941
942parameter_types! {
943 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *
944 RuntimeBlockWeights::get().max_block;
945 pub const MaxScheduledPerBlock: u32 = 50;
946}
947
948type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
949use frame_support::traits::NamedReservableCurrency;
950
951fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
952 (
953 frame_system::CheckSpecVersion::<Runtime>::new(),
954 frame_system::CheckGenesis::<Runtime>::new(),
955 frame_system::CheckEra::<Runtime>::from(Era::Immortal),
956 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
957 from,
958 )),
959 frame_system::CheckWeight::<Runtime>::new(),
960 // sponsoring transaction logic
961 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
962 )
963}
964
965pub struct SchedulerPaymentExecutor;
966impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
967 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
968where
969 <T as frame_system::Config>::Call: Member
970 + Dispatchable<Origin = Origin, Info = DispatchInfo>
971 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
972 + GetDispatchInfo
973 + From<frame_system::Call<Runtime>>,
974 SelfContainedSignedInfo: Send + Sync + 'static,
975 Call: From<<T as frame_system::Config>::Call>
976 + From<<T as pallet_unique_scheduler::Config>::Call>
977 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
978 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
979{
980 fn dispatch_call(
981 signer: <T as frame_system::Config>::AccountId,
982 call: <T as pallet_unique_scheduler::Config>::Call,
983 ) -> Result<
984 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
985 TransactionValidityError,
986 > {
987 let dispatch_info = call.get_dispatch_info();
988 let extrinsic = fp_self_contained::CheckedExtrinsic::<
989 AccountId,
990 Call,
991 SignedExtraScheduler,
992 SelfContainedSignedInfo,
993 > {
994 signed:
995 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
996 signer.clone().into(),
997 get_signed_extras(signer.into()),
998 ),
999 function: call.into(),
1000 };
1001
1002 extrinsic.apply::<Runtime>(&dispatch_info, 0)
1003 }
1004
1005 fn reserve_balance(
1006 id: [u8; 16],
1007 sponsor: <T as frame_system::Config>::AccountId,
1008 call: <T as pallet_unique_scheduler::Config>::Call,
1009 count: u32,
1010 ) -> Result<(), DispatchError> {
1011 let dispatch_info = call.get_dispatch_info();
1012 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
1013 .saturating_mul(count.into());
1014
1015 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
1016 &id,
1017 &(sponsor.into()),
1018 weight,
1019 )
1020 }
1021
1022 fn pay_for_call(
1023 id: [u8; 16],
1024 sponsor: <T as frame_system::Config>::AccountId,
1025 call: <T as pallet_unique_scheduler::Config>::Call,
1026 ) -> Result<u128, DispatchError> {
1027 let dispatch_info = call.get_dispatch_info();
1028 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
1029 Ok(
1030 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
1031 &id,
1032 &(sponsor.into()),
1033 weight,
1034 ),
1035 )
1036 }
1037
1038 fn cancel_reserve(
1039 id: [u8; 16],
1040 sponsor: <T as frame_system::Config>::AccountId,
1041 ) -> Result<u128, DispatchError> {
1042 Ok(
1043 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
1044 &id,
1045 &(sponsor.into()),
1046 u128::MAX,
1047 ),
1048 )
1049 }
1050}
1051
1052parameter_types! {
1053 pub const NoPreimagePostponement: Option<u32> = Some(10);
1054 pub const Preimage: Option<u32> = Some(10);
1055}
1056
1057/// Used the compare the privilege of an origin inside the scheduler.
1058pub struct OriginPrivilegeCmp;
1059
1060impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
1061 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {
1062 Some(Ordering::Equal)
1063 }
1064}
1065
1066impl pallet_unique_scheduler::Config for Runtime {
1067 type Event = Event;
1068 type Origin = Origin;
1069 type Currency = Balances;
1070 type PalletsOrigin = OriginCaller;
1071 type Call = Call;
1072 type MaximumWeight = MaximumSchedulerWeight;
1073 type ScheduleOrigin = EnsureSigned<AccountId>;
1074 type MaxScheduledPerBlock = MaxScheduledPerBlock;
1075 type WeightInfo = ();
1076 type CallExecutor = SchedulerPaymentExecutor;
1077 type OriginPrivilegeCmp = OriginPrivilegeCmp;
1078 type PreimageProvider = ();
1079 type NoPreimagePostponement = NoPreimagePostponement;
1080}
1081
1082type EvmSponsorshipHandler = (
1083 UniqueEthSponsorshipHandler<Runtime>,
1084 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
1085);
1086
1087type SponsorshipHandler = (
1088 UniqueSponsorshipHandler<Runtime>,
1089 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
1090 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
1091);
1092
1093impl pallet_evm_transaction_payment::Config for Runtime {
1094 type EvmSponsorshipHandler = EvmSponsorshipHandler;
1095 type Currency = Balances;
1096}
1097
1098impl pallet_charge_transaction::Config for Runtime {
1099 type SponsorshipHandler = SponsorshipHandler;
1100}
1101
1102// impl pallet_contract_helpers::Config for Runtime {
1103// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
1104// }
1105
1106parameter_types! {
1107 // 0x842899ECF380553E8a4de75bF534cdf6fBF64049
1108 pub const HelpersContractAddress: H160 = H160([
1109 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
1110 ]);
1111
1112 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
1113 pub const EvmCollectionHelpersAddress: H160 = H160([
1114 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
1115 ]);
1116}
1117
1118impl pallet_evm_contract_helpers::Config for Runtime {
1119 type ContractAddress = HelpersContractAddress;
1120 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
1121}
112260
1123construct_runtime!(61construct_runtime!(opal);
1124 pub enum Runtime where
1125 Block = Block,
1126 NodeBlock = opaque::Block,
1127 UncheckedExtrinsic = UncheckedExtrinsic
1128 {
1129 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
1130 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
1131
1132 Aura: pallet_aura::{Pallet, Config<T>} = 22,
1133 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
1134
1135 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
1136 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
1137 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
1138 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
1139 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
1140 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
1141 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,
1142 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,
1143 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
1144 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
1145
1146 // XCM helpers.
1147 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
1148 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
1149 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
1150 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
1151
1152 // Unique Pallets
1153 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
1154 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,
1155 Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
1156 // free = 63
1157 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
1158 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
1159 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
1160 Fungible: pallet_fungible::{Pallet, Storage} = 67,
1161 Refungible: pallet_refungible::{Pallet, Storage} = 68,
1162 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
1163 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
1164 RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,
1165 RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
1166
1167 // Frontier
1168 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
1169 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
1170
1171 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
1172 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
1173 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
1174 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
1175 }
1176);
1177
1178pub struct TransactionConverter;
1179
1180impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
1181 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
1182 UncheckedExtrinsic::new_unsigned(
1183 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1184 )
1185 }
1186}
1187
1188impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
1189 fn convert_transaction(
1190 &self,
1191 transaction: pallet_ethereum::Transaction,
1192 ) -> opaque::UncheckedExtrinsic {
1193 let extrinsic = UncheckedExtrinsic::new_unsigned(
1194 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1195 );
1196 let encoded = extrinsic.encode();
1197 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
1198 .expect("Encoded extrinsic is always valid")
1199 }
1200}
1201
1202/// The address format for describing accounts.
1203pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
1204/// Block header type as expected by this runtime.
1205pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
1206/// Block type as expected by this runtime.
1207pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1208/// A Block signed with a Justification
1209pub type SignedBlock = generic::SignedBlock<Block>;
1210/// BlockId type as expected by this runtime.
1211pub type BlockId = generic::BlockId<Block>;
1212/// The SignedExtension to the basic transaction logic.
1213pub type SignedExtra = (
1214 frame_system::CheckSpecVersion<Runtime>,
1215 // system::CheckTxVersion<Runtime>,
1216 frame_system::CheckGenesis<Runtime>,
1217 frame_system::CheckEra<Runtime>,
1218 frame_system::CheckNonce<Runtime>,
1219 frame_system::CheckWeight<Runtime>,
1220 ChargeTransactionPayment,
1221 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,
1222 pallet_ethereum::FakeTransactionFinalizer<Runtime>,
1223);
1224pub type SignedExtraScheduler = (
1225 frame_system::CheckSpecVersion<Runtime>,
1226 frame_system::CheckGenesis<Runtime>,
1227 frame_system::CheckEra<Runtime>,
1228 frame_system::CheckNonce<Runtime>,
1229 frame_system::CheckWeight<Runtime>,
1230);
1231/// Unchecked extrinsic type as expected by this runtime.
1232pub type UncheckedExtrinsic =
1233 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
1234/// Extrinsic type that has already been checked.
1235pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;
1236/// Executive: handles dispatch to the various modules.
1237pub type Executive = frame_executive::Executive<
1238 Runtime,
1239 Block,
1240 frame_system::ChainContext<Runtime>,
1241 Runtime,
1242 AllPalletsReversedWithSystemFirst,
1243>;
1244
1245impl_opaque_keys! {
1246 pub struct SessionKeys {
1247 pub aura: Aura,
1248 }
1249}
1250
1251impl fp_self_contained::SelfContainedCall for Call {
1252 type SignedInfo = H160;
1253
1254 fn is_self_contained(&self) -> bool {
1255 match self {
1256 Call::Ethereum(call) => call.is_self_contained(),
1257 _ => false,
1258 }
1259 }
1260
1261 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
1262 match self {
1263 Call::Ethereum(call) => call.check_self_contained(),
1264 _ => None,
1265 }
1266 }
1267
1268 fn validate_self_contained(
1269 &self,
1270 info: &Self::SignedInfo,
1271 dispatch_info: &DispatchInfoOf<Call>,
1272 len: usize,
1273 ) -> Option<TransactionValidity> {
1274 match self {
1275 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
1276 _ => None,
1277 }
1278 }
1279
1280 fn pre_dispatch_self_contained(
1281 &self,
1282 info: &Self::SignedInfo,
1283 ) -> Option<Result<(), TransactionValidityError>> {
1284 match self {
1285 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
1286 _ => None,
1287 }
1288 }
1289
1290 fn apply_self_contained(
1291 self,
1292 info: Self::SignedInfo,
1293 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
1294 match self {
1295 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(
1296 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),
1297 )),
1298 _ => None,
1299 }
1300 }
1301}
1302
1303macro_rules! dispatch_unique_runtime {
1304 ($collection:ident.$method:ident($($name:ident),*)) => {{
1305 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
1306 let dispatch = collection.as_dyn();
1307
1308 Ok::<_, DispatchError>(dispatch.$method($($name),*))
1309 }};
1310}
131162
1312impl_common_runtime_apis! {63impl_common_runtime_apis!();
1313 #![custom_apis]
1314
1315 impl rmrk_rpc::RmrkApi<
1316 Block,
1317 AccountId,
1318 RmrkCollectionInfo<AccountId>,
1319 RmrkInstanceInfo<AccountId>,
1320 RmrkResourceInfo,
1321 RmrkPropertyInfo,
1322 RmrkBaseInfo<AccountId>,
1323 RmrkPartType,
1324 RmrkTheme
1325 > for Runtime {
1326 fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
1327 pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>()
1328 }
1329
1330 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
1331 pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id)
1332 }
1333
1334 fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
1335 pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id)
1336 }
1337
1338 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
1339 pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id)
1340 }
1341
1342 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
1343 pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id)
1344 }
1345
1346 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
1347 pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys)
1348 }
1349
1350 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
1351 pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys)
1352 }
1353
1354 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
1355 pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id)
1356 }
1357
1358 fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {
1359 pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id)
1360 }
1361
1362 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
1363 pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id)
1364 }
1365
1366 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
1367 pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id)
1368 }
1369
1370 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
1371 pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id)
1372 }
1373
1374 fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
1375 pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys)
1376 }
1377 }
1378}
1379
1380struct CheckInherents;
1381
1382impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
1383 fn check_inherents(
1384 block: &Block,
1385 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
1386 ) -> sp_inherents::CheckInherentsResult {
1387 let relay_chain_slot = relay_state_proof
1388 .read_slot()
1389 .expect("Could not read the relay chain slot from the proof");
1390
1391 let inherent_data =
1392 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
1393 relay_chain_slot,
1394 sp_std::time::Duration::from_secs(6),
1395 )
1396 .create_inherent_data()
1397 .expect("Could not create the timestamp inherent data");
1398
1399 inherent_data.check_extrinsics(block)
1400 }
1401}
140264
1403cumulus_pallet_parachain_system::register_validate_block!(65cumulus_pallet_parachain_system::register_validate_block!(
1404 Runtime = Runtime,66 Runtime = Runtime,
modifiedruntime/quartz/Cargo.tomldiffbeforeafterboth
16targets = ['x86_64-unknown-linux-gnu']16targets = ['x86_64-unknown-linux-gnu']
1717
18[features]18[features]
19default = ['std']19default = ['std', 'quartz-runtime']
20runtime-benchmarks = [20runtime-benchmarks = [
21 'hex-literal',21 'hex-literal',
22 'frame-benchmarking',22 'frame-benchmarking',
113 'xcm/std',113 'xcm/std',
114 'xcm-builder/std',114 'xcm-builder/std',
115 'xcm-executor/std',115 'xcm-executor/std',
116 'unique-runtime-common/std',116 'up-common/std',
117117
118 "orml-vesting/std",118 "orml-vesting/std",
119]119]
120limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']120limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
121quartz-runtime = []
122
123refungible = []
124scheduler = []
125rmrk = []
121126
122################################################################################127################################################################################
123# Substrate Dependencies128# Substrate Dependencies
403408
404[dependencies]409[dependencies]
405log = { version = "0.4.16", default-features = false }410log = { version = "0.4.16", default-features = false }
406unique-runtime-common = { path = "../common", default-features = false }411up-common = { path = "../../primitives/common", default-features = false }
407scale-info = { version = "2.0.1", default-features = false, features = [412scale-info = { version = "2.0.1", default-features = false, features = [
408 "derive",413 "derive",
409] }414] }
432pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }437pallet-base-fee = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
433fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }438fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
434fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }439fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
440evm-coder = { default-features = false, path = '../../crates/evm-coder' }
441up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }
435442
436################################################################################443################################################################################
437# Build Dependencies444# Build Dependencies
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
25#[cfg(feature = "std")]25#[cfg(feature = "std")]
26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
2727
28use sp_api::impl_runtime_apis;28use frame_support::parameter_types;
29
29use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_version::RuntimeVersion;
30use sp_runtime::DispatchError;
31use fp_self_contained::*;
32// #[cfg(any(feature = "std", test))]
33// pub use sp_runtime::BuildStorage;
34
35use sp_runtime::{31use sp_runtime::create_runtime_str;
36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},
38 transaction_validity::{TransactionSource, TransactionValidity},
39 ApplyExtrinsicResult, RuntimeAppPublic,
40};
4132
42use sp_std::prelude::*;33use up_common::types::*;
4334
44#[cfg(feature = "std")]35#[path = "../../common/mod.rs"]
45use sp_version::NativeVersion;36mod runtime_common;
46use sp_version::RuntimeVersion;37
47pub use pallet_transaction_payment::{38pub use runtime_common::*;
48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,
49};
50// A few exports that help ease life for downstream crates.
51pub use pallet_balances::Call as BalancesCall;
52pub use pallet_evm::{
53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,
54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,
55};
56pub use frame_support::{
57 construct_runtime, match_types,
58 dispatch::DispatchResult,
59 PalletId, parameter_types, StorageValue, ConsensusEngineId,
60 traits::{
61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,
62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,
63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,
64 },
65 weights::{
66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,
69 WeightToFee,
70 },
71};
72use pallet_unique_scheduler::DispatchCall;
73use up_data_structs::{
74 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,
75 CollectionStats, RpcCollection,
76 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
77 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,
78 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,
79 RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,
80};
81
82// use pallet_contracts::weights::WeightInfo;
83// #[cfg(any(feature = "std", test))]
84use frame_system::{
85 self as frame_system, EnsureRoot, EnsureSigned,
86 limits::{BlockWeights, BlockLength},
87};
88use sp_arithmetic::{
89 traits::{BaseArithmetic, Unsigned},
90};
91use smallvec::smallvec;
92use codec::{Encode, Decode};
93use fp_rpc::TransactionStatus;
94use sp_runtime::{
95 traits::{
96 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,
97 Saturating, CheckedConversion,
98 },
99 generic::Era,
100 transaction_validity::TransactionValidityError,
101 DispatchErrorWithPostInfo, SaturatedConversion,
102};
103
104// pub use pallet_timestamp::Call as TimestampCall;
105pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
106
107// Polkadot imports
108use pallet_xcm::XcmPassthrough;
109use polkadot_parachain::primitives::Sibling;
110use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
111use xcm_builder::{
112 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
113 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,
114 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
115 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
116 ParentIsPreset,
117};
118use xcm_executor::{Config, XcmExecutor, Assets};
119use sp_std::{cmp::Ordering, marker::PhantomData};
120
121use xcm::latest::{
122 // Xcm,
123 AssetId::{Concrete},
124 Fungibility::Fungible as XcmFungible,
125 MultiAsset,
126 Error as XcmError,
127};
128use xcm_executor::traits::{MatchesFungible, WeightTrader};
129
130use unique_runtime_common::{
131 impl_common_runtime_apis,
132 types::*,
133 constants::*,
134 dispatch::{CollectionDispatchT, CollectionDispatch},
135 sponsoring::UniqueSponsorshipHandler,
136 eth_sponsoring::UniqueEthSponsorshipHandler,
137 weights::CommonWeights,
138};
13939
140pub const RUNTIME_NAME: &str = "quartz";40pub const RUNTIME_NAME: &str = "quartz";
141pub const TOKEN_SYMBOL: &str = "QTZ";41pub const TOKEN_SYMBOL: &str = "QTZ";
142
143type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
144
145impl RuntimeInstance for Runtime {
146 type CrossAccountId = self::CrossAccountId;
147
148 type TransactionConverter = self::TransactionConverter;
149
150 fn get_transaction_converter() -> TransactionConverter {
151 TransactionConverter
152 }
153}
154
155/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
156/// never know...
157pub type AccountIndex = u32;
158
159/// Balance of an account.
160pub type Balance = u128;
161
162/// Index of a transaction in the chain.
163pub type Index = u32;
164
165/// A hash of some data used by the chain.
166pub type Hash = sp_core::H256;
167
168/// Digest item type.
169pub type DigestItem = generic::DigestItem;
170
171/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
172/// the specifics of the runtime. They can then be made to be agnostic over specific formats
173/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
174/// to even the core data structures.
175pub mod opaque {
176 use sp_std::prelude::*;
177 use sp_runtime::impl_opaque_keys;
178 use super::Aura;
179
180 pub use unique_runtime_common::types::*;
181
182 impl_opaque_keys! {
183 pub struct SessionKeys {
184 pub aura: Aura,
185 }
186 }
187}
18842
189/// This runtime version.43/// This runtime version.
190pub const VERSION: RuntimeVersion = RuntimeVersion {44pub const VERSION: RuntimeVersion = RuntimeVersion {
198 state_version: 0,52 state_version: 0,
199};53};
200
201#[derive(codec::Encode, codec::Decode)]
202pub enum XCMPMessage<XAccountId, XBalance> {
203 /// Transfer tokens to the given account from the Parachain account.
204 TransferToken(XAccountId, XBalance),
205}
206
207/// The version information used to identify this runtime when compiled natively.
208#[cfg(feature = "std")]
209pub fn native_version() -> NativeVersion {
210 NativeVersion {
211 runtime_version: VERSION,
212 can_author_with: Default::default(),
213 }
214}
215
216type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
217
218pub struct DealWithFees;
219impl OnUnbalanced<NegativeImbalance> for DealWithFees {
220 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
221 if let Some(fees) = fees_then_tips.next() {
222 // for fees, 100% to treasury
223 let mut split = fees.ration(100, 0);
224 if let Some(tips) = fees_then_tips.next() {
225 // for tips, if any, 100% to treasury
226 tips.ration_merge_into(100, 0, &mut split);
227 }
228 Treasury::on_unbalanced(split.0);
229 // Author::on_unbalanced(split.1);
230 }
231 }
232}
23354
234parameter_types! {55parameter_types! {
235 pub const BlockHashCount: BlockNumber = 2400;
236 pub RuntimeBlockLength: BlockLength =
237 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
238 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
239 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
240 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
241 .base_block(BlockExecutionWeight::get())
242 .for_class(DispatchClass::all(), |weights| {
243 weights.base_extrinsic = ExtrinsicBaseWeight::get();
244 })
245 .for_class(DispatchClass::Normal, |weights| {
246 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
247 })
248 .for_class(DispatchClass::Operational, |weights| {
249 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
250 // Operational transactions have some extra reserved space, so that they
251 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
252 weights.reserved = Some(
253 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
254 );
255 })
256 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
257 .build_or_panic();
258 pub const Version: RuntimeVersion = VERSION;56 pub const Version: RuntimeVersion = VERSION;
259 pub const SS58Prefix: u8 = 255;57 pub const SS58Prefix: u8 = 255;
260}
261
262parameter_types! {
263 pub const ChainId: u64 = 8881;58 pub const ChainId: u64 = 8881;
264}59}
265
266pub struct FixedFee;
267impl FeeCalculator for FixedFee {
268 fn min_gas_price() -> (U256, u64) {
269 (MIN_GAS_PRICE.into(), 0)
270 }
271}
272
273// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
274// (contract, which only writes a lot of data),
275// approximating on top of our real store write weight
276parameter_types! {
277 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
278 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
279 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
280}
281
282/// Limiting EVM execution to 50% of block for substrate users and management tasks
283/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
284/// scheduled fairly
285const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
286parameter_types! {
287 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
288}
289
290pub enum FixedGasWeightMapping {}
291impl GasWeightMapping for FixedGasWeightMapping {
292 fn gas_to_weight(gas: u64) -> Weight {
293 gas.saturating_mul(WeightPerGas::get())
294 }
295 fn weight_to_gas(weight: Weight) -> u64 {
296 weight / WeightPerGas::get()
297 }
298}
299
300impl pallet_evm::account::Config for Runtime {
301 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;
302 type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;
303 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
304}
305
306impl pallet_evm::Config for Runtime {
307 type BlockGasLimit = BlockGasLimit;
308 type FeeCalculator = FixedFee;
309 type GasWeightMapping = FixedGasWeightMapping;
310 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
311 type CallOrigin = EnsureAddressTruncated<Self>;
312 type WithdrawOrigin = EnsureAddressTruncated<Self>;
313 type AddressMapping = HashedAddressMapping<Self::Hashing>;
314 type PrecompilesType = ();
315 type PrecompilesValue = ();
316 type Currency = Balances;
317 type Event = Event;
318 type OnMethodCall = (
319 pallet_evm_migration::OnMethodCall<Self>,
320 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
321 CollectionDispatchT<Self>,
322 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
323 );
324 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
325 type ChainId = ChainId;
326 type Runner = pallet_evm::runner::stack::Runner<Self>;
327 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
328 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
329 type FindAuthor = EthereumFindAuthor<Aura>;
330}
331
332impl pallet_evm_migration::Config for Runtime {
333 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
334}
335
336pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
337impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {
338 fn find_author<'a, I>(digests: I) -> Option<H160>
339 where
340 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
341 {
342 if let Some(author_index) = F::find_author(digests) {
343 let authority_id = Aura::authorities()[author_index as usize].clone();
344 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
345 }
346 None
347 }
348}
349
350impl pallet_ethereum::Config for Runtime {
351 type Event = Event;
352 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
353}
354
355impl pallet_randomness_collective_flip::Config for Runtime {}
356
357impl frame_system::Config for Runtime {
358 /// The data to be stored in an account.
359 type AccountData = pallet_balances::AccountData<Balance>;
360 /// The identifier used to distinguish between accounts.
361 type AccountId = AccountId;
362 /// The basic call filter to use in dispatchable.
363 type BaseCallFilter = Everything;
364 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
365 type BlockHashCount = BlockHashCount;
366 /// The maximum length of a block (in bytes).
367 type BlockLength = RuntimeBlockLength;
368 /// The index type for blocks.
369 type BlockNumber = BlockNumber;
370 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.
371 type BlockWeights = RuntimeBlockWeights;
372 /// The aggregated dispatch type that is available for extrinsics.
373 type Call = Call;
374 /// The weight of database operations that the runtime can invoke.
375 type DbWeight = RocksDbWeight;
376 /// The ubiquitous event type.
377 type Event = Event;
378 /// The type for hashing blocks and tries.
379 type Hash = Hash;
380 /// The hashing algorithm used.
381 type Hashing = BlakeTwo256;
382 /// The header type.
383 type Header = generic::Header<BlockNumber, BlakeTwo256>;
384 /// The index type for storing how many extrinsics an account has signed.
385 type Index = Index;
386 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
387 type Lookup = AccountIdLookup<AccountId, ()>;
388 /// What to do if an account is fully reaped from the system.
389 type OnKilledAccount = ();
390 /// What to do if a new account is created.
391 type OnNewAccount = ();
392 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
393 /// The ubiquitous origin type.
394 type Origin = Origin;
395 /// This type is being generated by `construct_runtime!`.
396 type PalletInfo = PalletInfo;
397 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
398 type SS58Prefix = SS58Prefix;
399 /// Weight information for the extrinsics of this pallet.
400 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;
401 /// Version of the runtime.
402 type Version = Version;
403 type MaxConsumers = ConstU32<16>;
404}
405
406parameter_types! {
407 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
408}
409
410impl pallet_timestamp::Config for Runtime {
411 /// A timestamp: milliseconds since the unix epoch.
412 type Moment = u64;
413 type OnTimestampSet = ();
414 type MinimumPeriod = MinimumPeriod;
415 type WeightInfo = ();
416}
417
418parameter_types! {
419 // pub const ExistentialDeposit: u128 = 500;
420 pub const ExistentialDeposit: u128 = 0;
421 pub const MaxLocks: u32 = 50;
422 pub const MaxReserves: u32 = 50;
423}
424
425impl pallet_balances::Config for Runtime {
426 type MaxLocks = MaxLocks;
427 type MaxReserves = MaxReserves;
428 type ReserveIdentifier = [u8; 16];
429 /// The type for recording an account's balance.
430 type Balance = Balance;
431 /// The ubiquitous event type.
432 type Event = Event;
433 type DustRemoval = Treasury;
434 type ExistentialDeposit = ExistentialDeposit;
435 type AccountStore = System;
436 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
437}
438
439pub const fn deposit(items: u32, bytes: u32) -> Balance {
440 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE
441}
442
443/*
444parameter_types! {
445 pub TombstoneDeposit: Balance = deposit(
446 1,
447 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,
448 );
449 pub DepositPerContract: Balance = TombstoneDeposit::get();
450 pub const DepositPerStorageByte: Balance = deposit(0, 1);
451 pub const DepositPerStorageItem: Balance = deposit(1, 0);
452 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
453 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;
454 pub const SignedClaimHandicap: u32 = 2;
455 pub const MaxDepth: u32 = 32;
456 pub const MaxValueSize: u32 = 16 * 1024;
457 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb
458 // The lazy deletion runs inside on_initialize.
459 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
460 RuntimeBlockWeights::get().max_block;
461 // The weight needed for decoding the queue should be less or equal than a fifth
462 // of the overall weight dedicated to the lazy deletion.
463 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
464 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
465 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
466 )) / 5) as u32;
467 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
468}
469
470impl pallet_contracts::Config for Runtime {
471 type Time = Timestamp;
472 type Randomness = RandomnessCollectiveFlip;
473 type Currency = Balances;
474 type Event = Event;
475 type RentPayment = ();
476 type SignedClaimHandicap = SignedClaimHandicap;
477 type TombstoneDeposit = TombstoneDeposit;
478 type DepositPerContract = DepositPerContract;
479 type DepositPerStorageByte = DepositPerStorageByte;
480 type DepositPerStorageItem = DepositPerStorageItem;
481 type RentFraction = RentFraction;
482 type SurchargeReward = SurchargeReward;
483 type WeightPrice = pallet_transaction_payment::Pallet<Self>;
484 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
485 type ChainExtension = NFTExtension;
486 type DeletionQueueDepth = DeletionQueueDepth;
487 type DeletionWeightLimit = DeletionWeightLimit;
488 type Schedule = Schedule;
489 type CallStack = [pallet_contracts::Frame<Self>; 31];
490}
491*/
492
493parameter_types! {
494 /// This value increases the priority of `Operational` transactions by adding
495 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
496 pub const OperationalFeeMultiplier: u8 = 5;
497}
498
499/// Linear implementor of `WeightToFeePolynomial`
500pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);
501
502impl<T> WeightToFeePolynomial for LinearFee<T>
503where
504 T: BaseArithmetic + From<u32> + Copy + Unsigned,
505{
506 type Balance = T;
507
508 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
509 smallvec!(WeightToFeeCoefficient {
510 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),
511 coeff_frac: Perbill::zero(),
512 negative: false,
513 degree: 1,
514 })
515 }
516}
517
518impl pallet_transaction_payment::Config for Runtime {
519 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;
520 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
521 type OperationalFeeMultiplier = OperationalFeeMultiplier;
522 type WeightToFee = LinearFee<Balance>;
523 type FeeMultiplierUpdate = ();
524}
525
526parameter_types! {
527 pub const ProposalBond: Permill = Permill::from_percent(5);
528 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;
529 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;
530 pub const SpendPeriod: BlockNumber = 5 * MINUTES;
531 pub const Burn: Permill = Permill::from_percent(0);
532 pub const TipCountdown: BlockNumber = 1 * DAYS;
533 pub const TipFindersFee: Percent = Percent::from_percent(20);
534 pub const TipReportDepositBase: Balance = 1 * UNIQUE;
535 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;
536 pub const BountyDepositBase: Balance = 1 * UNIQUE;
537 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
538 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");
539 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
540 pub const MaximumReasonLength: u32 = 16384;
541 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
542 pub const BountyValueMinimum: Balance = 5 * UNIQUE;
543 pub const MaxApprovals: u32 = 100;
544}
545
546impl pallet_treasury::Config for Runtime {
547 type PalletId = TreasuryModuleId;
548 type Currency = Balances;
549 type ApproveOrigin = EnsureRoot<AccountId>;
550 type RejectOrigin = EnsureRoot<AccountId>;
551 type Event = Event;
552 type OnSlash = ();
553 type ProposalBond = ProposalBond;
554 type ProposalBondMinimum = ProposalBondMinimum;
555 type ProposalBondMaximum = ProposalBondMaximum;
556 type SpendPeriod = SpendPeriod;
557 type Burn = Burn;
558 type BurnDestination = ();
559 type SpendFunds = ();
560 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
561 type MaxApprovals = MaxApprovals;
562}
563
564impl pallet_sudo::Config for Runtime {
565 type Event = Event;
566 type Call = Call;
567}
568
569pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);
570
571impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider
572 for RelayChainBlockNumberProvider<T>
573{
574 type BlockNumber = BlockNumber;
575
576 fn current_block_number() -> Self::BlockNumber {
577 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()
578 .map(|d| d.relay_parent_number)
579 .unwrap_or_default()
580 }
581}
582
583parameter_types! {
584 pub const MinVestedTransfer: Balance = 10 * UNIQUE;
585 pub const MaxVestingSchedules: u32 = 28;
586}
587
588impl orml_vesting::Config for Runtime {
589 type Event = Event;
590 type Currency = pallet_balances::Pallet<Runtime>;
591 type MinVestedTransfer = MinVestedTransfer;
592 type VestedTransferOrigin = EnsureSigned<AccountId>;
593 type WeightInfo = ();
594 type MaxVestingSchedules = MaxVestingSchedules;
595 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
596}
597
598parameter_types! {
599 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
600 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
601}
602
603impl cumulus_pallet_parachain_system::Config for Runtime {
604 type Event = Event;
605 type SelfParaId = parachain_info::Pallet<Self>;
606 type OnSystemEvent = ();
607 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
608 // MaxDownwardMessageWeight,
609 // XcmExecutor<XcmConfig>,
610 // Call,
611 // >;
612 type OutboundXcmpMessageSource = XcmpQueue;
613 type DmpMessageHandler = DmpQueue;
614 type ReservedDmpWeight = ReservedDmpWeight;
615 type ReservedXcmpWeight = ReservedXcmpWeight;
616 type XcmpMessageHandler = XcmpQueue;
617}
618
619impl parachain_info::Config for Runtime {}
620
621impl cumulus_pallet_aura_ext::Config for Runtime {}
622
623parameter_types! {
624 pub const RelayLocation: MultiLocation = MultiLocation::parent();
625 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
626 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
627 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
628}
629
630/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
631/// when determining ownership of accounts for asset transacting and when attempting to use XCM
632/// `Transact` in order to determine the dispatch Origin.
633pub type LocationToAccountId = (
634 // The parent (Relay-chain) origin converts to the default `AccountId`.
635 ParentIsPreset<AccountId>,
636 // Sibling parachain origins convert to AccountId via the `ParaId::into`.
637 SiblingParachainConvertsVia<Sibling, AccountId>,
638 // Straight up local `AccountId32` origins just alias directly to `AccountId`.
639 AccountId32Aliases<RelayNetwork, AccountId>,
640);
641
642pub struct OnlySelfCurrency;
643impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
644 fn matches_fungible(a: &MultiAsset) -> Option<B> {
645 match (&a.id, &a.fun) {
646 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
647 _ => None,
648 }
649 }
650}
651
652/// Means for transacting assets on this chain.
653pub type LocalAssetTransactor = CurrencyAdapter<
654 // Use this currency:
655 Balances,
656 // Use this currency when it is a fungible asset matching the given location or name:
657 OnlySelfCurrency,
658 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
659 LocationToAccountId,
660 // Our chain's account ID type (we can't get away without mentioning it explicitly):
661 AccountId,
662 // We don't track any teleports.
663 (),
664>;
665
666/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
667/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
668/// biases the kind of local `Origin` it will become.
669pub type XcmOriginToTransactDispatchOrigin = (
670 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
671 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
672 // foreign chains who want to have a local sovereign account on this chain which they control.
673 SovereignSignedViaLocation<LocationToAccountId, Origin>,
674 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
675 // recognised.
676 RelayChainAsNative<RelayOrigin, Origin>,
677 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
678 // recognised.
679 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
680 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
681 // transaction from the Root origin.
682 ParentAsSuperuser<Origin>,
683 // Native signed account converter; this just converts an `AccountId32` origin into a normal
684 // `Origin::Signed` origin of the same 32-byte value.
685 SignedAccountId32AsNative<RelayNetwork, Origin>,
686 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
687 XcmPassthrough<Origin>,
688);
689
690parameter_types! {
691 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
692 pub UnitWeightCost: Weight = 1_000_000;
693 // 1200 UNIQUEs buy 1 second of weight.
694 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);
695 pub const MaxInstructions: u32 = 100;
696 pub const MaxAuthorities: u32 = 100_000;
697}
698
699match_types! {
700 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
701 MultiLocation { parents: 1, interior: Here } |
702 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
703 };
704}
705
706pub type Barrier = (
707 TakeWeightCredit,
708 AllowTopLevelPaidExecutionFrom<Everything>,
709 // ^^^ Parent & its unit plurality gets free execution
710);
711
712pub struct UsingOnlySelfCurrencyComponents<
713 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
714 AssetId: Get<MultiLocation>,
715 AccountId,
716 Currency: CurrencyT<AccountId>,
717 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
718>(
719 Weight,
720 Currency::Balance,
721 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
722);
723impl<
724 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
725 AssetId: Get<MultiLocation>,
726 AccountId,
727 Currency: CurrencyT<AccountId>,
728 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
729 > WeightTrader
730 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
731{
732 fn new() -> Self {
733 Self(0, Zero::zero(), PhantomData)
734 }
735
736 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
737 let amount = WeightToFee::weight_to_fee(&weight);
738 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
739
740 // location to this parachain through relay chain
741 let option1: xcm::v1::AssetId = Concrete(MultiLocation {
742 parents: 1,
743 interior: X1(Parachain(ParachainInfo::parachain_id().into())),
744 });
745 // direct location
746 let option2: xcm::v1::AssetId = Concrete(MultiLocation {
747 parents: 0,
748 interior: Here,
749 });
750
751 let required = if payment.fungible.contains_key(&option1) {
752 (option1, u128_amount).into()
753 } else if payment.fungible.contains_key(&option2) {
754 (option2, u128_amount).into()
755 } else {
756 (Concrete(MultiLocation::default()), u128_amount).into()
757 };
758
759 let unused = payment
760 .checked_sub(required)
761 .map_err(|_| XcmError::TooExpensive)?;
762 self.0 = self.0.saturating_add(weight);
763 self.1 = self.1.saturating_add(amount);
764 Ok(unused)
765 }
766
767 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
768 let weight = weight.min(self.0);
769 let amount = WeightToFee::weight_to_fee(&weight);
770 self.0 -= weight;
771 self.1 = self.1.saturating_sub(amount);
772 let amount: u128 = amount.saturated_into();
773 if amount > 0 {
774 Some((AssetId::get(), amount).into())
775 } else {
776 None
777 }
778 }
779}
780impl<
781 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
782 AssetId: Get<MultiLocation>,
783 AccountId,
784 Currency: CurrencyT<AccountId>,
785 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
786 > Drop
787 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
788{
789 fn drop(&mut self) {
790 OnUnbalanced::on_unbalanced(Currency::issue(self.1));
791 }
792}
793
794pub struct XcmConfig;
795impl Config for XcmConfig {
796 type Call = Call;
797 type XcmSender = XcmRouter;
798 // How to withdraw and deposit an asset.
799 type AssetTransactor = LocalAssetTransactor;
800 type OriginConverter = XcmOriginToTransactDispatchOrigin;
801 type IsReserve = NativeAsset;
802 type IsTeleporter = (); // Teleportation is disabled
803 type LocationInverter = LocationInverter<Ancestry>;
804 type Barrier = Barrier;
805 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
806 type Trader =
807 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;
808 type ResponseHandler = (); // Don't handle responses for now.
809 type SubscriptionService = PolkadotXcm;
810
811 type AssetTrap = PolkadotXcm;
812 type AssetClaims = PolkadotXcm;
813}
814
815// parameter_types! {
816// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
817// }
818
819/// No local origins on this chain are allowed to dispatch XCM sends/executions.
820pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);
821
822/// The means for routing XCM messages which are not for local execution into the right message
823/// queues.
824pub type XcmRouter = (
825 // Two routers - use UMP to communicate with the relay chain:
826 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
827 // ..and XCMP to communicate with the sibling chains.
828 XcmpQueue,
829);
830
831impl pallet_evm_coder_substrate::Config for Runtime {}
832
833impl pallet_xcm::Config for Runtime {
834 type Event = Event;
835 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
836 type XcmRouter = XcmRouter;
837 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
838 type XcmExecuteFilter = Everything;
839 type XcmExecutor = XcmExecutor<XcmConfig>;
840 type XcmTeleportFilter = Everything;
841 type XcmReserveTransferFilter = Everything;
842 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
843 type LocationInverter = LocationInverter<Ancestry>;
844 type Origin = Origin;
845 type Call = Call;
846 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
847 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
848}
849
850impl cumulus_pallet_xcm::Config for Runtime {
851 type Event = Event;
852 type XcmExecutor = XcmExecutor<XcmConfig>;
853}
854
855impl cumulus_pallet_xcmp_queue::Config for Runtime {
856 type WeightInfo = ();
857 type Event = Event;
858 type XcmExecutor = XcmExecutor<XcmConfig>;
859 type ChannelInfo = ParachainSystem;
860 type VersionWrapper = ();
861 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
862 type ControllerOrigin = EnsureRoot<AccountId>;
863 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
864}
865
866impl cumulus_pallet_dmp_queue::Config for Runtime {
867 type Event = Event;
868 type XcmExecutor = XcmExecutor<XcmConfig>;
869 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
870}
871
872impl pallet_aura::Config for Runtime {
873 type AuthorityId = AuraId;
874 type DisabledValidators = ();
875 type MaxAuthorities = MaxAuthorities;
876}
877
878parameter_types! {
879 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
880 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
881}
882
883impl pallet_common::Config for Runtime {
884 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;
885 type Event = Event;
886 type Currency = Balances;
887 type CollectionCreationPrice = CollectionCreationPrice;
888 type TreasuryAccountId = TreasuryAccountId;
889 type CollectionDispatch = CollectionDispatchT<Self>;
890
891 type EvmTokenAddressMapping = EvmTokenAddressMapping;
892 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
893 type ContractAddress = EvmCollectionHelpersAddress;
894}
895
896impl pallet_structure::Config for Runtime {
897 type Event = Event;
898 type Call = Call;
899 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;
900}
901
902impl pallet_fungible::Config for Runtime {
903 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;
904}
905impl pallet_refungible::Config for Runtime {
906 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;
907}
908impl pallet_nonfungible::Config for Runtime {
909 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
910}
911
912impl pallet_proxy_rmrk_core::Config for Runtime {
913 type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
914 type Event = Event;
915}
916
917impl pallet_proxy_rmrk_equip::Config for Runtime {
918 type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;
919 type Event = Event;
920}
921
922impl pallet_unique::Config for Runtime {
923 type Event = Event;
924 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
925 type CommonWeightInfo = CommonWeights<Self>;
926 type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
927}
928
929parameter_types! {
930 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied
931}
932
933/// Used for the pallet inflation
934impl pallet_inflation::Config for Runtime {
935 type Currency = Balances;
936 type TreasuryAccountId = TreasuryAccountId;
937 type InflationBlockInterval = InflationBlockInterval;
938 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
939}
940
941parameter_types! {
942 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *
943 RuntimeBlockWeights::get().max_block;
944 pub const MaxScheduledPerBlock: u32 = 50;
945}
946
947type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
948use frame_support::traits::NamedReservableCurrency;
949
950fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
951 (
952 frame_system::CheckSpecVersion::<Runtime>::new(),
953 frame_system::CheckGenesis::<Runtime>::new(),
954 frame_system::CheckEra::<Runtime>::from(Era::Immortal),
955 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
956 from,
957 )),
958 frame_system::CheckWeight::<Runtime>::new(),
959 // sponsoring transaction logic
960 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
961 )
962}
963
964pub struct SchedulerPaymentExecutor;
965impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
966 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
967where
968 <T as frame_system::Config>::Call: Member
969 + Dispatchable<Origin = Origin, Info = DispatchInfo>
970 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
971 + GetDispatchInfo
972 + From<frame_system::Call<Runtime>>,
973 SelfContainedSignedInfo: Send + Sync + 'static,
974 Call: From<<T as frame_system::Config>::Call>
975 + From<<T as pallet_unique_scheduler::Config>::Call>
976 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
977 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
978{
979 fn dispatch_call(
980 signer: <T as frame_system::Config>::AccountId,
981 call: <T as pallet_unique_scheduler::Config>::Call,
982 ) -> Result<
983 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
984 TransactionValidityError,
985 > {
986 let dispatch_info = call.get_dispatch_info();
987 let extrinsic = fp_self_contained::CheckedExtrinsic::<
988 AccountId,
989 Call,
990 SignedExtraScheduler,
991 SelfContainedSignedInfo,
992 > {
993 signed:
994 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
995 signer.clone().into(),
996 get_signed_extras(signer.into()),
997 ),
998 function: call.into(),
999 };
1000
1001 extrinsic.apply::<Runtime>(&dispatch_info, 0)
1002 }
1003
1004 fn reserve_balance(
1005 id: [u8; 16],
1006 sponsor: <T as frame_system::Config>::AccountId,
1007 call: <T as pallet_unique_scheduler::Config>::Call,
1008 count: u32,
1009 ) -> Result<(), DispatchError> {
1010 let dispatch_info = call.get_dispatch_info();
1011 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
1012 .saturating_mul(count.into());
1013
1014 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
1015 &id,
1016 &(sponsor.into()),
1017 weight.into(),
1018 )
1019 }
1020
1021 fn pay_for_call(
1022 id: [u8; 16],
1023 sponsor: <T as frame_system::Config>::AccountId,
1024 call: <T as pallet_unique_scheduler::Config>::Call,
1025 ) -> Result<u128, DispatchError> {
1026 let dispatch_info = call.get_dispatch_info();
1027 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
1028 Ok(
1029 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
1030 &id,
1031 &(sponsor.into()),
1032 weight.into(),
1033 ),
1034 )
1035 }
1036
1037 fn cancel_reserve(
1038 id: [u8; 16],
1039 sponsor: <T as frame_system::Config>::AccountId,
1040 ) -> Result<u128, DispatchError> {
1041 Ok(
1042 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
1043 &id,
1044 &(sponsor.into()),
1045 u128::MAX,
1046 ),
1047 )
1048 }
1049}
1050
1051parameter_types! {
1052 pub const NoPreimagePostponement: Option<u32> = Some(10);
1053 pub const Preimage: Option<u32> = Some(10);
1054}
1055
1056/// Used the compare the privilege of an origin inside the scheduler.
1057pub struct OriginPrivilegeCmp;
1058
1059impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
1060 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {
1061 Some(Ordering::Equal)
1062 }
1063}
1064
1065impl pallet_unique_scheduler::Config for Runtime {
1066 type Event = Event;
1067 type Origin = Origin;
1068 type Currency = Balances;
1069 type PalletsOrigin = OriginCaller;
1070 type Call = Call;
1071 type MaximumWeight = MaximumSchedulerWeight;
1072 type ScheduleOrigin = EnsureSigned<AccountId>;
1073 type MaxScheduledPerBlock = MaxScheduledPerBlock;
1074 type WeightInfo = ();
1075 type CallExecutor = SchedulerPaymentExecutor;
1076 type OriginPrivilegeCmp = OriginPrivilegeCmp;
1077 type PreimageProvider = ();
1078 type NoPreimagePostponement = NoPreimagePostponement;
1079}
1080
1081type EvmSponsorshipHandler = (
1082 UniqueEthSponsorshipHandler<Runtime>,
1083 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
1084);
1085type SponsorshipHandler = (
1086 UniqueSponsorshipHandler<Runtime>,
1087 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
1088 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
1089);
1090
1091impl pallet_evm_transaction_payment::Config for Runtime {
1092 type EvmSponsorshipHandler = EvmSponsorshipHandler;
1093 type Currency = Balances;
1094}
1095
1096impl pallet_charge_transaction::Config for Runtime {
1097 type SponsorshipHandler = SponsorshipHandler;
1098}
1099
1100// impl pallet_contract_helpers::Config for Runtime {
1101// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
1102// }
1103
1104parameter_types! {
1105 // 0x842899ECF380553E8a4de75bF534cdf6fBF64049
1106 pub const HelpersContractAddress: H160 = H160([
1107 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
1108 ]);
1109
1110 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
1111 pub const EvmCollectionHelpersAddress: H160 = H160([
1112 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
1113 ]);
1114}
1115
1116impl pallet_evm_contract_helpers::Config for Runtime {
1117 type ContractAddress = HelpersContractAddress;
1118 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
1119}
112060
1121construct_runtime!(61construct_runtime!(quartz);
1122 pub enum Runtime where
1123 Block = Block,
1124 NodeBlock = opaque::Block,
1125 UncheckedExtrinsic = UncheckedExtrinsic
1126 {
1127 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
1128 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
1129
1130 Aura: pallet_aura::{Pallet, Config<T>} = 22,
1131 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
1132
1133 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
1134 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
1135 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
1136 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
1137 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
1138 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
1139 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,
1140 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,
1141 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
1142 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
1143
1144 // XCM helpers.
1145 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
1146 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
1147 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
1148 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
1149
1150 // Unique Pallets
1151 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
1152 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,
1153 Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
1154 // free = 63
1155 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
1156 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
1157 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
1158 Fungible: pallet_fungible::{Pallet, Storage} = 67,
1159 Refungible: pallet_refungible::{Pallet, Storage} = 68,
1160 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
1161 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
1162 RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,
1163 RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
1164
1165 // Frontier
1166 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
1167 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
1168
1169 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
1170 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
1171 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
1172 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
1173 }
1174);
1175
1176pub struct TransactionConverter;
1177
1178impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
1179 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
1180 UncheckedExtrinsic::new_unsigned(
1181 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1182 )
1183 }
1184}
1185
1186impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
1187 fn convert_transaction(
1188 &self,
1189 transaction: pallet_ethereum::Transaction,
1190 ) -> opaque::UncheckedExtrinsic {
1191 let extrinsic = UncheckedExtrinsic::new_unsigned(
1192 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1193 );
1194 let encoded = extrinsic.encode();
1195 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
1196 .expect("Encoded extrinsic is always valid")
1197 }
1198}
1199
1200/// The address format for describing accounts.
1201pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
1202/// Block header type as expected by this runtime.
1203pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
1204/// Block type as expected by this runtime.
1205pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1206/// A Block signed with a Justification
1207pub type SignedBlock = generic::SignedBlock<Block>;
1208/// BlockId type as expected by this runtime.
1209pub type BlockId = generic::BlockId<Block>;
1210/// The SignedExtension to the basic transaction logic.
1211pub type SignedExtra = (
1212 frame_system::CheckSpecVersion<Runtime>,
1213 // system::CheckTxVersion<Runtime>,
1214 frame_system::CheckGenesis<Runtime>,
1215 frame_system::CheckEra<Runtime>,
1216 frame_system::CheckNonce<Runtime>,
1217 frame_system::CheckWeight<Runtime>,
1218 ChargeTransactionPayment,
1219 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,
1220 pallet_ethereum::FakeTransactionFinalizer<Runtime>,
1221);
1222
1223pub type SignedExtraScheduler = (
1224 frame_system::CheckSpecVersion<Runtime>,
1225 frame_system::CheckGenesis<Runtime>,
1226 frame_system::CheckEra<Runtime>,
1227 frame_system::CheckNonce<Runtime>,
1228 frame_system::CheckWeight<Runtime>,
1229 // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
1230);
1231/// Unchecked extrinsic type as expected by this runtime.
1232pub type UncheckedExtrinsic =
1233 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
1234/// Extrinsic type that has already been checked.
1235pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;
1236/// Executive: handles dispatch to the various modules.
1237pub type Executive = frame_executive::Executive<
1238 Runtime,
1239 Block,
1240 frame_system::ChainContext<Runtime>,
1241 Runtime,
1242 AllPalletsReversedWithSystemFirst,
1243>;
1244
1245impl_opaque_keys! {
1246 pub struct SessionKeys {
1247 pub aura: Aura,
1248 }
1249}
1250
1251impl fp_self_contained::SelfContainedCall for Call {
1252 type SignedInfo = H160;
1253
1254 fn is_self_contained(&self) -> bool {
1255 match self {
1256 Call::Ethereum(call) => call.is_self_contained(),
1257 _ => false,
1258 }
1259 }
1260
1261 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
1262 match self {
1263 Call::Ethereum(call) => call.check_self_contained(),
1264 _ => None,
1265 }
1266 }
1267
1268 fn validate_self_contained(
1269 &self,
1270 info: &Self::SignedInfo,
1271 dispatch_info: &DispatchInfoOf<Call>,
1272 len: usize,
1273 ) -> Option<TransactionValidity> {
1274 match self {
1275 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
1276 _ => None,
1277 }
1278 }
1279
1280 fn pre_dispatch_self_contained(
1281 &self,
1282 info: &Self::SignedInfo,
1283 ) -> Option<Result<(), TransactionValidityError>> {
1284 match self {
1285 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
1286 _ => None,
1287 }
1288 }
1289
1290 fn apply_self_contained(
1291 self,
1292 info: Self::SignedInfo,
1293 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
1294 match self {
1295 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(
1296 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),
1297 )),
1298 _ => None,
1299 }
1300 }
1301}
1302
1303macro_rules! dispatch_unique_runtime {
1304 ($collection:ident.$method:ident($($name:ident),*)) => {{
1305 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
1306 let dispatch = collection.as_dyn();
1307
1308 Ok::<_, DispatchError>(dispatch.$method($($name),*))
1309 }};
1310}
131162
1312impl_common_runtime_apis! {63impl_common_runtime_apis!();
1313 #![custom_apis]
1314
1315 impl rmrk_rpc::RmrkApi<
1316 Block,
1317 AccountId,
1318 RmrkCollectionInfo<AccountId>,
1319 RmrkInstanceInfo<AccountId>,
1320 RmrkResourceInfo,
1321 RmrkPropertyInfo,
1322 RmrkBaseInfo<AccountId>,
1323 RmrkPartType,
1324 RmrkTheme
1325 > for Runtime {
1326 fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
1327 pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>()
1328 }
1329
1330 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
1331 pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id)
1332 }
1333
1334 fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
1335 pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id)
1336 }
1337
1338 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
1339 pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id)
1340 }
1341
1342 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
1343 pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id)
1344 }
1345
1346 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
1347 pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys)
1348 }
1349
1350 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
1351 pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys)
1352 }
1353
1354 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
1355 pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id)
1356 }
1357
1358 fn nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {
1359 pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id)
1360 }
1361
1362 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
1363 pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id)
1364 }
1365
1366 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
1367 pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id)
1368 }
1369
1370 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
1371 pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id)
1372 }
1373
1374 fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
1375 pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys)
1376 }
1377 }
1378}
1379
1380struct CheckInherents;
1381
1382impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
1383 fn check_inherents(
1384 block: &Block,
1385 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
1386 ) -> sp_inherents::CheckInherentsResult {
1387 let relay_chain_slot = relay_state_proof
1388 .read_slot()
1389 .expect("Could not read the relay chain slot from the proof");
1390
1391 let inherent_data =
1392 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
1393 relay_chain_slot,
1394 sp_std::time::Duration::from_secs(6),
1395 )
1396 .create_inherent_data()
1397 .expect("Could not create the timestamp inherent data");
1398
1399 inherent_data.check_extrinsics(block)
1400 }
1401}
140264
1403cumulus_pallet_parachain_system::register_validate_block!(65cumulus_pallet_parachain_system::register_validate_block!(
1404 Runtime = Runtime,66 Runtime = Runtime,
modifiedruntime/tests/Cargo.tomldiffbeforeafterboth
3version = "0.1.0"3version = "0.1.0"
4edition = "2021"4edition = "2021"
5
6[features]
7default = ['refungible']
8
9refungible = []
510
6[dependencies]11[dependencies]
7unique-runtime-common = { path = '../common' }
8up-data-structs = { default-features = false, path = '../../primitives/data-structs' }12up-data-structs = { default-features = false, path = '../../primitives/data-structs' }
913
10sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24' }14sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24' }
38] }42] }
39scale-info = "*"43scale-info = "*"
44
45evm-coder = { default-features = false, path = '../../crates/evm-coder' }
46up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }
4047
modifiedruntime/tests/src/lib.rsdiffbeforeafterboth
35use parity_scale_codec::{Encode, Decode, MaxEncodedLen};35use parity_scale_codec::{Encode, Decode, MaxEncodedLen};
36use scale_info::TypeInfo;36use scale_info::TypeInfo;
3737
38use unique_runtime_common::{dispatch::CollectionDispatchT, weights::CommonWeights};
39use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping};38use up_data_structs::mapping::{CrossTokenAddressMapping, EvmTokenAddressMapping};
39
40#[path = "../../common/dispatch.rs"]
41mod dispatch;
42
43use dispatch::CollectionDispatchT;
44
45#[path = "../../common/weights.rs"]
46mod weights;
47
48use weights::CommonWeights;
4049
41type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;50type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
42type Block = frame_system::mocking::MockBlock<Test>;51type Block = frame_system::mocking::MockBlock<Test>;
modifiedruntime/unique/Cargo.tomldiffbeforeafterboth
114 'xcm/std',114 'xcm/std',
115 'xcm-builder/std',115 'xcm-builder/std',
116 'xcm-executor/std',116 'xcm-executor/std',
117 'unique-runtime-common/std',117 'up-common/std',
118118
119 "orml-vesting/std",119 "orml-vesting/std",
120]120]
121limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']121limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
122unique-runtime = []122unique-runtime = []
123
124refungible = []
125scheduler = []
126rmrk = []
123127
124################################################################################128################################################################################
125# Substrate Dependencies129# Substrate Dependencies
397401
398[dependencies]402[dependencies]
399log = { version = "0.4.16", default-features = false }403log = { version = "0.4.16", default-features = false }
400unique-runtime-common = { path = "../common", default-features = false }404up-common = { path = "../../primitives/common", default-features = false }
401scale-info = { version = "2.0.1", default-features = false, features = [405scale-info = { version = "2.0.1", default-features = false, features = [
402 "derive",406 "derive",
403] }407] }
427fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }431fp-rpc = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
428fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }432fp-self-contained = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
429fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }433fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }
434evm-coder = { default-features = false, path = '../../crates/evm-coder' }
435up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.24' }
430436
431################################################################################437################################################################################
432# Build Dependencies438# Build Dependencies
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
25#[cfg(feature = "std")]25#[cfg(feature = "std")]
26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));26include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
2727
28use sp_api::impl_runtime_apis;28use frame_support::parameter_types;
29
29use sp_core::{crypto::KeyTypeId, OpaqueMetadata, H256, U256, H160};30use sp_version::RuntimeVersion;
30use sp_runtime::DispatchError;
31use fp_self_contained::*;
32// #[cfg(any(feature = "std", test))]
33// pub use sp_runtime::BuildStorage;
34
35use sp_runtime::{31use sp_runtime::create_runtime_str;
36 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,
37 traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, AccountIdConversion, Zero, Member},
38 transaction_validity::{TransactionSource, TransactionValidity},
39 ApplyExtrinsicResult, RuntimeAppPublic,
40};
4132
42use sp_std::prelude::*;33use up_common::types::*;
4334
44#[cfg(feature = "std")]35#[path = "../../common/mod.rs"]
45use sp_version::NativeVersion;36mod runtime_common;
46use sp_version::RuntimeVersion;37
47pub use pallet_transaction_payment::{38pub use runtime_common::*;
48 Multiplier, TargetedFeeAdjustment, FeeDetails, RuntimeDispatchInfo,
49};
50// A few exports that help ease life for downstream crates.
51pub use pallet_balances::Call as BalancesCall;
52pub use pallet_evm::{
53 EnsureAddressTruncated, HashedAddressMapping, Runner, account::CrossAccountId as _,
54 OnMethodCall, Account as EVMAccount, FeeCalculator, GasWeightMapping,
55};
56pub use frame_support::{
57 construct_runtime, match_types,
58 dispatch::DispatchResult,
59 PalletId, parameter_types, StorageValue, ConsensusEngineId,
60 traits::{
61 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,
62 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,
63 OnUnbalanced, Randomness, FindAuthor, ConstU32, Imbalance, PrivilegeCmp,
64 },
65 weights::{
66 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
67 DispatchClass, DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
68 WeightToFeePolynomial, WeightToFeeCoefficient, WeightToFeeCoefficients, ConstantMultiplier,
69 WeightToFee,
70 },
71};
72use pallet_unique_scheduler::DispatchCall;
73use up_data_structs::{
74 CollectionId, TokenId, TokenData, Property, PropertyKeyPermission, CollectionLimits,
75 CollectionStats, RpcCollection,
76 mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
77 TokenChild, RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo,
78 RmrkBaseInfo, RmrkPartType, RmrkTheme, RmrkThemeName, RmrkCollectionId, RmrkNftId,
79 RmrkNftChild, RmrkPropertyKey, RmrkResourceId, RmrkBaseId,
80};
81
82// use pallet_contracts::weights::WeightInfo;
83// #[cfg(any(feature = "std", test))]
84use frame_system::{
85 self as frame_system, EnsureRoot, EnsureSigned,
86 limits::{BlockWeights, BlockLength},
87};
88use sp_arithmetic::{
89 traits::{BaseArithmetic, Unsigned},
90};
91use smallvec::smallvec;
92use codec::{Encode, Decode};
93use fp_rpc::TransactionStatus;
94use sp_runtime::{
95 traits::{
96 Applyable, BlockNumberProvider, Dispatchable, PostDispatchInfoOf, DispatchInfoOf,
97 Saturating, CheckedConversion,
98 },
99 generic::Era,
100 transaction_validity::TransactionValidityError,
101 DispatchErrorWithPostInfo, SaturatedConversion,
102};
103
104// pub use pallet_timestamp::Call as TimestampCall;
105pub use sp_consensus_aura::sr25519::AuthorityId as AuraId;
106
107// Polkadot imports
108use pallet_xcm::XcmPassthrough;
109use polkadot_parachain::primitives::Sibling;
110use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};
111use xcm_builder::{
112 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,
113 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,
114 RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,
115 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
116 ParentIsPreset,
117};
118use xcm_executor::{Config, XcmExecutor, Assets};
119use sp_std::{cmp::Ordering, marker::PhantomData};
120
121use xcm::latest::{
122 // Xcm,
123 AssetId::{Concrete},
124 Fungibility::Fungible as XcmFungible,
125 MultiAsset,
126 Error as XcmError,
127};
128use xcm_executor::traits::{MatchesFungible, WeightTrader};
129
130use unique_runtime_common::{
131 impl_common_runtime_apis,
132 types::*,
133 constants::*,
134 dispatch::{CollectionDispatchT, CollectionDispatch},
135 sponsoring::UniqueSponsorshipHandler,
136 eth_sponsoring::UniqueEthSponsorshipHandler,
137 weights::CommonWeights,
138};
13939
140pub const RUNTIME_NAME: &str = "unique";40pub const RUNTIME_NAME: &str = "unique";
141pub const TOKEN_SYMBOL: &str = "UNQ";41pub const TOKEN_SYMBOL: &str = "UNQ";
142
143type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Runtime>;
144
145impl RuntimeInstance for Runtime {
146 type CrossAccountId = self::CrossAccountId;
147 type TransactionConverter = self::TransactionConverter;
148
149 fn get_transaction_converter() -> TransactionConverter {
150 TransactionConverter
151 }
152}
153
154/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
155/// never know...
156pub type AccountIndex = u32;
157
158/// Balance of an account.
159pub type Balance = u128;
160
161/// Index of a transaction in the chain.
162pub type Index = u32;
163
164/// A hash of some data used by the chain.
165pub type Hash = sp_core::H256;
166
167/// Digest item type.
168pub type DigestItem = generic::DigestItem;
169
170/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
171/// the specifics of the runtime. They can then be made to be agnostic over specific formats
172/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
173/// to even the core data structures.
174pub mod opaque {
175 use sp_std::prelude::*;
176 use sp_runtime::impl_opaque_keys;
177 use super::Aura;
178
179 pub use unique_runtime_common::types::*;
180
181 impl_opaque_keys! {
182 pub struct SessionKeys {
183 pub aura: Aura,
184 }
185 }
186}
18742
188/// This runtime version.43/// This runtime version.
189pub const VERSION: RuntimeVersion = RuntimeVersion {44pub const VERSION: RuntimeVersion = RuntimeVersion {
197 state_version: 0,52 state_version: 0,
198};53};
199
200#[derive(codec::Encode, codec::Decode)]
201pub enum XCMPMessage<XAccountId, XBalance> {
202 /// Transfer tokens to the given account from the Parachain account.
203 TransferToken(XAccountId, XBalance),
204}
205
206/// The version information used to identify this runtime when compiled natively.
207#[cfg(feature = "std")]
208pub fn native_version() -> NativeVersion {
209 NativeVersion {
210 runtime_version: VERSION,
211 can_author_with: Default::default(),
212 }
213}
214
215type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
216
217pub struct DealWithFees;
218impl OnUnbalanced<NegativeImbalance> for DealWithFees {
219 fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
220 if let Some(fees) = fees_then_tips.next() {
221 // for fees, 100% to treasury
222 let mut split = fees.ration(100, 0);
223 if let Some(tips) = fees_then_tips.next() {
224 // for tips, if any, 100% to treasury
225 tips.ration_merge_into(100, 0, &mut split);
226 }
227 Treasury::on_unbalanced(split.0);
228 // Author::on_unbalanced(split.1);
229 }
230 }
231}
23254
233parameter_types! {55parameter_types! {
234 pub const BlockHashCount: BlockNumber = 2400;
235 pub RuntimeBlockLength: BlockLength =
236 BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
237 pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
238 pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
239 pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
240 .base_block(BlockExecutionWeight::get())
241 .for_class(DispatchClass::all(), |weights| {
242 weights.base_extrinsic = ExtrinsicBaseWeight::get();
243 })
244 .for_class(DispatchClass::Normal, |weights| {
245 weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
246 })
247 .for_class(DispatchClass::Operational, |weights| {
248 weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
249 // Operational transactions have some extra reserved space, so that they
250 // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
251 weights.reserved = Some(
252 MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
253 );
254 })
255 .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
256 .build_or_panic();
257 pub const Version: RuntimeVersion = VERSION;56 pub const Version: RuntimeVersion = VERSION;
258 pub const SS58Prefix: u16 = 7391;57 pub const SS58Prefix: u16 = 7391;
259}
260
261parameter_types! {
262 pub const ChainId: u64 = 8880;58 pub const ChainId: u64 = 8880;
263}59}
264
265pub struct FixedFee;
266impl FeeCalculator for FixedFee {
267 fn min_gas_price() -> (U256, u64) {
268 (MIN_GAS_PRICE.into(), 0)
269 }
270}
271
272// Assuming slowest ethereum opcode is SSTORE, with gas price of 20000 as our worst case
273// (contract, which only writes a lot of data),
274// approximating on top of our real store write weight
275parameter_types! {
276 pub const WritesPerSecond: u64 = WEIGHT_PER_SECOND / <Runtime as frame_system::Config>::DbWeight::get().write;
277 pub const GasPerSecond: u64 = WritesPerSecond::get() * 20000;
278 pub const WeightPerGas: u64 = WEIGHT_PER_SECOND / GasPerSecond::get();
279}
280
281/// Limiting EVM execution to 50% of block for substrate users and management tasks
282/// EVM transaction consumes more weight than substrate's, so we can't rely on them being
283/// scheduled fairly
284const EVM_DISPATCH_RATIO: Perbill = Perbill::from_percent(50);
285parameter_types! {
286 pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * EVM_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT / WeightPerGas::get());
287}
288
289pub enum FixedGasWeightMapping {}
290impl GasWeightMapping for FixedGasWeightMapping {
291 fn gas_to_weight(gas: u64) -> Weight {
292 gas.saturating_mul(WeightPerGas::get())
293 }
294 fn weight_to_gas(weight: Weight) -> u64 {
295 weight / WeightPerGas::get()
296 }
297}
298
299impl pallet_evm::account::Config for Runtime {
300 type CrossAccountId = pallet_evm::account::BasicCrossAccountId<Self>;
301 type EvmAddressMapping = pallet_evm::HashedAddressMapping<Self::Hashing>;
302 type EvmBackwardsAddressMapping = fp_evm_mapping::MapBackwardsAddressTruncated;
303}
304
305impl pallet_evm::Config for Runtime {
306 type BlockGasLimit = BlockGasLimit;
307 type FeeCalculator = FixedFee;
308 type GasWeightMapping = FixedGasWeightMapping;
309 type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
310 type CallOrigin = EnsureAddressTruncated<Self>;
311 type WithdrawOrigin = EnsureAddressTruncated<Self>;
312 type AddressMapping = HashedAddressMapping<Self::Hashing>;
313 type PrecompilesType = ();
314 type PrecompilesValue = ();
315 type Currency = Balances;
316 type Event = Event;
317 type OnMethodCall = (
318 pallet_evm_migration::OnMethodCall<Self>,
319 pallet_evm_contract_helpers::HelpersOnMethodCall<Self>,
320 CollectionDispatchT<Self>,
321 pallet_unique::eth::CollectionHelpersOnMethodCall<Self>,
322 );
323 type OnCreate = pallet_evm_contract_helpers::HelpersOnCreate<Self>;
324 type ChainId = ChainId;
325 type Runner = pallet_evm::runner::stack::Runner<Self>;
326 type OnChargeTransaction = pallet_evm::EVMCurrencyAdapter<Balances, DealWithFees>;
327 type TransactionValidityHack = pallet_evm_transaction_payment::TransactionValidityHack<Self>;
328 type FindAuthor = EthereumFindAuthor<Aura>;
329}
330
331impl pallet_evm_migration::Config for Runtime {
332 type WeightInfo = pallet_evm_migration::weights::SubstrateWeight<Self>;
333}
334
335pub struct EthereumFindAuthor<F>(core::marker::PhantomData<F>);
336impl<F: FindAuthor<u32>> FindAuthor<H160> for EthereumFindAuthor<F> {
337 fn find_author<'a, I>(digests: I) -> Option<H160>
338 where
339 I: 'a + IntoIterator<Item = (ConsensusEngineId, &'a [u8])>,
340 {
341 if let Some(author_index) = F::find_author(digests) {
342 let authority_id = Aura::authorities()[author_index as usize].clone();
343 return Some(H160::from_slice(&authority_id.to_raw_vec()[4..24]));
344 }
345 None
346 }
347}
348
349impl pallet_ethereum::Config for Runtime {
350 type Event = Event;
351 type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
352}
353
354impl pallet_randomness_collective_flip::Config for Runtime {}
355
356impl frame_system::Config for Runtime {
357 /// The data to be stored in an account.
358 type AccountData = pallet_balances::AccountData<Balance>;
359 /// The identifier used to distinguish between accounts.
360 type AccountId = AccountId;
361 /// The basic call filter to use in dispatchable.
362 type BaseCallFilter = Everything;
363 /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
364 type BlockHashCount = BlockHashCount;
365 /// The maximum length of a block (in bytes).
366 type BlockLength = RuntimeBlockLength;
367 /// The index type for blocks.
368 type BlockNumber = BlockNumber;
369 /// The weight of the overhead invoked on the block import process, independent of the extrinsics included in that block.
370 type BlockWeights = RuntimeBlockWeights;
371 /// The aggregated dispatch type that is available for extrinsics.
372 type Call = Call;
373 /// The weight of database operations that the runtime can invoke.
374 type DbWeight = RocksDbWeight;
375 /// The ubiquitous event type.
376 type Event = Event;
377 /// The type for hashing blocks and tries.
378 type Hash = Hash;
379 /// The hashing algorithm used.
380 type Hashing = BlakeTwo256;
381 /// The header type.
382 type Header = generic::Header<BlockNumber, BlakeTwo256>;
383 /// The index type for storing how many extrinsics an account has signed.
384 type Index = Index;
385 /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
386 type Lookup = AccountIdLookup<AccountId, ()>;
387 /// What to do if an account is fully reaped from the system.
388 type OnKilledAccount = ();
389 /// What to do if a new account is created.
390 type OnNewAccount = ();
391 type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
392 /// The ubiquitous origin type.
393 type Origin = Origin;
394 /// This type is being generated by `construct_runtime!`.
395 type PalletInfo = PalletInfo;
396 /// This is used as an identifier of the chain. 42 is the generic substrate prefix.
397 type SS58Prefix = SS58Prefix;
398 /// Weight information for the extrinsics of this pallet.
399 type SystemWeightInfo = frame_system::weights::SubstrateWeight<Self>;
400 /// Version of the runtime.
401 type Version = Version;
402 type MaxConsumers = ConstU32<16>;
403}
404
405parameter_types! {
406 pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
407}
408
409impl pallet_timestamp::Config for Runtime {
410 /// A timestamp: milliseconds since the unix epoch.
411 type Moment = u64;
412 type OnTimestampSet = ();
413 type MinimumPeriod = MinimumPeriod;
414 type WeightInfo = ();
415}
416
417parameter_types! {
418 // pub const ExistentialDeposit: u128 = 500;
419 pub const ExistentialDeposit: u128 = 0;
420 pub const MaxLocks: u32 = 50;
421 pub const MaxReserves: u32 = 50;
422}
423
424impl pallet_balances::Config for Runtime {
425 type MaxLocks = MaxLocks;
426 type MaxReserves = MaxReserves;
427 type ReserveIdentifier = [u8; 16];
428 /// The type for recording an account's balance.
429 type Balance = Balance;
430 /// The ubiquitous event type.
431 type Event = Event;
432 type DustRemoval = Treasury;
433 type ExistentialDeposit = ExistentialDeposit;
434 type AccountStore = System;
435 type WeightInfo = pallet_balances::weights::SubstrateWeight<Self>;
436}
437
438pub const fn deposit(items: u32, bytes: u32) -> Balance {
439 items as Balance * 15 * CENTIUNIQUE + (bytes as Balance) * 6 * CENTIUNIQUE
440}
441
442/*
443parameter_types! {
444 pub TombstoneDeposit: Balance = deposit(
445 1,
446 sp_std::mem::size_of::<pallet_contracts::Pallet<Runtime>> as u32,
447 );
448 pub DepositPerContract: Balance = TombstoneDeposit::get();
449 pub const DepositPerStorageByte: Balance = deposit(0, 1);
450 pub const DepositPerStorageItem: Balance = deposit(1, 0);
451 pub RentFraction: Perbill = Perbill::from_rational(1u32, 30 * DAYS);
452 pub const SurchargeReward: Balance = 150 * MILLIUNIQUE;
453 pub const SignedClaimHandicap: u32 = 2;
454 pub const MaxDepth: u32 = 32;
455 pub const MaxValueSize: u32 = 16 * 1024;
456 pub const MaxCodeSize: u32 = 1024 * 1024 * 25; // 25 Mb
457 // The lazy deletion runs inside on_initialize.
458 pub DeletionWeightLimit: Weight = AVERAGE_ON_INITIALIZE_RATIO *
459 RuntimeBlockWeights::get().max_block;
460 // The weight needed for decoding the queue should be less or equal than a fifth
461 // of the overall weight dedicated to the lazy deletion.
462 pub DeletionQueueDepth: u32 = ((DeletionWeightLimit::get() / (
463 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(1) -
464 <Runtime as pallet_contracts::Config>::WeightInfo::on_initialize_per_queue_item(0)
465 )) / 5) as u32;
466 pub Schedule: pallet_contracts::Schedule<Runtime> = Default::default();
467}
468
469impl pallet_contracts::Config for Runtime {
470 type Time = Timestamp;
471 type Randomness = RandomnessCollectiveFlip;
472 type Currency = Balances;
473 type Event = Event;
474 type RentPayment = ();
475 type SignedClaimHandicap = SignedClaimHandicap;
476 type TombstoneDeposit = TombstoneDeposit;
477 type DepositPerContract = DepositPerContract;
478 type DepositPerStorageByte = DepositPerStorageByte;
479 type DepositPerStorageItem = DepositPerStorageItem;
480 type RentFraction = RentFraction;
481 type SurchargeReward = SurchargeReward;
482 type WeightPrice = pallet_transaction_payment::Pallet<Self>;
483 type WeightInfo = pallet_contracts::weights::SubstrateWeight<Self>;
484 type ChainExtension = NFTExtension;
485 type DeletionQueueDepth = DeletionQueueDepth;
486 type DeletionWeightLimit = DeletionWeightLimit;
487 type Schedule = Schedule;
488 type CallStack = [pallet_contracts::Frame<Self>; 31];
489}
490*/
491
492parameter_types! {
493 /// This value increases the priority of `Operational` transactions by adding
494 /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`.
495 pub const OperationalFeeMultiplier: u8 = 5;
496}
497
498/// Linear implementor of `WeightToFeePolynomial`
499pub struct LinearFee<T>(sp_std::marker::PhantomData<T>);
500
501impl<T> WeightToFeePolynomial for LinearFee<T>
502where
503 T: BaseArithmetic + From<u32> + Copy + Unsigned,
504{
505 type Balance = T;
506
507 fn polynomial() -> WeightToFeeCoefficients<Self::Balance> {
508 smallvec!(WeightToFeeCoefficient {
509 coeff_integer: WEIGHT_TO_FEE_COEFF.into(),
510 coeff_frac: Perbill::zero(),
511 negative: false,
512 degree: 1,
513 })
514 }
515}
516
517impl pallet_transaction_payment::Config for Runtime {
518 type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter<Balances, DealWithFees>;
519 type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
520 type OperationalFeeMultiplier = OperationalFeeMultiplier;
521 type WeightToFee = LinearFee<Balance>;
522 type FeeMultiplierUpdate = ();
523}
524
525parameter_types! {
526 pub const ProposalBond: Permill = Permill::from_percent(5);
527 pub const ProposalBondMinimum: Balance = 1 * UNIQUE;
528 pub const ProposalBondMaximum: Balance = 1000 * UNIQUE;
529 pub const SpendPeriod: BlockNumber = 5 * MINUTES;
530 pub const Burn: Permill = Permill::from_percent(0);
531 pub const TipCountdown: BlockNumber = 1 * DAYS;
532 pub const TipFindersFee: Percent = Percent::from_percent(20);
533 pub const TipReportDepositBase: Balance = 1 * UNIQUE;
534 pub const DataDepositPerByte: Balance = 1 * CENTIUNIQUE;
535 pub const BountyDepositBase: Balance = 1 * UNIQUE;
536 pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS;
537 pub const TreasuryModuleId: PalletId = PalletId(*b"py/trsry");
538 pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS;
539 pub const MaximumReasonLength: u32 = 16384;
540 pub const BountyCuratorDeposit: Permill = Permill::from_percent(50);
541 pub const BountyValueMinimum: Balance = 5 * UNIQUE;
542 pub const MaxApprovals: u32 = 100;
543}
544
545impl pallet_treasury::Config for Runtime {
546 type PalletId = TreasuryModuleId;
547 type Currency = Balances;
548 type ApproveOrigin = EnsureRoot<AccountId>;
549 type RejectOrigin = EnsureRoot<AccountId>;
550 type Event = Event;
551 type OnSlash = ();
552 type ProposalBond = ProposalBond;
553 type ProposalBondMinimum = ProposalBondMinimum;
554 type ProposalBondMaximum = ProposalBondMaximum;
555 type SpendPeriod = SpendPeriod;
556 type Burn = Burn;
557 type BurnDestination = ();
558 type SpendFunds = ();
559 type WeightInfo = pallet_treasury::weights::SubstrateWeight<Self>;
560 type MaxApprovals = MaxApprovals;
561}
562
563impl pallet_sudo::Config for Runtime {
564 type Event = Event;
565 type Call = Call;
566}
567
568pub struct RelayChainBlockNumberProvider<T>(sp_std::marker::PhantomData<T>);
569
570impl<T: cumulus_pallet_parachain_system::Config> BlockNumberProvider
571 for RelayChainBlockNumberProvider<T>
572{
573 type BlockNumber = BlockNumber;
574
575 fn current_block_number() -> Self::BlockNumber {
576 cumulus_pallet_parachain_system::Pallet::<T>::validation_data()
577 .map(|d| d.relay_parent_number)
578 .unwrap_or_default()
579 }
580}
581
582parameter_types! {
583 pub const MinVestedTransfer: Balance = 10 * UNIQUE;
584 pub const MaxVestingSchedules: u32 = 28;
585}
586
587impl orml_vesting::Config for Runtime {
588 type Event = Event;
589 type Currency = pallet_balances::Pallet<Runtime>;
590 type MinVestedTransfer = MinVestedTransfer;
591 type VestedTransferOrigin = EnsureSigned<AccountId>;
592 type WeightInfo = ();
593 type MaxVestingSchedules = MaxVestingSchedules;
594 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
595}
596
597parameter_types! {
598 pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
599 pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4;
600}
601
602impl cumulus_pallet_parachain_system::Config for Runtime {
603 type Event = Event;
604 type SelfParaId = parachain_info::Pallet<Self>;
605 type OnSystemEvent = ();
606 // type DownwardMessageHandlers = cumulus_primitives_utility::UnqueuedDmpAsParent<
607 // MaxDownwardMessageWeight,
608 // XcmExecutor<XcmConfig>,
609 // Call,
610 // >;
611 type OutboundXcmpMessageSource = XcmpQueue;
612 type DmpMessageHandler = DmpQueue;
613 type ReservedDmpWeight = ReservedDmpWeight;
614 type ReservedXcmpWeight = ReservedXcmpWeight;
615 type XcmpMessageHandler = XcmpQueue;
616}
617
618impl parachain_info::Config for Runtime {}
619
620impl cumulus_pallet_aura_ext::Config for Runtime {}
621
622parameter_types! {
623 pub const RelayLocation: MultiLocation = MultiLocation::parent();
624 pub const RelayNetwork: NetworkId = NetworkId::Polkadot;
625 pub RelayOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into();
626 pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into();
627}
628
629/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used
630/// when determining ownership of accounts for asset transacting and when attempting to use XCM
631/// `Transact` in order to determine the dispatch Origin.
632pub type LocationToAccountId = (
633 // The parent (Relay-chain) origin converts to the default `AccountId`.
634 ParentIsPreset<AccountId>,
635 // Sibling parachain origins convert to AccountId via the `ParaId::into`.
636 SiblingParachainConvertsVia<Sibling, AccountId>,
637 // Straight up local `AccountId32` origins just alias directly to `AccountId`.
638 AccountId32Aliases<RelayNetwork, AccountId>,
639);
640
641pub struct OnlySelfCurrency;
642impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {
643 fn matches_fungible(a: &MultiAsset) -> Option<B> {
644 match (&a.id, &a.fun) {
645 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),
646 _ => None,
647 }
648 }
649}
650
651/// Means for transacting assets on this chain.
652pub type LocalAssetTransactor = CurrencyAdapter<
653 // Use this currency:
654 Balances,
655 // Use this currency when it is a fungible asset matching the given location or name:
656 OnlySelfCurrency,
657 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:
658 LocationToAccountId,
659 // Our chain's account ID type (we can't get away without mentioning it explicitly):
660 AccountId,
661 // We don't track any teleports.
662 (),
663>;
664
665/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
666/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
667/// biases the kind of local `Origin` it will become.
668pub type XcmOriginToTransactDispatchOrigin = (
669 // Sovereign account converter; this attempts to derive an `AccountId` from the origin location
670 // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for
671 // foreign chains who want to have a local sovereign account on this chain which they control.
672 SovereignSignedViaLocation<LocationToAccountId, Origin>,
673 // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when
674 // recognised.
675 RelayChainAsNative<RelayOrigin, Origin>,
676 // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when
677 // recognised.
678 SiblingParachainAsNative<cumulus_pallet_xcm::Origin, Origin>,
679 // Superuser converter for the Relay-chain (Parent) location. This will allow it to issue a
680 // transaction from the Root origin.
681 ParentAsSuperuser<Origin>,
682 // Native signed account converter; this just converts an `AccountId32` origin into a normal
683 // `Origin::Signed` origin of the same 32-byte value.
684 SignedAccountId32AsNative<RelayNetwork, Origin>,
685 // Xcm origins can be represented natively under the Xcm pallet's Xcm origin.
686 XcmPassthrough<Origin>,
687);
688
689parameter_types! {
690 // One XCM operation is 1_000_000 weight - almost certainly a conservative estimate.
691 pub UnitWeightCost: Weight = 1_000_000;
692 // 1200 UNIQUEs buy 1 second of weight.
693 pub const WeightPrice: (MultiLocation, u128) = (MultiLocation::parent(), 1_200 * UNIQUE);
694 pub const MaxInstructions: u32 = 100;
695 pub const MaxAuthorities: u32 = 100_000;
696}
697
698match_types! {
699 pub type ParentOrParentsUnitPlurality: impl Contains<MultiLocation> = {
700 MultiLocation { parents: 1, interior: Here } |
701 MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Unit, .. }) }
702 };
703}
704
705pub type Barrier = (
706 TakeWeightCredit,
707 AllowTopLevelPaidExecutionFrom<Everything>,
708 // ^^^ Parent & its unit plurality gets free execution
709);
710
711pub struct UsingOnlySelfCurrencyComponents<
712 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
713 AssetId: Get<MultiLocation>,
714 AccountId,
715 Currency: CurrencyT<AccountId>,
716 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
717>(
718 Weight,
719 Currency::Balance,
720 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,
721);
722impl<
723 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
724 AssetId: Get<MultiLocation>,
725 AccountId,
726 Currency: CurrencyT<AccountId>,
727 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
728 > WeightTrader
729 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
730{
731 fn new() -> Self {
732 Self(0, Zero::zero(), PhantomData)
733 }
734
735 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {
736 let amount = WeightToFee::weight_to_fee(&weight);
737 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;
738
739 // location to this parachain through relay chain
740 let option1: xcm::v1::AssetId = Concrete(MultiLocation {
741 parents: 1,
742 interior: X1(Parachain(ParachainInfo::parachain_id().into())),
743 });
744 // direct location
745 let option2: xcm::v1::AssetId = Concrete(MultiLocation {
746 parents: 0,
747 interior: Here,
748 });
749
750 let required = if payment.fungible.contains_key(&option1) {
751 (option1, u128_amount).into()
752 } else if payment.fungible.contains_key(&option2) {
753 (option2, u128_amount).into()
754 } else {
755 (Concrete(MultiLocation::default()), u128_amount).into()
756 };
757
758 let unused = payment
759 .checked_sub(required)
760 .map_err(|_| XcmError::TooExpensive)?;
761 self.0 = self.0.saturating_add(weight);
762 self.1 = self.1.saturating_add(amount);
763 Ok(unused)
764 }
765
766 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {
767 let weight = weight.min(self.0);
768 let amount = WeightToFee::weight_to_fee(&weight);
769 self.0 -= weight;
770 self.1 = self.1.saturating_sub(amount);
771 let amount: u128 = amount.saturated_into();
772 if amount > 0 {
773 Some((AssetId::get(), amount).into())
774 } else {
775 None
776 }
777 }
778}
779impl<
780 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,
781 AssetId: Get<MultiLocation>,
782 AccountId,
783 Currency: CurrencyT<AccountId>,
784 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,
785 > Drop
786 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>
787{
788 fn drop(&mut self) {
789 OnUnbalanced::on_unbalanced(Currency::issue(self.1));
790 }
791}
792
793pub struct XcmConfig;
794impl Config for XcmConfig {
795 type Call = Call;
796 type XcmSender = XcmRouter;
797 // How to withdraw and deposit an asset.
798 type AssetTransactor = LocalAssetTransactor;
799 type OriginConverter = XcmOriginToTransactDispatchOrigin;
800 type IsReserve = NativeAsset;
801 type IsTeleporter = (); // Teleportation is disabled
802 type LocationInverter = LocationInverter<Ancestry>;
803 type Barrier = Barrier;
804 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
805 type Trader =
806 UsingOnlySelfCurrencyComponents<LinearFee<Balance>, RelayLocation, AccountId, Balances, ()>;
807 type ResponseHandler = (); // Don't handle responses for now.
808 type SubscriptionService = PolkadotXcm;
809
810 type AssetTrap = PolkadotXcm;
811 type AssetClaims = PolkadotXcm;
812}
813
814// parameter_types! {
815// pub const MaxDownwardMessageWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 10;
816// }
817
818/// No local origins on this chain are allowed to dispatch XCM sends/executions.
819pub type LocalOriginToLocation = (SignedToAccountId32<Origin, AccountId, RelayNetwork>,);
820
821/// The means for routing XCM messages which are not for local execution into the right message
822/// queues.
823pub type XcmRouter = (
824 // Two routers - use UMP to communicate with the relay chain:
825 cumulus_primitives_utility::ParentAsUmp<ParachainSystem, ()>,
826 // ..and XCMP to communicate with the sibling chains.
827 XcmpQueue,
828);
829
830impl pallet_evm_coder_substrate::Config for Runtime {}
831
832impl pallet_xcm::Config for Runtime {
833 type Event = Event;
834 type SendXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
835 type XcmRouter = XcmRouter;
836 type ExecuteXcmOrigin = EnsureXcmOrigin<Origin, LocalOriginToLocation>;
837 type XcmExecuteFilter = Everything;
838 type XcmExecutor = XcmExecutor<XcmConfig>;
839 type XcmTeleportFilter = Everything;
840 type XcmReserveTransferFilter = Everything;
841 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;
842 type LocationInverter = LocationInverter<Ancestry>;
843 type Origin = Origin;
844 type Call = Call;
845 const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
846 type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion;
847}
848
849impl cumulus_pallet_xcm::Config for Runtime {
850 type Event = Event;
851 type XcmExecutor = XcmExecutor<XcmConfig>;
852}
853
854impl cumulus_pallet_xcmp_queue::Config for Runtime {
855 type WeightInfo = ();
856 type Event = Event;
857 type XcmExecutor = XcmExecutor<XcmConfig>;
858 type ChannelInfo = ParachainSystem;
859 type VersionWrapper = ();
860 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
861 type ControllerOrigin = EnsureRoot<AccountId>;
862 type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin;
863}
864
865impl cumulus_pallet_dmp_queue::Config for Runtime {
866 type Event = Event;
867 type XcmExecutor = XcmExecutor<XcmConfig>;
868 type ExecuteOverweightOrigin = frame_system::EnsureRoot<AccountId>;
869}
870
871impl pallet_aura::Config for Runtime {
872 type AuthorityId = AuraId;
873 type DisabledValidators = ();
874 type MaxAuthorities = MaxAuthorities;
875}
876
877parameter_types! {
878 pub TreasuryAccountId: AccountId = TreasuryModuleId::get().into_account_truncating();
879 pub const CollectionCreationPrice: Balance = 2 * UNIQUE;
880}
881
882impl pallet_common::Config for Runtime {
883 type WeightInfo = pallet_common::weights::SubstrateWeight<Self>;
884 type Event = Event;
885 type Currency = Balances;
886 type CollectionCreationPrice = CollectionCreationPrice;
887 type TreasuryAccountId = TreasuryAccountId;
888 type CollectionDispatch = CollectionDispatchT<Self>;
889
890 type EvmTokenAddressMapping = EvmTokenAddressMapping;
891 type CrossTokenAddressMapping = CrossTokenAddressMapping<Self::AccountId>;
892 type ContractAddress = EvmCollectionHelpersAddress;
893}
894
895impl pallet_structure::Config for Runtime {
896 type Event = Event;
897 type Call = Call;
898 type WeightInfo = pallet_structure::weights::SubstrateWeight<Self>;
899}
900
901impl pallet_fungible::Config for Runtime {
902 type WeightInfo = pallet_fungible::weights::SubstrateWeight<Self>;
903}
904impl pallet_refungible::Config for Runtime {
905 type WeightInfo = pallet_refungible::weights::SubstrateWeight<Self>;
906}
907impl pallet_nonfungible::Config for Runtime {
908 type WeightInfo = pallet_nonfungible::weights::SubstrateWeight<Self>;
909}
910
911impl pallet_unique::Config for Runtime {
912 type Event = Event;
913 type WeightInfo = pallet_unique::weights::SubstrateWeight<Self>;
914 type CommonWeightInfo = CommonWeights<Self>;
915 type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
916}
917
918parameter_types! {
919 pub const InflationBlockInterval: BlockNumber = 100; // every time per how many blocks inflation is applied
920}
921
922/// Used for the pallet inflation
923impl pallet_inflation::Config for Runtime {
924 type Currency = Balances;
925 type TreasuryAccountId = TreasuryAccountId;
926 type InflationBlockInterval = InflationBlockInterval;
927 type BlockNumberProvider = RelayChainBlockNumberProvider<Runtime>;
928}
929
930parameter_types! {
931 pub MaximumSchedulerWeight: Weight = Perbill::from_percent(50) *
932 RuntimeBlockWeights::get().max_block;
933 pub const MaxScheduledPerBlock: u32 = 50;
934}
935
936type ChargeTransactionPayment = pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
937use frame_support::traits::NamedReservableCurrency;
938
939fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
940 (
941 frame_system::CheckSpecVersion::<Runtime>::new(),
942 frame_system::CheckGenesis::<Runtime>::new(),
943 frame_system::CheckEra::<Runtime>::from(Era::Immortal),
944 frame_system::CheckNonce::<Runtime>::from(frame_system::Pallet::<Runtime>::account_nonce(
945 from,
946 )),
947 frame_system::CheckWeight::<Runtime>::new(),
948 // sponsoring transaction logic
949 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
950 )
951}
952
953pub struct SchedulerPaymentExecutor;
954impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
955 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
956where
957 <T as frame_system::Config>::Call: Member
958 + Dispatchable<Origin = Origin, Info = DispatchInfo>
959 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
960 + GetDispatchInfo
961 + From<frame_system::Call<Runtime>>,
962 SelfContainedSignedInfo: Send + Sync + 'static,
963 Call: From<<T as frame_system::Config>::Call>
964 + From<<T as pallet_unique_scheduler::Config>::Call>
965 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
966 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
967{
968 fn dispatch_call(
969 signer: <T as frame_system::Config>::AccountId,
970 call: <T as pallet_unique_scheduler::Config>::Call,
971 ) -> Result<
972 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
973 TransactionValidityError,
974 > {
975 let dispatch_info = call.get_dispatch_info();
976 let extrinsic = fp_self_contained::CheckedExtrinsic::<
977 AccountId,
978 Call,
979 SignedExtraScheduler,
980 SelfContainedSignedInfo,
981 > {
982 signed:
983 CheckedSignature::<AccountId, SignedExtraScheduler, SelfContainedSignedInfo>::Signed(
984 signer.clone().into(),
985 get_signed_extras(signer.into()),
986 ),
987 function: call.into(),
988 };
989
990 extrinsic.apply::<Runtime>(&dispatch_info, 0)
991 }
992
993 fn reserve_balance(
994 id: [u8; 16],
995 sponsor: <T as frame_system::Config>::AccountId,
996 call: <T as pallet_unique_scheduler::Config>::Call,
997 count: u32,
998 ) -> Result<(), DispatchError> {
999 let dispatch_info = call.get_dispatch_info();
1000 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
1001 .saturating_mul(count.into());
1002
1003 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
1004 &id,
1005 &(sponsor.into()),
1006 weight,
1007 )
1008 }
1009
1010 fn pay_for_call(
1011 id: [u8; 16],
1012 sponsor: <T as frame_system::Config>::AccountId,
1013 call: <T as pallet_unique_scheduler::Config>::Call,
1014 ) -> Result<u128, DispatchError> {
1015 let dispatch_info = call.get_dispatch_info();
1016 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
1017 Ok(
1018 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
1019 &id,
1020 &(sponsor.into()),
1021 weight,
1022 ),
1023 )
1024 }
1025
1026 fn cancel_reserve(
1027 id: [u8; 16],
1028 sponsor: <T as frame_system::Config>::AccountId,
1029 ) -> Result<u128, DispatchError> {
1030 Ok(
1031 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
1032 &id,
1033 &(sponsor.into()),
1034 u128::MAX,
1035 ),
1036 )
1037 }
1038}
1039
1040parameter_types! {
1041 pub const NoPreimagePostponement: Option<u32> = Some(10);
1042 pub const Preimage: Option<u32> = Some(10);
1043}
1044
1045/// Used the compare the privilege of an origin inside the scheduler.
1046pub struct OriginPrivilegeCmp;
1047
1048impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {
1049 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {
1050 Some(Ordering::Equal)
1051 }
1052}
1053
1054impl pallet_unique_scheduler::Config for Runtime {
1055 type Event = Event;
1056 type Origin = Origin;
1057 type Currency = Balances;
1058 type PalletsOrigin = OriginCaller;
1059 type Call = Call;
1060 type MaximumWeight = MaximumSchedulerWeight;
1061 type ScheduleOrigin = EnsureSigned<AccountId>;
1062 type MaxScheduledPerBlock = MaxScheduledPerBlock;
1063 type WeightInfo = ();
1064 type CallExecutor = SchedulerPaymentExecutor;
1065 type OriginPrivilegeCmp = OriginPrivilegeCmp;
1066 type PreimageProvider = ();
1067 type NoPreimagePostponement = NoPreimagePostponement;
1068}
1069
1070type EvmSponsorshipHandler = (
1071 UniqueEthSponsorshipHandler<Runtime>,
1072 pallet_evm_contract_helpers::HelpersContractSponsoring<Runtime>,
1073);
1074type SponsorshipHandler = (
1075 UniqueSponsorshipHandler<Runtime>,
1076 //pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,
1077 pallet_evm_transaction_payment::BridgeSponsorshipHandler<Runtime>,
1078);
1079
1080impl pallet_evm_transaction_payment::Config for Runtime {
1081 type EvmSponsorshipHandler = EvmSponsorshipHandler;
1082 type Currency = Balances;
1083}
1084
1085impl pallet_charge_transaction::Config for Runtime {
1086 type SponsorshipHandler = SponsorshipHandler;
1087}
1088
1089// impl pallet_contract_helpers::Config for Runtime {
1090// type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
1091// }
1092
1093parameter_types! {
1094 // 0x842899ECF380553E8a4de75bF534cdf6fBF64049
1095 pub const HelpersContractAddress: H160 = H160([
1096 0x84, 0x28, 0x99, 0xec, 0xf3, 0x80, 0x55, 0x3e, 0x8a, 0x4d, 0xe7, 0x5b, 0xf5, 0x34, 0xcd, 0xf6, 0xfb, 0xf6, 0x40, 0x49,
1097 ]);
1098
1099 // 0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f
1100 pub const EvmCollectionHelpersAddress: H160 = H160([
1101 0x6c, 0x4e, 0x9f, 0xe1, 0xae, 0x37, 0xa4, 0x1e, 0x93, 0xce, 0xe4, 0x29, 0xe8, 0xe1, 0x88, 0x1a, 0xbd, 0xcb, 0xb5, 0x4f,
1102 ]);
1103}
1104
1105impl pallet_evm_contract_helpers::Config for Runtime {
1106 type ContractAddress = HelpersContractAddress;
1107 type DefaultSponsoringRateLimit = DefaultSponsoringRateLimit;
1108}
110960
1110construct_runtime!(61construct_runtime!(unique);
1111 pub enum Runtime where
1112 Block = Block,
1113 NodeBlock = opaque::Block,
1114 UncheckedExtrinsic = UncheckedExtrinsic
1115 {
1116 ParachainSystem: cumulus_pallet_parachain_system::{Pallet, Call, Config, Storage, Inherent, Event<T>, ValidateUnsigned} = 20,
1117 ParachainInfo: parachain_info::{Pallet, Storage, Config} = 21,
1118
1119 Aura: pallet_aura::{Pallet, Config<T>} = 22,
1120 AuraExt: cumulus_pallet_aura_ext::{Pallet, Config} = 23,
1121
1122 Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 30,
1123 RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage} = 31,
1124 Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 32,
1125 TransactionPayment: pallet_transaction_payment::{Pallet, Storage} = 33,
1126 Treasury: pallet_treasury::{Pallet, Call, Storage, Config, Event<T>} = 34,
1127 Sudo: pallet_sudo::{Pallet, Call, Storage, Config<T>, Event<T>} = 35,
1128 System: frame_system::{Pallet, Call, Storage, Config, Event<T>} = 36,
1129 Vesting: orml_vesting::{Pallet, Storage, Call, Event<T>, Config<T>} = 37,
1130 // Vesting: pallet_vesting::{Pallet, Call, Config<T>, Storage, Event<T>} = 37,
1131 // Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>} = 38,
1132
1133 // XCM helpers.
1134 XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event<T>} = 50,
1135 PolkadotXcm: pallet_xcm::{Pallet, Call, Event<T>, Origin} = 51,
1136 CumulusXcm: cumulus_pallet_xcm::{Pallet, Call, Event<T>, Origin} = 52,
1137 DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event<T>} = 53,
1138
1139 // Unique Pallets
1140 Inflation: pallet_inflation::{Pallet, Call, Storage} = 60,
1141 Unique: pallet_unique::{Pallet, Call, Storage, Event<T>} = 61,
1142 Scheduler: pallet_unique_scheduler::{Pallet, Call, Storage, Event<T>} = 62,
1143 // free = 63
1144 Charging: pallet_charge_transaction::{Pallet, Call, Storage } = 64,
1145 // ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage} = 65,
1146 Common: pallet_common::{Pallet, Storage, Event<T>} = 66,
1147 Fungible: pallet_fungible::{Pallet, Storage} = 67,
1148 Refungible: pallet_refungible::{Pallet, Storage} = 68,
1149 Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
1150 Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
1151
1152 // Frontier
1153 EVM: pallet_evm::{Pallet, Config, Call, Storage, Event<T>} = 100,
1154 Ethereum: pallet_ethereum::{Pallet, Config, Call, Storage, Event, Origin} = 101,
1155
1156 EvmCoderSubstrate: pallet_evm_coder_substrate::{Pallet, Storage} = 150,
1157 EvmContractHelpers: pallet_evm_contract_helpers::{Pallet, Storage} = 151,
1158 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
1159 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
1160 }
1161);
1162
1163pub struct TransactionConverter;
1164
1165impl fp_rpc::ConvertTransaction<UncheckedExtrinsic> for TransactionConverter {
1166 fn convert_transaction(&self, transaction: pallet_ethereum::Transaction) -> UncheckedExtrinsic {
1167 UncheckedExtrinsic::new_unsigned(
1168 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1169 )
1170 }
1171}
1172
1173impl fp_rpc::ConvertTransaction<opaque::UncheckedExtrinsic> for TransactionConverter {
1174 fn convert_transaction(
1175 &self,
1176 transaction: pallet_ethereum::Transaction,
1177 ) -> opaque::UncheckedExtrinsic {
1178 let extrinsic = UncheckedExtrinsic::new_unsigned(
1179 pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
1180 );
1181 let encoded = extrinsic.encode();
1182 opaque::UncheckedExtrinsic::decode(&mut &encoded[..])
1183 .expect("Encoded extrinsic is always valid")
1184 }
1185}
1186
1187/// The address format for describing accounts.
1188pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
1189/// Block header type as expected by this runtime.
1190pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
1191/// Block type as expected by this runtime.
1192pub type Block = generic::Block<Header, UncheckedExtrinsic>;
1193/// A Block signed with a Justification
1194pub type SignedBlock = generic::SignedBlock<Block>;
1195/// BlockId type as expected by this runtime.
1196pub type BlockId = generic::BlockId<Block>;
1197/// The SignedExtension to the basic transaction logic.
1198pub type SignedExtra = (
1199 frame_system::CheckSpecVersion<Runtime>,
1200 // system::CheckTxVersion<Runtime>,
1201 frame_system::CheckGenesis<Runtime>,
1202 frame_system::CheckEra<Runtime>,
1203 frame_system::CheckNonce<Runtime>,
1204 frame_system::CheckWeight<Runtime>,
1205 pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
1206 //pallet_contract_helpers::ContractHelpersExtension<Runtime>,
1207 pallet_ethereum::FakeTransactionFinalizer<Runtime>,
1208);
1209pub type SignedExtraScheduler = (
1210 frame_system::CheckSpecVersion<Runtime>,
1211 frame_system::CheckGenesis<Runtime>,
1212 frame_system::CheckEra<Runtime>,
1213 frame_system::CheckNonce<Runtime>,
1214 frame_system::CheckWeight<Runtime>,
1215 // pallet_charge_transaction::ChargeTransactionPayment<Runtime>,
1216);
1217/// Unchecked extrinsic type as expected by this runtime.
1218pub type UncheckedExtrinsic =
1219 fp_self_contained::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
1220/// Extrinsic type that has already been checked.
1221pub type CheckedExtrinsic = fp_self_contained::CheckedExtrinsic<AccountId, Call, SignedExtra, H160>;
1222/// Executive: handles dispatch to the various modules.
1223pub type Executive = frame_executive::Executive<
1224 Runtime,
1225 Block,
1226 frame_system::ChainContext<Runtime>,
1227 Runtime,
1228 AllPalletsReversedWithSystemFirst,
1229>;
1230
1231impl_opaque_keys! {
1232 pub struct SessionKeys {
1233 pub aura: Aura,
1234 }
1235}
1236
1237impl fp_self_contained::SelfContainedCall for Call {
1238 type SignedInfo = H160;
1239
1240 fn is_self_contained(&self) -> bool {
1241 match self {
1242 Call::Ethereum(call) => call.is_self_contained(),
1243 _ => false,
1244 }
1245 }
1246
1247 fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>> {
1248 match self {
1249 Call::Ethereum(call) => call.check_self_contained(),
1250 _ => None,
1251 }
1252 }
1253
1254 fn validate_self_contained(
1255 &self,
1256 info: &Self::SignedInfo,
1257 dispatch_info: &DispatchInfoOf<Call>,
1258 len: usize,
1259 ) -> Option<TransactionValidity> {
1260 match self {
1261 Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
1262 _ => None,
1263 }
1264 }
1265
1266 fn pre_dispatch_self_contained(
1267 &self,
1268 info: &Self::SignedInfo,
1269 ) -> Option<Result<(), TransactionValidityError>> {
1270 match self {
1271 Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
1272 _ => None,
1273 }
1274 }
1275
1276 fn apply_self_contained(
1277 self,
1278 info: Self::SignedInfo,
1279 ) -> Option<sp_runtime::DispatchResultWithInfo<PostDispatchInfoOf<Self>>> {
1280 match self {
1281 call @ Call::Ethereum(pallet_ethereum::Call::transact { .. }) => Some(call.dispatch(
1282 Origin::from(pallet_ethereum::RawOrigin::EthereumTransaction(info)),
1283 )),
1284 _ => None,
1285 }
1286 }
1287}
1288
1289macro_rules! dispatch_unique_runtime {
1290 ($collection:ident.$method:ident($($name:ident),*)) => {{
1291 let collection = <Runtime as pallet_common::Config>::CollectionDispatch::dispatch(<pallet_common::CollectionHandle<Runtime>>::try_get($collection)?);
1292 let dispatch = collection.as_dyn();
1293
1294 Ok::<_, DispatchError>(dispatch.$method($($name),*))
1295 }};
1296}
129762
1298impl_common_runtime_apis! {63impl_common_runtime_apis!();
1299 #![custom_apis]
1300
1301 impl rmrk_rpc::RmrkApi<
1302 Block,
1303 AccountId,
1304 RmrkCollectionInfo<AccountId>,
1305 RmrkInstanceInfo<AccountId>,
1306 RmrkResourceInfo,
1307 RmrkPropertyInfo,
1308 RmrkBaseInfo<AccountId>,
1309 RmrkPartType,
1310 RmrkTheme
1311 > for Runtime {
1312 fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
1313 Ok(Default::default())
1314 }
1315
1316 fn collection_by_id(_collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
1317 Ok(Default::default())
1318 }
1319
1320 fn nft_by_id(_collection_id: RmrkCollectionId, _nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
1321 Ok(Default::default())
1322 }
1323
1324 fn account_tokens(_account_id: AccountId, _collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
1325 Ok(Default::default())
1326 }
1327
1328 fn nft_children(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
1329 Ok(Default::default())
1330 }
1331
1332 fn collection_properties(_collection_id: RmrkCollectionId, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
1333 Ok(Default::default())
1334 }
1335
1336 fn nft_properties(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
1337 Ok(Default::default())
1338 }
1339
1340 fn nft_resources(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
1341 Ok(Default::default())
1342 }
1343
1344 fn nft_resource_priority(_collection_id: RmrkCollectionId, _nft_id: RmrkNftId, _resource_id: RmrkResourceId) -> Result<Option<u32>, DispatchError> {
1345 Ok(Default::default())
1346 }
1347
1348 fn base(_base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
1349 Ok(Default::default())
1350 }
1351
1352 fn base_parts(_base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
1353 Ok(Default::default())
1354 }
1355
1356 fn theme_names(_base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
1357 Ok(Default::default())
1358 }
1359
1360 fn theme(_base_id: RmrkBaseId, _theme_name: RmrkThemeName, _filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
1361 Ok(Default::default())
1362 }
1363 }
1364}
1365
1366struct CheckInherents;
1367
1368impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
1369 fn check_inherents(
1370 block: &Block,
1371 relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
1372 ) -> sp_inherents::CheckInherentsResult {
1373 let relay_chain_slot = relay_state_proof
1374 .read_slot()
1375 .expect("Could not read the relay chain slot from the proof");
1376
1377 let inherent_data =
1378 cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration(
1379 relay_chain_slot,
1380 sp_std::time::Duration::from_secs(6),
1381 )
1382 .create_inherent_data()
1383 .expect("Could not create the timestamp inherent data");
1384
1385 inherent_data.check_extrinsics(block)
1386 }
1387}
138864
1389cumulus_pallet_parachain_system::register_validate_block!(65cumulus_pallet_parachain_system::register_validate_block!(
1390 Runtime = Runtime,66 Runtime = Runtime,
modifiedtests/src/approve.test.tsdiffbeforeafterboth
32 getCreatedCollectionCount,32 getCreatedCollectionCount,
33 transferFromExpectSuccess,33 transferFromExpectSuccess,
34 transferFromExpectFail,34 transferFromExpectFail,
35 requirePallets,
36 Pallets,
35} from './util/helpers';37} from './util/helpers';
3638
37chai.use(chaiAsPromised);39chai.use(chaiAsPromised);
49 });51 });
50 });52 });
53
54 it('[nft] Execute the extrinsic and check approvedList', async () => {
55 const nftCollectionId = await createCollectionExpectSuccess();
56 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
57 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
58 });
59
60 it('[fungible] Execute the extrinsic and check approvedList', async () => {
61 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
62 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
63 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
64 });
65
66 it('[refungible] Execute the extrinsic and check approvedList', async function() {
67 await requirePallets(this, [Pallets.ReFungible]);
68
69 const reFungibleCollectionId =
70 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
71 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
72 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
73 });
74
75 it('[nft] Remove approval by using 0 amount', async () => {
76 const nftCollectionId = await createCollectionExpectSuccess();
77 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
78 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);
79 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);
80 });
5181
52 it('Execute the extrinsic and check approvedList', async () => {82 it('[fungible] Remove approval by using 0 amount', async () => {
53 const nftCollectionId = await createCollectionExpectSuccess();
54 // nft
55 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
56 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
57 // fungible
58 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});83 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
59 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');84 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
60 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);85 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);
61 // reFungible
62 const reFungibleCollectionId =
63 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
64 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
65 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);86 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);
66 });87 });
6788
68 it('Remove approval by using 0 amount', async () => {89 it('[refungible] Remove approval by using 0 amount', async function() {
69 const nftCollectionId = await createCollectionExpectSuccess();
70 // nft
71 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
72 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);90 await requirePallets(this, [Pallets.ReFungible]);
73 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);91
74 // fungible
75 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
76 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
77 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);
78 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);
79 // reFungible
80 const reFungibleCollectionId =92 const reFungibleCollectionId =
81 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});93 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
82 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');94 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
117 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);129 await approveExpectSuccess(collectionId, itemId, bob, charlie.address);
118 });130 });
119131
120 it('ReFungible up to an approved amount', async () => {132 it('ReFungible up to an approved amount', async function() {
133 await requirePallets(this, [Pallets.ReFungible]);
134
121 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});135 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
122 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);136 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
151 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');165 await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');
152 });166 });
153167
154 it('ReFungible up to an approved amount', async () => {168 it('ReFungible up to an approved amount', async function() {
169 await requirePallets(this, [Pallets.ReFungible]);
170
155 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});171 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
156 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);172 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
188 await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);204 await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);
189 });205 });
190206
191 it('ReFungible up to an approved amount', async () => {207 it('ReFungible up to an approved amount', async function() {
208 await requirePallets(this, [Pallets.ReFungible]);
209
192 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});210 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
193 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);211 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);
250 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);268 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);
251 });269 });
252270
253 it('ReFungible', async () => {271 it('ReFungible', async function() {
272 await requirePallets(this, [Pallets.ReFungible]);
273
254 const reFungibleCollectionId =274 const reFungibleCollectionId =
255 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});275 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
285 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);305 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);
286 });306 });
287307
288 it('ReFungible', async () => {308 it('ReFungible', async function() {
309 await requirePallets(this, [Pallets.ReFungible]);
310
289 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});311 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
290 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');312 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
325 await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');347 await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');
326 });348 });
327349
328 it('ReFungible up to an approved amount', async () => {350 it('ReFungible up to an approved amount', async function() {
351 await requirePallets(this, [Pallets.ReFungible]);
352
329 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});353 const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});
330 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});354 await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true});
422 });446 });
423 });447 });
424448
425 it('Approve for a collection that does not exist', async () => {449 it('[nft] Approve for a collection that does not exist', async () => {
426 await usingApi(async (api: ApiPromise) => {450 await usingApi(async (api: ApiPromise) => {
427 // nft
428 const nftCollectionCount = await getCreatedCollectionCount(api);451 const nftCollectionCount = await getCreatedCollectionCount(api);
429 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);452 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);
430 // fungible
431 const fungibleCollectionCount = await getCreatedCollectionCount(api);
432 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);
433 // reFungible
434 const reFungibleCollectionCount = await getCreatedCollectionCount(api);
435 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
436 });453 });
437 });454 });
455
456 it('[fungible] Approve for a collection that does not exist', async () => {
457 await usingApi(async (api: ApiPromise) => {
458 const fungibleCollectionCount = await getCreatedCollectionCount(api);
459 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);
460 });
461 });
462
463 it('[refungible] Approve for a collection that does not exist', async function() {
464 await requirePallets(this, [Pallets.ReFungible]);
465
466 await usingApi(async (api: ApiPromise) => {
467 const reFungibleCollectionCount = await getCreatedCollectionCount(api);
468 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
469 });
470 });
471
472 it('[nft] Approve for a collection that was destroyed', async () => {
473 const nftCollectionId = await createCollectionExpectSuccess();
474 await destroyCollectionExpectSuccess(nftCollectionId);
475 await approveExpectFail(nftCollectionId, 1, alice, bob);
476 });
438477
439 it('Approve for a collection that was destroyed', async () => {478 it('Approve for a collection that was destroyed', async () => {
440 // nft
441 const nftCollectionId = await createCollectionExpectSuccess();
442 await destroyCollectionExpectSuccess(nftCollectionId);
443 await approveExpectFail(nftCollectionId, 1, alice, bob);
444 // fungible
445 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});479 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
446 await destroyCollectionExpectSuccess(fungibleCollectionId);480 await destroyCollectionExpectSuccess(fungibleCollectionId);
447 await approveExpectFail(fungibleCollectionId, 0, alice, bob);481 await approveExpectFail(fungibleCollectionId, 0, alice, bob);
448 // reFungible
449 const reFungibleCollectionId =
450 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
451 await destroyCollectionExpectSuccess(reFungibleCollectionId);
452 await approveExpectFail(reFungibleCollectionId, 1, alice, bob);
453 });482 });
483
484 it('[refungible] Approve for a collection that was destroyed', async function() {
485 await requirePallets(this, [Pallets.ReFungible]);
486
487 const reFungibleCollectionId =
488 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
489 await destroyCollectionExpectSuccess(reFungibleCollectionId);
490 await approveExpectFail(reFungibleCollectionId, 1, alice, bob);
491 });
492
493 it('[nft] Approve transfer of a token that does not exist', async () => {
494 const nftCollectionId = await createCollectionExpectSuccess();
495 await approveExpectFail(nftCollectionId, 2, alice, bob);
496 });
454497
455 it('Approve transfer of a token that does not exist', async () => {498 it('[refungible] Approve transfer of a token that does not exist', async function() {
456 // nft
457 const nftCollectionId = await createCollectionExpectSuccess();
458 await approveExpectFail(nftCollectionId, 2, alice, bob);499 await requirePallets(this, [Pallets.ReFungible]);
459 // reFungible500
460 const reFungibleCollectionId =501 const reFungibleCollectionId =
461 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});502 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
462 await approveExpectFail(reFungibleCollectionId, 2, alice, bob);503 await approveExpectFail(reFungibleCollectionId, 2, alice, bob);
463 });504 });
505
506 it('[nft] Approve using the address that does not own the approved token', async () => {
507 const nftCollectionId = await createCollectionExpectSuccess();
508 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
509 await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);
510 });
511
512 it('[fungible] Approve using the address that does not own the approved token', async () => {
513 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
514 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
515 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);
516 });
464517
465 it('Approve using the address that does not own the approved token', async () => {518 it('[refungible] Approve using the address that does not own the approved token', async function() {
466 const nftCollectionId = await createCollectionExpectSuccess();
467 // nft
468 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
469 await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);
470 // fungible
471 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});519 await requirePallets(this, [Pallets.ReFungible]);
472 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');520
473 await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);
474 // reFungible
475 const reFungibleCollectionId =521 const reFungibleCollectionId =
476 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});522 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
477 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');523 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
478 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);524 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);
479 });525 });
480526
481 it('should fail if approved more ReFungibles than owned', async () => {527 it('should fail if approved more ReFungibles than owned', async function() {
528 await requirePallets(this, [Pallets.ReFungible]);
529
482 const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});530 const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
483 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');531 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');
modifiedtests/src/burnItem.test.tsdiffbeforeafterboth
25 getBalance,25 getBalance,
26 setCollectionLimitsExpectSuccess,26 setCollectionLimitsExpectSuccess,
27 isTokenExists,27 isTokenExists,
28 requirePallets,
29 Pallets,
28} from './util/helpers';30} from './util/helpers';
2931
30import chai from 'chai';32import chai from 'chai';
80 });82 });
81 });83 });
8284
83 it('Burn item in ReFungible collection', async () => {85 it('Burn item in ReFungible collection', async function() {
86 await requirePallets(this, [Pallets.ReFungible]);
87
84 const createMode = 'ReFungible';88 const createMode = 'ReFungible';
85 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});89 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
99 });103 });
100 });104 });
101105
102 it('Burn owned portion of item in ReFungible collection', async () => {106 it('Burn owned portion of item in ReFungible collection', async function() {
107 await requirePallets(this, [Pallets.ReFungible]);
108
103 const createMode = 'ReFungible';109 const createMode = 'ReFungible';
104 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});110 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
189 });195 });
190196
191 // TODO: burnFrom197 // TODO: burnFrom
192 it('Burn item in ReFungible collection', async () => {198 it('Burn item in ReFungible collection', async function() {
199 await requirePallets(this, [Pallets.ReFungible]);
200
193 const createMode = 'ReFungible';201 const createMode = 'ReFungible';
194 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});202 const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
modifiedtests/src/confirmSponsorship.test.tsdiffbeforeafterboth
33 addCollectionAdminExpectSuccess,33 addCollectionAdminExpectSuccess,
34 getCreatedCollectionCount,34 getCreatedCollectionCount,
35 UNIQUE,35 UNIQUE,
36 requirePallets,
37 Pallets,
36} from './util/helpers';38} from './util/helpers';
37import {IKeyringPair} from '@polkadot/types/types';39import {IKeyringPair} from '@polkadot/types/types';
3840
124 });126 });
125 });127 });
126128
127 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {129 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async function() {
130 await requirePallets(this, [Pallets.ReFungible]);
131
128 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});132 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
129 await setCollectionSponsorExpectSuccess(collectionId, bob.address);133 await setCollectionSponsorExpectSuccess(collectionId, bob.address);
252 });256 });
253 });257 });
254258
255 it('ReFungible: Sponsoring is rate limited', async () => {259 it('ReFungible: Sponsoring is rate limited', async function() {
260 await requirePallets(this, [Pallets.ReFungible]);
261
256 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});262 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
257 await setCollectionSponsorExpectSuccess(collectionId, bob.address);263 await setCollectionSponsorExpectSuccess(collectionId, bob.address);
modifiedtests/src/createCollection.test.tsdiffbeforeafterboth
1616
17import {expect} from 'chai';17import {expect} from 'chai';
18import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';18import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';
19import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess} from './util/helpers';19import {createCollectionWithPropsExpectFailure, createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo, createCollectionWithPropsExpectSuccess, requirePallets, Pallets} from './util/helpers';
2020
21describe('integration test: ext. createCollection():', () => {21describe('integration test: ext. createCollection():', () => {
22 it('Create new NFT collection', async () => {22 it('Create new NFT collection', async () => {
34 it('Create new Fungible collection', async () => {34 it('Create new Fungible collection', async () => {
35 await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});35 await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
36 });36 });
37 it('Create new ReFungible collection', async () => {37 it('Create new ReFungible collection', async function() {
38 await requirePallets(this, [Pallets.ReFungible]);
39
38 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});40 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
39 });41 });
modifiedtests/src/createItem.test.tsdiffbeforeafterboth
29 itApi,29 itApi,
30 normalizeAccountId,30 normalizeAccountId,
31 getCreateItemResult,31 getCreateItemResult,
32 requirePallets,
33 Pallets,
32} from './util/helpers';34} from './util/helpers';
3335
34const expect = chai.expect;36const expect = chai.expect;
79 }81 }
8082
81 });83 });
82 it('Create new item in ReFungible collection', async () => {84 it('Create new item in ReFungible collection', async function() {
85 await requirePallets(this, [Pallets.ReFungible]);
86
83 const createMode = 'ReFungible';87 const createMode = 'ReFungible';
84 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});88 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
96 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);100 await addCollectionAdminExpectSuccess(alice, newCollectionID, bob.address);
97 await createItemExpectSuccess(bob, newCollectionID, createMode);101 await createItemExpectSuccess(bob, newCollectionID, createMode);
98 });102 });
99 it('Create new item in ReFungible collection with collection admin permissions', async () => {103 it('Create new item in ReFungible collection with collection admin permissions', async function() {
104 await requirePallets(this, [Pallets.ReFungible]);
105
100 const createMode = 'ReFungible';106 const createMode = 'ReFungible';
101 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});107 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
175 });181 });
176 });182 });
177183
178 it('Check total pieces of ReFungible token', async () => {184 it('Check total pieces of ReFungible token', async function() {
185 await requirePallets(this, [Pallets.ReFungible]);
186
179 await usingApi(async api => {187 await usingApi(async api => {
180 const createMode = 'ReFungible';188 const createMode = 'ReFungible';
219 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});227 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
220 await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;228 await expect(createItemExpectSuccess(bob, newCollectionID, createMode)).to.be.rejected;
221 });229 });
222 it('Regular user cannot create new item in ReFungible collection', async () => {230 it('Regular user cannot create new item in ReFungible collection', async function() {
231 await requirePallets(this, [Pallets.ReFungible]);
232
223 const createMode = 'ReFungible';233 const createMode = 'ReFungible';
224 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});234 const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
296 });306 });
297 });307 });
298308
299 it('Check total pieces for invalid Refungible token', async () => {309 it('Check total pieces for invalid Refungible token', async function() {
310 await requirePallets(this, [Pallets.ReFungible]);
311
300 await usingApi(async api => {312 await usingApi(async api => {
301 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});313 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
33 createCollectionWithPropsExpectSuccess,33 createCollectionWithPropsExpectSuccess,
34 createMultipleItemsWithPropsExpectSuccess,34 createMultipleItemsWithPropsExpectSuccess,
35 getTokenProperties,35 getTokenProperties,
36 requirePallets,
37 Pallets,
38 checkPalletsPresence,
36} from './util/helpers';39} from './util/helpers';
3740
38chai.use(chaiAsPromised);41chai.use(chaiAsPromised);
91 });94 });
92 });95 });
9396
94 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {97 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {
98 await requirePallets(this, [Pallets.ReFungible]);
99
95 await usingApi(async (api, privateKeyWrapper) => {100 await usingApi(async (api, privateKeyWrapper) => {
96 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});101 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
272 });277 });
273 });278 });
274279
275 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {280 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async function() {
281 await requirePallets(this, [Pallets.ReFungible]);
282
276 await usingApi(async (api: ApiPromise) => {283 await usingApi(async (api: ApiPromise) => {
277 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});284 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
335 });342 });
336 });343 });
337344
338 it('Regular user cannot create items in active ReFungible collection', async () => {345 it('Regular user cannot create items in active ReFungible collection', async function() {
346 await requirePallets(this, [Pallets.ReFungible]);
347
339 await usingApi(async (api: ApiPromise) => {348 await usingApi(async (api: ApiPromise) => {
340 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});349 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
358 });367 });
359 });368 });
369
370 it('Create NFTs that has reached the maximum data limit', async function() {
371 await usingApi(async (api, privateKeyWrapper) => {
372 const collectionId = await createCollectionWithPropsExpectSuccess({
373 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],
374 });
375 const alice = privateKeyWrapper('//Alice');
376 const args = [
377 {NFT: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},
378 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},
379 {NFT: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},
380 ];
381 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
382 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
383 });
384 });
360385
361 it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {386 it('Create Refungible tokens that has reached the maximum data limit', async function() {
387 await requirePallets(this, [Pallets.ReFungible]);
388
362 await usingApi(async (api, privateKeyWrapper) => {389 await usingApi(async api => {
363 // NFT
364 const collectionId = await createCollectionWithPropsExpectSuccess({
365 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],
366 });
367 const alice = privateKeyWrapper('//Alice');
368 const args = [
369 {NFT: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},
370 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},
371 {NFT: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},
372 ];
373 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);
374 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;
375
376 // ReFungible
377 const collectionIdReFungible =390 const collectionIdReFungible =
378 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});391 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
379 {392 {
403 await usingApi(async (api: ApiPromise) => {416 await usingApi(async (api: ApiPromise) => {
404 const collectionId = await createCollectionExpectSuccess();417 const collectionId = await createCollectionExpectSuccess();
418
419 const types = ['NFT', 'Fungible'];
420
421 if (await checkPalletsPresence([Pallets.ReFungible])) {
422 types.push('ReFungible');
423 }
424
405 const createMultipleItemsTx = api.tx.unique425 const createMultipleItemsTx = api.tx.unique
406 .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'Fungible', 'ReFungible']);426 .createMultipleItems(collectionId, normalizeAccountId(alice.address), types);
407 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);427 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);
408 // garbage collection :-D // lol428 // garbage collection :-D // lol
409 await destroyCollectionExpectSuccess(collectionId);429 await destroyCollectionExpectSuccess(collectionId);
modifiedtests/src/createMultipleItemsEx.test.tsdiffbeforeafterboth
1616
17import {expect} from 'chai';17import {expect} from 'chai';
18import usingApi, {executeTransaction} from './substrate/substrate-api';18import usingApi, {executeTransaction} from './substrate/substrate-api';
19import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties} from './util/helpers';19import {addCollectionAdminExpectSuccess, createCollectionExpectSuccess, createCollectionWithPropsExpectSuccess, getBalance, getLastTokenId, getTokenProperties, requirePallets, Pallets} from './util/helpers';
2020
21describe('Integration Test: createMultipleItemsEx', () => {21describe('Integration Test: createMultipleItemsEx', () => {
22 it('can initialize multiple NFT with different owners', async () => {22 it('can initialize multiple NFT with different owners', async () => {
146 });146 });
147 });147 });
148148
149 it('can initialize an RFT with multiple owners', async () => {149 it('can initialize an RFT with multiple owners', async function() {
150 await requirePallets(this, [Pallets.ReFungible]);
151
150 await usingApi(async (api, privateKeyWrapper) => {152 await usingApi(async (api, privateKeyWrapper) => {
151 const alice = privateKeyWrapper('//Alice');153 const alice = privateKeyWrapper('//Alice');
178 });180 });
179 });181 });
180182
181 it('can initialize multiple RFTs with the same owner', async () => {183 it('can initialize multiple RFTs with the same owner', async function() {
184 await requirePallets(this, [Pallets.ReFungible]);
185
182 await usingApi(async (api, privateKeyWrapper) => {186 await usingApi(async (api, privateKeyWrapper) => {
183 const alice = privateKeyWrapper('//Alice');187 const alice = privateKeyWrapper('//Alice');
389 });393 });
390 });394 });
391395
392 it('fails when trying to set multiple owners when creating multiple refungibles', async () => {396 it('fails when trying to set multiple owners when creating multiple refungibles', async function() {
397 await requirePallets(this, [Pallets.ReFungible]);
398
393 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});399 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
394400
modifiedtests/src/destroyCollection.test.tsdiffbeforeafterboth
25 addCollectionAdminExpectSuccess,25 addCollectionAdminExpectSuccess,
26 getCreatedCollectionCount,26 getCreatedCollectionCount,
27 createItemExpectSuccess,27 createItemExpectSuccess,
28 requirePallets,
29 Pallets,
28} from './util/helpers';30} from './util/helpers';
2931
30chai.use(chaiAsPromised);32chai.use(chaiAsPromised);
38 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});40 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
39 await destroyCollectionExpectSuccess(collectionId);41 await destroyCollectionExpectSuccess(collectionId);
40 });42 });
41 it('ReFungible collection can be destroyed', async () => {43 it('ReFungible collection can be destroyed', async function() {
44 await requirePallets(this, [Pallets.ReFungible]);
45
42 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});46 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
43 await destroyCollectionExpectSuccess(collectionId);47 await destroyCollectionExpectSuccess(collectionId);
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
1616
17import {evmToAddress} from '@polkadot/util-crypto';17import {evmToAddress} from '@polkadot/util-crypto';
18import {expect} from 'chai';18import {expect} from 'chai';
19import {getCreatedCollectionCount, getDetailedCollectionInfo} from '../util/helpers';19import {getCreatedCollectionCount, getDetailedCollectionInfo, requirePallets, Pallets} from '../util/helpers';
20import {20import {
21 evmCollectionHelpers,21 evmCollectionHelpers,
22 collectionIdToAddress,22 collectionIdToAddress,
28} from './util/helpers';28} from './util/helpers';
2929
30describe('Create RFT collection from EVM', () => {30describe('Create RFT collection from EVM', () => {
31 before(async function() {
32 await requirePallets(this, [Pallets.ReFungible]);
33 });
34
31 itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {35 itWeb3('Create collection', async ({api, web3, privateKeyWrapper}) => {
32 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);36 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
146});150});
147151
148describe('(!negative tests!) Create RFT collection from EVM', () => {152describe('(!negative tests!) Create RFT collection from EVM', () => {
153 before(async function() {
154 await requirePallets(this, [Pallets.ReFungible]);
155 });
156
149 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {157 itWeb3('(!negative test!) Create collection (bad lengths)', async ({api, web3, privateKeyWrapper}) => {
150 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);158 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
modifiedtests/src/eth/reFungible.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {createCollectionExpectSuccess, UNIQUE} from '../util/helpers';17import {createCollectionExpectSuccess, UNIQUE, requirePallets, Pallets} from '../util/helpers';
18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress} from './util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, tokenIdToAddress} from './util/helpers';
19import reFungibleTokenAbi from './reFungibleTokenAbi.json';19import reFungibleTokenAbi from './reFungibleTokenAbi.json';
20import {expect} from 'chai';20import {expect} from 'chai';
2121
22describe('Refungible: Information getting', () => {22describe('Refungible: Information getting', () => {
23 before(async function() {
24 await requirePallets(this, [Pallets.ReFungible]);
25 });
26
23 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {27 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
24 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);28 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
120});124});
121125
122describe('Refungible: Plain calls', () => {126describe('Refungible: Plain calls', () => {
127 before(async function() {
128 await requirePallets(this, [Pallets.ReFungible]);
129 });
130
123 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {131 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
124 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);132 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
399});407});
400408
401describe('RFT: Fees', () => {409describe('RFT: Fees', () => {
410 before(async function() {
411 await requirePallets(this, [Pallets.ReFungible]);
412 });
413
402 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {414 itWeb3('transferFrom() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
403 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);415 const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
435});447});
436448
437describe('Common metadata', () => {449describe('Common metadata', () => {
450 before(async function() {
451 await requirePallets(this, [Pallets.ReFungible]);
452 });
453
438 itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {454 itWeb3('Returns collection name', async ({api, web3, privateKeyWrapper}) => {
439 const collection = await createCollectionExpectSuccess({455 const collection = await createCollectionExpectSuccess({
modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE} from '../util/helpers';17import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE, requirePallets, Pallets} from '../util/helpers';
18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';
19import reFungibleTokenAbi from './reFungibleTokenAbi.json';19import reFungibleTokenAbi from './reFungibleTokenAbi.json';
2020
24const expect = chai.expect;24const expect = chai.expect;
2525
26describe('Refungible token: Information getting', () => {26describe('Refungible token: Information getting', () => {
27 before(async function() {
28 await requirePallets(this, [Pallets.ReFungible]);
29 });
30
27 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {31 itWeb3('totalSupply', async ({api, web3, privateKeyWrapper}) => {
28 const alice = privateKeyWrapper('//Alice');32 const alice = privateKeyWrapper('//Alice');
7579
76// FIXME: Need erc721 for ReFubgible.80// FIXME: Need erc721 for ReFubgible.
77describe('Check ERC721 token URI for ReFungible', () => {81describe('Check ERC721 token URI for ReFungible', () => {
82 before(async function() {
83 await requirePallets(this, [Pallets.ReFungible]);
84 });
85
78 itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {86 itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {
79 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);87 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
216});224});
217225
218describe('Refungible: Plain calls', () => {226describe('Refungible: Plain calls', () => {
227 before(async function() {
228 await requirePallets(this, [Pallets.ReFungible]);
229 });
230
219 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {231 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
220 const alice = privateKeyWrapper('//Alice');232 const alice = privateKeyWrapper('//Alice');
477});489});
478490
479describe('Refungible: Fees', () => {491describe('Refungible: Fees', () => {
492 before(async function() {
493 await requirePallets(this, [Pallets.ReFungible]);
494 });
495
480 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {496 itWeb3('approve() call fee is less than 0.2UNQ', async ({web3, api, privateKeyWrapper}) => {
481 const alice = privateKeyWrapper('//Alice');497 const alice = privateKeyWrapper('//Alice');
532});548});
533549
534describe('Refungible: Substrate calls', () => {550describe('Refungible: Substrate calls', () => {
551 before(async function() {
552 await requirePallets(this, [Pallets.ReFungible]);
553 });
554
535 itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {555 itWeb3('Events emitted for approve()', async ({web3, api, privateKeyWrapper}) => {
536 const alice = privateKeyWrapper('//Alice');556 const alice = privateKeyWrapper('//Alice');
modifiedtests/src/eth/scheduling.test.tsdiffbeforeafterboth
1616
17import {expect} from 'chai';17import {expect} from 'chai';
18import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';18import {createEthAccountWithBalance, deployFlipper, GAS_ARGS, itWeb3, subToEth, transferBalanceToEth} from './util/helpers';
19import {scheduleExpectSuccess, waitNewBlocks} from '../util/helpers';19import {scheduleExpectSuccess, waitNewBlocks, requirePallets, Pallets} from '../util/helpers';
2020
21describe('Scheduing EVM smart contracts', () => {21describe('Scheduing EVM smart contracts', () => {
22 before(async function() {
23 await requirePallets(this, [Pallets.Scheduler]);
24 });
25
22 itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {26 itWeb3('Successfully schedules and periodically executes an EVM contract', async ({api, web3, privateKeyWrapper}) => {
23 const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);27 const deployer = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
modifiedtests/src/limits.test.tsdiffbeforeafterboth
27 transferExpectSuccess,27 transferExpectSuccess,
28 getFreeBalance,28 getFreeBalance,
29 waitNewBlocks, burnItemExpectSuccess,29 waitNewBlocks, burnItemExpectSuccess,
30 requirePallets,
31 Pallets,
30} from './util/helpers';32} from './util/helpers';
31import {expect} from 'chai';33import {expect} from 'chai';
3234
67describe('Number of tokens per address (ReFungible)', () => {69describe('Number of tokens per address (ReFungible)', () => {
68 let alice: IKeyringPair;70 let alice: IKeyringPair;
6971
70 before(async () => {72 before(async function() {
73 await requirePallets(this, [Pallets.ReFungible]);
74
71 await usingApi(async (api, privateKeyWrapper) => {75 await usingApi(async (api, privateKeyWrapper) => {
72 alice = privateKeyWrapper('//Alice');76 alice = privateKeyWrapper('//Alice');
367 let bob: IKeyringPair;371 let bob: IKeyringPair;
368 let charlie: IKeyringPair;372 let charlie: IKeyringPair;
369373
370 before(async () => {374 before(async function() {
375 await requirePallets(this, [Pallets.ReFungible]);
376
371 await usingApi(async (api, privateKeyWrapper) => {377 await usingApi(async (api, privateKeyWrapper) => {
372 alice = privateKeyWrapper('//Alice');378 alice = privateKeyWrapper('//Alice');
modifiedtests/src/nesting/nest.test.tsdiffbeforeafterboth
17 transferExpectSuccess,17 transferExpectSuccess,
18 transferFromExpectSuccess,18 transferFromExpectSuccess,
19 setCollectionLimitsExpectSuccess,19 setCollectionLimitsExpectSuccess,
20 requirePallets,
21 Pallets,
20} from '../util/helpers';22} from '../util/helpers';
21import {IKeyringPair} from '@polkadot/types/types';23import {IKeyringPair} from '@polkadot/types/types';
2224
311313
312 // ---------- Re-Fungible ----------314 // ---------- Re-Fungible ----------
313315
314 it('ReFungible: allows an Owner to nest/unnest their token', async () => {316 it('ReFungible: allows an Owner to nest/unnest their token', async function() {
317 await requirePallets(this, [Pallets.ReFungible]);
318
315 await usingApi(async api => {319 await usingApi(async api => {
316 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});320 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
333 });337 });
334 });338 });
335339
336 it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async () => {340 it('ReFungible: allows an Owner to nest/unnest their token (Restricted nesting)', async function() {
341 await requirePallets(this, [Pallets.ReFungible]);
342
337 await usingApi(async api => {343 await usingApi(async api => {
338 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});344 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
715721
716 // ---------- Re-Fungible ----------722 // ---------- Re-Fungible ----------
717723
718 it('ReFungible: disallows to nest token if nesting is disabled', async () => {724 it('ReFungible: disallows to nest token if nesting is disabled', async function() {
725 await requirePallets(this, [Pallets.ReFungible]);
726
719 await usingApi(async api => {727 await usingApi(async api => {
720 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});728 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
745 });753 });
746 });754 });
747755
748 it('ReFungible: disallows a non-Owner to nest someone else\'s token', async () => {756 it('ReFungible: disallows a non-Owner to nest someone else\'s token', async function() {
757 await requirePallets(this, [Pallets.ReFungible]);
758
749 await usingApi(async api => {759 await usingApi(async api => {
750 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});760 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
773 });783 });
774 });784 });
775785
776 it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async () => {786 it('ReFungible: disallows a non-Owner to nest someone else\'s token (Restricted nesting)', async function() {
787 await requirePallets(this, [Pallets.ReFungible]);
788
777 await usingApi(async api => {789 await usingApi(async api => {
778 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});790 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
800 });812 });
801 });813 });
802814
803 it('ReFungible: disallows to nest token to an unlisted collection', async () => {815 it('ReFungible: disallows to nest token to an unlisted collection', async function() {
816 await requirePallets(this, [Pallets.ReFungible]);
817
804 await usingApi(async api => {818 await usingApi(async api => {
805 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});819 const collectionNFT = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
8 createItemExpectSuccess,8 createItemExpectSuccess,
9 getCreateCollectionResult,9 getCreateCollectionResult,
10 transferExpectSuccess,10 transferExpectSuccess,
11 requirePallets,
12 Pallets,
11} from '../util/helpers';13} from '../util/helpers';
12import {IKeyringPair} from '@polkadot/types/types';14import {IKeyringPair} from '@polkadot/types/types';
13import {tokenIdToAddress} from '../eth/util/helpers';15import {tokenIdToAddress} from '../eth/util/helpers';
64 await testMakeSureSuppliesRequired({type: 'NFT'});66 await testMakeSureSuppliesRequired({type: 'NFT'});
65 });67 });
6668
67 it('Makes sure collectionById supplies required fields for ReFungible', async () => {69 it('Makes sure collectionById supplies required fields for ReFungible', async function() {
70 await requirePallets(this, [Pallets.ReFungible]);
71
68 await testMakeSureSuppliesRequired({type: 'ReFungible'});72 await testMakeSureSuppliesRequired({type: 'ReFungible'});
69 });73 });
120 it('Sets properties for a NFT collection', async () => {124 it('Sets properties for a NFT collection', async () => {
121 await testSetsPropertiesForCollection('NFT');125 await testSetsPropertiesForCollection('NFT');
122 });126 });
123 it('Sets properties for a ReFungible collection', async () => {127 it('Sets properties for a ReFungible collection', async function() {
128 await requirePallets(this, [Pallets.ReFungible]);
129
124 await testSetsPropertiesForCollection('ReFungible');130 await testSetsPropertiesForCollection('ReFungible');
125 });131 });
178 it('Check valid names for NFT collection properties keys', async () => {184 it('Check valid names for NFT collection properties keys', async () => {
179 await testCheckValidNames('NFT');185 await testCheckValidNames('NFT');
180 });186 });
181 it('Check valid names for ReFungible collection properties keys', async () => {187 it('Check valid names for ReFungible collection properties keys', async function() {
188 await requirePallets(this, [Pallets.ReFungible]);
189
182 await testCheckValidNames('ReFungible');190 await testCheckValidNames('ReFungible');
183 });191 });
209 it('Changes properties of a NFT collection', async () => {217 it('Changes properties of a NFT collection', async () => {
210 await testChangesProperties({type: 'NFT'});218 await testChangesProperties({type: 'NFT'});
211 });219 });
212 it('Changes properties of a ReFungible collection', async () => {220 it('Changes properties of a ReFungible collection', async function() {
221 await requirePallets(this, [Pallets.ReFungible]);
222
213 await testChangesProperties({type: 'ReFungible'});223 await testChangesProperties({type: 'ReFungible'});
214 });224 });
238 it('Deletes properties of a NFT collection', async () => {248 it('Deletes properties of a NFT collection', async () => {
239 await testDeleteProperties({type: 'NFT'});249 await testDeleteProperties({type: 'NFT'});
240 });250 });
241 it('Deletes properties of a ReFungible collection', async () => {251 it('Deletes properties of a ReFungible collection', async function() {
252 await requirePallets(this, [Pallets.ReFungible]);
253
242 await testDeleteProperties({type: 'ReFungible'});254 await testDeleteProperties({type: 'ReFungible'});
243 });255 });
269 it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {281 it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {
270 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});282 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});
271 });283 });
272 it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async () => {284 it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async function() {
285 await requirePallets(this, [Pallets.ReFungible]);
286
273 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});287 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});
274 });288 });
307 it('Fails to set properties that exceed the limits (NFT)', async () => {321 it('Fails to set properties that exceed the limits (NFT)', async () => {
308 await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});322 await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});
309 });323 });
310 it('Fails to set properties that exceed the limits (ReFungible)', async () => {324 it('Fails to set properties that exceed the limits (ReFungible)', async function() {
325 await requirePallets(this, [Pallets.ReFungible]);
326
311 await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});327 await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});
312 });328 });
337 it('Fails to set more properties than it is allowed (NFT)', async () => {353 it('Fails to set more properties than it is allowed (NFT)', async () => {
338 await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});354 await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});
339 });355 });
340 it('Fails to set more properties than it is allowed (ReFungible)', async () => {356 it('Fails to set more properties than it is allowed (ReFungible)', async function() {
357 await requirePallets(this, [Pallets.ReFungible]);
358
341 await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});359 await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});
342 });360 });
392 it('Fails to set properties with invalid names (NFT)', async () => {410 it('Fails to set properties with invalid names (NFT)', async () => {
393 await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});411 await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});
394 });412 });
395 it('Fails to set properties with invalid names (ReFungible)', async () => {413 it('Fails to set properties with invalid names (ReFungible)', async function() {
414 await requirePallets(this, [Pallets.ReFungible]);
415
396 await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});416 await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});
397 });417 });
443 it('Sets access rights to properties of a collection (NFT)', async () => {463 it('Sets access rights to properties of a collection (NFT)', async () => {
444 await testSetsAccessRightsToProperties({type: 'NFT'});464 await testSetsAccessRightsToProperties({type: 'NFT'});
445 });465 });
446 it('Sets access rights to properties of a collection (ReFungible)', async () => {466 it('Sets access rights to properties of a collection (ReFungible)', async function() {
467 await requirePallets(this, [Pallets.ReFungible]);
468
447 await testSetsAccessRightsToProperties({type: 'ReFungible'});469 await testSetsAccessRightsToProperties({type: 'ReFungible'});
448 });470 });
472 it('Changes access rights to properties of a NFT collection', async () => {494 it('Changes access rights to properties of a NFT collection', async () => {
473 await testChangesAccessRightsToProperty({type: 'NFT'});495 await testChangesAccessRightsToProperty({type: 'NFT'});
474 });496 });
475 it('Changes access rights to properties of a ReFungible collection', async () => {497 it('Changes access rights to properties of a ReFungible collection', async function() {
498 await requirePallets(this, [Pallets.ReFungible]);
499
476 await testChangesAccessRightsToProperty({type: 'ReFungible'});500 await testChangesAccessRightsToProperty({type: 'ReFungible'});
477 });501 });
502 it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {526 it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {
503 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});527 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});
504 });528 });
505 it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async () => {529 it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async function() {
530 await requirePallets(this, [Pallets.ReFungible]);
531
506 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});532 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});
507 });533 });
531 it('Prevents from adding too many possible properties (NFT)', async () => {557 it('Prevents from adding too many possible properties (NFT)', async () => {
532 await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});558 await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});
533 });559 });
534 it('Prevents from adding too many possible properties (ReFungible)', async () => {560 it('Prevents from adding too many possible properties (ReFungible)', async function() {
561 await requirePallets(this, [Pallets.ReFungible]);
562
535 await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});563 await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});
536 });564 });
560 it('Prevents access rights to be modified if constant (NFT)', async () => {588 it('Prevents access rights to be modified if constant (NFT)', async () => {
561 await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});589 await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});
562 });590 });
563 it('Prevents access rights to be modified if constant (ReFungible)', async () => {591 it('Prevents access rights to be modified if constant (ReFungible)', async function() {
592 await requirePallets(this, [Pallets.ReFungible]);
593
564 await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});594 await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});
565 });595 });
608 it('Prevents adding properties with invalid names (NFT)', async () => {638 it('Prevents adding properties with invalid names (NFT)', async () => {
609 await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});639 await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});
610 });640 });
611 it('Prevents adding properties with invalid names (ReFungible)', async () => {641 it('Prevents adding properties with invalid names (ReFungible)', async function() {
642 await requirePallets(this, [Pallets.ReFungible]);
643
612 await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});644 await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});
613 });645 });
651 it('Reads yet empty properties of a token (NFT)', async () => {683 it('Reads yet empty properties of a token (NFT)', async () => {
652 await testReadsYetEmptyProperties({type: 'NFT'});684 await testReadsYetEmptyProperties({type: 'NFT'});
653 });685 });
654 it('Reads yet empty properties of a token (ReFungible)', async () => {686 it('Reads yet empty properties of a token (ReFungible)', async function() {
687 await requirePallets(this, [Pallets.ReFungible]);
688
655 await testReadsYetEmptyProperties({type: 'ReFungible'});689 await testReadsYetEmptyProperties({type: 'ReFungible'});
656 });690 });
696 it('Assigns properties to a token according to permissions (NFT)', async () => {730 it('Assigns properties to a token according to permissions (NFT)', async () => {
697 await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);731 await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);
698 });732 });
699 it('Assigns properties to a token according to permissions (ReFungible)', async () => {733 it('Assigns properties to a token according to permissions (ReFungible)', async function() {
734 await requirePallets(this, [Pallets.ReFungible]);
735
700 await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);736 await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);
701 });737 });
749 it('Changes properties of a token according to permissions (NFT)', async () => {785 it('Changes properties of a token according to permissions (NFT)', async () => {
750 await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);786 await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);
751 });787 });
752 it('Changes properties of a token according to permissions (ReFungible)', async () => {788 it('Changes properties of a token according to permissions (ReFungible)', async function() {
789 await requirePallets(this, [Pallets.ReFungible]);
790
753 await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);791 await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);
754 });792 });
802 it('Deletes properties of a token according to permissions (NFT)', async () => {840 it('Deletes properties of a token according to permissions (NFT)', async () => {
803 await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);841 await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);
804 });842 });
805 it('Deletes properties of a token according to permissions (ReFungible)', async () => {843 it('Deletes properties of a token according to permissions (ReFungible)', async function() {
844 await requirePallets(this, [Pallets.ReFungible]);
845
806 await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);846 await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);
807 });847 });
1029 it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {1069 it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {
1030 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);1070 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);
1031 });1071 });
1032 it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async () => {1072 it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async function() {
1073 await requirePallets(this, [Pallets.ReFungible]);
1074
1033 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);1075 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);
1034 });1076 });
1062 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {1104 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {
1063 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);1105 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);
1064 });1106 });
1065 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async () => {1107 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async function() {
1108 await requirePallets(this, [Pallets.ReFungible]);
1109
1066 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);1110 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);
1067 });1111 });
1096 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async () => {1140 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (NFT)', async () => {
1097 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'NFT'}, 1);1141 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'NFT'}, 1);
1098 });1142 });
1099 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async () => {1143 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async function() {
1144 await requirePallets(this, [Pallets.ReFungible]);
1145
1100 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);1146 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);
1101 });1147 });
1140 it('Forbids adding too many properties to a token (NFT)', async () => {1186 it('Forbids adding too many properties to a token (NFT)', async () => {
1141 await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);1187 await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);
1142 });1188 });
1143 it('Forbids adding too many properties to a token (ReFungible)', async () => {1189 it('Forbids adding too many properties to a token (ReFungible)', async function() {
1190 await requirePallets(this, [Pallets.ReFungible]);
1191
1144 await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);1192 await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);
1145 });1193 });
1149 let collection: number;1197 let collection: number;
1150 let token: number;1198 let token: number;
11511199
1152 before(async () => {1200 before(async function() {
1201 await requirePallets(this, [Pallets.ReFungible]);
1202
1153 await usingApi(async (api, privateKeyWrapper) => {1203 await usingApi(async (api, privateKeyWrapper) => {
1154 alice = privateKeyWrapper('//Alice');1204 alice = privateKeyWrapper('//Alice');
modifiedtests/src/nesting/rules-smoke.test.tsdiffbeforeafterboth
1import {expect} from 'chai';1import {expect} from 'chai';
2import {tokenIdToAddress} from '../eth/util/helpers';2import {tokenIdToAddress} from '../eth/util/helpers';
3import usingApi, {executeTransaction} from '../substrate/substrate-api';3import usingApi, {executeTransaction} from '../substrate/substrate-api';
4import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult} from '../util/helpers';4import {createCollectionExpectSuccess, createFungibleItemExpectSuccess, createItemExpectSuccess, CrossAccountId, getCreateCollectionResult, requirePallets, Pallets} from '../util/helpers';
5import {IKeyringPair} from '@polkadot/types/types';5import {IKeyringPair} from '@polkadot/types/types';
66
7describe('nesting check', () => {7describe('nesting check', () => {
47 });47 });
48 });48 });
4949
50 it('called for refungible', async () => {50 it('called for refungible', async function() {
51 await requirePallets(this, [Pallets.ReFungible]);
52
51 await usingApi(async api => {53 await usingApi(async api => {
52 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});54 const collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
modifiedtests/src/nesting/unnest.test.tsdiffbeforeafterboth
10 setCollectionPermissionsExpectSuccess,10 setCollectionPermissionsExpectSuccess,
11 transferExpectSuccess,11 transferExpectSuccess,
12 transferFromExpectSuccess,12 transferFromExpectSuccess,
13 requirePallets,
14 Pallets,
13} from '../util/helpers';15} from '../util/helpers';
14import {IKeyringPair} from '@polkadot/types/types';16import {IKeyringPair} from '@polkadot/types/types';
1517
80 });82 });
81 });83 });
8284
83 it('ReFungible: allows the owner to successfully unnest a token', async () => {85 it('ReFungible: allows the owner to successfully unnest a token', async function() {
86 await requirePallets(this, [Pallets.ReFungible]);
87
84 await usingApi(async api => {88 await usingApi(async api => {
85 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});89 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
modifiedtests/src/nextSponsoring.test.tsdiffbeforeafterboth
27 transferExpectSuccess,27 transferExpectSuccess,
28 normalizeAccountId,28 normalizeAccountId,
29 getNextSponsored,29 getNextSponsored,
30 requirePallets,
31 Pallets,
30} from './util/helpers';32} from './util/helpers';
3133
32chai.use(chaiAsPromised);34chai.use(chaiAsPromised);
89 });91 });
90 });92 });
9193
92 it('ReFungible', async () => {94 it('ReFungible', async function() {
95 await requirePallets(this, [Pallets.ReFungible]);
96
93 await usingApi(async (api: ApiPromise) => {97 await usingApi(async (api: ApiPromise) => {
9498
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
49 'inflation',49 'inflation',
50 'unique',50 'unique',
51 'nonfungible',51 'nonfungible',
52 'refungible',
53 'scheduler',
54 'charging',52 'charging',
55];53];
5654
66 await usingApi(async api => {64 await usingApi(async api => {
67 const chain = await api.rpc.system.chain();65 const chain = await api.rpc.system.chain();
66
67 const refungible = 'refungible';
68 const scheduler = 'scheduler';
69 const rmrkPallets = ['rmrkcore', 'rmrkequip'];
6870
69 if (!chain.eq('UNIQUE')) {71 if (chain.eq('OPAL by UNIQUE')) {
70 requiredPallets.push(...['rmrkcore', 'rmrkequip']);72 requiredPallets.push(refungible, scheduler, ...rmrkPallets);
71 }73 } else if (chain.eq('QUARTZ by UNIQUE')) {
74 // Insert Quartz additional pallets here
75 } else if (chain.eq('UNIQUE')) {
76 // Insert Unique additional pallets here
77 }
72 });78 });
73 });79 });
7480
modifiedtests/src/refungible.test.tsdiffbeforeafterboth
36 CrossAccountId,36 CrossAccountId,
37 getCreateItemsResult,37 getCreateItemsResult,
38 getDestroyItemsResult,38 getDestroyItemsResult,
39 getModuleNames,
40 Pallets,
41 requirePallets,
39} from './util/helpers';42} from './util/helpers';
4043
41import chai from 'chai';44import chai from 'chai';
46let alice: IKeyringPair;49let alice: IKeyringPair;
47let bob: IKeyringPair;50let bob: IKeyringPair;
4851
52
53
49describe('integration test: Refungible functionality:', () => {54describe('integration test: Refungible functionality:', async () => {
50 before(async () => {55 before(async function() {
56 await requirePallets(this, [Pallets.ReFungible]);
57
51 await usingApi(async (api, privateKeyWrapper) => {58 await usingApi(async (api, privateKeyWrapper) => {
52 alice = privateKeyWrapper('//Alice');59 alice = privateKeyWrapper('//Alice');
53 bob = privateKeyWrapper('//Bob');60 bob = privateKeyWrapper('//Bob');
61 if (!getModuleNames(api).includes(Pallets.ReFungible)) this.skip();
54 });62 });
63
55 });64 });
5665
57 it('Create refungible collection and token', async () => {66 it('Create refungible collection and token', async () => {
58 await usingApi(async api => {67 await usingApi(async api => {
59 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});68 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});
268 ]);277 ]);
269 });278 });
270 });279 });
271});
272
273describe('Test Refungible properties:', () => {
274 before(async () => {
275 await usingApi(async (api, privateKeyWrapper) => {
276 alice = privateKeyWrapper('//Alice');
277 bob = privateKeyWrapper('//Bob');
278 });
279 });
280 280
281 it('Сreate new collection with properties', async () => {281 it('Сreate new collection with properties', async () => {
282 await usingApi(async api => {282 await usingApi(async api => {
292 });292 });
293 });293 });
294});294});
295
295296
modifiedtests/src/rmrk/acceptNft.test.tsdiffbeforeafterboth
8} from './util/tx';8} from './util/tx';
9import {NftIdTuple} from './util/fetch';9import {NftIdTuple} from './util/fetch';
10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';
11import {requirePallets, Pallets} from '../util/helpers';
1112
12describe('integration test: accept NFT', () => {13describe('integration test: accept NFT', () => {
13 let api: any;14 let api: any;
14 before(async () => { api = await getApiConnection(); });15 before(async function() {
1516 api = await getApiConnection();
17 await requirePallets(this, [Pallets.RmrkCore]);
18 });
19
20
modifiedtests/src/rmrk/addResource.test.tsdiffbeforeafterboth
12 addNftComposableResource,12 addNftComposableResource,
13} from './util/tx';13} from './util/tx';
14import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';14import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';
15import {requirePallets, Pallets} from '../util/helpers';
1516
16describe('integration test: add NFT resource', () => {17describe('integration test: add NFT resource', () => {
17 const Alice = '//Alice';18 const Alice = '//Alice';
24 const nonexistentId = 99999;25 const nonexistentId = 99999;
2526
26 let api: any;27 let api: any;
27 before(async () => {28 before(async function() {
28 api = await getApiConnection();29 api = await getApiConnection();
30 await requirePallets(this, [Pallets.RmrkCore]);
29 });31 });
3032
31 it('add resource', async () => {33 it('add resource', async () => {
modifiedtests/src/rmrk/addTheme.test.tsdiffbeforeafterboth
3import {createBase, addTheme} from './util/tx';3import {createBase, addTheme} from './util/tx';
4import {expectTxFailure} from './util/helpers';4import {expectTxFailure} from './util/helpers';
5import {getThemeNames} from './util/fetch';5import {getThemeNames} from './util/fetch';
6import {requirePallets, Pallets} from '../util/helpers';
67
7describe('integration test: add Theme to Base', () => {8describe('integration test: add Theme to Base', () => {
8 let api: any;9 let api: any;
9 before(async () => { api = await getApiConnection(); });10 before(async function() {
11 api = await getApiConnection();
12 await requirePallets(this, [Pallets.RmrkEquip]);
13 });
1014
11 const alice = '//Alice';15 const alice = '//Alice';
modifiedtests/src/rmrk/burnNft.test.tsdiffbeforeafterboth
55
6import chai from 'chai';6import chai from 'chai';
7import chaiAsPromised from 'chai-as-promised';7import chaiAsPromised from 'chai-as-promised';
8import {requirePallets, Pallets} from '../util/helpers';
89
9chai.use(chaiAsPromised);10chai.use(chaiAsPromised);
10const expect = chai.expect;11const expect = chai.expect;
14 const Bob = '//Bob';15 const Bob = '//Bob';
1516
16 let api: any;17 let api: any;
17 before(async () => {18 before(async function() {
18 api = await getApiConnection();19 api = await getApiConnection();
20 await requirePallets(this, [Pallets.RmrkCore]);
19 });21 });
22
2023
modifiedtests/src/rmrk/changeCollectionIssuer.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';
3import {4import {
4 changeIssuer,5 changeIssuer,
10 const Bob = '//Bob';11 const Bob = '//Bob';
1112
12 let api: any;13 let api: any;
13 before(async () => {14 before(async function() {
14 api = await getApiConnection();15 api = await getApiConnection();
16 await requirePallets(this, [Pallets.RmrkCore]);
15 });17 });
18
19
modifiedtests/src/rmrk/createBase.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {createCollection, createBase} from './util/tx';3import {createCollection, createBase} from './util/tx';
34
4describe('integration test: create new Base', () => {5describe('integration test: create new Base', () => {
5 let api: any;6 let api: any;
6 before(async () => { api = await getApiConnection(); });7 before(async function() {
8 api = await getApiConnection();
9 await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
10 });
711
8 const alice = '//Alice';12 const alice = '//Alice';
modifiedtests/src/rmrk/createCollection.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {createCollection} from './util/tx';3import {createCollection} from './util/tx';
34
4describe('Integration test: create new collection', () => {5describe('Integration test: create new collection', () => {
5 let api: any;6 let api: any;
6 before(async () => { api = await getApiConnection(); });7 before(async function () {
8 api = await getApiConnection();
9 await requirePallets(this, [Pallets.RmrkCore]);
10 });
11
12
modifiedtests/src/rmrk/deleteCollection.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';
3import {createCollection, deleteCollection} from './util/tx';4import {createCollection, deleteCollection} from './util/tx';
45
5describe('integration test: delete collection', () => {6describe('integration test: delete collection', () => {
6 let api: any;7 let api: any;
7 before(async () => {8 before(async function () {
8 api = await getApiConnection();9 api = await getApiConnection();
10 await requirePallets(this, [Pallets.RmrkCore]);
9 });11 });
1012
11 const Alice = '//Alice';13 const Alice = '//Alice';
modifiedtests/src/rmrk/equipNft.test.tsdiffbeforeafterboth
1import {ApiPromise} from '@polkadot/api';1import {ApiPromise} from '@polkadot/api';
2import {expect} from 'chai';2import {expect} from 'chai';
3import {getApiConnection} from '../substrate/substrate-api';3import {getApiConnection} from '../substrate/substrate-api';
4import {requirePallets, Pallets} from '../util/helpers';
4import {getNft, getParts, NftIdTuple} from './util/fetch';5import {getNft, getParts, NftIdTuple} from './util/fetch';
5import {expectTxFailure} from './util/helpers';6import {expectTxFailure} from './util/helpers';
6import {7import {
123124
124 let api: any;125 let api: any;
126
125 before(async () => {127 before(async function () {
126 api = await getApiConnection();128 api = await getApiConnection();
129 await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
127 });130 });
128131
129 it('equip nft', async () => {132 it('equip nft', async () => {
modifiedtests/src/rmrk/getOwnedNfts.test.tsdiffbeforeafterboth
1import {expect} from 'chai';1import {expect} from 'chai';
2import {getApiConnection} from '../substrate/substrate-api';2import {getApiConnection} from '../substrate/substrate-api';
3import {requirePallets, Pallets} from '../util/helpers';
3import {getOwnedNfts} from './util/fetch';4import {getOwnedNfts} from './util/fetch';
4import {mintNft, createCollection} from './util/tx';5import {mintNft, createCollection} from './util/tx';
56
6describe('integration test: get owned NFTs', () => {7describe('integration test: get owned NFTs', () => {
7 let api: any;8 let api: any;
9
8 before(async () => { api = await getApiConnection(); });10 before(async function () {
11 api = await getApiConnection();
12 await requirePallets(this, [Pallets.RmrkCore]);
13 });
14
915
modifiedtests/src/rmrk/lockCollection.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';
3import {createCollection, lockCollection, mintNft} from './util/tx';4import {createCollection, lockCollection, mintNft} from './util/tx';
45
8 const Max = 5;9 const Max = 5;
910
10 let api: any;11 let api: any;
11 before(async () => {12 before(async function () {
12 api = await getApiConnection();13 api = await getApiConnection();
14 await requirePallets(this, [Pallets.RmrkCore]);
13 });15 });
1416
15 it('lock collection', async () => {17 it('lock collection', async () => {
modifiedtests/src/rmrk/mintNft.test.tsdiffbeforeafterboth
1import {expect} from 'chai';1import {expect} from 'chai';
2import {getApiConnection} from '../substrate/substrate-api';2import {getApiConnection} from '../substrate/substrate-api';
3import {requirePallets, Pallets} from '../util/helpers';
3import {getNft} from './util/fetch';4import {getNft} from './util/fetch';
4import {expectTxFailure} from './util/helpers';5import {expectTxFailure} from './util/helpers';
5import {createCollection, mintNft} from './util/tx';6import {createCollection, mintNft} from './util/tx';
67
7describe('integration test: mint new NFT', () => {8describe('integration test: mint new NFT', () => {
8 let api: any;9 let api: any;
10
9 before(async () => { api = await getApiConnection(); });11 before(async function () {
12 api = await getApiConnection();
13 await requirePallets(this, [Pallets.RmrkCore]);
14 });
15
1016
modifiedtests/src/rmrk/rejectNft.test.tsdiffbeforeafterboth
8} from './util/tx';8} from './util/tx';
9import {getChildren, NftIdTuple} from './util/fetch';9import {getChildren, NftIdTuple} from './util/fetch';
10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';10import {isNftChildOfAnother, expectTxFailure} from './util/helpers';
11import {requirePallets, Pallets} from '../util/helpers';
1112
12describe('integration test: reject NFT', () => {13describe('integration test: reject NFT', () => {
13 let api: any;14 let api: any;
14 before(async () => { api = await getApiConnection(); });15 before(async function () {
16 api = await getApiConnection();
17 await requirePallets(this, [Pallets.RmrkCore]);
18 });
19
20
modifiedtests/src/rmrk/removeResource.test.tsdiffbeforeafterboth
1import {expect} from 'chai';1import {expect} from 'chai';
2import privateKey from '../substrate/privateKey';2import privateKey from '../substrate/privateKey';
3import {executeTransaction, getApiConnection} from '../substrate/substrate-api';3import {executeTransaction, getApiConnection} from '../substrate/substrate-api';
4import {requirePallets, Pallets} from '../util/helpers';
4import {getNft, NftIdTuple} from './util/fetch';5import {getNft, NftIdTuple} from './util/fetch';
5import {expectTxFailure} from './util/helpers';6import {expectTxFailure} from './util/helpers';
6import {7import {
16describe('Integration test: remove nft resource', () => {17describe('Integration test: remove nft resource', () => {
17 let api: any;18 let api: any;
18 let ss58Format: string;19 let ss58Format: string;
19 before(async () => {20 before(async function() {
20 api = await getApiConnection();21 api = await getApiConnection();
21 ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;22 ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
23 await requirePallets(this, [Pallets.RmrkCore]);
22 });24 });
2325
24 const Alice = '//Alice';26 const Alice = '//Alice';
modifiedtests/src/rmrk/rmrkIsolation.test.tsdiffbeforeafterboth
6 getCreateCollectionResult,6 getCreateCollectionResult,
7 getDetailedCollectionInfo,7 getDetailedCollectionInfo,
8 getGenericResult,8 getGenericResult,
9 requirePallets,
9 normalizeAccountId,10 normalizeAccountId,
11 Pallets,
10} from '../util/helpers';12} from '../util/helpers';
11import {IKeyringPair} from '@polkadot/types/types';13import {IKeyringPair} from '@polkadot/types/types';
12import {ApiPromise} from '@polkadot/api';14import {ApiPromise} from '@polkadot/api';
59describe('RMRK External Integration Test', async () => {61describe('RMRK External Integration Test', async () => {
60 const it_rmrk = (await isUnique() ? it : it.skip);62 const it_rmrk = (await isUnique() ? it : it.skip);
6163
62 before(async () => {64 before(async function() {
63 await usingApi(async (api, privateKeyWrapper) => {65 await usingApi(async (api, privateKeyWrapper) => {
64 alice = privateKeyWrapper('//Alice');66 alice = privateKeyWrapper('//Alice');
6567 await requirePallets(this, [Pallets.RmrkCore]);
66
67 });68 });
68 });69 });
modifiedtests/src/rmrk/sendNft.test.tsdiffbeforeafterboth
3import {createCollection, mintNft, sendNft} from './util/tx';3import {createCollection, mintNft, sendNft} from './util/tx';
4import {NftIdTuple} from './util/fetch';4import {NftIdTuple} from './util/fetch';
5import {isNftChildOfAnother, expectTxFailure} from './util/helpers';5import {isNftChildOfAnother, expectTxFailure} from './util/helpers';
6import {requirePallets, Pallets} from '../util/helpers';
67
7describe('integration test: send NFT', () => {8describe('integration test: send NFT', () => {
8 let api: any;9 let api: any;
9 before(async () => { api = await getApiConnection(); });10 before(async function () {
11 api = await getApiConnection();
12 await requirePallets(this, [Pallets.RmrkCore]);
13 });
1014
11 const maxNftId = 0xFFFFFFFF;15 const maxNftId = 0xFFFFFFFF;
modifiedtests/src/rmrk/setCollectionProperty.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';
3import {createCollection, setPropertyCollection} from './util/tx';4import {createCollection, setPropertyCollection} from './util/tx';
45
7 const Bob = '//Bob';8 const Bob = '//Bob';
89
9 let api: any;10 let api: any;
10 before(async () => {11 before(async function () {
11 api = await getApiConnection();12 api = await getApiConnection();
13 await requirePallets(this, [Pallets.RmrkCore]);
12 });14 });
1315
14 it('set collection property', async () => {16 it('set collection property', async () => {
modifiedtests/src/rmrk/setEquippableList.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';
3import {createCollection, createBase, setEquippableList} from './util/tx';4import {createCollection, createBase, setEquippableList} from './util/tx';
45
5describe("integration test: set slot's Equippable List", () => {6describe("integration test: set slot's Equippable List", () => {
6 let api: any;7 let api: any;
7 before(async () => { api = await getApiConnection(); });8 before(async function () {
9 api = await getApiConnection();
10 await requirePallets(this, [Pallets.RmrkCore]);
11 });
812
9 const alice = '//Alice';13 const alice = '//Alice';
modifiedtests/src/rmrk/setNftProperty.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {NftIdTuple} from './util/fetch';3import {NftIdTuple} from './util/fetch';
3import {expectTxFailure} from './util/helpers';4import {expectTxFailure} from './util/helpers';
4import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';5import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';
56
6describe('integration test: set NFT property', () => {7describe('integration test: set NFT property', () => {
7 let api: any;8 let api: any;
8 before(async () => { api = await getApiConnection(); });9 before(async function () {
10 api = await getApiConnection();
11 await requirePallets(this, [Pallets.RmrkCore]);
12 });
913
10 const alice = '//Alice';14 const alice = '//Alice';
modifiedtests/src/rmrk/setResourcePriorities.test.tsdiffbeforeafterboth
1import {getApiConnection} from '../substrate/substrate-api';1import {getApiConnection} from '../substrate/substrate-api';
2import {requirePallets, Pallets} from '../util/helpers';
2import {expectTxFailure} from './util/helpers';3import {expectTxFailure} from './util/helpers';
3import {mintNft, createCollection, setResourcePriorities} from './util/tx';4import {mintNft, createCollection, setResourcePriorities} from './util/tx';
45
5describe('integration test: set NFT resource priorities', () => {6describe('integration test: set NFT resource priorities', () => {
6 let api: any;7 let api: any;
7 before(async () => { api = await getApiConnection(); });8 before(async function () {
9 api = await getApiConnection();
10 await requirePallets(this, [Pallets.RmrkCore]);
11 });
812
9 const alice = '//Alice';13 const alice = '//Alice';
modifiedtests/src/setCollectionSponsor.test.tsdiffbeforeafterboth
23 setCollectionSponsorExpectFailure,23 setCollectionSponsorExpectFailure,
24 addCollectionAdminExpectSuccess,24 addCollectionAdminExpectSuccess,
25 getCreatedCollectionCount,25 getCreatedCollectionCount,
26 requirePallets,
27 Pallets,
26} from './util/helpers';28} from './util/helpers';
27import {IKeyringPair} from '@polkadot/types/types';29import {IKeyringPair} from '@polkadot/types/types';
2830
50 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});52 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
51 await setCollectionSponsorExpectSuccess(collectionId, bob.address);53 await setCollectionSponsorExpectSuccess(collectionId, bob.address);
52 });54 });
53 it('Set ReFungible collection sponsor', async () => {55 it('Set ReFungible collection sponsor', async function() {
56 await requirePallets(this, [Pallets.ReFungible]);
57
54 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});58 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
55 await setCollectionSponsorExpectSuccess(collectionId, bob.address);59 await setCollectionSponsorExpectSuccess(collectionId, bob.address);
modifiedtests/src/transfer.test.tsdiffbeforeafterboth
35 getBalance as getTokenBalance,35 getBalance as getTokenBalance,
36 transferFromExpectSuccess,36 transferFromExpectSuccess,
37 transferFromExpectFail,37 transferFromExpectFail,
38 requirePallets,
39 Pallets,
38} from './util/helpers';40} from './util/helpers';
39import {41import {
40 subToEth,42 subToEth,
41 itWeb3, 43 itWeb3,
42} from './eth/util/helpers';44} from './eth/util/helpers';
45import {request} from 'https';
4346
44let alice: IKeyringPair;47let alice: IKeyringPair;
45let bob: IKeyringPair;48let bob: IKeyringPair;
89 });92 });
90 });93 });
94
95 it('[nft] User can transfer owned token', async () => {
96 const nftCollectionId = await createCollectionExpectSuccess();
97 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
98 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');
99 });
91100
92 it('User can transfer owned token', async () => {101 it('[fungible] User can transfer owned token', async () => {
93 await usingApi(async (api, privateKeyWrapper) => {
94 // nft
95 const nftCollectionId = await createCollectionExpectSuccess();
96 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
97 await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');
98 // fungible
99 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});102 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
100 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');103 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
101 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');104 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');
102 // reFungible
103 const reFungibleCollectionId = await
104 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
105 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
106 await transferExpectSuccess(
107 reFungibleCollectionId,
108 newReFungibleTokenId,
109 alice,
110 bob,
111 100,
112 'ReFungible',
113 );
114 });
115 });105 });
106
107 it('[refungible] User can transfer owned token', async function() {
108 await requirePallets(this, [Pallets.ReFungible]);
109
110 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
111 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
112 await transferExpectSuccess(
113 reFungibleCollectionId,
114 newReFungibleTokenId,
115 alice,
116 bob,
117 100,
118 'ReFungible',
119 );
120 });
121
122 it('[nft] Collection admin can transfer owned token', async () => {
123 const nftCollectionId = await createCollectionExpectSuccess();
124 await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
125 const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);
126 await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');
127 });
116128
117 it('Collection admin can transfer owned token', async () => {129 it('[fungible] Collection admin can transfer owned token', async () => {
118 await usingApi(async (api, privateKeyWrapper) => {
119 // nft
120 const nftCollectionId = await createCollectionExpectSuccess();
121 await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);
122 const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);
123 await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');
124 // fungible
125 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});130 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
126 await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);131 await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);
127 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);132 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);
128 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');133 await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');
129 // reFungible
130 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
131 await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);
132 const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);
133 await transferExpectSuccess(
134 reFungibleCollectionId,
135 newReFungibleTokenId,
136 bob,
137 alice,
138 100,
139 'ReFungible',
140 );
141 });
142 });134 });
135
136 it('[refungible] Collection admin can transfer owned token', async function() {
137 await requirePallets(this, [Pallets.ReFungible]);
138
139 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
140 await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);
141 const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);
142 await transferExpectSuccess(
143 reFungibleCollectionId,
144 newReFungibleTokenId,
145 bob,
146 alice,
147 100,
148 'ReFungible',
149 );
150 });
143});151});
144152
145describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {153describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {
151 });159 });
152 });160 });
161
153 it('Transfer with not existed collection_id', async () => {162 it('[nft] Transfer with not existed collection_id', async () => {
154 await usingApi(async (api) => {163 await usingApi(async (api) => {
155 // nft
156 const nftCollectionCount = await getCreatedCollectionCount(api);164 const nftCollectionCount = await getCreatedCollectionCount(api);
157 await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);165 await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);
158 // fungible
159 const fungibleCollectionCount = await getCreatedCollectionCount(api);
160 await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);
161 // reFungible
162 const reFungibleCollectionCount = await getCreatedCollectionCount(api);
163 await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);
164 });166 });
165 });167 });
166 it('Transfer with deleted collection_id', async () => {168
167 // nft169 it('[fungible] Transfer with not existed collection_id', async () => {
170 await usingApi(async (api) => {
171 const fungibleCollectionCount = await getCreatedCollectionCount(api);
172 await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);
173 });
174 });
175
176 it('[refungible] Transfer with not existed collection_id', async function() {
177 await requirePallets(this, [Pallets.ReFungible]);
178
179 await usingApi(async (api) => {
180 const reFungibleCollectionCount = await getCreatedCollectionCount(api);
181 await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);
182 });
168 const nftCollectionId = await createCollectionExpectSuccess();183 });
169 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');184
170 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);185 it('[nft] Transfer with deleted collection_id', async () => {
171 await destroyCollectionExpectSuccess(nftCollectionId);186 const nftCollectionId = await createCollectionExpectSuccess();
172 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);187 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
173 // fungible188 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);
189 await destroyCollectionExpectSuccess(nftCollectionId);
190 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);
191 });
192
193 it('[fungible] Transfer with deleted collection_id', async () => {
174 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});194 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
175 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');195 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
176 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);196 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
177 await destroyCollectionExpectSuccess(fungibleCollectionId);197 await destroyCollectionExpectSuccess(fungibleCollectionId);
178 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);198 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);
179 // reFungible199 });
200
201 it('[refungible] Transfer with deleted collection_id', async function() {
202 await requirePallets(this, [Pallets.ReFungible]);
203
180 const reFungibleCollectionId = await204 const reFungibleCollectionId = await
181 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});205 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
189 bob,213 bob,
190 1,214 1,
191 );215 );
192 });216 });
217
218 it('[nft] Transfer with not existed item_id', async () => {
219 const nftCollectionId = await createCollectionExpectSuccess();
220 await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);
221 });
222
223 it('[fungible] Transfer with not existed item_id', async () => {
224 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
225 await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);
226 });
227
228 it('[refungible] Transfer with not existed item_id', async function() {
229 await requirePallets(this, [Pallets.ReFungible]);
230
231 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
232 await transferExpectFailure(
233 reFungibleCollectionId,
234 2,
235 alice,
236 bob,
237 1,
238 );
239 });
240
241 it('[nft] Transfer with deleted item_id', async () => {
242 const nftCollectionId = await createCollectionExpectSuccess();
243 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
244 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);
245 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);
246 });
247
193 it('Transfer with not existed item_id', async () => {248 it('[fungible] Transfer with deleted item_id', async () => {
194 // nft
195 const nftCollectionId = await createCollectionExpectSuccess();
196 await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);
197 // fungible
198 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});249 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
199 await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);250 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
200 // reFungible
201 const reFungibleCollectionId = await251 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
202 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
203 await transferExpectFailure(252 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);
204 reFungibleCollectionId,
205 2,
206 alice,
207 bob,
208 1,
209 );
210 });253 });
254
211 it('Transfer with deleted item_id', async () => {255 it('[refungible] Transfer with deleted item_id', async function() {
212 // nft
213 const nftCollectionId = await createCollectionExpectSuccess();
214 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
215 await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);
216 await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);
217 // fungible
218 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});256 await requirePallets(this, [Pallets.ReFungible]);
219 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');257
220 await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);
221 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);
222 // reFungible
223 const reFungibleCollectionId = await258 const reFungibleCollectionId = await
224 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});259 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
225 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');260 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
233 );268 );
234 });269 });
270
271 it('[nft] Transfer with recipient that is not owner', async () => {
272 const nftCollectionId = await createCollectionExpectSuccess();
273 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
274 await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);
275 });
276
277 it('[fungible] Transfer with recipient that is not owner', async () => {
278 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
279 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
280 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);
281 });
282
235 it('Transfer with recipient that is not owner', async () => {283 it('[refungible] Transfer with recipient that is not owner', async function() {
236 // nft
237 const nftCollectionId = await createCollectionExpectSuccess();
238 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
239 await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);
240 // fungible
241 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});284 await requirePallets(this, [Pallets.ReFungible]);
242 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');285
243 await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);
244 // reFungible
245 const reFungibleCollectionId = await286 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
246 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
247 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');287 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
276 });316 });
277 });317 });
278318
279 it('RFT', async () => {319 it('RFT', async function() {
320 await requirePallets(this, [Pallets.ReFungible]);
321
280 await usingApi(async (api: ApiPromise) => {322 await usingApi(async (api: ApiPromise) => {
281 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});323 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
modifiedtests/src/transferFrom.test.tsdiffbeforeafterboth
31 burnItemExpectSuccess,31 burnItemExpectSuccess,
32 setCollectionLimitsExpectSuccess,32 setCollectionLimitsExpectSuccess,
33 getCreatedCollectionCount,33 getCreatedCollectionCount,
34 requirePallets,
35 Pallets,
34} from './util/helpers';36} from './util/helpers';
3537
36chai.use(chaiAsPromised);38chai.use(chaiAsPromised);
49 });51 });
50 });52 });
53
54 it('[nft] Execute the extrinsic and check nftItemList - owner of token', async () => {
55 const nftCollectionId = await createCollectionExpectSuccess();
56 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
57 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
58
59 await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');
60 });
5161
52 it('Execute the extrinsic and check nftItemList - owner of token', async () => {62 it('[fungible] Execute the extrinsic and check nftItemList - owner of token', async () => {
53 await usingApi(async () => {
54 // nft
55 const nftCollectionId = await createCollectionExpectSuccess();
56 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
57 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
58
59 await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT');
60
61 // fungible
62 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});63 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
63 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');64 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
64 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);65 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
65 await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible');66 await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible');
66
67 // reFungible
68 const reFungibleCollectionId = await
69 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
70 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
71 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100);
72 await transferFromExpectSuccess(
73 reFungibleCollectionId,
74 newReFungibleTokenId,
75 bob,
76 alice,
77 charlie,
78 100,
79 'ReFungible',
80 );
81 });
82 });67 });
68
69 it('[refungible] Execute the extrinsic and check nftItemList - owner of token', async function() {
70 await requirePallets(this, [Pallets.ReFungible]);
71
72 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
73 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
74 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100);
75 await transferFromExpectSuccess(
76 reFungibleCollectionId,
77 newReFungibleTokenId,
78 bob,
79 alice,
80 charlie,
81 100,
82 'ReFungible',
83 );
84 });
8385
84 it('Should reduce allowance if value is big', async () => {86 it('Should reduce allowance if value is big', async () => {
85 await usingApi(async (api, privateKeyWrapper) => {87 await usingApi(async (api, privateKeyWrapper) => {
119 });121 });
120 });122 });
121123
122 it('transferFrom for a collection that does not exist', async () => {124 it('[nft] transferFrom for a collection that does not exist', async () => {
123 await usingApi(async (api: ApiPromise) => {125 await usingApi(async (api: ApiPromise) => {
124 // nft
125 const nftCollectionCount = await getCreatedCollectionCount(api);126 const nftCollectionCount = await getCreatedCollectionCount(api);
126 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);127 await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);
127128
128 await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1);129 await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1);
129
130 // fungible
131 const fungibleCollectionCount = await getCreatedCollectionCount(api);
132 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);
133
134 await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1);
135 // reFungible
136 const reFungibleCollectionCount = await getCreatedCollectionCount(api);
137 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
138
139 await transferFromExpectFail(reFungibleCollectionCount + 1, 1, bob, alice, charlie, 1);
140 });130 });
141 });131 });
132
133 it('[fungible] transferFrom for a collection that does not exist', async () => {
134 await usingApi(async (api: ApiPromise) => {
135 const fungibleCollectionCount = await getCreatedCollectionCount(api);
136 await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);
137
138 await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1);
139 });
140 });
141
142 it('[refungible] transferFrom for a collection that does not exist', async function() {
143 await requirePallets(this, [Pallets.ReFungible]);
144
145 await usingApi(async (api: ApiPromise) => {
146 const reFungibleCollectionCount = await getCreatedCollectionCount(api);
147 await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);
148
149 await transferFromExpectFail(reFungibleCollectionCount + 1, 1, bob, alice, charlie, 1);
150 });
151 });
142152
143 /* it('transferFrom for a collection that was destroyed', async () => {153 /* it('transferFrom for a collection that was destroyed', async () => {
144 await usingApi(async (api: ApiPromise) => {154 await usingApi(async (api: ApiPromise) => {
158 });168 });
159 }); */169 }); */
170
171 it('[nft] transferFrom for not approved address', async () => {
172 const nftCollectionId = await createCollectionExpectSuccess();
173 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
174
175 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
176 });
160177
161 it('transferFrom for not approved address', async () => {178 it('[fungible] transferFrom for not approved address', async () => {
162 await usingApi(async () => {
163 // nft
164 const nftCollectionId = await createCollectionExpectSuccess();
165 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
166
167 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1);
168
169 // fungible
170 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});179 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
171 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');180 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
172 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);181 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1);
173 // reFungible
174 const reFungibleCollectionId = await
175 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
176 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
177 await transferFromExpectFail(
178 reFungibleCollectionId,
179 newReFungibleTokenId,
180 bob,
181 alice,
182 charlie,
183 1,
184 );
185 });
186 });182 });
183
184 it('[refungible] transferFrom for not approved address', async function() {
185 await requirePallets(this, [Pallets.ReFungible]);
186
187 const reFungibleCollectionId = await
188 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
189 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
190 await transferFromExpectFail(
191 reFungibleCollectionId,
192 newReFungibleTokenId,
193 bob,
194 alice,
195 charlie,
196 1,
197 );
198 });
199
200 it('[nft] transferFrom incorrect token count', async () => {
201 const nftCollectionId = await createCollectionExpectSuccess();
202 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
203 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
204
205 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);
206 });
187207
188 it('transferFrom incorrect token count', async () => {208 it('[fungible] transferFrom incorrect token count', async () => {
189 await usingApi(async () => {
190 // nft
191 const nftCollectionId = await createCollectionExpectSuccess();
192 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
193 await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);
194
195 await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2);
196
197 // fungible
198 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});209 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
199 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');210 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
200 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);211 await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);
201 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2);212 await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2);
202 // reFungible
203 const reFungibleCollectionId = await
204 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
205 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
206 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
207 await transferFromExpectFail(
208 reFungibleCollectionId,
209 newReFungibleTokenId,
210 bob,
211 alice,
212 charlie,
213 2,
214 );
215 });
216 });213 });
214
215 it('[refungible] transferFrom incorrect token count', async function() {
216 await requirePallets(this, [Pallets.ReFungible]);
217
218 const reFungibleCollectionId = await
219 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
220 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
221 await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);
222 await transferFromExpectFail(
223 reFungibleCollectionId,
224 newReFungibleTokenId,
225 bob,
226 alice,
227 charlie,
228 2,
229 );
230 });
231
232 it('[nft] execute transferFrom from account that is not owner of collection', async () => {
233 await usingApi(async (api, privateKeyWrapper) => {
234 const dave = privateKeyWrapper('//Dave');
235 const nftCollectionId = await createCollectionExpectSuccess();
236 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
237 try {
238 await approveExpectFail(nftCollectionId, newNftTokenId, dave, bob);
239 await transferFromExpectFail(nftCollectionId, newNftTokenId, dave, alice, charlie, 1);
240 } catch (e) {
241 // tslint:disable-next-line:no-unused-expression
242 expect(e).to.be.exist;
243 }
244
245 // await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1);
246 });
247 });
217248
218 it('execute transferFrom from account that is not owner of collection', async () => {249 it('[fungible] execute transferFrom from account that is not owner of collection', async () => {
219 await usingApi(async (api, privateKeyWrapper) => {250 await usingApi(async (api, privateKeyWrapper) => {
220 const dave = privateKeyWrapper('//Dave');251 const dave = privateKeyWrapper('//Dave');
221 // nft252
222 const nftCollectionId = await createCollectionExpectSuccess();
223 const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');
224 try {
225 await approveExpectFail(nftCollectionId, newNftTokenId, dave, bob);
226 await transferFromExpectFail(nftCollectionId, newNftTokenId, dave, alice, charlie, 1);
227 } catch (e) {
228 // tslint:disable-next-line:no-unused-expression
229 expect(e).to.be.exist;
230 }
231
232 // await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1);
233
234 // fungible
235 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});253 const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
236 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');254 const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');
237 try {255 try {
241 // tslint:disable-next-line:no-unused-expression259 // tslint:disable-next-line:no-unused-expression
242 expect(e).to.be.exist;260 expect(e).to.be.exist;
243 }261 }
244 // reFungible
245 const reFungibleCollectionId = await
246 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
247 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
248 try {
249 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, bob);
250 await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, alice, charlie, 1);
251 } catch (e) {
252 // tslint:disable-next-line:no-unused-expression
253 expect(e).to.be.exist;
254 }
255 });262 });
256 });263 });
264
265 it('[refungible] execute transferFrom from account that is not owner of collection', async function() {
266 await requirePallets(this, [Pallets.ReFungible]);
267
268 await usingApi(async (api, privateKeyWrapper) => {
269 const dave = privateKeyWrapper('//Dave');
270 const reFungibleCollectionId = await
271 createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
272 const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');
273 try {
274 await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, bob);
275 await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, alice, charlie, 1);
276 } catch (e) {
277 // tslint:disable-next-line:no-unused-expression
278 expect(e).to.be.exist;
279 }
280 });
281 });
257 it('transferFrom burnt token before approve NFT', async () => {282 it('transferFrom burnt token before approve NFT', async () => {
258 await usingApi(async () => {283 await usingApi(async () => {
259 // nft284 // nft
276301
277 });302 });
278 });303 });
279 it('transferFrom burnt token before approve ReFungible', async () => {304 it('transferFrom burnt token before approve ReFungible', async function() {
305 await requirePallets(this, [Pallets.ReFungible]);
306
280 await usingApi(async () => {307 await usingApi(async () => {
281 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});308 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
308335
309 });336 });
310 });337 });
311 it('transferFrom burnt token after approve ReFungible', async () => {338 it('transferFrom burnt token after approve ReFungible', async function() {
339 await requirePallets(this, [Pallets.ReFungible]);
340
312 await usingApi(async () => {341 await usingApi(async () => {
313 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});342 const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
28import {hexToStr, strToUTF16, utf16ToStr} from './util';28import {hexToStr, strToUTF16, utf16ToStr} from './util';
29import {UpDataStructsRpcCollection, UpDataStructsCreateItemData, UpDataStructsProperty} from '@polkadot/types/lookup';29import {UpDataStructsRpcCollection, UpDataStructsCreateItemData, UpDataStructsProperty} from '@polkadot/types/lookup';
30import {UpDataStructsTokenChild} from '../interfaces';30import {UpDataStructsTokenChild} from '../interfaces';
31import {Context} from 'mocha';
3132
32chai.use(chaiAsPromised);33chai.use(chaiAsPromised);
33const expect = chai.expect;34const expect = chai.expect;
39};40};
41
42
43export enum Pallets {
44 Inflation = 'inflation',
45 RmrkCore = 'rmrkcore',
46 RmrkEquip = 'rmrkequip',
47 ReFungible = 'refungible',
48 Fungible = 'fungible',
49 NFT = 'nonfungible',
50 Scheduler = 'scheduler',
51}
52
53export async function isUnique(): Promise<boolean> {
54 return usingApi(async api => {
55 const chain = await api.rpc.system.chain();
56
57 return chain.eq('UNIQUE');
58 });
59}
60
61export async function isQuartz(): Promise<boolean> {
62 return usingApi(async api => {
63 const chain = await api.rpc.system.chain();
64
65 return chain.eq('QUARTZ');
66 });
67}
68
69let modulesNames: any;
70export function getModuleNames(api: ApiPromise): string[] {
71 if (typeof modulesNames === 'undefined')
72 modulesNames = api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());
73 return modulesNames;
74}
75
76export async function missingRequiredPallets(requiredPallets: string[]): Promise<string[]> {
77 return await usingApi(async api => {
78 const pallets = getModuleNames(api);
79
80 return requiredPallets.filter(p => !pallets.includes(p));
81 });
82}
83
84export async function checkPalletsPresence(requiredPallets: string[]): Promise<boolean> {
85 return (await missingRequiredPallets(requiredPallets)).length == 0;
86}
87
88export async function requirePallets(mocha: Context, requiredPallets: string[]) {
89 const missingPallets = await missingRequiredPallets(requiredPallets);
90
91 if (missingPallets.length > 0) {
92 const skippingTestMsg = `\tSkipping test "${mocha.test?.title}".`;
93 const missingPalletsMsg = `\tThe following pallets are missing:\n\t- ${missingPallets.join('\n\t- ')}`;
94 const skipMsg = `${skippingTestMsg}\n${missingPalletsMsg}`;
95
96 console.error('\x1b[38:5:208m%s\x1b[0m', skipMsg);
97
98 mocha.skip();
99 }
100}
40101
41export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId {102export function normalizeAccountId(input: string | AccountId | CrossAccountId | IKeyringPair): CrossAccountId {
42 if (typeof input === 'string') {103 if (typeof input === 'string') {