difftreelog
Merge branch 'develop' into feature/contract-sponsoring-modes
in: master
34 files changed
Cargo.lockdiffbeforeafterboth382382383[[package]]383[[package]]384name = "autocfg"384name = "autocfg"385version = "1.0.1"385version = "1.1.0"386source = "registry+https://github.com/rust-lang/crates.io-index"386source = "registry+https://github.com/rust-lang/crates.io-index"387checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"387checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"388388389[[package]]389[[package]]390name = "backtrace"390name = "backtrace"634634635[[package]]635[[package]]636name = "block-buffer"636name = "block-buffer"637version = "0.10.1"637version = "0.10.2"638source = "registry+https://github.com/rust-lang/crates.io-index"638source = "registry+https://github.com/rust-lang/crates.io-index"639checksum = "03588e54c62ae6d763e2a80090d50353b785795361b4ff5b3bf0a5097fc31c0b"639checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"640dependencies = [640dependencies = [641 "generic-array 0.14.5",641 "generic-array 0.14.5",642]642]109710971098[[package]]1098[[package]]1099name = "core-foundation"1099name = "core-foundation"1100version = "0.9.2"1100version = "0.9.3"1101source = "registry+https://github.com/rust-lang/crates.io-index"1101source = "registry+https://github.com/rust-lang/crates.io-index"1102checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"1102checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"1103dependencies = [1103dependencies = [1104 "core-foundation-sys",1104 "core-foundation-sys",1105 "libc",1105 "libc",122912291230[[package]]1230[[package]]1231name = "crc32fast"1231name = "crc32fast"1232version = "1.3.1"1232version = "1.3.2"1233source = "registry+https://github.com/rust-lang/crates.io-index"1233source = "registry+https://github.com/rust-lang/crates.io-index"1234checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3"1234checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"1235dependencies = [1235dependencies = [1236 "cfg-if 1.0.0",1236 "cfg-if 1.0.0",1237]1237]128812881289[[package]]1289[[package]]1290name = "crypto-common"1290name = "crypto-common"1291version = "0.1.1"1291version = "0.1.2"1292source = "registry+https://github.com/rust-lang/crates.io-index"1292source = "registry+https://github.com/rust-lang/crates.io-index"1293checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0"1293checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"1294dependencies = [1294dependencies = [1295 "generic-array 0.14.5",1295 "generic-array 0.14.5",1296]1296]189818981899[[package]]1899[[package]]1900name = "digest"1900name = "digest"1901version = "0.10.1"1901version = "0.10.2"1902source = "registry+https://github.com/rust-lang/crates.io-index"1902source = "registry+https://github.com/rust-lang/crates.io-index"1903checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b"1903checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"1904dependencies = [1904dependencies = [1905 "block-buffer 0.10.1",1905 "block-buffer 0.10.2",1906 "crypto-common",1906 "crypto-common",1907 "generic-array 0.14.5",1908]1907]190919081910[[package]]1909[[package]]324132403242[[package]]3241[[package]]3243name = "httparse"3242name = "httparse"3244version = "1.5.1"3243version = "1.6.0"3245source = "registry+https://github.com/rust-lang/crates.io-index"3244source = "registry+https://github.com/rust-lang/crates.io-index"3246checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"3245checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4"324732463248[[package]]3247[[package]]3249name = "httpdate"3248name = "httpdate"466446634665[[package]]4664[[package]]4666name = "memmap2"4665name = "memmap2"4667version = "0.5.2"4666version = "0.5.3"4668source = "registry+https://github.com/rust-lang/crates.io-index"4667source = "registry+https://github.com/rust-lang/crates.io-index"4669checksum = "fe3179b85e1fd8b14447cbebadb75e45a1002f541b925f0bfec366d56a81c56d"4668checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f"4670dependencies = [4669dependencies = [4671 "libc",4670 "libc",4672]4671]8805source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.16#4aeb95f7f38fcd519e2628f32f79044a8fef99d5"8804source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.16#4aeb95f7f38fcd519e2628f32f79044a8fef99d5"8806dependencies = [8805dependencies = [8807 "impl-trait-for-tuples",8806 "impl-trait-for-tuples",8808 "memmap2 0.5.2",8807 "memmap2 0.5.3",8809 "parity-scale-codec",8808 "parity-scale-codec",8810 "sc-chain-spec-derive",8809 "sc-chain-spec-derive",8811 "sc-network",8810 "sc-network",9912dependencies = [9911dependencies = [9913 "cfg-if 1.0.0",9912 "cfg-if 1.0.0",9914 "cpufeatures 0.2.1",9913 "cpufeatures 0.2.1",9915 "digest 0.10.1",9914 "digest 0.10.2",9916]9915]991799169918[[package]]9917[[package]]116441164311645[[package]]11644[[package]]11646name = "unique-node"11645name = "unique-node"11647version = "0.9.14"11646version = "0.9.16"11648dependencies = [11647dependencies = [11649 "cumulus-client-cli",11648 "cumulus-client-cli",11650 "cumulus-client-collator",11649 "cumulus-client-collator",Dockerfile-parachaindiffbeforeafterboth90 nvm install v15.5.0 && \90 nvm install v15.5.0 && \91 nvm use v15.5.091 nvm use v15.5.0929293RUN git clone https://github.com/PureStake/polkadot-launch -b jlm-use-para-id-in-specs93RUN git clone https://github.com/paritytech/polkadot-launch949495RUN export NVM_DIR="$HOME/.nvm" && \95RUN export NVM_DIR="$HOME/.nvm" && \96 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \96 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && \README.mddiffbeforeafterboth292930Please see our [walk-thorugh instructions](doc/hackusama_walk_through.md) to try everything out!30Please see our [walk-thorugh instructions](doc/hackusama_walk_through.md) to try everything out!313132## Hackusama Update3334During the Kusama Hackaphon the following changes were made:3536- Enabled Smart Contracts Pallet37- Enabled integration between Smart Contracts and Unique Pallet (required special edition of RC4 Substrate version)38- Fixed misc. bugs in Unique Pallet39- Deployed Unique TestNet. Public node available at wss://unique.usetech.com, custom UI types - see below in this README.40- New Features:41 - Re-Fungible Token Mode42 - Off-Chain Schema to store token image URLs43 - Alternative economic model44 - Allow Lists and Public Mint Permission45- Use example: [SubstraPunks Game](https://github.com/usetech-llc/substrapunks), fully hosted on IPFS and Unique Testnet46 Blockchain.4748## Application Development32## Application Development493350If you are building an application that operates NFT tokens, use [this document](doc/application_development.md).34If you are building an application that operates NFT tokens, use [this document](doc/application_development.md).51353652## Building37## Building533854Building Unique chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything39Building Unique chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything571. Install Rust:421. Install Rust:584359```bash44```bash45sudo apt-get install git curl libssl-dev llvm pkg-config libclang-dev clang60curl https://sh.rustup.rs -sSf | sh46curl https://sh.rustup.rs -sSf | sh61sudo apt-get install libssl-dev pkg-config libclang-dev clang62```47```6348642. Remove all installed toolchains with `rustup toolchain list` and `rustup toolchain uninstall <toolchain>`.492. Remove all installed toolchains with `rustup toolchain list` and `rustup toolchain uninstall <toolchain>`.86cargo build --release71cargo build --release87```72```887389## Run74## Building as Parachain locally907591You can start a development chain with:76Note: checkout this project and all related projects (see below) in the sibling folders (both under the same folder)927793```bash94cargo run -- --dev78### Polkadot launch utility95```967997Detailed logs may be shown by running the node with the following environment variables set:98`RUST_LOG=debug RUST_BACKTRACE=1 cargo run -- --dev`.99100If you want to see the multi-node consensus algorithm in action locally, then you can create a local testnet with two101validator nodes for Alice and Bob, who are the initial authorities of the genesis chain that have been endowed with102testnet units. Give each node a name and expose them so they are listed on the Polkadot103[telemetry site](https://telemetry.polkadot.io/#/Local%20Testnet). You'll need two terminal windows open.104105We'll start Alice's substrate node first on default TCP port 30333 with her chain database stored locally at106`/tmp/alice`. The bootnode ID of her node is `QmQZ8TjTqeDj3ciwr93EJ95hxfDsb9pEYDizUAbWpigtQN`, which is generated from107the `--node-key` value that we specify below:108109```bash110cargo run -- \111 --base-path /tmp/alice \112 --chain=local \113 --alice \114 --node-key 0000000000000000000000000000000000000000000000000000000000000001 \115 --telemetry-url ws://telemetry.polkadot.io:1024 \116 --validator117```80```118119In the second terminal, we'll start Bob's substrate node on a different TCP port of 30334, and with his chain database81git clone https://github.com/paritytech/polkadot-launch120stored locally at `/tmp/bob`. We'll specify a value for the `--bootnodes` option that will connect his node to Alice's121bootnode ID on TCP port 30333:122123```bash124cargo run -- \125 --base-path /tmp/bob \126 --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/QmQZ8TjTqeDj3ciwr93EJ95hxfDsb9pEYDizUAbWpigtQN \127 --chain=local \128 --bob \129 --port 30334 \130 --telemetry-url ws://telemetry.polkadot.io:1024 \131 --validator132```82```13383134Additional CLI usage options are available and may be shown by running `cargo run -- --help`.135136## Building and Running as Parachain locally137138Rust toolchain: nightly-2021-11-11139Note: checkout this project and polkadot project (see below) in the sibling folders (both under the same folder)140141### Build relay84### Build relay14285143```86```144git clone https://github.com/paritytech/polkadot.git87git clone https://github.com/paritytech/polkadot.git145cd polkadot88cd polkadot146git checkout release-v0.9.989git checkout release-v0.9.16147cargo build --release90cargo build --release148```91```14992150### Build parachain93### Build Unique parachain15194152Run in the root of this project:95Run in the root of this project:153```96```154cargo --build97cargo build --release155```98```15699157### Run 4-node Relay100### Build Acala parachain (optional, full config only)1581011591. Download `rococo-custom-4.json` chain spec here: https://substrate.dev/cumulus-workshop/shared/chainspecs/rococo-custom-4.json1602. Use these instructions to launch 4 nodes: https://substrate.dev/cumulus-workshop/#/en/2-relay-chain/1-launch161162Example (Run in polkadot folder. Replace `12D3KooWNLAmKcyee3oqSgTMthaQVXaAcXeo8RrGCzMfMVA3B5on` with output from Alice node):163```102```164./target/release/polkadot --alice --validator --base-path ./cumulus_relay0 --chain rococo-custom-4.json --port 50555 --ws-port 9944103git clone https://github.com/AcalaNetwork/Acala165./target/release/polkadot --bob --validator --base-path ./cumulus_relay1 --chain rococo-custom-4.json --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWNLAmKcyee3oqSgTMthaQVXaAcXeo8RrGCzMfMVA3B5on --port 50556 --ws-port 9945104cd Acala166./target/release/polkadot --charlie --validator --base-path ./cumulus_relay1 --chain rococo-custom-4.json --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWNLAmKcyee3oqSgTMthaQVXaAcXeo8RrGCzMfMVA3B5on --port 50557 --ws-port 9946105git checkout 54db3acd409a0b787f116f20e163a3b24101ce38167./target/release/polkadot --dave --validator --base-path ./cumulus_relay1 --chain rococo-custom-4.json --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooWNLAmKcyee3oqSgTMthaQVXaAcXeo8RrGCzMfMVA3B5on --port 50558 --ws-port 9947106make build-release168169```107```1701081713. Export genesis state and runtime wasm from Unique parachain:109## Running as Parachain locally172110173Run from this project root:174```111```175./target/release/unique-collator export-genesis-state --parachain-id 2000 > ./resources/para-2000-genesis112./launch-testnet.sh176./target/release/unique-collator export-genesis-wasm > ./resources/para-2000-wasm177```113```1781141794. Run two parachain nodes:115Optional, full setup with Acala and Statemint180181Replace `12D3KooWN1ah2bFQSysEFnwZqcmcVpDDR8UedXyo6xfzV1zDNMNg` with Alice or Bob relay ID182183Run from this project root:184```116```185./target/release/unique-collator --alice --collator --force-authoring --base-path ./tmp/parachain-alice --parachain-id 2000 --port 40333 --ws-port 9844 -- --execution wasm --chain ../polkadot/rococo-custom-4.json --port 30343 --ws-port 9977117./launch-testnet-full.sh186./target/release/unique-collator --bob --collator --force-authoring --parachain-id 2000 --base-path ./tmp/parachain/bob --port 40334 --ws-port 9845 -- --execution wasm --chain ../polkadot/rococo-custom-4.json --port 30344 --ws-port 9978 --bootnodes /ip4/127.0.0.1/tcp/50556/p2p/12D3KooWN1ah2bFQSysEFnwZqcmcVpDDR8UedXyo6xfzV1zDNMNg187```118```1881191894. Reserve parachain ID as described here: https://substrate.dev/cumulus-workshop/#/en/2-relay-chain/2-reserve1901915. Register parachain in relay as described here: https://substrate.dev/cumulus-workshop/#/en/3-parachains/2-register192193194## Run Integration Tests120## Run Integration Tests1951211961. Install all needed dependecies1221. Install all needed dependecies204yarn test130yarn test205```131```206132207## Benchmarks208133209First of all, add rust toolchain and make it default.210```bash211rustup target add wasm32-unknown-unknown --toolchain nightly-2021-11-11212```213214Then in "/node/src" run build command below215```bash216cargo +nightly-2021-11-11 build --release --features runtime-benchmarks217```218219Run benchmark220```bash221target/release/unique-collator benchmark --chain dev --pallet "pallet_unique" --extrinsic "*" --repeat 1222```223224## UI custom types225226Moved to [runtime_types.json](./runtime_types.json).227228## Running Integration Tests229230See [tests/README.md](./tests/README.md).231232## Code Formatting134## Code Formatting233135234### Get formatter and linter settings into your branch (if you forked before they were introduced)235```bash236git cherry-pick -n 8ff77c21b0d30b2a4648fa35dbf61dfa9d3948a7237```238239### Apply formatting and clippy fixes136### Apply formatting and clippy fixes240```bash137```bash241cargo clippy138cargo clippy252cd tests && yarn eslint --ext .ts,.js src/149cd tests && yarn eslint --ext .ts,.js src/253```150```254151255## Re-Enabling Ink! Contracts256152257Uncomment following lies:2581. In node/rpc/Cargo.toml259```260# pallet-contracts-rpc = { version = "3.0", git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.9' }153## Karura token transfer261```2621542632. In node/rpc/src/lib.rs155To get started, you need to open inbound and outbound hrmp channels.264```265// C::Api: pallet_contracts_rpc::ContractsRuntimeApi<Block, AccountId, Balance, BlockNumber, Hash>,266...267// use pallet_contracts_rpc::{Contracts, ContractsApi};268...269// io.extend_with(ContractsApi::to_delegate(Contracts::new(client.clone())));270156157### Next, we need to register our asset at Karura.271```158```159assetRegistry -> registerForeignAsset(location, metadata)160location:161 V0(X2(Parent, Parachain(PARA_ID))) 162metadata:163 name OPL164 symbol OPL165 decimals 18166minimalBalance 1167```2721682733. In runtime/Cargo.toml169### Next, we can send tokens from Opal to Karura:274```170```275 # 'pallet-contracts/std',171polkadotXcm -> reserveTransferAssets276 # 'pallet-contracts-primitives/std',172dest:277 # 'pallet-contracts-rpc-runtime-api/std',278 # 'pallet-contract-helpers/std',173 V0(X2(Parent, Parachain(<KARURA_PARA_ID>))) 279...174beneficiary:280 # [dependencies.pallet-contracts]175 X1(AccountId(Any, <ACCOUNT>))281 # git = 'https://github.com/paritytech/substrate.git'176assets:282 # default-features = false177 V1(Concrete(0,Here), Fungible(<AMOUNT>))283 # branch = 'polkadot-v0.9.9'178feeAssetItem: 284 # version = '3.0.0'179 0 180weightLimit:181 <LIMIT>182``` 285183286 # [dependencies.pallet-contracts-primitives]184The result will be displayed in ChainState 287 # git = 'https://github.com/paritytech/substrate.git'288 # default-features = false185tokens -> accounts 289 # branch = 'polkadot-v0.9.9'290 # version = '3.0.0'291186292 # [dependencies.pallet-contracts-rpc-runtime-api]187### To send tokens from Karura to Opal:293 # git = 'https://github.com/paritytech/substrate.git'294 # default-features = false295 # branch = 'polkadot-v0.9.9'296 # version = '3.0.0'297...298 # pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' }299```188```189xtokens -> transfer3001903014. runtime/src/lib.rs302```303// use pallet_contracts::weights::WeightInfo;191currencyId:304...305// pub use pallet_timestamp::Call as TimestampCall;306...307// mod chain_extension;308// use crate::chain_extension::{NFTExtension, Imbalance};309...310/*311parameter_types! {312 pub TombstoneDeposit: Balance = deposit(192 ForeingAsset313 ...314}315*/316...317//pallet_contract_helpers::ContractSponsorshipHandler<Runtime>,318...319// impl pallet_contract_helpers::Config for Runtime {}320...321// Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},322...323// ContractHelpers: pallet_contract_helpers::{Pallet, Call, Storage},324...325//pallet_contract_helpers::ContractHelpersExtension<Runtime>,326...327/*328 impl pallet_contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash>193 <TOKEN_ID>329 for Runtime330 {331 ...332 }333*/334194195amount:196 <AMOUNT>197dest:198 V1199 (200 Parents:1, 201 X2(Parachain(<KARURA_PARA_ID>), AccountId(Any, <ACCOUNT>)202 )203destWeight:204 <WEIGHT>335```205```336client/rpc/src/lib.rsdiffbeforeafterboth4use jsonrpc_core::{Error as RpcError, ErrorCode, Result};4use jsonrpc_core::{Error as RpcError, ErrorCode, Result};5use jsonrpc_derive::rpc;5use jsonrpc_derive::rpc;6use up_data_structs::{Collection, CollectionId, CollectionStats, TokenId};6use up_data_structs::{Collection, CollectionId, CollectionStats, TokenId};7use sp_api::{BlockId, BlockT, ProvideRuntimeApi};7use sp_api::{BlockId, BlockT, ProvideRuntimeApi, ApiExt};8use sp_blockchain::HeaderBackend;8use sp_blockchain::HeaderBackend;9use up_rpc::UniqueApi as UniqueRuntimeApi;9use up_rpc::UniqueApi as UniqueRuntimeApi;1010134macro_rules! pass_method {134macro_rules! pass_method {135 ($method_name:ident($($name:ident: $ty:ty),* $(,)?) -> $result:ty $(=> $mapper:expr)?) => {135 (136 $method_name:ident($($name:ident: $ty:ty),* $(,)?) -> $result:ty $(=> $mapper:expr)?137 $(; changed_in $ver:expr, $changed_method_name:ident ($($changed_name:expr), * $(,)?) => $fixer:expr)*138 ) => {136 fn $method_name(139 fn $method_name(137 &self,140 &self,142 ) -> Result<$result> {145 ) -> Result<$result> {143 let api = self.client.runtime_api();146 let api = self.client.runtime_api();144 let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));147 let at = BlockId::hash(at.unwrap_or_else(|| self.client.info().best_hash));148 let _api_version = if let Ok(Some(api_version)) =149 api.api_version::<dyn UniqueRuntimeApi<Block, CrossAccountId, AccountId>>(&at)150 {151 api_version152 } else {153 // unreachable for our runtime154 return Err(RpcError {155 code: ErrorCode::InvalidParams,156 message: "Api is not available".into(),157 data: None,158 })159 };145160146 let result = api.$method_name(&at, $($name),*).map_err(|e| RpcError {161 let result = $(if _api_version < $ver {162 api.$changed_method_name(&at, $($changed_name),*).map(|r| r.map($fixer))163 } else)*164 { api.$method_name(&at, $($name),*) };165166 let result = result.map_err(|e| RpcError {147 code: ErrorCode::ServerError(Error::RuntimeError.into()),167 code: ErrorCode::ServerError(Error::RuntimeError.into()),148 message: "Unable to query".into(),168 message: "Unable to query".into(),149 data: Some(format!("{:?}", e).into()),169 data: Some(format!("{:?}", e).into()),169 pass_method!(account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId>);189 pass_method!(account_tokens(collection: CollectionId, account: CrossAccountId) -> Vec<TokenId>);170 pass_method!(token_exists(collection: CollectionId, token: TokenId) -> bool);190 pass_method!(token_exists(collection: CollectionId, token: TokenId) -> bool);171 pass_method!(token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>);191 pass_method!(192 token_owner(collection: CollectionId, token: TokenId) -> Option<CrossAccountId>;193 changed_in 2, token_owner_before_version_2(collection, token) => |u| Some(u)194 );172 pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);195 pass_method!(const_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);173 pass_method!(variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);196 pass_method!(variable_metadata(collection: CollectionId, token: TokenId) -> Vec<u8>);doc/hackusama_update.mddiffbeforeafterbothno changes
doc/re-enable_ink_contracts.mddiffbeforeafterbothno changes
launch-config-full.jsondiffbeforeafterbothno changes
launch-config-westend.jsondiffbeforeafterbothno changes
launch-config.jsondiffbeforeafterboth9 "rpcPort": 9843,9 "rpcPort": 9843,10 "port": 30444,10 "port": 30444,11 "flags": [11 "flags": [12 "-lparachain::candidate_validation=debug"12 "-lparachain::candidate_validation=debug",13 "-lxcm=trace"13 ]14 ]14 },15 },15 {16 {18 "rpcPort": 9854,19 "rpcPort": 9854,19 "port": 30555,20 "port": 30555,20 "flags": [21 "flags": [21 "-lparachain::candidate_validation=debug"22 "-lparachain::candidate_validation=debug",23 "-lxcm=trace"22 ]24 ]23 },25 },24 {26 {38 "flags": [40 "flags": [39 "-lparachain::candidate_validation=debug"41 "-lparachain::candidate_validation=debug"40 ]42 ]41 }43 },44 {45 "name": "eve",46 "wsPort": 9888,47 "rpcPort": 9887,48 "port": 30888,49 "flags": [50 "-lparachain::candidate_validation=debug"51 ]52 }42 ],53 ],43 "genesis": {54 "genesis": {44 "runtime": {55 "runtime": {67 "flags": [78 "flags": [68 "--rpc-cors=all",79 "--rpc-cors=all",69 "--unsafe-rpc-external",80 "--unsafe-rpc-external",70 "--unsafe-ws-external"81 "--unsafe-ws-external",82 "-lxcm=trace"71 ]83 ]72 },84 },73 {85 {78 "flags": [90 "flags": [79 "--rpc-cors=all",91 "--rpc-cors=all",80 "--unsafe-rpc-external",92 "--unsafe-rpc-external",81 "--unsafe-ws-external"93 "--unsafe-ws-external",94 "-lxcm=trace"82 ]95 ]83 }96 }84 ]97 ]launch-test-env.shdiffbeforeafterbothno changes
launch-testnet-full.shdiffbeforeafterbothno changes
launch-testnet.shdiffbeforeafterbothno changes
node/cli/Cargo.tomldiffbeforeafterboth257license = 'All Rights Reserved'257license = 'All Rights Reserved'258name = 'unique-node'258name = 'unique-node'259repository = 'https://github.com/UniqueNetwork/unique-chain'259repository = 'https://github.com/UniqueNetwork/unique-chain'260version = '0.9.14'260version = '0.9.16'261261262[[bin]]262[[bin]]263name = 'unique-collator'263name = 'unique-collator'pallets/common/src/lib.rsdiffbeforeafterboth14use up_data_structs::{14use up_data_structs::{15 COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,15 COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,16 MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo,16 MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo,17 TokenId, Weight, WithdrawReasons, CollectionStats, CustomDataLimit,17 TokenId, Weight, WithdrawReasons, CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode,18 NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,19 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, CUSTOM_DATA_LIMIT, CollectionLimits,20 CustomDataLimit, CreateCollectionData, SponsorshipState,18};21};19pub use pallet::*;22pub use pallet::*;20use sp_core::H160;23use sp_core::H160;285 TokenVariableDataLimitExceeded,288 TokenVariableDataLimitExceeded,286 /// Exceeded max admin count289 /// Exceeded max admin count287 CollectionAdminCountExceeded,290 CollectionAdminCountExceeded,291 /// Collection limit bounds per collection exceeded292 CollectionLimitBoundsExceeded,293 /// Tried to enable permissions which are only permitted to be disabled294 OwnerPermissionsCantBeReverted,288295289 /// Collection settings not allowing items transferring296 /// Collection settings not allowing items transferring290 TransferNotAllowed,297 TransferNotAllowed,300 /// Item balance not enough.307 /// Item balance not enough.301 TokenValueTooLow,308 TokenValueTooLow,302 /// Requested value more than approved.309 /// Requested value more than approved.303 TokenValueNotEnough,310 ApprovedValueTooLow,304 /// Tried to approve more than owned311 /// Tried to approve more than owned305 CantApproveMoreThanOwned,312 CantApproveMoreThanOwned,306313395}402}396403397impl<T: Config> Pallet<T> {404impl<T: Config> Pallet<T> {398 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {405 pub fn init_collection(406 owner: T::AccountId,407 data: CreateCollectionData<T::AccountId>,408 ) -> Result<CollectionId, DispatchError> {399 {409 {400 ensure!(410 ensure!(418428419 // =========429 // =========430431 let collection = Collection {432 owner: owner.clone(),433 name: data.name,434 mode: data.mode.clone(),435 mint_mode: false,436 access: data.access.unwrap_or_default(),437 description: data.description,438 token_prefix: data.token_prefix,439 offchain_schema: data.offchain_schema,440 schema_version: data.schema_version.unwrap_or_default(),441 sponsorship: data442 .pending_sponsor443 .map(SponsorshipState::Unconfirmed)444 .unwrap_or_default(),445 variable_on_chain_schema: data.variable_on_chain_schema,446 const_on_chain_schema: data.const_on_chain_schema,447 limits: data448 .limits449 .map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))450 .unwrap_or_else(|| Ok(CollectionLimits::default()))?,451 meta_update_permission: data.meta_update_permission.unwrap_or_default(),452 };420453421 // Take a (non-refundable) deposit of collection creation454 // Take a (non-refundable) deposit of collection creation422 {455 {429 ),462 ),430 );463 );431 <T as Config>::Currency::settle(464 <T as Config>::Currency::settle(432 &data.owner,465 &owner,433 imbalance,466 imbalance,434 WithdrawReasons::TRANSFER,467 WithdrawReasons::TRANSFER,435 ExistenceRequirement::KeepAlive,468 ExistenceRequirement::KeepAlive,441 <Pallet<T>>::deposit_event(Event::CollectionCreated(474 <Pallet<T>>::deposit_event(Event::CollectionCreated(id, data.mode.id(), owner.clone()));442 id,443 data.mode.id(),444 data.owner.clone(),445 ));446 <CollectionById<T>>::insert(id, data);475 <CollectionById<T>>::insert(id, collection);447 Ok(id)476 Ok(id)448 }477 }449478528 Ok(())557 Ok(())529 }558 }559560 pub fn clamp_limits(561 mode: CollectionMode,562 old_limit: &CollectionLimits,563 mut new_limit: CollectionLimits,564 ) -> Result<CollectionLimits, DispatchError> {565 macro_rules! limit_default {566 ($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{567 $(568 if let Some($new) = $new.$field {569 let $old = $old.$field($($arg)?);570 let _ = $new;571 let _ = $old;572 $check573 } else {574 $new.$field = $old.$field575 }576 )*577 }};578 }579580 limit_default!(old_limit, new_limit,581 account_token_ownership_limit => ensure!(582 new_limit <= MAX_TOKEN_OWNERSHIP,583 <Error<T>>::CollectionLimitBoundsExceeded,584 ),585 sponsor_transfer_timeout(match mode {586 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,587 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,588 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,589 }) => ensure!(590 new_limit <= MAX_SPONSOR_TIMEOUT,591 <Error<T>>::CollectionLimitBoundsExceeded,592 ),593 sponsored_data_size => ensure!(594 new_limit <= CUSTOM_DATA_LIMIT,595 <Error<T>>::CollectionLimitBoundsExceeded,596 ),597 token_limit => ensure!(598 old_limit >= new_limit && new_limit > 0,599 <Error<T>>::CollectionTokenLimitExceeded600 ),601 owner_can_transfer => ensure!(602 old_limit || !new_limit,603 <Error<T>>::OwnerPermissionsCantBeReverted,604 ),605 owner_can_destroy => ensure!(606 old_limit || !new_limit,607 <Error<T>>::OwnerPermissionsCantBeReverted,608 ),609 sponsored_data_rate_limit => {},610 transfers_enabled => {},611 );612 Ok(new_limit)613 }530}614}531615532#[macro_export]616#[macro_export]pallets/fungible/src/lib.rsdiffbeforeafterboth223use core::ops::Deref;3use core::ops::Deref;4use frame_support::{ensure};4use frame_support::{ensure};5use up_data_structs::{AccessMode, Collection, CollectionId, TokenId};5use up_data_structs::{AccessMode, CollectionId, TokenId, CreateCollectionData};6use pallet_common::{6use pallet_common::{7 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,7 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,8};8};100}100}101101102impl<T: Config> Pallet<T> {102impl<T: Config> Pallet<T> {103 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {103 pub fn init_collection(104 owner: T::AccountId,105 data: CreateCollectionData<T::AccountId>,106 ) -> Result<CollectionId, DispatchError> {104 <PalletCommon<T>>::init_collection(data)107 <PalletCommon<T>>::init_collection(owner, data)105 }108 }106 pub fn destroy_collection(109 pub fn destroy_collection(107 collection: FungibleHandle<T>,110 collection: FungibleHandle<T>,343 if allowance.is_none() {346 if allowance.is_none() {344 ensure!(347 ensure!(345 collection.ignores_allowance(spender),348 collection.ignores_allowance(spender),346 <CommonError<T>>::TokenValueNotEnough349 <CommonError<T>>::ApprovedValueTooLow347 );350 );348 }351 }349352374 if allowance.is_none() {377 if allowance.is_none() {375 ensure!(378 ensure!(376 collection.ignores_allowance(spender),379 collection.ignores_allowance(spender),377 <CommonError<T>>::TokenValueNotEnough380 <CommonError<T>>::ApprovedValueTooLow378 );381 );379 }382 }380383pallets/nonfungible/src/lib.rsdiffbeforeafterboth223use erc::ERC721Events;3use erc::ERC721Events;4use frame_support::{BoundedVec, ensure};4use frame_support::{BoundedVec, ensure};5use up_data_structs::{AccessMode, Collection, CollectionId, CustomDataLimit, TokenId};5use up_data_structs::{AccessMode, CollectionId, CustomDataLimit, TokenId, CreateCollectionData};6use pallet_common::{6use pallet_common::{7 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,7 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,8};8};140140141// unchecked calls skips any permission checks141// unchecked calls skips any permission checks142impl<T: Config> Pallet<T> {142impl<T: Config> Pallet<T> {143 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {143 pub fn init_collection(144 owner: T::AccountId,145 data: CreateCollectionData<T::AccountId>,146 ) -> Result<CollectionId, DispatchError> {144 <PalletCommon<T>>::init_collection(data)147 <PalletCommon<T>>::init_collection(owner, data)145 }148 }146 pub fn destroy_collection(149 pub fn destroy_collection(147 collection: NonfungibleHandle<T>,150 collection: NonfungibleHandle<T>,492 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {495 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {493 ensure!(496 ensure!(494 collection.ignores_allowance(spender),497 collection.ignores_allowance(spender),495 <CommonError<T>>::TokenValueNotEnough498 <CommonError<T>>::ApprovedValueTooLow496 );499 );497 }500 }498501520 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {523 if <Allowance<T>>::get((collection.id, token)).as_ref() != Some(spender) {521 ensure!(524 ensure!(522 collection.ignores_allowance(spender),525 collection.ignores_allowance(spender),523 <CommonError<T>>::TokenValueNotEnough526 <CommonError<T>>::ApprovedValueTooLow524 );527 );525 }528 }526529pallets/refungible/src/lib.rsdiffbeforeafterboth223use frame_support::{ensure, BoundedVec};3use frame_support::{ensure, BoundedVec};4use up_data_structs::{4use up_data_structs::{5 AccessMode, Collection, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,5 AccessMode, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId, CreateCollectionData,6};6};7use pallet_common::{7use pallet_common::{8 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,8 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,155155156// unchecked calls skips any permission checks156// unchecked calls skips any permission checks157impl<T: Config> Pallet<T> {157impl<T: Config> Pallet<T> {158 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {158 pub fn init_collection(159 owner: T::AccountId,160 data: CreateCollectionData<T::AccountId>,161 ) -> Result<CollectionId, DispatchError> {159 <PalletCommon<T>>::init_collection(data)162 <PalletCommon<T>>::init_collection(owner, data)160 }163 }161 pub fn destroy_collection(164 pub fn destroy_collection(162 collection: RefungibleHandle<T>,165 collection: RefungibleHandle<T>,528 if allowance.is_none() {531 if allowance.is_none() {529 ensure!(532 ensure!(530 collection.ignores_allowance(spender),533 collection.ignores_allowance(spender),531 <CommonError<T>>::TokenValueNotEnough534 <CommonError<T>>::ApprovedValueTooLow532 );535 );533 }536 }534537561 if allowance.is_none() {564 if allowance.is_none() {562 ensure!(565 ensure!(563 collection.ignores_allowance(spender),566 collection.ignores_allowance(spender),564 <CommonError<T>>::TokenValueNotEnough567 <CommonError<T>>::ApprovedValueTooLow565 );568 );566 }569 }567570pallets/unique/src/lib.rsdiffbeforeafterboth36use frame_system::{self as system, ensure_signed};36use frame_system::{self as system, ensure_signed};37use sp_runtime::{sp_std::prelude::Vec};37use sp_runtime::{sp_std::prelude::Vec};38use up_data_structs::{38use up_data_structs::{39 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,39 MAX_DECIMAL_POINTS, VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT,40 VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,40 OFFCHAIN_SCHEMA_LIMIT, MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH,41 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,42 NFT_SPONSOR_TRANSFER_TIMEOUT, MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH,43 MAX_TOKEN_PREFIX_LENGTH, AccessMode, Collection, CreateItemData, CollectionLimits,41 MAX_TOKEN_PREFIX_LENGTH, AccessMode, CreateItemData, CollectionLimits, CollectionId,44 CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,42 CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,45 CustomDataLimit,43 CreateCollectionData, CustomDataLimit,46};44};47use pallet_common::{45use pallet_common::{48 account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,46 account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,84 ConfirmUnsetSponsorFail,82 ConfirmUnsetSponsorFail,85 /// Length of items properties must be greater than 0.83 /// Length of items properties must be greater than 0.86 EmptyArgument,84 EmptyArgument,87 /// Collection limit bounds per collection exceeded88 CollectionLimitBoundsExceeded,89 /// Tried to enable permissions which are only permitted to be disabled90 OwnerPermissionsCantBeReverted,91 }85 }92}86}9387321 // returns collection ID315 // returns collection ID322 #[weight = <SelfWeightOf<T>>::create_collection()]316 #[weight = <SelfWeightOf<T>>::create_collection()]323 #[transactional]317 #[transactional]318 #[deprecated]324 pub fn create_collection(origin,319 pub fn create_collection(origin,325 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,320 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,326 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,321 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,327 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,322 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,328 mode: CollectionMode) -> DispatchResult {323 mode: CollectionMode) -> DispatchResult {329330 // Anyone can create a collection331 let who = ensure_signed(origin)?;324 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {332333 // Create new collection334 let new_collection = Collection {335 owner: who,336 name: collection_name,325 name: collection_name,337 mode: mode.clone(),338 mint_mode: false,339 access: AccessMode::Normal,340 description: collection_description,326 description: collection_description,341 token_prefix,327 token_prefix,342 offchain_schema: BoundedVec::default(),328 mode,343 schema_version: SchemaVersion::ImageURL,344 sponsorship: SponsorshipState::Disabled,345 variable_on_chain_schema: BoundedVec::default(),329 ..Default::default()330 };346 const_on_chain_schema: BoundedVec::default(),331 Self::create_collection_ex(origin, data)332 }333334 /// This method creates a collection335 ///336 /// Prefer it to deprecated [`created_collection`] method347 limits: Default::default(),337 #[weight = <SelfWeightOf<T>>::create_collection()]338 #[transactional]348 meta_update_permission: Default::default(),339 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {349 };340 let owner = ensure_signed(origin)?;350341351 let _id = match mode {342 let _id = match data.mode {352 CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(new_collection)?},343 CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(owner, data)?},353 CollectionMode::Fungible(decimal_points) => {344 CollectionMode::Fungible(decimal_points) => {354 // check params345 // check params355 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);346 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);356 <PalletFungible<T>>::init_collection(new_collection)?347 <PalletFungible<T>>::init_collection(owner, data)?357 }348 }358 CollectionMode::ReFungible => {349 CollectionMode::ReFungible => {359 <PalletRefungible<T>>::init_collection(new_collection)?350 <PalletRefungible<T>>::init_collection(owner, data)?360 }351 }361 };352 };362353363 Ok(())354 Ok(())364 }355 }365356366 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.357 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.367 ///358 ///1093 collection_id: CollectionId,1084 collection_id: CollectionId,1094 new_limit: CollectionLimits,1085 new_limit: CollectionLimits,1095 ) -> DispatchResult {1086 ) -> DispatchResult {1096 let mut new_limit = new_limit;1097 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1087 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1098 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1088 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1099 target_collection.check_is_owner(&sender)?;1089 target_collection.check_is_owner(&sender)?;1100 let old_limit = &target_collection.limits;1090 let old_limit = &target_collection.limits;110110911102 macro_rules! limit_default {1103 ($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{1104 $(1105 if let Some($new) = $new.$field {1092 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;1106 let $old = $old.$field($($arg)?);1107 let _ = $new;1108 let _ = $old;1109 $check1110 } else {1111 $new.$field = $old.$field1112 }1113 )*1114 }};1115 }11161117 limit_default!(old_limit, new_limit,1118 account_token_ownership_limit => ensure!(1119 new_limit <= MAX_TOKEN_OWNERSHIP,1120 <Error<T>>::CollectionLimitBoundsExceeded,1121 ),1122 sponsor_transfer_timeout(match target_collection.mode {1123 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,1124 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1125 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1126 }) => ensure!(1127 new_limit <= MAX_SPONSOR_TIMEOUT,1128 <Error<T>>::CollectionLimitBoundsExceeded,1129 ),1130 sponsored_data_size => ensure!(1131 new_limit <= CUSTOM_DATA_LIMIT,1132 <Error<T>>::CollectionLimitBoundsExceeded,1133 ),1134 token_limit => ensure!(1135 old_limit >= new_limit && new_limit > 0,1136 <CommonError<T>>::CollectionTokenLimitExceeded1137 ),1138 owner_can_transfer => ensure!(1139 old_limit || !new_limit,1140 <Error<T>>::OwnerPermissionsCantBeReverted,1141 ),1142 owner_can_destroy => ensure!(1143 old_limit || !new_limit,1144 <Error<T>>::OwnerPermissionsCantBeReverted,1145 ),1146 sponsored_data_rate_limit => {},1147 transfers_enabled => {},1148 );11491150 target_collection.limits = new_limit;115110931152 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1094 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1153 collection_id1095 collection_idpallets/unique/src/tests.rsdiffbeforeafterboth5use up_data_structs::{5use up_data_structs::{6 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,6 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,7 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission,7 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission,8 TokenId,8 TokenId, MAX_TOKEN_OWNERSHIP,9};9};10use frame_support::{assert_noop, assert_ok};10use frame_support::{assert_noop, assert_ok};11use sp_std::convert::TryInto;11use sp_std::convert::TryInto;601 1601 1602 )602 )603 .map_err(|e| e.error),603 .map_err(|e| e.error),604 CommonError::<Test>::TokenValueNotEnough604 CommonError::<Test>::ApprovedValueTooLow605 );605 );606606607 // do approve607 // do approve916 4916 4917 )917 )918 .map_err(|e| e.error),918 .map_err(|e| e.error),919 CommonError::<Test>::TokenValueNotEnough919 CommonError::<Test>::ApprovedValueTooLow920 );920 );921 });921 });922}922}primitives/data-structs/src/lib.rsdiffbeforeafterboth263 pub meta_update_permission: MetaUpdatePermission,263 pub meta_update_permission: MetaUpdatePermission,264}264}265266#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Debug, Derivative, MaxEncodedLen)]267#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]268#[derivative(Default(bound = ""))]269pub struct CreateCollectionData<AccountId> {270 #[derivative(Default(value = "CollectionMode::NFT"))]271 pub mode: CollectionMode,272 pub access: Option<AccessMode>,273 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]274 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,275 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]276 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,277 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]278 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,279 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]280 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,281 pub schema_version: Option<SchemaVersion>,282 pub pending_sponsor: Option<AccountId>,283 pub limits: Option<CollectionLimits>,284 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]285 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,286 #[cfg_attr(feature = "serde1", serde(with = "bounded_serde"))]287 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,288 pub meta_update_permission: Option<MetaUpdatePermission>,289}265290266#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]291#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]267#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]292#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]primitives/rpc/src/lib.rsdiffbeforeafterboth9type Result<T> = core::result::Result<T, DispatchError>;9type Result<T> = core::result::Result<T, DispatchError>;101011sp_api::decl_runtime_apis! {11sp_api::decl_runtime_apis! {12 #[api_version(2)]12 pub trait UniqueApi<CrossAccountId, AccountId> where13 pub trait UniqueApi<CrossAccountId, AccountId> where13 AccountId: Decode,14 AccountId: Decode,14 CrossAccountId: pallet_common::account::CrossAccountId<AccountId>,15 CrossAccountId: pallet_common::account::CrossAccountId<AccountId>,15 {16 {17 #[changed_in(2)]18 fn token_owner(collection: CollectionId, token: TokenId) -> Result<CrossAccountId>;1916 fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>>;20 fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>>;17 fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool>;21 fn token_exists(collection: CollectionId, token: TokenId) -> Result<bool>;runtime/src/lib.rsdiffbeforeafterboth24 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,24 Permill, Perbill, Percent, create_runtime_str, generic, impl_opaque_keys,25 traits::{25 traits::{26 AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify, AccountIdConversion,26 AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify,27 AccountIdConversion, Zero,27 },28 },28 transaction_validity::{TransactionSource, TransactionValidity},29 transaction_validity::{TransactionSource, TransactionValidity},29 ApplyExtrinsicResult, MultiSignature, RuntimeAppPublic,30 ApplyExtrinsicResult, MultiSignature, RuntimeAppPublic,45 dispatch::DispatchResult,46 dispatch::DispatchResult,46 PalletId, parameter_types, StorageValue, ConsensusEngineId,47 PalletId, parameter_types, StorageValue, ConsensusEngineId,47 traits::{48 traits::{48 Everything, Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem,49 tokens::currency::Currency as CurrencyT, OnUnbalanced as OnUnbalancedT, Everything,49 LockIdentifier, OnUnbalanced, Randomness, FindAuthor,50 Currency, ExistenceRequirement, Get, IsInVec, KeyOwnerProofSystem, LockIdentifier,51 OnUnbalanced, Randomness, FindAuthor,50 },52 },69use pallet_evm::{Account as EVMAccount, FeeCalculator, GasWeightMapping, OnMethodCall};71use pallet_evm::{Account as EVMAccount, FeeCalculator, GasWeightMapping, OnMethodCall};70use fp_rpc::TransactionStatus;72use fp_rpc::TransactionStatus;71use sp_runtime::{73use sp_runtime::{72 traits::{BlockNumberProvider, Dispatchable, PostDispatchInfoOf},74 traits::{BlockNumberProvider, Dispatchable, PostDispatchInfoOf, Saturating},73 transaction_validity::TransactionValidityError,75 transaction_validity::TransactionValidityError,76 SaturatedConversion,74};77};757876// pub use pallet_timestamp::Call as TimestampCall;79// pub use pallet_timestamp::Call as TimestampCall;82use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};85use xcm::v1::{BodyId, Junction::*, MultiLocation, NetworkId, Junctions::*};83use xcm_builder::{86use xcm_builder::{84 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,87 AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, CurrencyAdapter,85 EnsureXcmOrigin, FixedWeightBounds, IsConcrete, LocationInverter, NativeAsset,88 EnsureXcmOrigin, FixedWeightBounds, LocationInverter, NativeAsset, ParentAsSuperuser,86 ParentAsSuperuser, ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative,89 ParentIsDefault, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia,87 SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,90 SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,88 SovereignSignedViaLocation, TakeWeightCredit, UsingComponents,89};91};90use xcm_executor::{Config, XcmExecutor};92use xcm_executor::{Config, XcmExecutor, Assets};93use sp_std::{marker::PhantomData};9495use xcm::latest::{96 // Xcm,97 AssetId::{Concrete},98 Fungibility::Fungible as XcmFungible,99 MultiAsset,100 Error as XcmError,101};102use xcm_executor::traits::{MatchesFungible, WeightTrader};103//use xcm_executor::traits::MatchesFungible;104use sp_runtime::traits::CheckedConversion;9110592// mod chain_extension;106// mod chain_extension;93// use crate::chain_extension::{NFTExtension, Imbalance};107// use crate::chain_extension::{NFTExtension, Imbalance};146 spec_name: create_runtime_str!("opal"),160 spec_name: create_runtime_str!("opal"),147 impl_name: create_runtime_str!("opal"),161 impl_name: create_runtime_str!("opal"),148 authoring_version: 1,162 authoring_version: 1,149 spec_version: 914000,163 spec_version: 916001,150 impl_version: 1,164 impl_version: 0,151 apis: RUNTIME_API_VERSIONS,165 apis: RUNTIME_API_VERSIONS,152 transaction_version: 0,166 transaction_version: 1,153 state_version: 0,167 state_version: 0,154};168};155169616 AccountId32Aliases<RelayNetwork, AccountId>,630 AccountId32Aliases<RelayNetwork, AccountId>,617);631);632633pub struct OnlySelfCurrency;634impl<B: TryFrom<u128>> MatchesFungible<B> for OnlySelfCurrency {635 fn matches_fungible(a: &MultiAsset) -> Option<B> {636 match (&a.id, &a.fun) {637 (Concrete(_), XcmFungible(ref amount)) => CheckedConversion::checked_from(*amount),638 _ => None,639 }640 }641}618642619/// Means for transacting assets on this chain.643/// Means for transacting assets on this chain.620pub type LocalAssetTransactor = CurrencyAdapter<644pub type LocalAssetTransactor = CurrencyAdapter<621 // Use this currency:645 // Use this currency:622 Balances,646 Balances,623 // Use this currency when it is a fungible asset matching the given location or name:647 // Use this currency when it is a fungible asset matching the given location or name:624 IsConcrete<RelayLocation>,648 OnlySelfCurrency,625 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:649 // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID:626 LocationToAccountId,650 LocationToAccountId,627 // Our chain's account ID type (we can't get away without mentioning it explicitly):651 // Our chain's account ID type (we can't get away without mentioning it explicitly):677 // ^^^ Parent & its unit plurality gets free execution701 // ^^^ Parent & its unit plurality gets free execution678);702);703704pub struct UsingOnlySelfCurrencyComponents<705 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,706 AssetId: Get<MultiLocation>,707 AccountId,708 Currency: CurrencyT<AccountId>,709 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,710>(711 Weight,712 Currency::Balance,713 PhantomData<(WeightToFee, AssetId, AccountId, Currency, OnUnbalanced)>,714);715impl<716 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,717 AssetId: Get<MultiLocation>,718 AccountId,719 Currency: CurrencyT<AccountId>,720 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,721 > WeightTrader722 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>723{724 fn new() -> Self {725 Self(0, Zero::zero(), PhantomData)726 }727728 fn buy_weight(&mut self, weight: Weight, payment: Assets) -> Result<Assets, XcmError> {729 let amount = WeightToFee::calc(&weight);730 let u128_amount: u128 = amount.try_into().map_err(|_| XcmError::Overflow)?;731732 // location to this parachain through relay chain733 let option1: xcm::v1::AssetId = Concrete(MultiLocation {734 parents: 1,735 interior: X1(Parachain(ParachainInfo::parachain_id().into())),736 });737 // direct location738 let option2: xcm::v1::AssetId = Concrete(MultiLocation {739 parents: 0,740 interior: Here,741 });742743 let required = if payment.fungible.contains_key(&option1) {744 (option1, u128_amount).into()745 } else if payment.fungible.contains_key(&option2) {746 (option2, u128_amount).into()747 } else {748 (Concrete(MultiLocation::default()), u128_amount).into()749 };750751 let unused = payment752 .checked_sub(required)753 .map_err(|_| XcmError::TooExpensive)?;754 self.0 = self.0.saturating_add(weight);755 self.1 = self.1.saturating_add(amount);756 Ok(unused)757 }758759 fn refund_weight(&mut self, weight: Weight) -> Option<MultiAsset> {760 let weight = weight.min(self.0);761 let amount = WeightToFee::calc(&weight);762 self.0 -= weight;763 self.1 = self.1.saturating_sub(amount);764 let amount: u128 = amount.saturated_into();765 if amount > 0 {766 Some((AssetId::get(), amount).into())767 } else {768 None769 }770 }771}772impl<773 WeightToFee: WeightToFeePolynomial<Balance = Currency::Balance>,774 AssetId: Get<MultiLocation>,775 AccountId,776 Currency: CurrencyT<AccountId>,777 OnUnbalanced: OnUnbalancedT<Currency::NegativeImbalance>,778 > Drop779 for UsingOnlySelfCurrencyComponents<WeightToFee, AssetId, AccountId, Currency, OnUnbalanced>780{781 fn drop(&mut self) {782 OnUnbalanced::on_unbalanced(Currency::issue(self.1));783 }784}679785680pub struct XcmConfig;786pub struct XcmConfig;681impl Config for XcmConfig {787impl Config for XcmConfig {689 type LocationInverter = LocationInverter<Ancestry>;795 type LocationInverter = LocationInverter<Ancestry>;690 type Barrier = Barrier;796 type Barrier = Barrier;691 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;797 type Weigher = FixedWeightBounds<UnitWeightCost, Call, MaxInstructions>;692 type Trader = UsingComponents<IdentityFee<Balance>, RelayLocation, AccountId, Balances, ()>;798 type Trader = UsingOnlySelfCurrencyComponents<799 IdentityFee<Balance>,800 RelayLocation,801 AccountId,802 Balances,803 (),804 >;693 type ResponseHandler = (); // Don't handle responses for now.805 type ResponseHandler = (); // Don't handle responses for now.694 type SubscriptionService = PolkadotXcm;806 type SubscriptionService = PolkadotXcm;tests/package.jsondiffbeforeafterboth64 "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",64 "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",65 "testSetVariableMetadataSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetadataSponsoringRateLimit.test.ts",65 "testSetVariableMetadataSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetadataSponsoringRateLimit.test.ts",66 "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts",66 "testInflation": "mocha --timeout 9999999 -r ts-node/register ./**/inflation.test.ts",67 "testXcmTransfer": "mocha --timeout 9999999 -r ts-node/register ./**/xcmTransfer.test.ts",67 "testPalletPresence": "mocha --timeout 9999999 -r ts-node/register ./**/pallet-presence.test.ts",68 "testPalletPresence": "mocha --timeout 9999999 -r ts-node/register ./**/pallet-presence.test.ts",68 "testBlockProduction": "mocha --timeout 9999999 -r ts-node/register ./**/block-production.test.ts",69 "testBlockProduction": "mocha --timeout 9999999 -r ts-node/register ./**/block-production.test.ts",69 "testEnableDisableTransfers": "mocha --timeout 9999999 -r ts-node/register ./**/enableDisableTransfer.test.ts",70 "testEnableDisableTransfers": "mocha --timeout 9999999 -r ts-node/register ./**/enableDisableTransfer.test.ts",71 "polkadot-types-fetch-metadata": "curl -H 'Content-Type: application/json' -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9933 > src/interfaces/metadata.json",70 "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --input src/interfaces/ --package .",72 "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --input src/interfaces/ --package .",71 "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint ws://localhost:9944 --output src/interfaces/ --package .",73 "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint src/interfaces/metadata.json --output src/interfaces/ --package .",72 "polkadot-types": "yarn polkadot-types-from-defs && yarn polkadot-types-from-chain"74 "polkadot-types": "yarn polkadot-types-fetch-metadata && yarn polkadot-types-from-defs && yarn polkadot-types-from-chain"73 },75 },74 "author": "",76 "author": "",75 "license": "SEE LICENSE IN ../LICENSE",77 "license": "SEE LICENSE IN ../LICENSE",tests/src/check-event/createCollectionEvent.test.tsdiffbeforeafterboth27 });27 });28 it('Check event from createCollection(): ', async () => {28 it('Check event from createCollection(): ', async () => {29 await usingApi(async (api: ApiPromise) => {29 await usingApi(async (api: ApiPromise) => {30 const tx = api.tx.unique.createCollection([0x31], [0x32], '0x33', 'NFT');30 const tx = api.tx.unique.createCollectionEx({name: [0x31], description: [0x32], tokenPrefix: '0x33', mode: 'NFT'});31 const events = await submitTransactionAsync(alice, tx);31 const events = await submitTransactionAsync(alice, tx);32 const msg = JSON.stringify(uniqueEventMessage(events));32 const msg = JSON.stringify(uniqueEventMessage(events));33 expect(msg).to.be.contain(checkSection);33 expect(msg).to.be.contain(checkSection);tests/src/createCollection.test.tsdiffbeforeafterboth3// file 'LICENSE', which is part of this source code package.3// file 'LICENSE', which is part of this source code package.4//4//556import chai from 'chai';6import {expect} from 'chai';7import chaiAsPromised from 'chai-as-promised';7import privateKey from './substrate/privateKey';8import usingApi, {executeTransaction, submitTransactionAsync} from './substrate/substrate-api';8import {createCollectionExpectFailure, createCollectionExpectSuccess} from './util/helpers';9import {createCollectionExpectFailure, createCollectionExpectSuccess, getCreateCollectionResult, getDetailedCollectionInfo} from './util/helpers';910chai.use(chaiAsPromised);111012describe('integration test: ext. createCollection():', () => {11describe('integration test: ext. createCollection():', () => {13 it('Create new NFT collection', async () => {12 it('Create new NFT collection', async () => {28 it('Create new ReFungible collection', async () => {27 it('Create new ReFungible collection', async () => {29 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});28 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});30 });29 });30 it('Create new collection with extra fields', async () => {31 await usingApi(async api => {32 const alice = privateKey('//Alice');33 const bob = privateKey('//Bob');34 const tx = api.tx.unique.createCollectionEx({35 mode: {Fungible: 8},36 access: 'AllowList',37 name: [1],38 description: [2],39 tokenPrefix: '0x000000',40 offchainSchema: '0x111111',41 schemaVersion: 'Unique',42 pendingSponsor: bob.address,43 limits: {44 accountTokenOwnershipLimit: 3,45 },46 variableOnChainSchema: '0x222222',47 constOnChainSchema: '0x333333',48 metaUpdatePermission: 'Admin',49 });50 const events = await submitTransactionAsync(alice, tx);51 const result = getCreateCollectionResult(events);5253 const collection = (await getDetailedCollectionInfo(api, result.collectionId))!;54 expect(collection.owner.toString()).to.equal(alice.address);55 expect(collection.mode.asFungible.toNumber()).to.equal(8);56 expect(collection.access.isAllowList).to.be.true;57 expect(collection.name.map(v => v.toNumber())).to.deep.equal([1]);58 expect(collection.description.map(v => v.toNumber())).to.deep.equal([2]);59 expect(collection.tokenPrefix.toString()).to.equal('0x000000');60 expect(collection.offchainSchema.toString()).to.equal('0x111111');61 expect(collection.schemaVersion.isUnique).to.be.true;62 expect(collection.sponsorship.asUnconfirmed.toString()).to.equal(bob.address);63 expect(collection.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.equal(3);64 expect(collection.variableOnChainSchema.toString()).to.equal('0x222222');65 expect(collection.constOnChainSchema.toString()).to.equal('0x333333');66 expect(collection.metaUpdatePermission.isAdmin).to.be.true;67 });68 });31});69});327033describe('(!negative test!) integration test: ext. createCollection():', () => {71describe('(!negative test!) integration test: ext. createCollection():', () => {40 it('(!negative test!) create new NFT collection whith incorrect data (token_prefix)', async () => {78 it('(!negative test!) create new NFT collection whith incorrect data (token_prefix)', async () => {41 await createCollectionExpectFailure({tokenPrefix: 'A'.repeat(17), mode: {type: 'NFT'}});79 await createCollectionExpectFailure({tokenPrefix: 'A'.repeat(17), mode: {type: 'NFT'}});42 });80 });81 it('fails when bad limits are set', async () => {82 await usingApi(async api => {83 const alice = privateKey('//Alice');84 const tx = api.tx.unique.createCollectionEx({mode: 'NFT', limits: {tokenLimit: 0}});85 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/^common.CollectionTokenLimitExceeded$/);86 });87 });43});88});4489tests/src/interfaces/.gitignorediffbeforeafterbothno changes
tests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth68 * Collection description can not be longer than 255 char.68 * Collection description can not be longer than 255 char.69 **/69 **/70 CollectionDescriptionLimitExceeded: AugmentedError<ApiType>;70 CollectionDescriptionLimitExceeded: AugmentedError<ApiType>;71 /**72 * Collection limit bounds per collection exceeded73 **/74 CollectionLimitBoundsExceeded: AugmentedError<ApiType>;71 /**75 /**72 * Collection name can not be longer than 63 char.76 * Collection name can not be longer than 63 char.73 **/77 **/96 * No permission to perform action100 * No permission to perform action97 **/101 **/98 NoPermission: AugmentedError<ApiType>;102 NoPermission: AugmentedError<ApiType>;103 /**104 * Tried to enable permissions which are only permitted to be disabled105 **/106 OwnerPermissionsCantBeReverted: AugmentedError<ApiType>;99 /**107 /**100 * Collection is not in mint mode.108 * Collection is not in mint mode.101 **/109 **/107 /**115 /**108 * Requested value more than approved.116 * Requested value more than approved.109 **/117 **/110 TokenValueNotEnough: AugmentedError<ApiType>;118 ApprovedValueTooLow: AugmentedError<ApiType>;111 /**119 /**112 * Item balance not enough.120 * Item balance not enough.113 **/121 **/436 * Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.444 * Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.437 **/445 **/438 CollectionDecimalPointLimitExceeded: AugmentedError<ApiType>;446 CollectionDecimalPointLimitExceeded: AugmentedError<ApiType>;439 /**440 * Collection limit bounds per collection exceeded441 **/442 CollectionLimitBoundsExceeded: AugmentedError<ApiType>;443 /**447 /**444 * This address is not set as sponsor, use setCollectionSponsor first.448 * This address is not set as sponsor, use setCollectionSponsor first.445 **/449 **/448 * Length of items properties must be greater than 0.452 * Length of items properties must be greater than 0.449 **/453 **/450 EmptyArgument: AugmentedError<ApiType>;454 EmptyArgument: AugmentedError<ApiType>;451 /**452 * Tried to enable permissions which are only permitted to be disabled453 **/454 OwnerPermissionsCantBeReverted: AugmentedError<ApiType>;455 /**455 /**456 * Generic error456 * Generic error457 **/457 **/tests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth2/* eslint-disable */2/* eslint-disable */334import type { CumulusPrimitivesParachainInherentParachainInherentData } from './polkadot';4import type { CumulusPrimitivesParachainInherentParachainInherentData } from './polkadot';5import type { PalletCommonAccountBasicCrossAccountIdRepr, UpDataStructsAccessMode, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCreateItemData, UpDataStructsMetaUpdatePermission, UpDataStructsSchemaVersion } from './unique';5import type { PalletCommonAccountBasicCrossAccountIdRepr, UpDataStructsAccessMode, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsMetaUpdatePermission, UpDataStructsSchemaVersion } from './unique';6import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types';6import type { ApiTypes, SubmittableExtrinsic } from '@polkadot/api/types';7import type { Bytes, Compact, Option, U256, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types';7import type { Bytes, Compact, Option, U256, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types';8import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';8import type { Extrinsic } from '@polkadot/types/interfaces/extrinsics';670 * * mode: [CollectionMode] collection type and type dependent data.670 * * mode: [CollectionMode] collection type and type dependent data.671 **/671 **/672 createCollection: AugmentedSubmittable<(collectionName: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], collectionDescription: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], tokenPrefix: Bytes | string | Uint8Array, mode: UpDataStructsCollectionMode | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Vec<u16>, Vec<u16>, Bytes, UpDataStructsCollectionMode]>;672 createCollection: AugmentedSubmittable<(collectionName: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], collectionDescription: Vec<u16> | (u16 | AnyNumber | Uint8Array)[], tokenPrefix: Bytes | string | Uint8Array, mode: UpDataStructsCollectionMode | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [Vec<u16>, Vec<u16>, Bytes, UpDataStructsCollectionMode]>;673 /**674 * This method creates a collection675 * 676 * Prefer it to deprecated [`created_collection`] method677 **/678 createCollectionEx: AugmentedSubmittable<(data: UpDataStructsCreateCollectionData | { mode?: any; access?: any; name?: any; description?: any; tokenPrefix?: any; offchainSchema?: any; schemaVersion?: any; pendingSponsor?: any; limits?: any; variableOnChainSchema?: any; constOnChainSchema?: any; metaUpdatePermission?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [UpDataStructsCreateCollectionData]>;673 /**679 /**674 * This method creates a concrete instance of NFT Collection created with CreateCollection method.680 * This method creates a concrete instance of NFT Collection created with CreateCollection method.675 * 681 * tests/src/interfaces/augment-types.tsdiffbeforeafterboth334import type { EthereumBlock, EthereumLog, EthereumReceipt, EthereumTransactionLegacyTransaction, EvmCoreErrorExitReason, FpRpcTransactionStatus } from './ethereum';4import type { EthereumBlock, EthereumLog, EthereumReceipt, EthereumTransactionLegacyTransaction, EvmCoreErrorExitReason, FpRpcTransactionStatus } from './ethereum';5import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundStatus, CumulusPalletXcmpQueueOutboundStatus, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData } from './polkadot';5import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundStatus, CumulusPalletXcmpQueueOutboundStatus, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV1AbridgedHostConfiguration, PolkadotPrimitivesV1PersistedValidationData } from './polkadot';6import type { PalletCommonAccountBasicCrossAccountIdRepr, PalletNonfungibleItemData, PalletRefungibleItemData, PalletUnqSchedulerCallSpec, PalletUnqSchedulerReleases, PalletUnqSchedulerScheduledV2, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionId, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionStats, UpDataStructsCreateItemData, UpDataStructsMetaUpdatePermission, UpDataStructsSchemaVersion, UpDataStructsSponsorshipState, UpDataStructsTokenId } from './unique';6import type { PalletCommonAccountBasicCrossAccountIdRepr, PalletNonfungibleItemData, PalletRefungibleItemData, PalletUnqSchedulerCallSpec, PalletUnqSchedulerReleases, PalletUnqSchedulerScheduledV2, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionId, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateItemData, UpDataStructsMetaUpdatePermission, UpDataStructsSchemaVersion, UpDataStructsSponsorshipState, UpDataStructsTokenId } from './unique';7import type { BitVec, Bool, Bytes, Data, I128, I16, I256, I32, I64, I8, Json, Null, Raw, StorageKey, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types';7import type { BitVec, Bool, Bytes, Data, I128, I16, I256, I32, I64, I8, Json, Null, Raw, StorageKey, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types';8import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';8import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';9import type { BlockAttestations, IncludedBlocks, MoreAttestations } from '@polkadot/types/interfaces/attestations';9import type { BlockAttestations, IncludedBlocks, MoreAttestations } from '@polkadot/types/interfaces/attestations';1021 UpDataStructsCollectionLimits: UpDataStructsCollectionLimits;1021 UpDataStructsCollectionLimits: UpDataStructsCollectionLimits;1022 UpDataStructsCollectionMode: UpDataStructsCollectionMode;1022 UpDataStructsCollectionMode: UpDataStructsCollectionMode;1023 UpDataStructsCollectionStats: UpDataStructsCollectionStats;1023 UpDataStructsCollectionStats: UpDataStructsCollectionStats;1024 UpDataStructsCreateCollectionData: UpDataStructsCreateCollectionData;1024 UpDataStructsCreateItemData: UpDataStructsCreateItemData;1025 UpDataStructsCreateItemData: UpDataStructsCreateItemData;1025 UpDataStructsMetaUpdatePermission: UpDataStructsMetaUpdatePermission;1026 UpDataStructsMetaUpdatePermission: UpDataStructsMetaUpdatePermission;1026 UpDataStructsSchemaVersion: UpDataStructsSchemaVersion;1027 UpDataStructsSchemaVersion: UpDataStructsSchemaVersion;tests/src/interfaces/unique/definitions.tsdiffbeforeafterboth67 constOnChainSchema: 'Vec<u8>',67 constOnChainSchema: 'Vec<u8>',68 metaUpdatePermission: 'UpDataStructsMetaUpdatePermission',68 metaUpdatePermission: 'UpDataStructsMetaUpdatePermission',69 },69 },70 UpDataStructsCreateCollectionData: {71 mode: 'UpDataStructsCollectionMode',72 access: 'Option<UpDataStructsAccessMode>',73 name: 'Vec<u16>',74 description: 'Vec<u16>',75 tokenPrefix: 'Vec<u8>',76 offchainSchema: 'Vec<u8>',77 schemaVersion: 'Option<UpDataStructsSchemaVersion>',78 pendingSponsor: 'Option<AccountId>',79 limits: 'Option<UpDataStructsCollectionLimits>',80 variableOnChainSchema: 'Vec<u8>',81 constOnChainSchema: 'Vec<u8>',82 metaUpdatePermission: 'Option<UpDataStructsMetaUpdatePermission>',83 },70 UpDataStructsCollectionStats: {84 UpDataStructsCollectionStats: {71 created: 'u32',85 created: 'u32',72 destroyed: 'u32',86 destroyed: 'u32',76 UpDataStructsTokenId: 'u32',90 UpDataStructsTokenId: 'u32',77 PalletNonfungibleItemData: mkDummy('NftItemData'),91 PalletNonfungibleItemData: mkDummy('NftItemData'),78 PalletRefungibleItemData: mkDummy('RftItemData'),92 PalletRefungibleItemData: mkDummy('RftItemData'),79 UpDataStructsCollectionMode: mkDummy('CollectionMode'),93 UpDataStructsCollectionMode: {94 _enum: {95 NFT: null,96 Fungible: 'u32',97 ReFungible: null,98 },99 },80 UpDataStructsCreateItemData: mkDummy('CreateItemData'),100 UpDataStructsCreateItemData: mkDummy('CreateItemData'),81 UpDataStructsCollectionLimits: {101 UpDataStructsCollectionLimits: {82 accountTokenOwnershipLimit: 'Option<u32>',102 accountTokenOwnershipLimit: 'Option<u32>',101 UpDataStructsAccessMode: {121 UpDataStructsAccessMode: {102 _enum: ['Normal', 'AllowList'],122 _enum: ['Normal', 'AllowList'],103 },123 },104 UpDataStructsSchemaVersion: mkDummy('SchemaVersion'),124 UpDataStructsSchemaVersion: {125 _enum: ['ImageURL', 'Unique'],126 },105127106 PalletUnqSchedulerScheduledV2: mkDummy('ScheduledV2'),128 PalletUnqSchedulerScheduledV2: mkDummy('ScheduledV2'),107 PalletUnqSchedulerCallSpec: mkDummy('CallSpec'),129 PalletUnqSchedulerCallSpec: mkDummy('CallSpec'),tests/src/interfaces/unique/types.tsdiffbeforeafterboth77}77}787879/** @name UpDataStructsCollectionMode */79/** @name UpDataStructsCollectionMode */80export interface UpDataStructsCollectionMode extends Struct {80export interface UpDataStructsCollectionMode extends Enum {81 readonly isNft: boolean;82 readonly isFungible: boolean;81 readonly dummyCollectionMode: u32;83 readonly asFungible: u32;84 readonly isReFungible: boolean;82}85}838684/** @name UpDataStructsCollectionStats */87/** @name UpDataStructsCollectionStats */88 readonly alive: u32;91 readonly alive: u32;89}92}9394/** @name UpDataStructsCreateCollectionData */95export interface UpDataStructsCreateCollectionData extends Struct {96 readonly mode: UpDataStructsCollectionMode;97 readonly access: Option<UpDataStructsAccessMode>;98 readonly name: Vec<u16>;99 readonly description: Vec<u16>;100 readonly tokenPrefix: Bytes;101 readonly offchainSchema: Bytes;102 readonly schemaVersion: Option<UpDataStructsSchemaVersion>;103 readonly pendingSponsor: Option<AccountId>;104 readonly limits: Option<UpDataStructsCollectionLimits>;105 readonly variableOnChainSchema: Bytes;106 readonly constOnChainSchema: Bytes;107 readonly metaUpdatePermission: Option<UpDataStructsMetaUpdatePermission>;108}9010991/** @name UpDataStructsCreateItemData */110/** @name UpDataStructsCreateItemData */92export interface UpDataStructsCreateItemData extends Struct {111export interface UpDataStructsCreateItemData extends Struct {101}120}102121103/** @name UpDataStructsSchemaVersion */122/** @name UpDataStructsSchemaVersion */104export interface UpDataStructsSchemaVersion extends Struct {123export interface UpDataStructsSchemaVersion extends Enum {105 readonly dummySchemaVersion: u32;124 readonly isImageUrl: boolean;125 readonly isUnique: boolean;106}126}107127108/** @name UpDataStructsSponsorshipState */128/** @name UpDataStructsSponsorshipState */tests/src/substrate/substrate-api.tsdiffbeforeafterboth95 return TransactionStatus.Fail;95 return TransactionStatus.Fail;96}96}9798export function executeTransaction(api: ApiPromise, sender: IKeyringPair, transaction: SubmittableExtrinsic<'promise'>): Promise<EventRecord[]> {99 return new Promise(async (res, rej) => {100 try {101 await transaction.signAndSend(sender, ({events, status}) => {102 if (!status.isInBlock && !status.isFinalized) return;103 for (const {event} of events) {104 if (api.events.system.ExtrinsicSuccess.is(event)) {105 res(events);106 } else if (api.events.system.ExtrinsicFailed.is(event)) {107 const {data: [error]} = event;108 if (error.isModule) {109 const decoded = api.registry.findMetaError(error.asModule);110 const {method, section} = decoded;111 rej(new Error(`${section}.${method}`));112 } else {113 rej(new Error(error.toString()));114 }115 }116 }117 });118 } catch (e) {119 rej(e);120 }121 });122}9712398export function124export function99submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {125submitTransactionAsync(sender: IKeyringPair, transaction: SubmittableExtrinsic<ApiTypes>): Promise<EventRecord[]> {tests/src/util/helpers.tsdiffbeforeafterboth283 modeprm = {refungible: null};283 modeprm = {refungible: null};284 }284 }285285286 const tx = api.tx.unique.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm as any);286 const tx = api.tx.unique.createCollectionEx({name: strToUTF16(name), description: strToUTF16(description), tokenPrefix: strToUTF16(tokenPrefix), mode: modeprm as any});287 const events = await submitTransactionAsync(alicePrivateKey, tx);287 const events = await submitTransactionAsync(alicePrivateKey, tx);288 const result = getCreateCollectionResult(events);288 const result = getCreateCollectionResult(events);289289329329330 // Run the CreateCollection transaction330 // Run the CreateCollection transaction331 const alicePrivateKey = privateKey('//Alice');331 const alicePrivateKey = privateKey('//Alice');332 const tx = api.tx.unique.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm as any);332 const tx = api.tx.unique.createCollectionEx({name: strToUTF16(name), description: strToUTF16(description), tokenPrefix: strToUTF16(tokenPrefix), mode: modeprm as any});333 const events = await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;333 const events = await expect(submitTransactionExpectFailAsync(alicePrivateKey, tx)).to.be.rejected;334 const result = getCreateCollectionResult(events);334 const result = getCreateCollectionResult(events);335335tests/src/xcmTransfer.test.tsdiffbeforeafterbothno changes