difftreelog
Merge branch 'develop' into doc/architectural-changes
in: master
80 files changed
Cargo.lockdiffbeforeafterboth573157315732[[package]]5732[[package]]5733name = "pallet-common"5733name = "pallet-common"5734version = "0.1.0"5734version = "0.1.2"5735dependencies = [5735dependencies = [5736 "ethereum",5736 "ethereum",5737 "evm-coder",5737 "evm-coder",595359535954[[package]]5954[[package]]5955name = "pallet-fungible"5955name = "pallet-fungible"5956version = "0.1.0"5956version = "0.1.1"5957dependencies = [5957dependencies = [5958 "ethereum",5958 "ethereum",5959 "evm-coder",5959 "evm-coder",619861986199[[package]]6199[[package]]6200name = "pallet-nonfungible"6200name = "pallet-nonfungible"6201version = "0.1.0"6201version = "0.1.1"6202dependencies = [6202dependencies = [6203 "ethereum",6203 "ethereum",6204 "evm-coder",6204 "evm-coder",632063206321[[package]]6321[[package]]6322name = "pallet-refungible"6322name = "pallet-refungible"6323version = "0.1.0"6323version = "0.1.2"6324dependencies = [6324dependencies = [6325 "ethereum",6326 "evm-coder",6325 "frame-benchmarking",6327 "frame-benchmarking",6326 "frame-support",6328 "frame-support",6327 "frame-system",6329 "frame-system",6328 "pallet-common",6330 "pallet-common",6329 "pallet-evm",6331 "pallet-evm",6332 "pallet-evm-coder-substrate",6330 "pallet-structure",6333 "pallet-structure",6331 "parity-scale-codec 3.1.5",6334 "parity-scale-codec 3.1.5",6332 "scale-info",6335 "scale-info",123741237712375[[package]]12378[[package]]12376name = "uc-rpc"12379name = "uc-rpc"12377version = "0.1.0"12380version = "0.1.1"12378dependencies = [12381dependencies = [12379 "anyhow",12382 "anyhow",12380 "jsonrpsee",12383 "jsonrpsee",127331273612734[[package]]12737[[package]]12735name = "up-data-structs"12738name = "up-data-structs"12736version = "0.1.0"12739version = "0.1.1"12737dependencies = [12740dependencies = [12738 "derivative",12741 "derivative",12739 "frame-support",12742 "frame-support",127511275412752[[package]]12755[[package]]12753name = "up-rpc"12756name = "up-rpc"12754version = "0.1.0"12757version = "0.1.1"12755dependencies = [12758dependencies = [12756 "pallet-common",12759 "pallet-common",12757 "pallet-evm",12760 "pallet-evm",Makefilediffbeforeafterboth12NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs12NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs13NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json13NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json1415REFUNGIBLE_EVM_STUBS=./pallets/refungible/src/stubs16RENFUNGIBLE_EVM_ABI=./tests/src/eth/reFungibleAbi.json17RENFUNGIBLE_TOKEN_EVM_ABI=./tests/src/eth/reFungibleTokenAbi.json141815CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/19CONTRACT_HELPERS_STUBS=./pallets/evm-contract-helpers/src/stubs/16CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json20CONTRACT_HELPERS_ABI=./tests/src/eth/util/contractHelpersAbi.json21TESTS_API=./tests/src/eth/api/25TESTS_API=./tests/src/eth/api/222623.PHONY: regenerate_solidity27.PHONY: regenerate_solidity24regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol CollectionHelpers.sol28regenerate_solidity: UniqueFungible.sol UniqueNFT.sol UniqueRefungibleToken.sol ContractHelpers.sol CollectionHelpers.sol252926UniqueFungible.sol:30UniqueFungible.sol:27 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh31 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh30UniqueNFT.sol:34UniqueNFT.sol:31 PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh35 PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh32 PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh36 PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh37 38UniqueRefungibleToken.sol:39 PACKAGE=pallet-refungible NAME=erc_token::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh40 PACKAGE=pallet-refungible NAME=erc_token::gen_impl OUTPUT=$(REFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh334134ContractHelpers.sol:42ContractHelpers.sol:35 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh43 PACKAGE=pallet-evm-contract-helpers NAME=eth::contract_helpers_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh47 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.raw ./.maintain/scripts/compile_stub.sh55 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/UniqueNFT.raw ./.maintain/scripts/compile_stub.sh48 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh56 INPUT=$(NONFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(NONFUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh5758UniqueRefungibleToken: UniqueRefungibleToken.sol59 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungibleToken.raw ./.maintain/scripts/compile_stub.sh60 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(RENFUNGIBLE_TOKEN_EVM_ABI) ./.maintain/scripts/generate_abi.sh496150ContractHelpers: ContractHelpers.sol62ContractHelpers: ContractHelpers.sol51 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh63 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh55 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelpers.raw ./.maintain/scripts/compile_stub.sh67 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelpers.raw ./.maintain/scripts/compile_stub.sh56 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh68 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh576958evm_stubs: UniqueFungible UniqueNFT ContractHelpers CollectionHelpers70evm_stubs: UniqueFungible UniqueNFT UniqueRefungibleToken ContractHelpers CollectionHelpers597160.PHONY: _bench72.PHONY: _bench61_bench:73_bench:client/rpc/CHANGELOG.mddiffbeforeafterbothno changes
client/rpc/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "uc-rpc"2name = "uc-rpc"3version = "0.1.0"3version = "0.1.1"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66client/rpc/src/lib.rsdiffbeforeafterboth77 at: Option<BlockHash>,77 at: Option<BlockHash>,78 ) -> Result<Option<CrossAccountId>>;78 ) -> Result<Option<CrossAccountId>>;7980 /// Returns 10 tokens owners in no particular order.81 #[method(name = "unique_tokenOwners")]82 fn token_owners(83 &self,84 collection: CollectionId,85 token: TokenId,86 at: Option<BlockHash>,87 ) -> Result<Vec<CrossAccountId>>;798880 /// Get the topmost token owner in the hierarchy of a possibly nested token.89 /// Get the topmost token owner in the hierarchy of a possibly nested token.81 #[method(name = "unique_topmostTokenOwner")]90 #[method(name = "unique_topmostTokenOwner")]510 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);519 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);511 pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);520 pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);512 pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128>, unique_api);521 pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128>, unique_api);522 pass_method!(token_owners(collection: CollectionId, token: TokenId) -> Vec<CrossAccountId>, unique_api);513}523}514524515#[allow(deprecated)]525#[allow(deprecated)]pallets/common/CHANGELOG.MDdiffbeforeafterbothno changes
pallets/common/CHANGELOG.mddiffbeforeafterbothno changes
pallets/common/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-common"2name = "pallet-common"3version = "0.1.0"3version = "0.1.2"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/common/src/dispatch.rsdiffbeforeafterboth1//! Module with interfaces for dispatching collections.21use frame_support::{3use frame_support::{2 dispatch::{4 dispatch::{20 // submit_logs is measured as part of collection pallets22 // submit_logs is measured as part of collection pallets21}23}222423/// Helper function to implement substrate calls for common collection methods25/// Helper function to implement substrate calls for common collection methods.26///27/// * `collection` - The collection on which to call the method.28/// * `call` - The function in which to call the corresponding method from [`CommonCollectionOperations`].24pub fn dispatch_tx<29pub fn dispatch_tx<25 T: Config,30 T: Config,26 C: FnOnce(&dyn CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,31 C: FnOnce(&dyn CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,64 result69 result65}70}667172/// Interface for working with different collections through the dispatcher.67pub trait CollectionDispatch<T: Config> {73pub trait CollectionDispatch<T: Config> {74 /// Create a collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).75 ///76 /// * `sender` - The user who will become the owner of the collection.77 /// * `data` - Description of the created collection.68 fn create(78 fn create(69 sender: T::CrossAccountId,79 sender: T::CrossAccountId,70 data: CreateCollectionData<T::AccountId>,80 data: CreateCollectionData<T::AccountId>,71 ) -> DispatchResult;81 ) -> DispatchResult;8283 /// Delete the collection.84 ///85 /// * `sender` - The owner of the collection.86 /// * `handle` - Collection handle.72 fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;87 fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;738889 /// Get a specialized collection from the handle.90 ///91 /// * `handle` - Collection handle.74 fn dispatch(handle: CollectionHandle<T>) -> Self;92 fn dispatch(handle: CollectionHandle<T>) -> Self;9394 /// Get the collection handle for the corresponding implementation.75 fn into_inner(self) -> CollectionHandle<T>;95 fn into_inner(self) -> CollectionHandle<T>;769697 /// Get the implementation of [`CommonCollectionOperations`].77 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;98 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;78}99}79100pallets/common/src/erc.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! This module contains the implementation of pallet methods for evm.161817use evm_coder::{19use evm_coder::{18 solidity_interface, solidity, ToLog,20 solidity_interface, solidity, ToLog,293130use crate::{Pallet, CollectionHandle, Config, CollectionProperties};32use crate::{Pallet, CollectionHandle, Config, CollectionProperties};313334/// Events for ethereum collection helper.32#[derive(ToLog)]35#[derive(ToLog)]33pub enum CollectionHelpersEvents {36pub enum CollectionHelpersEvents {37 /// The collection has been created.34 CollectionCreated {38 CollectionCreated {39 /// Collection owner.35 #[indexed]40 #[indexed]36 owner: address,41 owner: address,4243 /// Collection ID.37 #[indexed]44 #[indexed]38 collection_id: address,45 collection_id: address,39 },46 },40}47}414842/// Does not always represent a full collection, for RFT it is either49/// Does not always represent a full collection, for RFT it is either43/// collection (Implementing ERC721), or specific collection token (Implementing ERC20)50/// collection (Implementing ERC721), or specific collection token (Implementing ERC20).44pub trait CommonEvmHandler {51pub trait CommonEvmHandler {45 const CODE: &'static [u8];52 const CODE: &'static [u8];465354 /// Call precompiled handle.47 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult>;55 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult>;48}56}495758/// @title A contract that allows you to work with collections.50#[solidity_interface(name = "Collection")]59#[solidity_interface(name = "Collection")]51impl<T: Config> CollectionHandle<T>60impl<T: Config> CollectionHandle<T>52where61where53 T::AccountId: From<[u8; 32]>,62 T::AccountId: From<[u8; 32]>,54{63{64 /// Set collection property.65 ///66 /// @param key Property key.67 /// @param value Propery value.55 fn set_collection_property(68 fn set_collection_property(56 &mut self,69 &mut self,57 caller: caller,70 caller: caller,68 .map_err(dispatch_to_evm::<T>)81 .map_err(dispatch_to_evm::<T>)69 }82 }708384 /// Delete collection property.85 ///86 /// @param key Property key.71 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {87 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {72 let caller = T::CrossAccountId::from_eth(caller);88 let caller = T::CrossAccountId::from_eth(caller);73 let key = <Vec<u8>>::from(key)89 let key = <Vec<u8>>::from(key)77 <Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)93 <Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)78 }94 }799596 /// Get collection property.97 ///80 /// Throws error if key not found98 /// @dev Throws error if key not found.99 ///100 /// @param key Property key.101 /// @return bytes The property corresponding to the key.81 fn collection_property(&self, key: string) -> Result<bytes> {102 fn collection_property(&self, key: string) -> Result<bytes> {82 let key = <Vec<u8>>::from(key)103 let key = <Vec<u8>>::from(key)83 .try_into()104 .try_into()89 Ok(prop.to_vec())110 Ok(prop.to_vec())90 }111 }91112113 /// Set the sponsor of the collection.114 ///115 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.116 ///117 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.92 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {118 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {93 check_is_owner_or_admin(caller, self)?;119 check_is_owner_or_admin(caller, self)?;9412098 save(self)124 save(self)99 }125 }100126127 /// Collection sponsorship confirmation.128 ///129 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.101 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {130 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {102 let caller = T::CrossAccountId::from_eth(caller);131 let caller = T::CrossAccountId::from_eth(caller);103 if !self132 if !self109 save(self)138 save(self)110 }139 }111140141 /// Set limits for the collection.142 /// @dev Throws error if limit not found.143 /// @param limit Name of the limit. Valid names:144 /// "accountTokenOwnershipLimit",145 /// "sponsoredDataSize",146 /// "sponsoredDataRateLimit",147 /// "tokenLimit",148 /// "sponsorTransferTimeout",149 /// "sponsorApproveTimeout"150 /// @param value Value of the limit.112 #[solidity(rename_selector = "setCollectionLimit")]151 #[solidity(rename_selector = "setCollectionLimit")]113 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {152 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {114 check_is_owner_or_admin(caller, self)?;153 check_is_owner_or_admin(caller, self)?;145 save(self)184 save(self)146 }185 }147186187 /// Set limits for the collection.188 /// @dev Throws error if limit not found.189 /// @param limit Name of the limit. Valid names:190 /// "ownerCanTransfer",191 /// "ownerCanDestroy",192 /// "transfersEnabled"193 /// @param value Value of the limit.148 #[solidity(rename_selector = "setCollectionLimit")]194 #[solidity(rename_selector = "setCollectionLimit")]149 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {195 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {150 check_is_owner_or_admin(caller, self)?;196 check_is_owner_or_admin(caller, self)?;172 save(self)218 save(self)173 }219 }174220221 /// Get contract address.175 fn contract_address(&self, _caller: caller) -> Result<address> {222 fn contract_address(&self, _caller: caller) -> Result<address> {176 Ok(crate::eth::collection_id_to_address(self.id))223 Ok(crate::eth::collection_id_to_address(self.id))177 }224 }178225226 /// Add collection admin by substrate address.227 /// @param new_admin Substrate administrator address.179 fn add_collection_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {228 fn add_collection_admin_substrate(229 &mut self,230 caller: caller,231 new_admin: uint256,232 ) -> Result<void> {180 let caller = T::CrossAccountId::from_eth(caller);233 let caller = T::CrossAccountId::from_eth(caller);181 let mut new_admin_arr: [u8; 32] = Default::default();234 let mut new_admin_arr: [u8; 32] = Default::default();186 Ok(())239 Ok(())187 }240 }188241242 /// Remove collection admin by substrate address.243 /// @param admin Substrate administrator address.189 fn remove_collection_admin_substrate(244 fn remove_collection_admin_substrate(190 &self,245 &mut self,191 caller: caller,246 caller: caller,192 new_admin: uint256,247 admin: uint256,193 ) -> Result<void> {248 ) -> Result<void> {194 let caller = T::CrossAccountId::from_eth(caller);249 let caller = T::CrossAccountId::from_eth(caller);195 let mut new_admin_arr: [u8; 32] = Default::default();250 let mut admin_arr: [u8; 32] = Default::default();196 new_admin.to_big_endian(&mut new_admin_arr);251 admin.to_big_endian(&mut admin_arr);197 let account_id = T::AccountId::from(new_admin_arr);252 let account_id = T::AccountId::from(admin_arr);198 let new_admin = T::CrossAccountId::from_sub(account_id);253 let admin = T::CrossAccountId::from_sub(account_id);199 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, false)254 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;200 .map_err(dispatch_to_evm::<T>)?;201 Ok(())255 Ok(())202 }256 }203257258 /// Add collection admin.259 /// @param new_admin Address of the added administrator.204 fn add_collection_admin(&self, caller: caller, new_admin: address) -> Result<void> {260 fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {205 let caller = T::CrossAccountId::from_eth(caller);261 let caller = T::CrossAccountId::from_eth(caller);206 let new_admin = T::CrossAccountId::from_eth(new_admin);262 let new_admin = T::CrossAccountId::from_eth(new_admin);207 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;263 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;208 Ok(())264 Ok(())209 }265 }210266267 /// Remove collection admin.268 ///269 /// @param new_admin Address of the removed administrator.211 fn remove_collection_admin(&self, caller: caller, admin: address) -> Result<void> {270 fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {212 let caller = T::CrossAccountId::from_eth(caller);271 let caller = T::CrossAccountId::from_eth(caller);213 let admin = T::CrossAccountId::from_eth(admin);272 let admin = T::CrossAccountId::from_eth(admin);214 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;273 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;215 Ok(())274 Ok(())216 }275 }217276277 /// Toggle accessibility of collection nesting.278 ///279 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'218 #[solidity(rename_selector = "setCollectionNesting")]280 #[solidity(rename_selector = "setCollectionNesting")]219 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {281 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {220 check_is_owner_or_admin(caller, self)?;282 check_is_owner_or_admin(caller, self)?;235 save(self)297 save(self)236 }298 }237299300 /// Toggle accessibility of collection nesting.301 ///302 /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'303 /// @param collections Addresses of collections that will be available for nesting.238 #[solidity(rename_selector = "setCollectionNesting")]304 #[solidity(rename_selector = "setCollectionNesting")]239 fn set_nesting(305 fn set_nesting(240 &mut self,306 &mut self,280 save(self)346 save(self)281 }347 }282348349 /// Set the collection access method.350 /// @param mode Access mode351 /// 0 for Normal352 /// 1 for AllowList283 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {353 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {284 check_is_owner_or_admin(caller, self)?;354 check_is_owner_or_admin(caller, self)?;285 let permissions = CollectionPermissions {355 let permissions = CollectionPermissions {300 save(self)370 save(self)301 }371 }302372373 /// Add the user to the allowed list.374 ///375 /// @param user Address of a trusted user.303 fn add_to_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {376 fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {304 let caller = T::CrossAccountId::from_eth(caller);377 let caller = T::CrossAccountId::from_eth(caller);305 let user = T::CrossAccountId::from_eth(user);378 let user = T::CrossAccountId::from_eth(user);306 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;379 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;307 Ok(())380 Ok(())308 }381 }309382383 /// Remove the user from the allowed list.384 ///385 /// @param user Address of a removed user.310 fn remove_from_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {386 fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {311 let caller = T::CrossAccountId::from_eth(caller);387 let caller = T::CrossAccountId::from_eth(caller);312 let user = T::CrossAccountId::from_eth(user);388 let user = T::CrossAccountId::from_eth(user);313 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;389 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;314 Ok(())390 Ok(())315 }391 }316392393 /// Switch permission for minting.394 ///395 /// @param mode Enable if "true".317 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {396 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {318 check_is_owner_or_admin(caller, self)?;397 check_is_owner_or_admin(caller, self)?;319 let permissions = CollectionPermissions {398 let permissions = CollectionPermissions {351 Ok(())430 Ok(())352}431}353432433/// Get the "tokenURI" key as [PropertyKey](up_data_structs::PropertyKey).354pub fn token_uri_key() -> up_data_structs::PropertyKey {434pub fn token_uri_key() -> up_data_structs::PropertyKey {355 b"tokenURI"435 b"tokenURI"356 .to_vec()436 .to_vec()pallets/common/src/eth.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! The module contains a number of functions for converting and checking ethereum identifiers.161817use up_data_structs::CollectionId;19use up_data_structs::CollectionId;18use sp_core::H160;20use sp_core::H160;23 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,25 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,24];26];252728/// Maps the ethereum address of the collection in substrate.26pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {29pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {27 if eth[0..16] != ETH_COLLECTION_PREFIX {30 if eth[0..16] != ETH_COLLECTION_PREFIX {28 return None;31 return None;32 Some(CollectionId(u32::from_be_bytes(id_bytes)))35 Some(CollectionId(u32::from_be_bytes(id_bytes)))33}36}3738/// Maps the substrate collection id in ethereum.34pub fn collection_id_to_address(id: CollectionId) -> H160 {39pub fn collection_id_to_address(id: CollectionId) -> H160 {35 let mut out = [0; 20];40 let mut out = [0; 20];36 out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX);41 out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX);37 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));42 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));38 H160(out)43 H160(out)39}44}404546/// Check if the ethereum address is a collection.41pub fn is_collection(address: &H160) -> bool {47pub fn is_collection(address: &H160) -> bool {42 address[0..16] == ETH_COLLECTION_PREFIX48 address[0..16] == ETH_COLLECTION_PREFIX43}49}pallets/common/src/lib.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617//! # Common pallet18//!19//! The Common pallet provides functionality for handling collections.20//!21//! ## Overview22//!23//! The Common pallet provides an interface for common collection operations for different collection types24//! (see [CommonCollectionOperations]), as well as a generic dispatcher for these, see [dispatch] module.25//! It also provides this functionality to EVM, see [erc] and [eth] modules.26//!27//! The Common pallet provides functions for:28//!29//! - Setting and approving collection sponsor.30//! - Get\set\delete allow list.31//! - Get\set\delete collection properties.32//! - Get\set\delete collection property permissions.33//! - Get\set\delete token property permissions.34//! - Get\set\delete collection administrators.35//! - Checking access permissions.36//!37//! ### Terminology38//! **Collection sponsor** - For the collection, you can set a sponsor, at whose expense it will39//! be possible to mint tokens.40//!41//! **Allow list** - List of users who have the right to minting tokens.42//!43//! **Collection properties** - Collection properties are simply key-value stores where various44//! metadata can be placed.45//!46//! **Permissions on token properties** - For each property in the token can be set permission47//! to change, see [`PropertyPermission`].48//!49//! **Collection administrator** - For a collection, you can set administrators who have the right50//! to most actions on the collection.5152#![warn(missing_docs)]17#![cfg_attr(not(feature = "std"), no_std)]53#![cfg_attr(not(feature = "std"), no_std)]1819extern crate alloc;54extern crate alloc;205521use core::ops::{Deref, DerefMut};56use core::ops::{Deref, DerefMut};90pub mod eth;125pub mod eth;91pub mod weights;126pub mod weights;92127128/// Weight info.93pub type SelfWeightOf<T> = <T as Config>::WeightInfo;129pub type SelfWeightOf<T> = <T as Config>::WeightInfo;94130131/// Collection handle contains information about collection data and id.132/// Also provides functionality to count consumed gas.133///134/// CollectionHandle is used as a generic wrapper for collections of all types.135/// It allows to perform common operations and queries on any collection type,136/// both completely general for all, as well as their respective implementations of [`CommonCollectionOperations`].95#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]137#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]96pub struct CollectionHandle<T: Config> {138pub struct CollectionHandle<T: Config> {139 /// Collection id97 pub id: CollectionId,140 pub id: CollectionId,98 collection: Collection<T::AccountId>,141 collection: Collection<T::AccountId>,142 /// Substrate recorder for counting consumed gas99 pub recorder: SubstrateRecorder<T>,143 pub recorder: SubstrateRecorder<T>,100}144}145101impl<T: Config> WithRecorder<T> for CollectionHandle<T> {146impl<T: Config> WithRecorder<T> for CollectionHandle<T> {102 fn recorder(&self) -> &SubstrateRecorder<T> {147 fn recorder(&self) -> &SubstrateRecorder<T> {103 &self.recorder148 &self.recorder106 self.recorder151 self.recorder107 }152 }108}153}154109impl<T: Config> CollectionHandle<T> {155impl<T: Config> CollectionHandle<T> {156 /// Same as [CollectionHandle::new] but with an explicit gas limit.110 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {157 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {111 <CollectionById<T>>::get(id).map(|collection| Self {158 <CollectionById<T>>::get(id).map(|collection| Self {112 id,159 id,115 })162 })116 }163 }117164165 /// Same as [CollectionHandle::new] but with an existed [`SubstrateRecorder`].118 pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {166 pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {119 <CollectionById<T>>::get(id).map(|collection| Self {167 <CollectionById<T>>::get(id).map(|collection| Self {120 id,168 id,123 })171 })124 }172 }125173174 /// Retrives collection data from storage and creates collection handle with default parameters.175 /// If collection not found return `None`126 pub fn new(id: CollectionId) -> Option<Self> {176 pub fn new(id: CollectionId) -> Option<Self> {127 Self::new_with_gas_limit(id, u64::MAX)177 Self::new_with_gas_limit(id, u64::MAX)128 }178 }129179180 /// Same as [`CollectionHandle::new`] but if collection not found [CollectionNotFound](Error::CollectionNotFound) returned.130 pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {181 pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {131 Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)182 Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)132 }183 }133184185 /// Consume gas for reading.134 pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {186 pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {135 self.recorder187 self.recorder136 .consume_gas(T::GasWeightMapping::weight_to_gas(188 .consume_gas(T::GasWeightMapping::weight_to_gas(140 ))192 ))141 }193 }142194195 /// Consume gas for writing.143 pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {196 pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {144 self.recorder197 self.recorder145 .consume_gas(T::GasWeightMapping::weight_to_gas(198 .consume_gas(T::GasWeightMapping::weight_to_gas(148 .saturating_mul(writes),201 .saturating_mul(writes),149 ))202 ))150 }203 }204205 /// Save collection to storage.151 pub fn save(self) -> DispatchResult {206 pub fn save(self) -> DispatchResult {152 <CollectionById<T>>::insert(self.id, self.collection);207 <CollectionById<T>>::insert(self.id, self.collection);153 Ok(())208 Ok(())154 }209 }155210211 /// Set collection sponsor.212 ///213 /// Unique collections allows sponsoring for certain actions.214 /// This method allows you to set the sponsor of the collection.215 /// In order for sponsorship to become active, it must be confirmed through [`Self::confirm_sponsorship`].156 pub fn set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {216 pub fn set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {157 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);217 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);158 Ok(())218 Ok(())159 }219 }160220221 /// Confirm sponsorship222 ///223 /// In order for the sponsorship to become active, the user set as the sponsor must confirm their participation.224 /// Before confirming sponsorship, the user must be specified as the sponsor of the collection via [`Self::set_sponsor`].161 pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> Result<bool, DispatchError> {225 pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> Result<bool, DispatchError> {162 if self.collection.sponsorship.pending_sponsor() != Some(sender) {226 if self.collection.sponsorship.pending_sponsor() != Some(sender) {163 return Ok(false);227 return Ok(false);168 }232 }169233170 /// Checks that the collection was created with, and must be operated upon through **Unique API**.234 /// Checks that the collection was created with, and must be operated upon through **Unique API**.171 /// Now check only the `external_collection` flag and if it's **true**, then return `CollectionIsExternal` error.235 /// Now check only the `external_collection` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.172 pub fn check_is_internal(&self) -> DispatchResult {236 pub fn check_is_internal(&self) -> DispatchResult {173 if self.external_collection {237 if self.external_collection {174 return Err(<Error<T>>::CollectionIsExternal)?;238 return Err(<Error<T>>::CollectionIsExternal)?;178 }242 }179243180 /// Checks that the collection was created with, and must be operated upon through an **assimilated API**.244 /// Checks that the collection was created with, and must be operated upon through an **assimilated API**.181 /// Now check only the `external_collection` flag and if it's **false**, then return `CollectionIsInternal` error.245 /// Now check only the `external_collection` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error.182 pub fn check_is_external(&self) -> DispatchResult {246 pub fn check_is_external(&self) -> DispatchResult {183 if !self.external_collection {247 if !self.external_collection {184 return Err(<Error<T>>::CollectionIsInternal)?;248 return Err(<Error<T>>::CollectionIsInternal)?;203}267}204268205impl<T: Config> CollectionHandle<T> {269impl<T: Config> CollectionHandle<T> {206 pub fn check_is_owner(&self, subject: &T::CrossAccountId) -> DispatchResult {270 /// Checks if the `user` is the owner of the collection.271 pub fn check_is_owner(&self, user: &T::CrossAccountId) -> DispatchResult {207 ensure!(*subject.as_sub() == self.owner, <Error<T>>::NoPermission);272 ensure!(*user.as_sub() == self.owner, <Error<T>>::NoPermission);208 Ok(())273 Ok(())209 }274 }275276 /// Returns **true** if the `user` is the owner or administrator of the collection.210 pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> bool {277 pub fn is_owner_or_admin(&self, user: &T::CrossAccountId) -> bool {211 *subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject))278 *user.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, user))212 }279 }280281 /// Checks if the `user` is the owner or administrator of the collection.213 pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {282 pub fn check_is_owner_or_admin(&self, user: &T::CrossAccountId) -> DispatchResult {214 ensure!(self.is_owner_or_admin(subject), <Error<T>>::NoPermission);283 ensure!(self.is_owner_or_admin(user), <Error<T>>::NoPermission);215 Ok(())284 Ok(())216 }285 }286287 /// Return **true** if `user` was not allowed to have tokens, and he can ignore such restrictions.217 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {288 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {218 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)289 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)219 }290 }291292 /// Return **true** if `user` does not have enough token parts, and he can ignore such restrictions.220 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {293 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {221 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)294 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)222 }295 }296297 /// Checks if the user is in the allow list. If not [Error::AddressNotInAllowlist] returns.223 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {298 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {224 ensure!(299 ensure!(225 <Allowlist<T>>::get((self.id, user)),300 <Allowlist<T>>::get((self.id, user)),249 + TypeInfo324 + TypeInfo250 + account::Config325 + account::Config251 {326 {327 /// Weight information for functions of this pallet.252 type WeightInfo: WeightInfo;328 type WeightInfo: WeightInfo;329330 /// Events compatible with [`frame_system::Config::Event`].253 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;331 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;254332333 /// Handler of accounts and payment.255 type Currency: Currency<Self::AccountId>;334 type Currency: Currency<Self::AccountId>;256335336 /// Set price to create a collection.257 #[pallet::constant]337 #[pallet::constant]258 type CollectionCreationPrice: Get<338 type CollectionCreationPrice: Get<259 <<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,339 <<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,260 >;340 >;341342 /// Dispatcher of operations on collections.261 type CollectionDispatch: CollectionDispatch<Self>;343 type CollectionDispatch: CollectionDispatch<Self>;262344345 /// Account which holds the chain's treasury.263 type TreasuryAccountId: Get<Self::AccountId>;346 type TreasuryAccountId: Get<Self::AccountId>;347348 /// Address under which the CollectionHelper contract would be available.264 type ContractAddress: Get<H160>;349 type ContractAddress: Get<H160>;265350351 /// Mapper for token addresses to Ethereum addresses.266 type EvmTokenAddressMapping: TokenAddressMapping<H160>;352 type EvmTokenAddressMapping: TokenAddressMapping<H160>;353354 /// Mapper for token addresses to [`CrossAccountId`].267 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;355 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;268 }356 }269357276364277 #[pallet::extra_constants]365 #[pallet::extra_constants]278 impl<T: Config> Pallet<T> {366 impl<T: Config> Pallet<T> {367 /// Maximum admins per collection.279 pub fn collection_admins_limit() -> u32 {368 pub fn collection_admins_limit() -> u32 {280 COLLECTION_ADMINS_LIMIT369 COLLECTION_ADMINS_LIMIT281 }370 }285 #[pallet::generate_deposit(pub fn deposit_event)]374 #[pallet::generate_deposit(pub fn deposit_event)]286 pub enum Event<T: Config> {375 pub enum Event<T: Config> {287 /// New collection was created376 /// New collection was created288 ///377 CollectionCreated(289 /// # Arguments378 /// Globally unique identifier of newly created collection.290 ///291 /// * collection_id - Globally unique identifier of newly created collection.292 /// * mode - [CollectionMode] converted into u8.379 CollectionId,380 /// [`CollectionMode`] converted into _u8_.293 /// * account_id - Collection owner.381 u8,382 /// Collection owner.294 CollectionCreated(CollectionId, u8, T::AccountId),383 T::AccountId,384 ),295385296 /// New collection was destroyed386 /// New collection was destroyed297 ///387 CollectionDestroyed(298 /// # Arguments388 /// Globally unique identifier of collection.299 ///300 /// * collection_id - Globally unique identifier of collection that has been destroyed.301 CollectionDestroyed(CollectionId),389 CollectionId,390 ),302391303 /// New item was created.392 /// New item was created.304 ///393 ItemCreated(305 /// # Arguments394 /// Id of the collection where item was created.306 ///307 /// * collection_id - ID of the collection where the item was created.308 /// * item_id - ID of the item. Unique within the collection.395 CollectionId,396 /// Id of an item. Unique within the collection.309 /// * recipient - Owner of the newly created item.397 TokenId,398 /// Owner of newly created item310 /// * amount - The amount of tokens that were created (always 1 for NFT).399 T::CrossAccountId,400 /// Always 1 for NFT311 ItemCreated(CollectionId, TokenId, T::CrossAccountId, u128),401 u128,402 ),312403313 /// Collection item was burned.404 /// Collection item was burned.314 ///405 ItemDestroyed(315 /// # Arguments406 /// Id of the collection where item was destroyed.316 ///317 /// * collection_id - Identifier of the collection to which the burned NFT belonged.318 /// * item_id - Identifier of burned NFT.407 CollectionId,408 /// Identifier of burned NFT.319 /// * owner - Which user has destroyed their tokens.409 TokenId,410 /// Which user has destroyed its tokens.320 /// * amount - Amount of tokens that were destroyed (always 1 for NFT).411 T::CrossAccountId,412 /// Amount of token pieces destroed. Always 1 for NFT.321 ItemDestroyed(CollectionId, TokenId, T::CrossAccountId, u128),413 u128,414 ),322415323 /// Item was transferred.416 /// Item was transferred324 ///325 /// # Arguments326 ///327 /// * collection_id - ID of the collection to which the item belongs.328 /// * item_id - ID of the item transferred.329 /// * sender - Original owner of the item.330 /// * recipient - New owner of the item.331 /// * amount - Amount of tokens that were transferred (always 1 for NFT).332 Transfer(417 Transfer(418 /// Id of collection to which item is belong.333 CollectionId,419 CollectionId,420 /// Id of an item.334 TokenId,421 TokenId,422 /// Original owner of item.335 T::CrossAccountId,423 T::CrossAccountId,424 /// New owner of item.336 T::CrossAccountId,425 T::CrossAccountId,426 /// Amount of token pieces transfered. Always 1 for NFT.337 u128,427 u128,338 ),428 ),339429340 /// Sponsoring allowance was approved.430 /// Amount pieces of token owned by `sender` was approved for `spender`.341 ///342 /// # Arguments343 ///344 /// * collection_id - todo:doc flesh out345 /// * item_id346 /// * sender347 /// * spender348 /// * amount349 Approved(431 Approved(432 /// Id of collection to which item is belong.350 CollectionId,433 CollectionId,434 /// Id of an item.351 TokenId,435 TokenId,436 /// Original owner of item.352 T::CrossAccountId,437 T::CrossAccountId,438 /// Id for which the approval was granted.353 T::CrossAccountId,439 T::CrossAccountId,440 /// Amount of token pieces transfered. Always 1 for NFT.354 u128,441 u128,355 ),442 ),356443357 /// Collection property was added or edited.444 /// The colletion property has been added or edited.358 ///445 CollectionPropertySet(359 /// # Arguments446 /// Id of collection to which property has been set.360 ///361 /// * collection_id - ID of the collection, whose property was just set.362 /// * property_key - Key of the property that was just set.447 CollectionId,448 /// The property that was set.363 CollectionPropertySet(CollectionId, PropertyKey),449 PropertyKey,450 ),364451365 /// Collection property was deleted.452 /// The property has been deleted.366 ///453 CollectionPropertyDeleted(367 /// # Arguments454 /// Id of collection to which property has been deleted.368 ///369 /// * collection_id - ID of the collection, whose property was just deleted.370 /// * property_key - Key of the property that was just deleted.455 CollectionId,456 /// The property that was deleted.371 CollectionPropertyDeleted(CollectionId, PropertyKey),457 PropertyKey,458 ),372459373 /// Item property was added or edited.460 /// The token property has been added or edited.374 ///461 TokenPropertySet(375 /// # Arguments462 /// Identifier of the collection whose token has the property set.376 ///377 /// * collection_id - ID of the collection, whose token's property was just set.378 /// * item_id - ID of the item, whose property was just set.463 CollectionId,464 /// The token for which the property was set.379 /// * property_key - Key of the property that was just set.465 TokenId,466 /// The property that was set.380 TokenPropertySet(CollectionId, TokenId, PropertyKey),467 PropertyKey,468 ),381469382 /// Item property was deleted.470 /// The token property has been deleted.383 ///471 TokenPropertyDeleted(384 /// # Arguments472 /// Identifier of the collection whose token has the property deleted.385 ///386 /// * collection_id - ID of the collection, whose token's property was just deleted.387 /// * item_id - ID of the item, whose property was just deleted.473 CollectionId,474 /// The token for which the property was deleted.388 /// * property_key - Key of the property that was just deleted.475 TokenId,476 /// The property that was deleted.389 TokenPropertyDeleted(CollectionId, TokenId, PropertyKey),477 PropertyKey,478 ),390479391 /// Token property permission was added or updated for a collection.480 /// The token property permission of a collection has been set.392 ///481 PropertyPermissionSet(393 /// # Arguments482 /// ID of collection to which property permission has been set.394 ///395 /// * collection_id - ID of the collection, whose permissions were just set/updated.396 /// * property_key - Key of the property of the set/updated permission.483 CollectionId,484 /// The property permission that was set.397 PropertyPermissionSet(CollectionId, PropertyKey),485 PropertyKey,486 ),398 }487 }399488400 #[pallet::error]489 #[pallet::error]482 CollectionIsInternal,571 CollectionIsInternal,483 }572 }484573485 /// The number of created collections. Essentially contains the last collection ID.574 /// Storage of the count of created collections. Essentially contains the last collection ID.486 #[pallet::storage]575 #[pallet::storage]487 pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;576 pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;488577489 /// The number of destroyed collections578 /// Storage of the count of deleted collections.490 #[pallet::storage]579 #[pallet::storage]491 pub type DestroyedCollectionCount<T> =580 pub type DestroyedCollectionCount<T> =492 StorageValue<Value = CollectionId, QueryKind = ValueQuery>;581 StorageValue<Value = CollectionId, QueryKind = ValueQuery>;493582494 /// Collection info583 /// Storage of collection info.495 #[pallet::storage]584 #[pallet::storage]496 pub type CollectionById<T> = StorageMap<585 pub type CollectionById<T> = StorageMap<497 Hasher = Blake2_128Concat,586 Hasher = Blake2_128Concat,500 QueryKind = OptionQuery,589 QueryKind = OptionQuery,501 >;590 >;502591503 /// Collection properties592 /// Storage of collection properties.504 #[pallet::storage]593 #[pallet::storage]505 #[pallet::getter(fn collection_properties)]594 #[pallet::getter(fn collection_properties)]506 pub type CollectionProperties<T> = StorageMap<595 pub type CollectionProperties<T> = StorageMap<511 OnEmpty = up_data_structs::CollectionProperties,600 OnEmpty = up_data_structs::CollectionProperties,512 >;601 >;513602514 /// Token permissions of a collection603 /// Storage of token property permissions of a collection.515 #[pallet::storage]604 #[pallet::storage]516 #[pallet::getter(fn property_permissions)]605 #[pallet::getter(fn property_permissions)]517 pub type CollectionPropertyPermissions<T> = StorageMap<606 pub type CollectionPropertyPermissions<T> = StorageMap<521 QueryKind = ValueQuery,610 QueryKind = ValueQuery,522 >;611 >;523612524 /// Amount of collection admins613 /// Storage of the amount of collection admins.525 #[pallet::storage]614 #[pallet::storage]526 pub type AdminAmount<T> = StorageMap<615 pub type AdminAmount<T> = StorageMap<527 Hasher = Blake2_128Concat,616 Hasher = Blake2_128Concat,530 QueryKind = ValueQuery,619 QueryKind = ValueQuery,531 >;620 >;532621533 /// List of collection admins622 /// List of collection admins.534 #[pallet::storage]623 #[pallet::storage]535 pub type IsAdmin<T: Config> = StorageNMap<624 pub type IsAdmin<T: Config> = StorageNMap<536 Key = (625 Key = (541 QueryKind = ValueQuery,630 QueryKind = ValueQuery,542 >;631 >;543632544 /// Allowlisted collection users633 /// Allowlisted collection users.545 #[pallet::storage]634 #[pallet::storage]546 pub type Allowlist<T: Config> = StorageNMap<635 pub type Allowlist<T: Config> = StorageNMap<547 Key = (636 Key = (552 QueryKind = ValueQuery,641 QueryKind = ValueQuery,553 >;642 >;554643555 /// Not used by code, exists only to provide some types to metadata644 /// Not used by code, exists only to provide some types to metadata.556 #[pallet::storage]645 #[pallet::storage]557 pub type DummyStorageValue<T: Config> = StorageValue<646 pub type DummyStorageValue<T: Config> = StorageValue<558 Value = (647 Value = (646}735}647736648impl<T: Config> Pallet<T> {737impl<T: Config> Pallet<T> {649 /// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens738 /// Enshure that receiver address is correct.739 ///740 /// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens.650 pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {741 pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {651 ensure!(742 ensure!(652 &T::CrossAccountId::from_eth(H160([0; 20])) != receiver,743 &T::CrossAccountId::from_eth(H160([0; 20])) != receiver,653 <Error<T>>::AddressIsZero744 <Error<T>>::AddressIsZero654 );745 );655 Ok(())746 Ok(())656 }747 }748749 /// Get a vector of collection admins.657 pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {750 pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {658 <IsAdmin<T>>::iter_prefix((collection,))751 <IsAdmin<T>>::iter_prefix((collection,))659 .map(|(a, _)| a)752 .map(|(a, _)| a)660 .collect()753 .collect()661 }754 }755756 /// Get a vector of users allowed to mint tokens.662 pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {757 pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {663 <Allowlist<T>>::iter_prefix((collection,))758 <Allowlist<T>>::iter_prefix((collection,))664 .map(|(a, _)| a)759 .map(|(a, _)| a)665 .collect()760 .collect()666 }761 }762763 /// Is `user` allowed to mint token in `collection`.667 pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {764 pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {668 <Allowlist<T>>::get((collection, user))765 <Allowlist<T>>::get((collection, user))669 }766 }767768 /// Get statistics of collections.670 pub fn collection_stats() -> CollectionStats {769 pub fn collection_stats() -> CollectionStats {671 let created = <CreatedCollectionCount<T>>::get();770 let created = <CreatedCollectionCount<T>>::get();672 let destroyed = <DestroyedCollectionCount<T>>::get();771 let destroyed = <DestroyedCollectionCount<T>>::get();677 }776 }678 }777 }679778779 /// Get the effective limits for the collection.680 pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {780 pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {681 let collection = <CollectionById<T>>::get(collection);781 let collection = <CollectionById<T>>::get(collection);682 if collection.is_none() {782 if collection.is_none() {710 Some(effective_limits)810 Some(effective_limits)711 }811 }712812813 /// Returns information about the `collection` adapted for rpc.713 pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {814 pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {714 let Collection {815 let Collection {715 name,816 name,785}886}786887787impl<T: Config> Pallet<T> {888impl<T: Config> Pallet<T> {889 /// Create new collection.890 ///891 /// * `owner` - The owner of the collection.892 /// * `data` - Description of the created collection.893 /// * `is_external` - Marks that collection managet by not "Unique network".788 pub fn init_collection(894 pub fn init_collection(789 owner: T::CrossAccountId,895 owner: T::CrossAccountId,790 data: CreateCollectionData<T::AccountId>,896 data: CreateCollectionData<T::AccountId>,860 ),966 ),861 );967 );862 <T as Config>::Currency::settle(968 <T as Config>::Currency::settle(863 &owner.as_sub(),969 owner.as_sub(),864 imbalance,970 imbalance,865 WithdrawReasons::TRANSFER,971 WithdrawReasons::TRANSFER,866 ExistenceRequirement::KeepAlive,972 ExistenceRequirement::KeepAlive,885 Ok(id)991 Ok(id)886 }992 }887993994 /// Destroy collection.995 ///996 /// * `collection` - Collection handler.997 /// * `sender` - The owner or administrator of the collection.888 pub fn destroy_collection(998 pub fn destroy_collection(889 collection: CollectionHandle<T>,999 collection: CollectionHandle<T>,890 sender: &T::CrossAccountId,1000 sender: &T::CrossAccountId,913 Ok(())1023 Ok(())914 }1024 }91510251026 /// Set collection property.1027 ///1028 /// * `collection` - Collection handler.1029 /// * `sender` - The owner or administrator of the collection.1030 /// * `property` - The property to set.916 pub fn set_collection_property(1031 pub fn set_collection_property(917 collection: &CollectionHandle<T>,1032 collection: &CollectionHandle<T>,918 sender: &T::CrossAccountId,1033 sender: &T::CrossAccountId,931 Ok(())1046 Ok(())932 }1047 }93310481049 /// Set scouped collection property.1050 ///1051 /// * `collection_id` - ID of the collection for which the property is being set.1052 /// * `scope` - Property scope.1053 /// * `property` - The property to set.934 pub fn set_scoped_collection_property(1054 pub fn set_scoped_collection_property(935 collection_id: CollectionId,1055 collection_id: CollectionId,936 scope: PropertyScope,1056 scope: PropertyScope,944 Ok(())1064 Ok(())945 }1065 }94610661067 /// Set scouped collection properties.1068 ///1069 /// * `collection_id` - ID of the collection for which the properties is being set.1070 /// * `scope` - Property scope.1071 /// * `properties` - The properties to set.947 pub fn set_scoped_collection_properties(1072 pub fn set_scoped_collection_properties(948 collection_id: CollectionId,1073 collection_id: CollectionId,949 scope: PropertyScope,1074 scope: PropertyScope,957 Ok(())1082 Ok(())958 }1083 }95910841085 /// Set collection properties.1086 ///1087 /// * `collection` - Collection handler.1088 /// * `sender` - The owner or administrator of the collection.1089 /// * `properties` - The properties to set.960 #[transactional]1090 #[transactional]961 pub fn set_collection_properties(1091 pub fn set_collection_properties(962 collection: &CollectionHandle<T>,1092 collection: &CollectionHandle<T>,970 Ok(())1100 Ok(())971 }1101 }97211021103 /// Delete collection property.1104 ///1105 /// * `collection` - Collection handler.1106 /// * `sender` - The owner or administrator of the collection.1107 /// * `property` - The property to delete.973 pub fn delete_collection_property(1108 pub fn delete_collection_property(974 collection: &CollectionHandle<T>,1109 collection: &CollectionHandle<T>,975 sender: &T::CrossAccountId,1110 sender: &T::CrossAccountId,990 Ok(())1125 Ok(())991 }1126 }99211271128 /// Delete collection properties.1129 ///1130 /// * `collection` - Collection handler.1131 /// * `sender` - The owner or administrator of the collection.1132 /// * `properties` - The properties to delete.993 #[transactional]1133 #[transactional]994 pub fn delete_collection_properties(1134 pub fn delete_collection_properties(995 collection: &CollectionHandle<T>,1135 collection: &CollectionHandle<T>,1003 Ok(())1143 Ok(())1004 }1144 }100511451006 // For migrations1146 /// Set collection propetry permission without any checks.1147 ///1148 /// Used for migrations.1149 ///1150 /// * `collection` - Collection handler.1151 /// * `property_permissions` - Property permissions.1007 pub fn set_property_permission_unchecked(1152 pub fn set_property_permission_unchecked(1008 collection: CollectionId,1153 collection: CollectionId,1009 property_permission: PropertyKeyPermission,1154 property_permission: PropertyKeyPermission,1015 Ok(())1160 Ok(())1016 }1161 }101711621163 /// Set collection property permission.1164 ///1165 /// * `collection` - Collection handler.1166 /// * `sender` - The owner or administrator of the collection.1167 /// * `property_permission` - Property permission.1018 pub fn set_property_permission(1168 pub fn set_property_permission(1019 collection: &CollectionHandle<T>,1169 collection: &CollectionHandle<T>,1020 sender: &T::CrossAccountId,1170 sender: &T::CrossAccountId,1045 Ok(())1195 Ok(())1046 }1196 }104711971198 /// Set token property permission.1199 ///1200 /// * `collection` - Collection handler.1201 /// * `sender` - The owner or administrator of the collection.1202 /// * `property_permissions` - Property permissions.1048 #[transactional]1203 #[transactional]1049 pub fn set_token_property_permissions(1204 pub fn set_token_property_permissions(1050 collection: &CollectionHandle<T>,1205 collection: &CollectionHandle<T>,1058 Ok(())1213 Ok(())1059 }1214 }106012151216 /// Get collection property.1061 pub fn get_collection_property(1217 pub fn get_collection_property(1062 collection_id: CollectionId,1218 collection_id: CollectionId,1063 key: &PropertyKey,1219 key: &PropertyKey,1064 ) -> Option<PropertyValue> {1220 ) -> Option<PropertyValue> {1065 Self::collection_properties(collection_id).get(key).cloned()1221 Self::collection_properties(collection_id).get(key).cloned()1066 }1222 }106712231224 /// Convert byte vector to property key vector.1068 pub fn bytes_keys_to_property_keys(1225 pub fn bytes_keys_to_property_keys(1069 keys: Vec<Vec<u8>>,1226 keys: Vec<Vec<u8>>,1070 ) -> Result<Vec<PropertyKey>, DispatchError> {1227 ) -> Result<Vec<PropertyKey>, DispatchError> {1076 .collect::<Result<Vec<PropertyKey>, DispatchError>>()1233 .collect::<Result<Vec<PropertyKey>, DispatchError>>()1077 }1234 }107812351236 /// Get properties according to given keys.1079 pub fn filter_collection_properties(1237 pub fn filter_collection_properties(1080 collection_id: CollectionId,1238 collection_id: CollectionId,1081 keys: Option<Vec<PropertyKey>>,1239 keys: Option<Vec<PropertyKey>>,1103 Ok(properties)1261 Ok(properties)1104 }1262 }110512631264 /// Get property permissions according to given keys.1106 pub fn filter_property_permissions(1265 pub fn filter_property_permissions(1107 collection_id: CollectionId,1266 collection_id: CollectionId,1108 keys: Option<Vec<PropertyKey>>,1267 keys: Option<Vec<PropertyKey>>,1132 Ok(key_permissions)1291 Ok(key_permissions)1133 }1292 }113412931294 /// Toggle `user` participation in the `collection`'s allow list.1135 pub fn toggle_allowlist(1295 pub fn toggle_allowlist(1136 collection: &CollectionHandle<T>,1296 collection: &CollectionHandle<T>,1137 sender: &T::CrossAccountId,1297 sender: &T::CrossAccountId,1151 Ok(())1311 Ok(())1152 }1312 }115313131314 /// Toggle `user` participation in the `collection`'s admin list.1154 pub fn toggle_admin(1315 pub fn toggle_admin(1155 collection: &CollectionHandle<T>,1316 collection: &CollectionHandle<T>,1156 sender: &T::CrossAccountId,1317 sender: &T::CrossAccountId,1186 Ok(())1347 Ok(())1187 }1348 }118813491350 /// Merge set fields from `new_limit` to `old_limit`.1189 pub fn clamp_limits(1351 pub fn clamp_limits(1190 mode: CollectionMode,1352 mode: CollectionMode,1191 old_limit: &CollectionLimits,1353 old_limit: &CollectionLimits,1231 Ok(new_limit)1393 Ok(new_limit)1232 }1394 }123313951396 /// Merge set fields from `new_permission` to `old_permission`.1234 pub fn clamp_permissions(1397 pub fn clamp_permissions(1235 _mode: CollectionMode,1398 _mode: CollectionMode,1236 old_limit: &CollectionPermissions,1399 old_permission: &CollectionPermissions,1237 mut new_limit: CollectionPermissions,1400 mut new_permission: CollectionPermissions,1238 ) -> Result<CollectionPermissions, DispatchError> {1401 ) -> Result<CollectionPermissions, DispatchError> {1239 limit_default_clone!(old_limit, new_limit,1402 limit_default_clone!(old_permission, new_permission,1240 access => {},1403 access => {},1241 mint_mode => {},1404 mint_mode => {},1242 nesting => { /* todo check for permissive, if only it gets out of benchmarks */ },1405 nesting => { /* todo check for permissive, if only it gets out of benchmarks */ },1243 );1406 );1244 Ok(new_limit)1407 Ok(new_permission)1245 }1408 }1246}1409}124714101411/// Indicates unsupported methods by returning [Error::UnsupportedOperation].1248#[macro_export]1412#[macro_export]1249macro_rules! unsupported {1413macro_rules! unsupported {1250 () => {1414 () => {1251 Err(<Error<T>>::UnsupportedOperation.into())1415 Err(<Error<T>>::UnsupportedOperation.into())1252 };1416 };1253}1417}125414181255/// Worst cases1419/// Return weights for various worst-case operations.1256pub trait CommonWeightInfo<CrossAccountId> {1420pub trait CommonWeightInfo<CrossAccountId> {1421 /// Weight of item creation.1257 fn create_item() -> Weight;1422 fn create_item() -> Weight;14231424 /// Weight of items creation.1258 fn create_multiple_items(amount: &[CreateItemData]) -> Weight;1425 fn create_multiple_items(amount: &[CreateItemData]) -> Weight;14261427 /// Weight of items creation.1259 fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;1428 fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;14291430 /// The weight of the burning item.1260 fn burn_item() -> Weight;1431 fn burn_item() -> Weight;14321433 /// Property setting weight.1434 ///1435 /// * `amount`- The number of properties to set.1261 fn set_collection_properties(amount: u32) -> Weight;1436 fn set_collection_properties(amount: u32) -> Weight;14371438 /// Collection property deletion weight.1439 ///1440 /// * `amount`- The number of properties to set.1262 fn delete_collection_properties(amount: u32) -> Weight;1441 fn delete_collection_properties(amount: u32) -> Weight;14421443 /// Token property setting weight.1444 ///1445 /// * `amount`- The number of properties to set.1263 fn set_token_properties(amount: u32) -> Weight;1446 fn set_token_properties(amount: u32) -> Weight;14471448 /// Token property deletion weight.1449 ///1450 /// * `amount`- The number of properties to delete.1264 fn delete_token_properties(amount: u32) -> Weight;1451 fn delete_token_properties(amount: u32) -> Weight;14521453 /// Token property permissions set weight.1454 ///1455 /// * `amount`- The number of property permissions to set.1265 fn set_token_property_permissions(amount: u32) -> Weight;1456 fn set_token_property_permissions(amount: u32) -> Weight;14571458 /// Transfer price of the token or its parts.1266 fn transfer() -> Weight;1459 fn transfer() -> Weight;14601461 /// The price of setting the permission of the operation from another user.1267 fn approve() -> Weight;1462 fn approve() -> Weight;14631464 /// Transfer price from another user.1268 fn transfer_from() -> Weight;1465 fn transfer_from() -> Weight;14661467 /// The price of burning a token from another user.1269 fn burn_from() -> Weight;1468 fn burn_from() -> Weight;127014691271 /// Differs from burn_item in case of Fungible and Refungible, as it should burn1470 /// Differs from burn_item in case of Fungible and Refungible, as it should burn1272 /// whole users's balance1471 /// whole users's balance.1273 ///1472 ///1274 /// This method shouldn't be used directly, as it doesn't count breadth price, use `burn_recursively` instead1473 /// This method shouldn't be used directly, as it doesn't count breadth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead1275 fn burn_recursively_self_raw() -> Weight;1474 fn burn_recursively_self_raw() -> Weight;14751276 /// Cost of iterating over `amount` children while burning, without counting child burning itself1476 /// Cost of iterating over `amount` children while burning, without counting child burning itself.1277 ///1477 ///1278 /// This method shouldn't be used directly, as it doesn't count depth price, use `burn_recursively` instead1478 /// This method shouldn't be used directly, as it doesn't count depth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead1279 fn burn_recursively_breadth_raw(amount: u32) -> Weight;1479 fn burn_recursively_breadth_raw(amount: u32) -> Weight;128014801481 /// The price of recursive burning a token.1482 ///1483 /// `max_selfs` - The maximum burning weight of the token itself.1484 /// `max_breadth` - The maximum number of nested tokens to burn.1281 fn burn_recursively(max_selfs: u32, max_breadth: u32) -> Weight {1485 fn burn_recursively(max_selfs: u32, max_breadth: u32) -> Weight {1282 Self::burn_recursively_self_raw()1486 Self::burn_recursively_self_raw()1283 .saturating_mul(max_selfs.max(1) as u64)1487 .saturating_mul(max_selfs.max(1) as u64)1284 .saturating_add(Self::burn_recursively_breadth_raw(max_breadth))1488 .saturating_add(Self::burn_recursively_breadth_raw(max_breadth))1285 }1489 }1286}1490}128714911492/// Weight info extension trait for refungible pallet.1288pub trait RefungibleExtensionsWeightInfo {1493pub trait RefungibleExtensionsWeightInfo {1494 /// Weight of token repartition.1289 fn repartition() -> Weight;1495 fn repartition() -> Weight;1290}1496}129114971498/// Common collection operations.1499///1500/// It wraps methods in Fungible, Nonfungible and Refungible pallets1501/// and adds weight info.1292pub trait CommonCollectionOperations<T: Config> {1502pub trait CommonCollectionOperations<T: Config> {1503 /// Create token.1504 ///1505 /// * `sender` - The user who mint the token and pays for the transaction.1506 /// * `to` - The user who will own the token.1507 /// * `data` - Token data.1508 /// * `nesting_budget` - A budget that can be spent on nesting tokens.1293 fn create_item(1509 fn create_item(1294 &self,1510 &self,1295 sender: T::CrossAccountId,1511 sender: T::CrossAccountId,1296 to: T::CrossAccountId,1512 to: T::CrossAccountId,1297 data: CreateItemData,1513 data: CreateItemData,1298 nesting_budget: &dyn Budget,1514 nesting_budget: &dyn Budget,1299 ) -> DispatchResultWithPostInfo;1515 ) -> DispatchResultWithPostInfo;15161517 /// Create multiple tokens.1518 ///1519 /// * `sender` - The user who mint the token and pays for the transaction.1520 /// * `to` - The user who will own the token.1521 /// * `data` - Token data.1522 /// * `nesting_budget` - A budget that can be spent on nesting tokens.1300 fn create_multiple_items(1523 fn create_multiple_items(1301 &self,1524 &self,1302 sender: T::CrossAccountId,1525 sender: T::CrossAccountId,1303 to: T::CrossAccountId,1526 to: T::CrossAccountId,1304 data: Vec<CreateItemData>,1527 data: Vec<CreateItemData>,1305 nesting_budget: &dyn Budget,1528 nesting_budget: &dyn Budget,1306 ) -> DispatchResultWithPostInfo;1529 ) -> DispatchResultWithPostInfo;15301531 /// Create multiple tokens.1532 ///1533 /// * `sender` - The user who mint the token and pays for the transaction.1534 /// * `to` - The user who will own the token.1535 /// * `data` - Token data.1536 /// * `nesting_budget` - A budget that can be spent on nesting tokens.1307 fn create_multiple_items_ex(1537 fn create_multiple_items_ex(1308 &self,1538 &self,1309 sender: T::CrossAccountId,1539 sender: T::CrossAccountId,1310 data: CreateItemExData<T::CrossAccountId>,1540 data: CreateItemExData<T::CrossAccountId>,1311 nesting_budget: &dyn Budget,1541 nesting_budget: &dyn Budget,1312 ) -> DispatchResultWithPostInfo;1542 ) -> DispatchResultWithPostInfo;15431544 /// Burn token.1545 ///1546 /// * `sender` - The user who owns the token.1547 /// * `token` - Token id that will burned.1548 /// * `amount` - The number of parts of the token that will be burned.1313 fn burn_item(1549 fn burn_item(1314 &self,1550 &self,1315 sender: T::CrossAccountId,1551 sender: T::CrossAccountId,1316 token: TokenId,1552 token: TokenId,1317 amount: u128,1553 amount: u128,1318 ) -> DispatchResultWithPostInfo;1554 ) -> DispatchResultWithPostInfo;15551556 /// Burn token and all nested tokens recursievly.1557 ///1558 /// * `sender` - The user who owns the token.1559 /// * `token` - Token id that will burned.1560 /// * `self_budget` - The budget that can be spent on burning tokens.1561 /// * `breadth_budget` - The budget that can be spent on burning nested tokens.1319 fn burn_item_recursively(1562 fn burn_item_recursively(1320 &self,1563 &self,1321 sender: T::CrossAccountId,1564 sender: T::CrossAccountId,1322 token: TokenId,1565 token: TokenId,1323 self_budget: &dyn Budget,1566 self_budget: &dyn Budget,1324 breadth_budget: &dyn Budget,1567 breadth_budget: &dyn Budget,1325 ) -> DispatchResultWithPostInfo;1568 ) -> DispatchResultWithPostInfo;15691570 /// Set collection properties.1571 ///1572 /// * `sender` - Must be either the owner of the collection or its admin.1573 /// * `properties` - Properties to be set.1326 fn set_collection_properties(1574 fn set_collection_properties(1327 &self,1575 &self,1328 sender: T::CrossAccountId,1576 sender: T::CrossAccountId,1329 properties: Vec<Property>,1577 properties: Vec<Property>,1330 ) -> DispatchResultWithPostInfo;1578 ) -> DispatchResultWithPostInfo;15791580 /// Delete collection properties.1581 ///1582 /// * `sender` - Must be either the owner of the collection or its admin.1583 /// * `properties` - The properties to be removed.1331 fn delete_collection_properties(1584 fn delete_collection_properties(1332 &self,1585 &self,1333 sender: &T::CrossAccountId,1586 sender: &T::CrossAccountId,1334 property_keys: Vec<PropertyKey>,1587 property_keys: Vec<PropertyKey>,1335 ) -> DispatchResultWithPostInfo;1588 ) -> DispatchResultWithPostInfo;15891590 /// Set token properties.1591 ///1592 /// The appropriate [`PropertyPermission`] for the token property1593 /// must be set with [`Self::set_token_property_permissions`].1594 ///1595 /// * `sender` - Must be either the owner of the token or its admin.1596 /// * `token_id` - The token for which the properties are being set.1597 /// * `properties` - Properties to be set.1598 /// * `budget` - Budget for setting properties.1336 fn set_token_properties(1599 fn set_token_properties(1337 &self,1600 &self,1338 sender: T::CrossAccountId,1601 sender: T::CrossAccountId,1339 token_id: TokenId,1602 token_id: TokenId,1340 property: Vec<Property>,1603 properties: Vec<Property>,1341 nesting_budget: &dyn Budget,1604 budget: &dyn Budget,1342 ) -> DispatchResultWithPostInfo;1605 ) -> DispatchResultWithPostInfo;16061607 /// Remove token properties.1608 ///1609 /// The appropriate [`PropertyPermission`] for the token property1610 /// must be set with [`Self::set_token_property_permissions`].1611 ///1612 /// * `sender` - Must be either the owner of the token or its admin.1613 /// * `token_id` - The token for which the properties are being remove.1614 /// * `property_keys` - Keys to remove corresponding properties.1615 /// * `budget` - Budget for removing properties.1343 fn delete_token_properties(1616 fn delete_token_properties(1344 &self,1617 &self,1345 sender: T::CrossAccountId,1618 sender: T::CrossAccountId,1346 token_id: TokenId,1619 token_id: TokenId,1347 property_keys: Vec<PropertyKey>,1620 property_keys: Vec<PropertyKey>,1348 nesting_budget: &dyn Budget,1621 budget: &dyn Budget,1349 ) -> DispatchResultWithPostInfo;1622 ) -> DispatchResultWithPostInfo;16231624 /// Set token property permissions.1625 ///1626 /// * `sender` - Must be either the owner of the token or its admin.1627 /// * `token_id` - The token for which the properties are being set.1628 /// * `properties` - Properties to be set.1629 /// * `budget` - Budget for setting properties.1350 fn set_token_property_permissions(1630 fn set_token_property_permissions(1351 &self,1631 &self,1352 sender: &T::CrossAccountId,1632 sender: &T::CrossAccountId,1353 property_permissions: Vec<PropertyKeyPermission>,1633 property_permissions: Vec<PropertyKeyPermission>,1354 ) -> DispatchResultWithPostInfo;1634 ) -> DispatchResultWithPostInfo;16351636 /// Transfer amount of token pieces.1637 ///1638 /// * `sender` - Donor user.1639 /// * `to` - Recepient user.1640 /// * `token` - The token of which parts are being sent.1641 /// * `amount` - The number of parts of the token that will be transferred.1642 /// * `budget` - The maximum budget that can be spent on the transfer.1355 fn transfer(1643 fn transfer(1356 &self,1644 &self,1357 sender: T::CrossAccountId,1645 sender: T::CrossAccountId,1358 to: T::CrossAccountId,1646 to: T::CrossAccountId,1359 token: TokenId,1647 token: TokenId,1360 amount: u128,1648 amount: u128,1361 nesting_budget: &dyn Budget,1649 budget: &dyn Budget,1362 ) -> DispatchResultWithPostInfo;1650 ) -> DispatchResultWithPostInfo;16511652 /// Grant access to another account to transfer parts of the token owned by the calling user via [Self::transfer_from].1653 ///1654 /// * `sender` - The user who grants access to the token.1655 /// * `spender` - The user to whom the rights are granted.1656 /// * `token` - The token to which access is granted.1657 /// * `amount` - The amount of pieces that another user can dispose of.1363 fn approve(1658 fn approve(1364 &self,1659 &self,1365 sender: T::CrossAccountId,1660 sender: T::CrossAccountId,1366 spender: T::CrossAccountId,1661 spender: T::CrossAccountId,1367 token: TokenId,1662 token: TokenId,1368 amount: u128,1663 amount: u128,1369 ) -> DispatchResultWithPostInfo;1664 ) -> DispatchResultWithPostInfo;16651666 /// Send parts of a token owned by another user.1667 ///1668 /// Before calling this method, you must grant rights to the calling user via [`Self::approve`].1669 ///1670 /// * `sender` - The user who must have access to the token (see [`Self::approve`]).1671 /// * `from` - The user who owns the token.1672 /// * `to` - Recepient user.1673 /// * `token` - The token of which parts are being sent.1674 /// * `amount` - The number of parts of the token that will be transferred.1675 /// * `budget` - The maximum budget that can be spent on the transfer.1370 fn transfer_from(1676 fn transfer_from(1371 &self,1677 &self,1372 sender: T::CrossAccountId,1678 sender: T::CrossAccountId,1373 from: T::CrossAccountId,1679 from: T::CrossAccountId,1374 to: T::CrossAccountId,1680 to: T::CrossAccountId,1375 token: TokenId,1681 token: TokenId,1376 amount: u128,1682 amount: u128,1377 nesting_budget: &dyn Budget,1683 budget: &dyn Budget,1378 ) -> DispatchResultWithPostInfo;1684 ) -> DispatchResultWithPostInfo;16851686 /// Burn parts of a token owned by another user.1687 ///1688 /// Before calling this method, you must grant rights to the calling user via [`Self::approve`].1689 ///1690 /// * `sender` - The user who must have access to the token (see [`Self::approve`]).1691 /// * `from` - The user who owns the token.1692 /// * `token` - The token of which parts are being sent.1693 /// * `amount` - The number of parts of the token that will be transferred.1694 /// * `budget` - The maximum budget that can be spent on the burn.1379 fn burn_from(1695 fn burn_from(1380 &self,1696 &self,1381 sender: T::CrossAccountId,1697 sender: T::CrossAccountId,1382 from: T::CrossAccountId,1698 from: T::CrossAccountId,1383 token: TokenId,1699 token: TokenId,1384 amount: u128,1700 amount: u128,1385 nesting_budget: &dyn Budget,1701 budget: &dyn Budget,1386 ) -> DispatchResultWithPostInfo;1702 ) -> DispatchResultWithPostInfo;138717031704 /// Check permission to nest token.1705 ///1706 /// * `sender` - The user who initiated the check.1707 /// * `from` - The token that is checked for embedding.1708 /// * `under` - Token under which to check.1709 /// * `budget` - The maximum budget that can be spent on the check.1388 fn check_nesting(1710 fn check_nesting(1389 &self,1711 &self,1390 sender: T::CrossAccountId,1712 sender: T::CrossAccountId,1391 from: (CollectionId, TokenId),1713 from: (CollectionId, TokenId),1392 under: TokenId,1714 under: TokenId,1393 nesting_budget: &dyn Budget,1715 budget: &dyn Budget,1394 ) -> DispatchResult;1716 ) -> DispatchResult;139517171718 /// Nest one token into another.1719 ///1720 /// * `under` - Token holder.1721 /// * `to_nest` - Nested token.1396 fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));1722 fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));139717231724 /// Unnest token.1725 ///1726 /// * `under` - Token holder.1727 /// * `to_nest` - Token to unnest.1398 fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));1728 fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));139917291730 /// Get all user tokens.1731 ///1732 /// * `account` - Account for which you need to get tokens.1400 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;1733 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;17341735 /// Get all the tokens in the collection.1401 fn collection_tokens(&self) -> Vec<TokenId>;1736 fn collection_tokens(&self) -> Vec<TokenId>;17371738 /// Check if the token exists.1739 ///1740 /// * `token` - Id token to check.1402 fn token_exists(&self, token: TokenId) -> bool;1741 fn token_exists(&self, token: TokenId) -> bool;17421743 /// Get the id of the last minted token.1403 fn last_token_id(&self) -> TokenId;1744 fn last_token_id(&self) -> TokenId;140417451746 /// Get the owner of the token.1747 ///1748 /// * `token` - The token for which you need to find out the owner.1405 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;1749 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;17501751 /// Returns 10 tokens owners in no particular order.1752 ///1753 /// * `token` - The token for which you need to find out the owners.1754 fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId>;17551756 /// Get the value of the token property by key.1757 ///1758 /// * `token` - Token with the property to get.1759 /// * `key` - Property name.1406 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;1760 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;17611407 fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;1762 /// Get a set of token properties by key vector.1763 ///1764 /// * `token` - Token with the property to get.1765 /// * `keys` - Vector of property keys. If this parameter is [None](sp_std::result::Result),1766 /// then all properties are returned.1767 fn token_properties(&self, token: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;17681408 /// Amount of unique collection tokens1769 /// Amount of unique collection tokens1409 fn total_supply(&self) -> u32;1770 fn total_supply(&self) -> u32;17711410 /// Amount of different tokens account has (Applicable to nonfungible/refungible)1772 /// Amount of different tokens account has.1773 ///1774 /// * `account` - The account for which need to get the balance.1411 fn account_balance(&self, account: T::CrossAccountId) -> u32;1775 fn account_balance(&self, account: T::CrossAccountId) -> u32;17761412 /// Amount of specific token account have (Applicable to fungible/refungible)1777 /// Amount of specific token account have.1413 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;1778 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;17791414 /// Amount of token pieces1780 /// Amount of token pieces1415 fn total_pieces(&self, token: TokenId) -> Option<u128>;1781 fn total_pieces(&self, token: TokenId) -> Option<u128>;17821783 /// Get the number of parts of the token that a trusted user can manage.1784 ///1785 /// * `sender` - Trusted user.1786 /// * `spender` - Owner of the token.1787 /// * `token` - The token for which to get the value.1416 fn allowance(1788 fn allowance(1417 &self,1789 &self,1418 sender: T::CrossAccountId,1790 sender: T::CrossAccountId,1419 spender: T::CrossAccountId,1791 spender: T::CrossAccountId,1420 token: TokenId,1792 token: TokenId,1421 ) -> u128;1793 ) -> u128;17941795 /// Get extension for RFT collection.1422 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;1796 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;1423}1797}142417981799/// Extension for RFT collection.1425pub trait RefungibleExtensions<T>1800pub trait RefungibleExtensions<T>1426where1801where1427 T: Config,1802 T: Config,1428{1803{1804 /// Change the number of parts of the token.1805 ///1806 /// When the value changes down, this function is equivalent to burning parts of the token.1807 ///1808 /// * `sender` - The user calling the repartition operation. Must be the owner of the token.1809 /// * `token` - The token for which you want to change the number of parts.1810 /// * `amount` - The new value of the parts of the token.1429 fn repartition(1811 fn repartition(1430 &self,1812 &self,1431 owner: &T::CrossAccountId,1813 sender: &T::CrossAccountId,1432 token: TokenId,1814 token: TokenId,1433 amount: u128,1815 amount: u128,1434 ) -> DispatchResultWithPostInfo;1816 ) -> DispatchResultWithPostInfo;1435}1817}143618181437// Flexible enough for implementing CommonCollectionOperations1819/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].1820///1821/// Used for [`CommonCollectionOperations`] implementations and flexible enough to do so.1438pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {1822pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {1439 let post_info = PostDispatchInfo {1823 let post_info = PostDispatchInfo {1440 actual_weight: Some(weight),1824 actual_weight: Some(weight),pallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/CHANGELOG.mddiffbeforeafterbothno changes
pallets/fungible/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-fungible"2name = "pallet-fungible"3version = "0.1.0"3version = "0.1.1"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/fungible/src/common.rsdiffbeforeafterboth105 }105 }106}106}107107108/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallete109/// methods and adds weight info.108impl<T: Config> CommonCollectionOperations<T> for FungibleHandle<T> {110impl<T: Config> CommonCollectionOperations<T> for FungibleHandle<T> {109 fn create_item(111 fn create_item(110 &self,112 &self,360 None362 None361 }363 }364365 /// Returns 10 tokens owners in no particular order.366 fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {367 <Pallet<T>>::token_owners(self.id, token).unwrap_or_default()368 }362369363 fn token_property(&self, _token_id: TokenId, _key: &PropertyKey) -> Option<PropertyValue> {370 fn token_property(&self, _token_id: TokenId, _key: &PropertyKey) -> Option<PropertyValue> {364 None371 Nonepallets/fungible/src/erc.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! ERC-20 standart support implementation.161817use core::char::{REPLACEMENT_CHARACTER, decode_utf16};19use core::char::{REPLACEMENT_CHARACTER, decode_utf16};18use core::convert::TryInto;20use core::convert::TryInto;pallets/fungible/src/lib.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! # Fungible Pallet18//!19//! The Fungible pallet provides functionality for dealing with fungible assets.20//!21//! - [`CreateItemData`]22//! - [`Config`]23//! - [`FungibleHandle`]24//! - [`Pallet`]25//! - [`TotalSupply`]26//! - [`Balance`]27//! - [`Allowance`]28//! - [`Error`]29//!30//! ## Fungible tokens31//!32//! Fungible tokens or assets are divisible and non-unique. For instance,33//! fiat currencies like the dollar are fungible: A $1 bill34//! in New York City has the same value as a $1 bill in Miami.35//! A fungible token can also be a cryptocurrency like Bitcoin: 1 BTC is worth 1 BTC,36//! no matter where it is issued. Thus, the fungibility refers to a specific currency’s37//! ability to maintain one standard value. As well, it needs to have uniform acceptance.38//! This means that a currency’s history should not be able to affect its value,39//! and this is due to the fact that each piece that is a part of the currency is equal40//! in value when compared to every other piece of that exact same currency.41//! In the world of cryptocurrencies, this is essentially a coin or a token42//! that can be replaced by another identical coin or token, and they are43//! both mutually interchangeable. A popular implementation of fungible tokens is44//! the ERC-20 token standard.45//!46//! ### ERC-2047//!48//! The [ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) (Ethereum Request for Comments 20), proposed by Fabian Vogelsteller in November 2015,49//! is a Token Standard that implements an API for tokens within Smart Contracts.50//!51//! Example functionalities ERC-20 provides:52//!53//! * transfer tokens from one account to another54//! * get the current token balance of an account55//! * get the total supply of the token available on the network56//! * approve whether an amount of token from an account can be spent by a third-party account57//!58//! ## Overview59//!60//! The module provides functionality for asset management of fungible asset, supports ERC-20 standart, includes:61//!62//! * Asset Issuance63//! * Asset Transferal64//! * Asset Destruction65//! * Delegated Asset Transfers66//!67//! **NOTE:** The created fungible asset always has `token_id` = 0.68//! So `tokenA` and `tokenB` will have different `collection_id`.69//!70//! ### Implementations71//!72//! The Fungible pallet provides implementations for the following traits.73//!74//! - [`WithRecorder`](pallet_evm_coder_substrate::WithRecorder): Trait for EVM support75//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing with collections76//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight77//! - [`CommonEvmHandler`](pallet_common::erc::CommonEvmHandler): Function for handling EVM runtime calls167817#![cfg_attr(not(feature = "std"), no_std)]79#![cfg_attr(not(feature = "std"), no_std)]188033use pallet_evm_coder_substrate::WithRecorder;95use pallet_evm_coder_substrate::WithRecorder;34use sp_core::H160;96use sp_core::H160;35use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};97use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};36use sp_std::{collections::btree_map::BTreeMap};98use sp_std::{collections::btree_map::BTreeMap, vec::Vec};379938pub use pallet::*;100pub use pallet::*;3910144pub mod erc;106pub mod erc;45pub mod weights;107pub mod weights;4610847/// todo:doc?48pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);109pub type CreateItemData<T> = (<T as pallet_evm::account::Config>::CrossAccountId, u128);49pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;110pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;5011158 pub enum Error<T> {119 pub enum Error<T> {59 /// Not Fungible item data used to mint in Fungible collection.120 /// Not Fungible item data used to mint in Fungible collection.60 NotFungibleDataUsedToMintFungibleCollectionToken,121 NotFungibleDataUsedToMintFungibleCollectionToken,61 /// Not default id passed as TokenId argument.122 /// Fungible tokens hold no ID, and the default value of TokenId for Fungible collection is 0.62 FungibleItemsHaveNoId,123 FungibleItemsHaveNoId,63 /// Tried to set data for fungible item.124 /// Tried to set data for fungible item.64 FungibleItemsDontHaveData,125 FungibleItemsDontHaveData,95 QueryKind = ValueQuery,156 QueryKind = ValueQuery,96 >;157 >;9715898 /// todo:doc159 /// Storage for assets delegated to a limited extent to other users.99 #[pallet::storage]160 #[pallet::storage]100 pub type Allowance<T: Config> = StorageNMap<161 pub type Allowance<T: Config> = StorageNMap<101 Key = (162 Key = (108 >;169 >;109}170}110171172/// Wrapper around untyped collection handle, asserting inner collection is of fungible type.173/// Required for interaction with Fungible collections, type safety and implementation [`solidity_interface`][`evm_coder::solidity_interface`].111pub struct FungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);174pub struct FungibleHandle<T: Config>(pallet_common::CollectionHandle<T>);175176/// Implementation of methods required for dispatching during runtime.112impl<T: Config> FungibleHandle<T> {177impl<T: Config> FungibleHandle<T> {178 /// Casts [`CollectionHandle`][`pallet_common::CollectionHandle`] into [`FungibleHandle`].113 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {179 pub fn cast(inner: pallet_common::CollectionHandle<T>) -> Self {114 Self(inner)180 Self(inner)115 }181 }182183 /// Casts [`FungibleHandle`] into [`CollectionHandle`][`pallet_common::CollectionHandle`].116 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {184 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {117 self.0185 self.0118 }186 }187 /// Returns a mutable reference to the internal [`CollectionHandle`][`pallet_common::CollectionHandle`].119 pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle<T> {188 pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle<T> {120 &mut self.0189 &mut self.0121 }190 }136 }205 }137}206}138207208/// Pallet implementation for fungible assets139impl<T: Config> Pallet<T> {209impl<T: Config> Pallet<T> {210 /// Initializes the collection. Returns [CollectionId] on success, [DispatchError] otherwise.140 pub fn init_collection(211 pub fn init_collection(141 owner: T::CrossAccountId,212 owner: T::CrossAccountId,142 data: CreateCollectionData<T::AccountId>,213 data: CreateCollectionData<T::AccountId>,143 ) -> Result<CollectionId, DispatchError> {214 ) -> Result<CollectionId, DispatchError> {144 <PalletCommon<T>>::init_collection(owner, data, false)215 <PalletCommon<T>>::init_collection(owner, data, false)145 }216 }217218 /// Destroys a collection.146 pub fn destroy_collection(219 pub fn destroy_collection(147 collection: FungibleHandle<T>,220 collection: FungibleHandle<T>,148 sender: &T::CrossAccountId,221 sender: &T::CrossAccountId,163 Ok(())236 Ok(())164 }237 }165238239 ///Checks if collection has tokens. Return `true` if it has.166 fn collection_has_tokens(collection_id: CollectionId) -> bool {240 fn collection_has_tokens(collection_id: CollectionId) -> bool {167 <TotalSupply<T>>::get(collection_id) != 0241 <TotalSupply<T>>::get(collection_id) != 0168 }242 }169243244 /// Burns the specified amount of the token. If the token balance245 /// or total supply is less than the given value,246 /// it will return [DispatchError].170 pub fn burn(247 pub fn burn(171 collection: &FungibleHandle<T>,248 collection: &FungibleHandle<T>,172 owner: &T::CrossAccountId,249 owner: &T::CrossAccountId,211 Ok(())288 Ok(())212 }289 }213290291 /// Transfers the specified amount of tokens. Will check that292 /// the transfer is allowed for the token.293 ///294 /// - `from`: Owner of tokens to transfer.295 /// - `to`: Recepient of transfered tokens.296 /// - `amount`: Amount of tokens to transfer.297 /// - `collection`: Collection that contains the token214 pub fn transfer(298 pub fn transfer(215 collection: &FungibleHandle<T>,299 collection: &FungibleHandle<T>,216 from: &T::CrossAccountId,300 from: &T::CrossAccountId,281 Ok(())365 Ok(())282 }366 }283367368 /// Minting tokens for multiple IDs.369 /// See [`create_item`][`Pallet::create_item`] for more details.284 pub fn create_multiple_items(370 pub fn create_multiple_items(285 collection: &FungibleHandle<T>,371 collection: &FungibleHandle<T>,286 sender: &T::CrossAccountId,372 sender: &T::CrossAccountId,382 ));468 ));383 }469 }384470471 /// Set allowance for the spender to `transfer` or `burn` owner's tokens.472 ///473 /// - `collection`: Collection that contains the token474 /// - `owner`: Owner of tokens that sets the allowance.475 /// - `spender`: Recipient of the allowance rights.476 /// - `amount`: Amount of tokens the spender is allowed to `transfer` or `burn`.385 pub fn set_allowance(477 pub fn set_allowance(386 collection: &FungibleHandle<T>,478 collection: &FungibleHandle<T>,387 owner: &T::CrossAccountId,479 owner: &T::CrossAccountId,406 Ok(())498 Ok(())407 }499 }408500501 /// Checks if a non-owner has (enough) allowance from the owner to perform operations on the tokens.502 /// Returns the expected remaining allowance - it should be set manually if the transaction proceeds.503 ///504 /// - `collection`: Collection that contains the token.505 /// - `spender`: CrossAccountId who has the allowance rights.506 /// - `from`: The owner of the tokens who sets the allowance.507 /// - `amount`: Amount of tokens by which the allowance sholud be reduced.409 fn check_allowed(508 fn check_allowed(410 collection: &FungibleHandle<T>,509 collection: &FungibleHandle<T>,411 spender: &T::CrossAccountId,510 spender: &T::CrossAccountId,445 Ok(allowance)544 Ok(allowance)446 }545 }546547 /// Transfer fungible tokens from one account to another.548 /// Same as the [`transfer`][`Pallet::transfer`] but spender doesn't needs to be an owner of the token pieces.549 /// The owner should set allowance for the spender to transfer pieces.550 /// See [`set_allowance`][`Pallet::set_allowance`] for more details.447551448 pub fn transfer_from(552 pub fn transfer_from(449 collection: &FungibleHandle<T>,553 collection: &FungibleHandle<T>,464 Ok(())568 Ok(())465 }569 }466570571 /// Burn fungible tokens from the account.572 ///573 /// Same as the [`burn`][`Pallet::burn`] but spender doesn't need to be an owner of the tokens. The `from` should574 /// set allowance for the spender to burn tokens.575 /// See [`set_allowance`][`Pallet::set_allowance`] for more details.467 pub fn burn_from(576 pub fn burn_from(468 collection: &FungibleHandle<T>,577 collection: &FungibleHandle<T>,469 spender: &T::CrossAccountId,578 spender: &T::CrossAccountId,482 Ok(())591 Ok(())483 }592 }484593485 /// Delegated to `create_multiple_items`594 /// Creates fungible token.595 ///596 /// The sender should be the owner/admin of the collection or collection should be configured597 /// to allow public minting.598 ///599 /// - `data`: Contains user who will become the owners of the tokens and amount600 /// of tokens he will receive.486 pub fn create_item(601 pub fn create_item(487 collection: &FungibleHandle<T>,602 collection: &FungibleHandle<T>,488 sender: &T::CrossAccountId,603 sender: &T::CrossAccountId,497 )612 )498 }613 }614615 /// Returns 10 tokens owners in no particular order616 ///617 /// There is no direct way to get token holders in ascending order,618 /// since `iter_prefix` returns values in no particular order.619 /// Therefore, getting the 10 largest holders with a large value of holders620 /// can lead to impact memory allocation + sorting with `n * log (n)`.621 pub fn token_owners(622 collection: CollectionId,623 _token: TokenId,624 ) -> Option<Vec<T::CrossAccountId>> {625 let res: Vec<T::CrossAccountId> = <Balance<T>>::iter_prefix((collection,))626 .map(|(owner, _amount)| owner)627 .take(10)628 .collect();629630 if res.is_empty() {631 None632 } else {633 Some(res)634 }635 }499}636}500637pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth43 }43 }44}44}4546// Selector: 7d9262e647contract Collection is Dummy, ERC165 {48 // Set collection property.49 //50 // @param key Property key.51 // @param value Propery value.52 //53 // Selector: setCollectionProperty(string,bytes) 2f073f6654 function setCollectionProperty(string memory key, bytes memory value)55 public56 {57 require(false, stub_error);58 key;59 value;60 dummy = 0;61 }6263 // Delete collection property.64 //65 // @param key Property key.66 //67 // Selector: deleteCollectionProperty(string) 7b7debce68 function deleteCollectionProperty(string memory key) public {69 require(false, stub_error);70 key;71 dummy = 0;72 }7374 // Get collection property.75 //76 // @dev Throws error if key not found.77 //78 // @param key Property key.79 // @return bytes The property corresponding to the key.80 //81 // Selector: collectionProperty(string) cf24fd6d82 function collectionProperty(string memory key)83 public84 view85 returns (bytes memory)86 {87 require(false, stub_error);88 key;89 dummy;90 return hex"";91 }9293 // Set the sponsor of the collection.94 //95 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.96 //97 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.98 //99 // Selector: setCollectionSponsor(address) 7623402e100 function setCollectionSponsor(address sponsor) public {101 require(false, stub_error);102 sponsor;103 dummy = 0;104 }105106 // Collection sponsorship confirmation.107 //108 // @dev After setting the sponsor for the collection, it must be confirmed with this function.109 //110 // Selector: confirmCollectionSponsorship() 3c50e97a111 function confirmCollectionSponsorship() public {112 require(false, stub_error);113 dummy = 0;114 }115116 // Set limits for the collection.117 // @dev Throws error if limit not found.118 // @param limit Name of the limit. Valid names:119 // "accountTokenOwnershipLimit",120 // "sponsoredDataSize",121 // "sponsoredDataRateLimit",122 // "tokenLimit",123 // "sponsorTransferTimeout",124 // "sponsorApproveTimeout"125 // @param value Value of the limit.126 //127 // Selector: setCollectionLimit(string,uint32) 6a3841db128 function setCollectionLimit(string memory limit, uint32 value) public {129 require(false, stub_error);130 limit;131 value;132 dummy = 0;133 }134135 // Set limits for the collection.136 // @dev Throws error if limit not found.137 // @param limit Name of the limit. Valid names:138 // "ownerCanTransfer",139 // "ownerCanDestroy",140 // "transfersEnabled"141 // @param value Value of the limit.142 //143 // Selector: setCollectionLimit(string,bool) 993b7fba144 function setCollectionLimit(string memory limit, bool value) public {145 require(false, stub_error);146 limit;147 value;148 dummy = 0;149 }150151 // Get contract address.152 //153 // Selector: contractAddress() f6b4dfb4154 function contractAddress() public view returns (address) {155 require(false, stub_error);156 dummy;157 return 0x0000000000000000000000000000000000000000;158 }159160 // Add collection admin by substrate address.161 // @param new_admin Substrate administrator address.162 //163 // Selector: addCollectionAdminSubstrate(uint256) 5730062b164 function addCollectionAdminSubstrate(uint256 newAdmin) public {165 require(false, stub_error);166 newAdmin;167 dummy = 0;168 }169170 // Remove collection admin by substrate address.171 // @param admin Substrate administrator address.172 //173 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9174 function removeCollectionAdminSubstrate(uint256 admin) public {175 require(false, stub_error);176 admin;177 dummy = 0;178 }179180 // Add collection admin.181 // @param new_admin Address of the added administrator.182 //183 // Selector: addCollectionAdmin(address) 92e462c7184 function addCollectionAdmin(address newAdmin) public {185 require(false, stub_error);186 newAdmin;187 dummy = 0;188 }189190 // Remove collection admin.191 //192 // @param new_admin Address of the removed administrator.193 //194 // Selector: removeCollectionAdmin(address) fafd7b42195 function removeCollectionAdmin(address admin) public {196 require(false, stub_error);197 admin;198 dummy = 0;199 }200201 // Toggle accessibility of collection nesting.202 //203 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'204 //205 // Selector: setCollectionNesting(bool) 112d4586206 function setCollectionNesting(bool enable) public {207 require(false, stub_error);208 enable;209 dummy = 0;210 }211212 // Toggle accessibility of collection nesting.213 //214 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'215 // @param collections Addresses of collections that will be available for nesting.216 //217 // Selector: setCollectionNesting(bool,address[]) 64872396218 function setCollectionNesting(bool enable, address[] memory collections)219 public220 {221 require(false, stub_error);222 enable;223 collections;224 dummy = 0;225 }226227 // Set the collection access method.228 // @param mode Access mode229 // 0 for Normal230 // 1 for AllowList231 //232 // Selector: setCollectionAccess(uint8) 41835d4c233 function setCollectionAccess(uint8 mode) public {234 require(false, stub_error);235 mode;236 dummy = 0;237 }238239 // Add the user to the allowed list.240 //241 // @param user Address of a trusted user.242 //243 // Selector: addToCollectionAllowList(address) 67844fe6244 function addToCollectionAllowList(address user) public {245 require(false, stub_error);246 user;247 dummy = 0;248 }249250 // Remove the user from the allowed list.251 //252 // @param user Address of a removed user.253 //254 // Selector: removeFromCollectionAllowList(address) 85c51acb255 function removeFromCollectionAllowList(address user) public {256 require(false, stub_error);257 user;258 dummy = 0;259 }260261 // Switch permission for minting.262 //263 // @param mode Enable if "true".264 //265 // Selector: setCollectionMintMode(bool) 00018e84266 function setCollectionMintMode(bool mode) public {267 require(false, stub_error);268 mode;269 dummy = 0;270 }271}4527246// Selector: 942e8b22273// Selector: 942e8b2247contract ERC20 is Dummy, ERC165, ERC20Events {274contract ERC20 is Dummy, ERC165, ERC20Events {127 }354 }128}355}129130// Selector: c894dc35131contract Collection is Dummy, ERC165 {132 // Selector: setCollectionProperty(string,bytes) 2f073f66133 function setCollectionProperty(string memory key, bytes memory value)134 public135 {136 require(false, stub_error);137 key;138 value;139 dummy = 0;140 }141142 // Selector: deleteCollectionProperty(string) 7b7debce143 function deleteCollectionProperty(string memory key) public {144 require(false, stub_error);145 key;146 dummy = 0;147 }148149 // Throws error if key not found150 //151 // Selector: collectionProperty(string) cf24fd6d152 function collectionProperty(string memory key)153 public154 view155 returns (bytes memory)156 {157 require(false, stub_error);158 key;159 dummy;160 return hex"";161 }162163 // Selector: ethSetSponsor(address) 8f9af356164 function ethSetSponsor(address sponsor) public {165 require(false, stub_error);166 sponsor;167 dummy = 0;168 }169170 // Selector: ethConfirmSponsorship() a8580d1a171 function ethConfirmSponsorship() public {172 require(false, stub_error);173 dummy = 0;174 }175176 // Selector: setLimit(string,uint32) 68db30ca177 function setLimit(string memory limit, uint32 value) public {178 require(false, stub_error);179 limit;180 value;181 dummy = 0;182 }183184 // Selector: setLimit(string,bool) ea67e4c2185 function setLimit(string memory limit, bool value) public {186 require(false, stub_error);187 limit;188 value;189 dummy = 0;190 }191192 // Selector: contractAddress() f6b4dfb4193 function contractAddress() public view returns (address) {194 require(false, stub_error);195 dummy;196 return 0x0000000000000000000000000000000000000000;197 }198}199356200contract UniqueFungible is357contract UniqueFungible is201 Dummy,358 Dummy,pallets/inflation/src/lib.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! # Inflation18//!19//! The inflation pallet is designed to increase the number of tokens at certain intervals.20//! With each iteration, increases the `total_issuance` value for the native token.21//! Executing an `on_initialize` hook at the beginning of each block, causing inflation to begin.22//!23//! ## Interface24//!25//! ### Dispatchable Functions26//!27//! * `start_inflation` - This method sets the inflation start date. Can be only called once.28//! Inflation start block can be backdated and will catch up. The method will create Treasury29//! account if it does not exist and perform the first inflation deposit.163017// #![recursion_limit = "1024"]31// #![recursion_limit = "1024"]18#![cfg_attr(not(feature = "std"), no_std)]32#![cfg_attr(not(feature = "std"), no_std)]pallets/nonfungible/CHANGELOG.mddiffbeforeafterbothno changes
pallets/nonfungible/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-nonfungible"2name = "pallet-nonfungible"3version = "0.1.0"3version = "0.1.1"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66pallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth183 value: property_value(),183 value: property_value(),184 }).collect::<Vec<_>>();184 }).collect::<Vec<_>>();185 let item = create_max_item(&collection, &owner, owner.clone())?;185 let item = create_max_item(&collection, &owner, owner.clone())?;186 }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props, false, &Unlimited)?}186 }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?}187187188 delete_token_properties {188 delete_token_properties {189 let b in 0..MAX_PROPERTIES_PER_ITEM;189 let b in 0..MAX_PROPERTIES_PER_ITEM;205 value: property_value(),205 value: property_value(),206 }).collect::<Vec<_>>();206 }).collect::<Vec<_>>();207 let item = create_max_item(&collection, &owner, owner.clone())?;207 let item = create_max_item(&collection, &owner, owner.clone())?;208 <Pallet<T>>::set_token_properties(&collection, &owner, item, props, false, &Unlimited)?;208 <Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?;209 let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();209 let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();210 }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete, &Unlimited)?}210 }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete.into_iter(), &Unlimited)?}211}211}212212pallets/nonfungible/src/common.rsdiffbeforeafterboth26 weights::WeightInfo as _,26 weights::WeightInfo as _,27};27};28use sp_runtime::DispatchError;28use sp_runtime::DispatchError;29use sp_std::vec::Vec;29use sp_std::{vec::Vec, vec};303031use crate::{31use crate::{32 AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,32 AccountBalance, Allowance, Config, CreateItemData, Error, NonfungibleHandle, Owned, Pallet,133 }133 }134}134}135135136/// Implementation of `CommonCollectionOperations` for `NonfungibleHandle`. It wraps Nonfungible Pallete137/// methods and adds weight info.136impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {138impl<T: Config> CommonCollectionOperations<T> for NonfungibleHandle<T> {137 fn create_item(139 fn create_item(138 &self,140 &self,420 <TokenData<T>>::get((self.id, token)).map(|t| t.owner)422 <TokenData<T>>::get((self.id, token)).map(|t| t.owner)421 }423 }424425 /// Returns token owners.426 fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {427 self.token_owner(token).map_or_else(|| vec![], |t| vec![t])428 }422429423 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {430 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue> {424 <Pallet<T>>::token_properties((self.id, token_id))431 <Pallet<T>>::token_properties((self.id, token_id))pallets/nonfungible/src/erc.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! # Nonfungible Pallet EVM API18//!19//! Provides ERC-721 standart support implementation and EVM API for unique extensions for Nonfungible Pallet.20//! Method implementations are mostly doing parameter conversion and calling Nonfungible Pallet methods.162117extern crate alloc;22extern crate alloc;18use core::{23use core::{40 SelfWeightOf, weights::WeightInfo, TokenProperties,45 SelfWeightOf, weights::WeightInfo, TokenProperties,41};46};424748/// @title A contract that allows to set and delete token properties and change token property permissions.43#[solidity_interface(name = "TokenProperties")]49#[solidity_interface(name = "TokenProperties")]44impl<T: Config> NonfungibleHandle<T> {50impl<T: Config> NonfungibleHandle<T> {51 /// @notice Set permissions for token property.52 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.53 /// @param key Property key.54 /// @param is_mutable Permission to mutate property.55 /// @param collection_admin Permission to mutate property by collection admin if property is mutable.56 /// @param token_owner Permission to mutate property by token owner if property is mutable.45 fn set_token_property_permission(57 fn set_token_property_permission(46 &mut self,58 &mut self,47 caller: caller,59 caller: caller,68 .map_err(dispatch_to_evm::<T>)80 .map_err(dispatch_to_evm::<T>)69 }81 }708283 /// @notice Set token property value.84 /// @dev Throws error if `msg.sender` has no permission to edit the property.85 /// @param tokenId ID of the token.86 /// @param key Property key.87 /// @param value Property value.71 fn set_property(88 fn set_property(72 &mut self,89 &mut self,73 caller: caller,90 caller: caller,96 .map_err(dispatch_to_evm::<T>)113 .map_err(dispatch_to_evm::<T>)97 }114 }98115116 /// @notice Delete token property value.117 /// @dev Throws error if `msg.sender` has no permission to edit the property.118 /// @param tokenId ID of the token.119 /// @param key Property key.99 fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {120 fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {100 let caller = T::CrossAccountId::from_eth(caller);121 let caller = T::CrossAccountId::from_eth(caller);101 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;122 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;111 .map_err(dispatch_to_evm::<T>)132 .map_err(dispatch_to_evm::<T>)112 }133 }113134135 /// @notice Get token property value.114 /// Throws error if key not found136 /// @dev Throws error if key not found137 /// @param tokenId ID of the token.138 /// @param key Property key.139 /// @return Property value bytes115 fn property(&self, token_id: uint256, key: string) -> Result<bytes> {140 fn property(&self, token_id: uint256, key: string) -> Result<bytes> {116 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;141 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;117 let key = <Vec<u8>>::from(key)142 let key = <Vec<u8>>::from(key)127152128#[derive(ToLog)]153#[derive(ToLog)]129pub enum ERC721Events {154pub enum ERC721Events {155 /// @dev This emits when ownership of any NFT changes by any mechanism.156 /// This event emits when NFTs are created (`from` == 0) and destroyed157 /// (`to` == 0). Exception: during contract creation, any number of NFTs158 /// may be created and assigned without emitting Transfer. At the time of159 /// any transfer, the approved address for that NFT (if any) is reset to none.130 Transfer {160 Transfer {131 #[indexed]161 #[indexed]132 from: address,162 from: address,135 #[indexed]165 #[indexed]136 token_id: uint256,166 token_id: uint256,137 },167 },168 /// @dev This emits when the approved address for an NFT is changed or169 /// reaffirmed. The zero address indicates there is no approved address.170 /// When a Transfer event emits, this also indicates that the approved171 /// address for that NFT (if any) is reset to none.138 Approval {172 Approval {139 #[indexed]173 #[indexed]140 owner: address,174 owner: address,143 #[indexed]177 #[indexed]144 token_id: uint256,178 token_id: uint256,145 },179 },180 /// @dev This emits when an operator is enabled or disabled for an owner.181 /// The operator can manage all NFTs of the owner.146 #[allow(dead_code)]182 #[allow(dead_code)]147 ApprovalForAll {183 ApprovalForAll {148 #[indexed]184 #[indexed]159 MintingFinished {},195 MintingFinished {},160}196}161197198/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension199/// @dev See https://eips.ethereum.org/EIPS/eip-721162#[solidity_interface(name = "ERC721Metadata")]200#[solidity_interface(name = "ERC721Metadata")]163impl<T: Config> NonfungibleHandle<T> {201impl<T: Config> NonfungibleHandle<T> {202 /// @notice A descriptive name for a collection of NFTs in this contract164 fn name(&self) -> Result<string> {203 fn name(&self) -> Result<string> {165 Ok(decode_utf16(self.name.iter().copied())204 Ok(decode_utf16(self.name.iter().copied())166 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))205 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))167 .collect::<string>())206 .collect::<string>())168 }207 }169208209 /// @notice An abbreviated name for NFTs in this contract170 fn symbol(&self) -> Result<string> {210 fn symbol(&self) -> Result<string> {171 Ok(string::from_utf8_lossy(&self.token_prefix).into())211 Ok(string::from_utf8_lossy(&self.token_prefix).into())172 }212 }173213214 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.215 /// @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC216 /// 3986. The URI may point to a JSON file that conforms to the "ERC721217 /// Metadata JSON Schema".174 /// Returns token's const_metadata218 /// @return token's const_metadata175 #[solidity(rename_selector = "tokenURI")]219 #[solidity(rename_selector = "tokenURI")]176 fn token_uri(&self, token_id: uint256) -> Result<string> {220 fn token_uri(&self, token_id: uint256) -> Result<string> {177 let key = token_uri_key();221 let key = token_uri_key();192 }236 }193}237}194238239/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension240/// @dev See https://eips.ethereum.org/EIPS/eip-721195#[solidity_interface(name = "ERC721Enumerable")]241#[solidity_interface(name = "ERC721Enumerable")]196impl<T: Config> NonfungibleHandle<T> {242impl<T: Config> NonfungibleHandle<T> {243 /// @notice Enumerate valid NFTs244 /// @param index A counter less than `totalSupply()`245 /// @return The token identifier for the `index`th NFT,246 /// (sort order not specified)197 fn token_by_index(&self, index: uint256) -> Result<uint256> {247 fn token_by_index(&self, index: uint256) -> Result<uint256> {198 Ok(index)248 Ok(index)199 }249 }200250201 /// Not implemented251 /// @dev Not implemented202 fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {252 fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {203 // TODO: Not implemetable253 // TODO: Not implemetable204 Err("not implemented".into())254 Err("not implemented".into())205 }255 }206256257 /// @notice Count NFTs tracked by this contract258 /// @return A count of valid NFTs tracked by this contract, where each one of259 /// them has an assigned and queryable owner not equal to the zero address207 fn total_supply(&self) -> Result<uint256> {260 fn total_supply(&self) -> Result<uint256> {208 self.consume_store_reads(1)?;261 self.consume_store_reads(1)?;209 Ok(<Pallet<T>>::total_supply(self).into())262 Ok(<Pallet<T>>::total_supply(self).into())210 }263 }211}264}212265266/// @title ERC-721 Non-Fungible Token Standard267/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md213#[solidity_interface(name = "ERC721", events(ERC721Events))]268#[solidity_interface(name = "ERC721", events(ERC721Events))]214impl<T: Config> NonfungibleHandle<T> {269impl<T: Config> NonfungibleHandle<T> {270 /// @notice Count all NFTs assigned to an owner271 /// @dev NFTs assigned to the zero address are considered invalid, and this272 /// function throws for queries about the zero address.273 /// @param owner An address for whom to query the balance274 /// @return The number of NFTs owned by `owner`, possibly zero215 fn balance_of(&self, owner: address) -> Result<uint256> {275 fn balance_of(&self, owner: address) -> Result<uint256> {216 self.consume_store_reads(1)?;276 self.consume_store_reads(1)?;217 let owner = T::CrossAccountId::from_eth(owner);277 let owner = T::CrossAccountId::from_eth(owner);218 let balance = <AccountBalance<T>>::get((self.id, owner));278 let balance = <AccountBalance<T>>::get((self.id, owner));219 Ok(balance.into())279 Ok(balance.into())220 }280 }281 /// @notice Find the owner of an NFT282 /// @dev NFTs assigned to zero address are considered invalid, and queries283 /// about them do throw.284 /// @param tokenId The identifier for an NFT285 /// @return The address of the owner of the NFT221 fn owner_of(&self, token_id: uint256) -> Result<address> {286 fn owner_of(&self, token_id: uint256) -> Result<address> {222 self.consume_store_reads(1)?;287 self.consume_store_reads(1)?;223 let token: TokenId = token_id.try_into()?;288 let token: TokenId = token_id.try_into()?;226 .owner291 .owner227 .as_eth())292 .as_eth())228 }293 }229 /// Not implemented294 /// @dev Not implemented230 fn safe_transfer_from_with_data(295 fn safe_transfer_from_with_data(231 &mut self,296 &mut self,232 _from: address,297 _from: address,238 // TODO: Not implemetable303 // TODO: Not implemetable239 Err("not implemented".into())304 Err("not implemented".into())240 }305 }241 /// Not implemented306 /// @dev Not implemented242 fn safe_transfer_from(307 fn safe_transfer_from(243 &mut self,308 &mut self,244 _from: address,309 _from: address,250 Err("not implemented".into())315 Err("not implemented".into())251 }316 }252317318 /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE319 /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE320 /// THEY MAY BE PERMANENTLY LOST321 /// @dev Throws unless `msg.sender` is the current owner or an authorized322 /// operator for this NFT. Throws if `from` is not the current owner. Throws323 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.324 /// @param from The current owner of the NFT325 /// @param to The new owner326 /// @param tokenId The NFT to transfer327 /// @param _value Not used for an NFT253 #[weight(<SelfWeightOf<T>>::transfer_from())]328 #[weight(<SelfWeightOf<T>>::transfer_from())]254 fn transfer_from(329 fn transfer_from(255 &mut self,330 &mut self,272 Ok(())347 Ok(())273 }348 }274349350 /// @notice Set or reaffirm the approved address for an NFT351 /// @dev The zero address indicates there is no approved address.352 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized353 /// operator of the current owner.354 /// @param approved The new approved NFT controller355 /// @param tokenId The NFT to approve275 #[weight(<SelfWeightOf<T>>::approve())]356 #[weight(<SelfWeightOf<T>>::approve())]276 fn approve(357 fn approve(277 &mut self,358 &mut self,289 Ok(())370 Ok(())290 }371 }291372292 /// Not implemented373 /// @dev Not implemented293 fn set_approval_for_all(374 fn set_approval_for_all(294 &mut self,375 &mut self,295 _caller: caller,376 _caller: caller,300 Err("not implemented".into())381 Err("not implemented".into())301 }382 }302383303 /// Not implemented384 /// @dev Not implemented304 fn get_approved(&self, _token_id: uint256) -> Result<address> {385 fn get_approved(&self, _token_id: uint256) -> Result<address> {305 // TODO: Not implemetable386 // TODO: Not implemetable306 Err("not implemented".into())387 Err("not implemented".into())307 }388 }308389309 /// Not implemented390 /// @dev Not implemented310 fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {391 fn is_approved_for_all(&self, _owner: address, _operator: address) -> Result<address> {311 // TODO: Not implemetable392 // TODO: Not implemetable312 Err("not implemented".into())393 Err("not implemented".into())313 }394 }314}395}315396397/// @title ERC721 Token that can be irreversibly burned (destroyed).316#[solidity_interface(name = "ERC721Burnable")]398#[solidity_interface(name = "ERC721Burnable")]317impl<T: Config> NonfungibleHandle<T> {399impl<T: Config> NonfungibleHandle<T> {400 /// @notice Burns a specific ERC721 token.401 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized402 /// operator of the current owner.403 /// @param tokenId The NFT to approve318 #[weight(<SelfWeightOf<T>>::burn_item())]404 #[weight(<SelfWeightOf<T>>::burn_item())]319 fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {405 fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {320 let caller = T::CrossAccountId::from_eth(caller);406 let caller = T::CrossAccountId::from_eth(caller);325 }411 }326}412}327413414/// @title ERC721 minting logic.328#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]415#[solidity_interface(name = "ERC721Mintable", events(ERC721MintableEvents))]329impl<T: Config> NonfungibleHandle<T> {416impl<T: Config> NonfungibleHandle<T> {330 fn minting_finished(&self) -> Result<bool> {417 fn minting_finished(&self) -> Result<bool> {331 Ok(false)418 Ok(false)332 }419 }333420421 /// @notice Function to mint token.334 /// `token_id` should be obtained with `next_token_id` method,422 /// @dev `tokenId` should be obtained with `nextTokenId` method,335 /// unlike standard, you can't specify it manually423 /// unlike standard, you can't specify it manually424 /// @param to The new owner425 /// @param tokenId ID of the minted NFT336 #[weight(<SelfWeightOf<T>>::create_item())]426 #[weight(<SelfWeightOf<T>>::create_item())]337 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {427 fn mint(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {338 let caller = T::CrossAccountId::from_eth(caller);428 let caller = T::CrossAccountId::from_eth(caller);364 Ok(true)454 Ok(true)365 }455 }366456457 /// @notice Function to mint token with the given tokenUri.367 /// `token_id` should be obtained with `next_token_id` method,458 /// @dev `tokenId` should be obtained with `nextTokenId` method,368 /// unlike standard, you can't specify it manually459 /// unlike standard, you can't specify it manually460 /// @param to The new owner461 /// @param tokenId ID of the minted NFT462 /// @param tokenUri Token URI that would be stored in the NFT properties369 #[solidity(rename_selector = "mintWithTokenURI")]463 #[solidity(rename_selector = "mintWithTokenURI")]370 #[weight(<SelfWeightOf<T>>::create_item())]464 #[weight(<SelfWeightOf<T>>::create_item())]371 fn mint_with_token_uri(465 fn mint_with_token_uri(420 Ok(true)514 Ok(true)421 }515 }422516423 /// Not implemented517 /// @dev Not implemented424 fn finish_minting(&mut self, _caller: caller) -> Result<bool> {518 fn finish_minting(&mut self, _caller: caller) -> Result<bool> {425 Err("not implementable".into())519 Err("not implementable".into())426 }520 }449 false543 false450}544}451545546/// @title Unique extensions for ERC721.452#[solidity_interface(name = "ERC721UniqueExtensions")]547#[solidity_interface(name = "ERC721UniqueExtensions")]453impl<T: Config> NonfungibleHandle<T> {548impl<T: Config> NonfungibleHandle<T> {549 /// @notice Transfer ownership of an NFT550 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`551 /// is the zero address. Throws if `tokenId` is not a valid NFT.552 /// @param to The new owner553 /// @param tokenId The NFT to transfer554 /// @param _value Not used for an NFT454 #[weight(<SelfWeightOf<T>>::transfer())]555 #[weight(<SelfWeightOf<T>>::transfer())]455 fn transfer(556 fn transfer(456 &mut self,557 &mut self,470 Ok(())571 Ok(())471 }572 }472573574 /// @notice Burns a specific ERC721 token.575 /// @dev Throws unless `msg.sender` is the current owner or an authorized576 /// operator for this NFT. Throws if `from` is not the current owner. Throws577 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.578 /// @param from The current owner of the NFT579 /// @param tokenId The NFT to transfer580 /// @param _value Not used for an NFT473 #[weight(<SelfWeightOf<T>>::burn_from())]581 #[weight(<SelfWeightOf<T>>::burn_from())]474 fn burn_from(582 fn burn_from(475 &mut self,583 &mut self,490 Ok(())598 Ok(())491 }599 }492600601 /// @notice Returns next free NFT ID.493 fn next_token_id(&self) -> Result<uint256> {602 fn next_token_id(&self) -> Result<uint256> {494 self.consume_store_reads(1)?;603 self.consume_store_reads(1)?;495 Ok(<TokensMinted<T>>::get(self.id)604 Ok(<TokensMinted<T>>::get(self.id)498 .into())607 .into())499 }608 }500609610 /// @notice Function to mint multiple tokens.611 /// @dev `tokenIds` should be an array of consecutive numbers and first number612 /// should be obtained with `nextTokenId` method613 /// @param to The new owner614 /// @param tokenIds IDs of the minted NFTs501 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]615 #[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]502 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {616 fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {503 let caller = T::CrossAccountId::from_eth(caller);617 let caller = T::CrossAccountId::from_eth(caller);529 Ok(true)643 Ok(true)530 }644 }531645646 /// @notice Function to mint multiple tokens with the given tokenUris.647 /// @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive648 /// numbers and first number should be obtained with `nextTokenId` method649 /// @param to The new owner650 /// @param tokens array of pairs of token ID and token URI for minted tokens532 #[solidity(rename_selector = "mintBulkWithTokenURI")]651 #[solidity(rename_selector = "mintBulkWithTokenURI")]533 #[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]652 #[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]534 fn mint_bulk_with_token_uri(653 fn mint_bulk_with_token_uri(pallets/nonfungible/src/lib.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! # Nonfungible Pallet18//!19//! The Nonfungible pallet provides functionality for handling nonfungible collections and tokens.20//!21//! - [`Config`]22//! - [`NonfungibleHandle`]23//! - [`Pallet`]24//! - [`CommonWeights`](common::CommonWeights)25//!26//! ## Overview27//!28//! The Nonfungible pallet provides functions for:29//!30//! - NFT collection creation and removal31//! - Minting and burning of NFT tokens32//! - Retrieving account balances33//! - Transfering NFT tokens34//! - Setting and checking allowance for NFT tokens35//! - Setting properties and permissions for NFT collections and tokens36//! - Nesting and unnesting tokens37//!38//! ### Terminology39//!40//! - **NFT token:** Non fungible token.41//!42//! - **NFT Collection:** A collection of NFT tokens. All NFT tokens are part of a collection.43//! Each collection can define it's own properties, properties for it's tokens and set of permissions.44//!45//! - **Balance:** Number of NFT tokens owned by an account46//!47//! - **Allowance:** NFT tokens owned by one account that another account is allowed to make operations on48//!49//! - **Burning:** The process of “deleting” a token from a collection and from50//! an account balance of the owner.51//!52//! - **Nesting:** Setting up parent-child relationship between tokens. Nested tokens are inhereting53//! owner from their parent. There could be multiple levels of nesting. Token couldn't be nested in54//! it's child token i.e. parent-child relationship graph shouldn't have cycles.55//!56//! - **Properties:** Key-Values pairs. Token properties are attached to a token. Collection properties are57//! attached to a collection. Set of permissions could be defined for each property.58//!59//! ### Implementations60//!61//! The Nonfungible pallet provides implementations for the following traits. If these traits provide62//! the functionality that you need, then you can avoid coupling with the Nonfungible pallet.63//!64//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight65//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing66//! with collections67//!68//! ## Interface69//!70//! ### Dispatchable Functions71//!72//! - `init_collection` - Create NFT collection. NFT collection can be configured to allow or deny access for73//! some accounts.74//! - `destroy_collection` - Destroy exising NFT collection. There should be no tokens in the collection.75//! - `burn` - Burn NFT token owned by account.76//! - `transfer` - Transfer NFT token. Transfers should be enabled for NFT collection.77//! Nests the NFT token if it is sent to another token.78//! - `create_item` - Mint NFT token in collection. Sender should have permission to mint tokens.79//! - `set_allowance` - Set allowance for another account.80//! - `set_token_property` - Set token property value.81//! - `delete_token_property` - Remove property from the token.82//! - `set_collection_properties` - Set collection properties.83//! - `delete_collection_properties` - Remove properties from the collection.84//! - `set_property_permission` - Set collection property permission.85//! - `set_token_property_permissions` - Set token property permissions.86//!87//! ## Assumptions88//!89//! * To perform operations on tokens sender should be in collection's allow list if collection access mode is `AllowList`.169017#![cfg_attr(not(feature = "std"), no_std)]91#![cfg_attr(not(feature = "std"), no_std)]189256pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;130pub type CreateItemData<T> = CreateNftExData<<T as pallet_evm::account::Config>::CrossAccountId>;57pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;131pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;5813259/// Token data, stored independently from other data used to describe it.133/// Token data, stored independently from other data used to describe it60/// Notably contains the owner account address.134/// for the convenience of database access. Notably contains the owner account address.61#[struct_versioning::versioned(version = 2, upper)]135#[struct_versioning::versioned(version = 2, upper)]62#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]136#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]63pub struct ItemData<CrossAccountId> {137pub struct ItemData<CrossAccountId> {122 QueryKind = OptionQuery,196 QueryKind = OptionQuery,123 >;197 >;124198125 /// Key-value pairs, describing the metadata of a token.199 /// Map of key-value pairs, describing the metadata of a token.126 #[pallet::storage]200 #[pallet::storage]127 #[pallet::getter(fn token_properties)]201 #[pallet::getter(fn token_properties)]128 pub type TokenProperties<T: Config> = StorageNMap<202 pub type TokenProperties<T: Config> = StorageNMap<132 OnEmpty = up_data_structs::TokenProperties,206 OnEmpty = up_data_structs::TokenProperties,133 >;207 >;134208135 /// Scoped, auxiliary properties of a token, primarily used for on-chain operations.209 /// Custom data of a token that is serialized to bytes, 210 /// primarily reserved for on-chain operations, 211 /// normally obscured from the external users.212 /// 213 /// Auxiliary properties are slightly different from 214 /// usual [`TokenProperties`] due to an unlimited number 215 /// and separately stored and written-to key-value pairs.216 /// 217 /// Currently used to store RMRK data.136 #[pallet::storage]218 #[pallet::storage]137 #[pallet::getter(fn token_aux_property)]219 #[pallet::getter(fn token_aux_property)]138 pub type TokenAuxProperties<T: Config> = StorageNMap<220 pub type TokenAuxProperties<T: Config> = StorageNMap<171 QueryKind = ValueQuery,253 QueryKind = ValueQuery,172 >;254 >;173255174 /// Amount of tokens owned in a collection.256 /// Amount of tokens owned by an account in a collection.175 #[pallet::storage]257 #[pallet::storage]176 pub type AccountBalance<T: Config> = StorageNMap<258 pub type AccountBalance<T: Config> = StorageNMap<177 Key = (259 Key = (182 QueryKind = ValueQuery,264 QueryKind = ValueQuery,183 >;265 >;184266185 /// todo:doc267 /// Allowance set by a token owner for another user to perform one of certain transactions on a token.186 #[pallet::storage]268 #[pallet::storage]187 pub type Allowance<T: Config> = StorageNMap<269 pub type Allowance<T: Config> = StorageNMap<188 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),270 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),284}366}285367286impl<T: Config> Pallet<T> {368impl<T: Config> Pallet<T> {369 /// Get number of NFT tokens in collection.287 pub fn total_supply(collection: &NonfungibleHandle<T>) -> u32 {370 pub fn total_supply(collection: &NonfungibleHandle<T>) -> u32 {288 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)371 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)289 }372 }373374 /// Check that NFT token exists.375 ///376 /// - `token`: Token ID.290 pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {377 pub fn token_exists(collection: &NonfungibleHandle<T>, token: TokenId) -> bool {291 <TokenData<T>>::contains_key((collection.id, token))378 <TokenData<T>>::contains_key((collection.id, token))292 }379 }293380381 /// Set the token property with the scope.382 ///383 /// - `property`: Contains key-value pair.294 pub fn set_scoped_token_property(384 pub fn set_scoped_token_property(295 collection_id: CollectionId,385 collection_id: CollectionId,296 token_id: TokenId,386 token_id: TokenId,305 Ok(())395 Ok(())306 }396 }307397398 /// Batch operation to set multiple properties with the same scope.308 pub fn set_scoped_token_properties(399 pub fn set_scoped_token_properties(309 collection_id: CollectionId,400 collection_id: CollectionId,310 token_id: TokenId,401 token_id: TokenId,319 Ok(())410 Ok(())320 }411 }321412413 /// Add or edit auxiliary data for the property.414 ///415 /// - `f`: function that adds or edits auxiliary data.322 pub fn try_mutate_token_aux_property<R, E>(416 pub fn try_mutate_token_aux_property<R, E>(323 collection_id: CollectionId,417 collection_id: CollectionId,324 token_id: TokenId,418 token_id: TokenId,329 <TokenAuxProperties<T>>::try_mutate((collection_id, token_id, scope, key), f)423 <TokenAuxProperties<T>>::try_mutate((collection_id, token_id, scope, key), f)330 }424 }331425426 /// Remove auxiliary data for the property.332 pub fn remove_token_aux_property(427 pub fn remove_token_aux_property(333 collection_id: CollectionId,428 collection_id: CollectionId,334 token_id: TokenId,429 token_id: TokenId,338 <TokenAuxProperties<T>>::remove((collection_id, token_id, scope, key));433 <TokenAuxProperties<T>>::remove((collection_id, token_id, scope, key));339 }434 }340435436 /// Get all auxiliary data in a given scope.437 ///438 /// Returns iterator over Property Key - Data pairs.341 pub fn iterate_token_aux_properties(439 pub fn iterate_token_aux_properties(342 collection_id: CollectionId,440 collection_id: CollectionId,343 token_id: TokenId,441 token_id: TokenId,346 <TokenAuxProperties<T>>::iter_prefix((collection_id, token_id, scope))444 <TokenAuxProperties<T>>::iter_prefix((collection_id, token_id, scope))347 }445 }348446447 /// Get ID of the last minted token349 pub fn current_token_id(collection_id: CollectionId) -> TokenId {448 pub fn current_token_id(collection_id: CollectionId) -> TokenId {350 TokenId(<TokensMinted<T>>::get(collection_id))449 TokenId(<TokensMinted<T>>::get(collection_id))351 }450 }352}451}353452354// unchecked calls skips any permission checks453// unchecked calls skips any permission checks355impl<T: Config> Pallet<T> {454impl<T: Config> Pallet<T> {455 /// Create NFT collection456 ///457 /// `init_collection` will take non-refundable deposit for collection creation.458 ///459 /// - `data`: Contains settings for collection limits and permissions.356 pub fn init_collection(460 pub fn init_collection(357 owner: T::CrossAccountId,461 owner: T::CrossAccountId,358 data: CreateCollectionData<T::AccountId>,462 data: CreateCollectionData<T::AccountId>,361 <PalletCommon<T>>::init_collection(owner, data, is_external)465 <PalletCommon<T>>::init_collection(owner, data, is_external)362 }466 }467468 /// Destroy NFT collection469 ///470 /// `destroy_collection` will throw error if collection contains any tokens.471 /// Only owner can destroy collection.363 pub fn destroy_collection(472 pub fn destroy_collection(364 collection: NonfungibleHandle<T>,473 collection: NonfungibleHandle<T>,365 sender: &T::CrossAccountId,474 sender: &T::CrossAccountId,384 Ok(())493 Ok(())385 }494 }386495496 /// Burn NFT token497 ///498 /// `burn` removes `token` from the `collection`, from it's owner and from the parent token499 /// if the token is nested.500 /// Only the owner can `burn` the token. The `token` shouldn't have any nested tokens.501 /// Also removes all corresponding properties and auxiliary properties.502 ///503 /// - `token`: Token that should be burned504 /// - `collection`: Collection that contains the token387 pub fn burn(505 pub fn burn(388 collection: &NonfungibleHandle<T>,506 collection: &NonfungibleHandle<T>,389 sender: &T::CrossAccountId,507 sender: &T::CrossAccountId,453 Ok(())571 Ok(())454 }572 }455573574 /// Same as [`burn`] but burns all the tokens that are nested in the token first575 ///576 /// - `self_budget`: Limit for searching children in depth.577 /// - `breadth_budget`: Limit of breadth of searching children.578 ///579 /// [`burn`]: struct.Pallet.html#method.burn456 #[transactional]580 #[transactional]457 pub fn burn_recursively(581 pub fn burn_recursively(458 collection: &NonfungibleHandle<T>,582 collection: &NonfungibleHandle<T>,492 })616 })493 }617 }494618619 /// Batch operation to add, edit or remove properties for the token620 ///621 /// All affected properties should have mutable permission and sender should have622 /// permission to edit those properties.623 ///624 /// - `nesting_budget`: Limit for searching parents in depth to check ownership.625 /// - `is_token_create`: Indicates that method is called during token initialization.626 /// Allows to bypass ownership check.495 #[transactional]627 #[transactional]496 fn modify_token_properties(628 fn modify_token_properties(497 collection: &NonfungibleHandle<T>,629 collection: &NonfungibleHandle<T>,585 Ok(())717 Ok(())586 }718 }587719720 /// Batch operation to add or edit properties for the token721 ///722 /// Same as [`modify_token_properties`] but doesn't allow to remove properties723 ///724 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties588 pub fn set_token_properties(725 pub fn set_token_properties(589 collection: &NonfungibleHandle<T>,726 collection: &NonfungibleHandle<T>,590 sender: &T::CrossAccountId,727 sender: &T::CrossAccountId,603 )740 )604 }741 }605742743 /// Add or edit single property for the token744 ///745 /// Calls [`set_token_properties`] internally746 ///747 /// [`set_token_properties`]: struct.Pallet.html#method.set_token_properties606 pub fn set_token_property(748 pub fn set_token_property(607 collection: &NonfungibleHandle<T>,749 collection: &NonfungibleHandle<T>,608 sender: &T::CrossAccountId,750 sender: &T::CrossAccountId,622 )764 )623 }765 }624766767 /// Batch operation to remove properties from the token768 ///769 /// Same as [`modify_token_properties`] but doesn't allow to add or edit properties770 ///771 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties625 pub fn delete_token_properties(772 pub fn delete_token_properties(626 collection: &NonfungibleHandle<T>,773 collection: &NonfungibleHandle<T>,627 sender: &T::CrossAccountId,774 sender: &T::CrossAccountId,641 )788 )642 }789 }643790791 /// Remove single property from the token792 ///793 /// Calls [`delete_token_properties`] internally794 ///795 /// [`delete_token_properties`]: struct.Pallet.html#method.delete_token_properties644 pub fn delete_token_property(796 pub fn delete_token_property(645 collection: &NonfungibleHandle<T>,797 collection: &NonfungibleHandle<T>,646 sender: &T::CrossAccountId,798 sender: &T::CrossAccountId,657 )809 )658 }810 }659811812 /// Add or edit properties for the collection660 pub fn set_collection_properties(813 pub fn set_collection_properties(661 collection: &NonfungibleHandle<T>,814 collection: &NonfungibleHandle<T>,662 sender: &T::CrossAccountId,815 sender: &T::CrossAccountId,665 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)818 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)666 }819 }667820821 /// Remove properties from the collection668 pub fn delete_collection_properties(822 pub fn delete_collection_properties(669 collection: &CollectionHandle<T>,823 collection: &CollectionHandle<T>,670 sender: &T::CrossAccountId,824 sender: &T::CrossAccountId,673 <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)827 <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)674 }828 }675829830 /// Set property permissions for the token.831 ///832 /// Sender should be the owner or admin of token's collection.676 pub fn set_token_property_permissions(833 pub fn set_token_property_permissions(677 collection: &CollectionHandle<T>,834 collection: &CollectionHandle<T>,678 sender: &T::CrossAccountId,835 sender: &T::CrossAccountId,681 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)838 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)682 }839 }683840841 /// Set property permissions for the collection.842 ///843 /// Sender should be the owner or admin of the collection.684 pub fn set_property_permission(844 pub fn set_property_permission(685 collection: &CollectionHandle<T>,845 collection: &CollectionHandle<T>,686 sender: &T::CrossAccountId,846 sender: &T::CrossAccountId,689 <PalletCommon<T>>::set_property_permission(collection, sender, permission)849 <PalletCommon<T>>::set_property_permission(collection, sender, permission)690 }850 }691851852 /// Transfer NFT token from one account to another.853 ///854 /// `from` account stops being the owner and `to` account becomes the owner of the token.855 /// If `to` is token than `to` becomes owner of the token and the token become nested.856 /// Unnests token from previous parent if it was nested before.857 /// Removes allowance for the token if there was any.858 /// Throws if transfers aren't allowed for collection or if receiver reached token ownership limit.859 ///860 /// - `nesting_budget`: Limit for token nesting depth692 pub fn transfer(861 pub fn transfer(693 collection: &NonfungibleHandle<T>,862 collection: &NonfungibleHandle<T>,694 from: &T::CrossAccountId,863 from: &T::CrossAccountId,780 Ok(())949 Ok(())781 }950 }782951952 /// Batch operation to mint multiple NFT tokens.953 ///954 /// The sender should be the owner/admin of the collection or collection should be configured955 /// to allow public minting.956 /// Throws if amount of tokens reached it's limit for the collection or if caller reached957 /// token ownership limit.958 ///959 /// - `data`: Contains list of token properties and users who will become the owners of the960 /// corresponging tokens.961 /// - `nesting_budget`: Limit for token nesting depth783 pub fn create_multiple_items(962 pub fn create_multiple_items(784 collection: &NonfungibleHandle<T>,963 collection: &NonfungibleHandle<T>,785 sender: &T::CrossAccountId,964 sender: &T::CrossAccountId,964 }1143 }965 }1144 }96611451146 /// Set allowance for the spender to `transfer` or `burn` sender's token.1147 ///1148 /// - `token`: Token the spender is allowed to `transfer` or `burn`.967 pub fn set_allowance(1149 pub fn set_allowance(968 collection: &NonfungibleHandle<T>,1150 collection: &NonfungibleHandle<T>,969 sender: &T::CrossAccountId,1151 sender: &T::CrossAccountId,996 Ok(())1178 Ok(())997 }1179 }99811801181 /// Checks allowance for the spender to use the token.999 fn check_allowed(1182 fn check_allowed(1000 collection: &NonfungibleHandle<T>,1183 collection: &NonfungibleHandle<T>,1001 spender: &T::CrossAccountId,1184 spender: &T::CrossAccountId,1038 Ok(())1221 Ok(())1039 }1222 }104012231224 /// Transfer NFT token from one account to another.1225 ///1226 /// Same as the [`transfer`] but spender doesn't needs to be the owner of the token.1227 /// The owner should set allowance for the spender to transfer token.1228 ///1229 /// [`transfer`]: struct.Pallet.html#method.transfer1041 pub fn transfer_from(1230 pub fn transfer_from(1042 collection: &NonfungibleHandle<T>,1231 collection: &NonfungibleHandle<T>,1043 spender: &T::CrossAccountId,1232 spender: &T::CrossAccountId,1054 Self::transfer(collection, from, to, token, nesting_budget)1243 Self::transfer(collection, from, to, token, nesting_budget)1055 }1244 }105612451246 /// Burn NFT token for `from` account.1247 ///1248 /// Same as the [`burn`] but spender doesn't need to be an owner of the token. The owner should1249 /// set allowance for the spender to burn token.1250 ///1251 /// [`burn`]: struct.Pallet.html#method.burn1057 pub fn burn_from(1252 pub fn burn_from(1058 collection: &NonfungibleHandle<T>,1253 collection: &NonfungibleHandle<T>,1059 spender: &T::CrossAccountId,1254 spender: &T::CrossAccountId,1068 Self::burn(collection, from, token)1263 Self::burn(collection, from, token)1069 }1264 }107012651266 /// Check that `from` token could be nested in `under` token.1267 ///1071 pub fn check_nesting(1268 pub fn check_nesting(1072 handle: &NonfungibleHandle<T>,1269 handle: &NonfungibleHandle<T>,1073 sender: T::CrossAccountId,1270 sender: T::CrossAccountId,1137 .collect()1334 .collect()1138 }1335 }113913361337 /// Mint single NFT token.1338 ///1140 /// Delegated to `create_multiple_items`1339 /// Delegated to [`create_multiple_items`]1340 ///1341 /// [`create_multiple_items`]: struct.Pallet.html#method.create_multiple_items1141 pub fn create_item(1342 pub fn create_item(1142 collection: &NonfungibleHandle<T>,1343 collection: &NonfungibleHandle<T>,1143 sender: &T::CrossAccountId,1344 sender: &T::CrossAccountId,pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth535354// Selector: 4136937754// Selector: 4136937755contract TokenProperties is Dummy, ERC165 {55contract TokenProperties is Dummy, ERC165 {56 // @notice Set permissions for token property.57 // @dev Throws error if `msg.sender` is not admin or owner of the collection.58 // @param key Property key.59 // @param is_mutable Permission to mutate property.60 // @param collection_admin Permission to mutate property by collection admin if property is mutable.61 // @param token_owner Permission to mutate property by token owner if property is mutable.62 //56 // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa63 // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa57 function setTokenPropertyPermission(64 function setTokenPropertyPermission(58 string memory key,65 string memory key,68 dummy = 0;75 dummy = 0;69 }76 }707778 // @notice Set token property value.79 // @dev Throws error if `msg.sender` has no permission to edit the property.80 // @param tokenId ID of the token.81 // @param key Property key.82 // @param value Property value.83 //71 // Selector: setProperty(uint256,string,bytes) 1752d67b84 // Selector: setProperty(uint256,string,bytes) 1752d67b72 function setProperty(85 function setProperty(73 uint256 tokenId,86 uint256 tokenId,81 dummy = 0;94 dummy = 0;82 }95 }839697 // @notice Delete token property value.98 // @dev Throws error if `msg.sender` has no permission to edit the property.99 // @param tokenId ID of the token.100 // @param key Property key.101 //84 // Selector: deleteProperty(uint256,string) 066111d1102 // Selector: deleteProperty(uint256,string) 066111d185 function deleteProperty(uint256 tokenId, string memory key) public {103 function deleteProperty(uint256 tokenId, string memory key) public {86 require(false, stub_error);104 require(false, stub_error);89 dummy = 0;107 dummy = 0;90 }108 }91109110 // @notice Get token property value.92 // Throws error if key not found111 // @dev Throws error if key not found112 // @param tokenId ID of the token.113 // @param key Property key.114 // @return Property value bytes93 //115 //94 // Selector: property(uint256,string) 7228c327116 // Selector: property(uint256,string) 7228c32795 function property(uint256 tokenId, string memory key)117 function property(uint256 tokenId, string memory key)107129108// Selector: 42966c68130// Selector: 42966c68109contract ERC721Burnable is Dummy, ERC165 {131contract ERC721Burnable is Dummy, ERC165 {132 // @notice Burns a specific ERC721 token.133 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized134 // operator of the current owner.135 // @param tokenId The NFT to approve136 //110 // Selector: burn(uint256) 42966c68137 // Selector: burn(uint256) 42966c68111 function burn(uint256 tokenId) public {138 function burn(uint256 tokenId) public {112 require(false, stub_error);139 require(false, stub_error);117144118// Selector: 58800161145// Selector: 58800161119contract ERC721 is Dummy, ERC165, ERC721Events {146contract ERC721 is Dummy, ERC165, ERC721Events {147 // @notice Count all NFTs assigned to an owner148 // @dev NFTs assigned to the zero address are considered invalid, and this149 // function throws for queries about the zero address.150 // @param owner An address for whom to query the balance151 // @return The number of NFTs owned by `owner`, possibly zero152 //120 // Selector: balanceOf(address) 70a08231153 // Selector: balanceOf(address) 70a08231121 function balanceOf(address owner) public view returns (uint256) {154 function balanceOf(address owner) public view returns (uint256) {122 require(false, stub_error);155 require(false, stub_error);125 return 0;158 return 0;126 }159 }127160161 // @notice Find the owner of an NFT162 // @dev NFTs assigned to zero address are considered invalid, and queries163 // about them do throw.164 // @param tokenId The identifier for an NFT165 // @return The address of the owner of the NFT166 //128 // Selector: ownerOf(uint256) 6352211e167 // Selector: ownerOf(uint256) 6352211e129 function ownerOf(uint256 tokenId) public view returns (address) {168 function ownerOf(uint256 tokenId) public view returns (address) {130 require(false, stub_error);169 require(false, stub_error);133 return 0x0000000000000000000000000000000000000000;172 return 0x0000000000000000000000000000000000000000;134 }173 }135174136 // Not implemented175 // @dev Not implemented137 //176 //138 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672177 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672139 function safeTransferFromWithData(178 function safeTransferFromWithData(150 dummy = 0;189 dummy = 0;151 }190 }152191153 // Not implemented192 // @dev Not implemented154 //193 //155 // Selector: safeTransferFrom(address,address,uint256) 42842e0e194 // Selector: safeTransferFrom(address,address,uint256) 42842e0e156 function safeTransferFrom(195 function safeTransferFrom(165 dummy = 0;204 dummy = 0;166 }205 }167206207 // @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE208 // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE209 // THEY MAY BE PERMANENTLY LOST210 // @dev Throws unless `msg.sender` is the current owner or an authorized211 // operator for this NFT. Throws if `from` is not the current owner. Throws212 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.213 // @param from The current owner of the NFT214 // @param to The new owner215 // @param tokenId The NFT to transfer216 // @param _value Not used for an NFT217 //168 // Selector: transferFrom(address,address,uint256) 23b872dd218 // Selector: transferFrom(address,address,uint256) 23b872dd169 function transferFrom(219 function transferFrom(170 address from,220 address from,178 dummy = 0;228 dummy = 0;179 }229 }180230231 // @notice Set or reaffirm the approved address for an NFT232 // @dev The zero address indicates there is no approved address.233 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized234 // operator of the current owner.235 // @param approved The new approved NFT controller236 // @param tokenId The NFT to approve237 //181 // Selector: approve(address,uint256) 095ea7b3238 // Selector: approve(address,uint256) 095ea7b3182 function approve(address approved, uint256 tokenId) public {239 function approve(address approved, uint256 tokenId) public {183 require(false, stub_error);240 require(false, stub_error);186 dummy = 0;243 dummy = 0;187 }244 }188245189 // Not implemented246 // @dev Not implemented190 //247 //191 // Selector: setApprovalForAll(address,bool) a22cb465248 // Selector: setApprovalForAll(address,bool) a22cb465192 function setApprovalForAll(address operator, bool approved) public {249 function setApprovalForAll(address operator, bool approved) public {196 dummy = 0;253 dummy = 0;197 }254 }198255199 // Not implemented256 // @dev Not implemented200 //257 //201 // Selector: getApproved(uint256) 081812fc258 // Selector: getApproved(uint256) 081812fc202 function getApproved(uint256 tokenId) public view returns (address) {259 function getApproved(uint256 tokenId) public view returns (address) {206 return 0x0000000000000000000000000000000000000000;263 return 0x0000000000000000000000000000000000000000;207 }264 }208265209 // Not implemented266 // @dev Not implemented210 //267 //211 // Selector: isApprovedForAll(address,address) e985e9c5268 // Selector: isApprovedForAll(address,address) e985e9c5212 function isApprovedForAll(address owner, address operator)269 function isApprovedForAll(address owner, address operator)224281225// Selector: 5b5e139f282// Selector: 5b5e139f226contract ERC721Metadata is Dummy, ERC165 {283contract ERC721Metadata is Dummy, ERC165 {284 // @notice A descriptive name for a collection of NFTs in this contract285 //227 // Selector: name() 06fdde03286 // Selector: name() 06fdde03228 function name() public view returns (string memory) {287 function name() public view returns (string memory) {229 require(false, stub_error);288 require(false, stub_error);230 dummy;289 dummy;231 return "";290 return "";232 }291 }233292293 // @notice An abbreviated name for NFTs in this contract294 //234 // Selector: symbol() 95d89b41295 // Selector: symbol() 95d89b41235 function symbol() public view returns (string memory) {296 function symbol() public view returns (string memory) {236 require(false, stub_error);297 require(false, stub_error);237 dummy;298 dummy;238 return "";299 return "";239 }300 }240301302 // @notice A distinct Uniform Resource Identifier (URI) for a given asset.303 // @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC304 // 3986. The URI may point to a JSON file that conforms to the "ERC721305 // Metadata JSON Schema".241 // Returns token's const_metadata306 // @return token's const_metadata242 //307 //243 // Selector: tokenURI(uint256) c87b56dd308 // Selector: tokenURI(uint256) c87b56dd244 function tokenURI(uint256 tokenId) public view returns (string memory) {309 function tokenURI(uint256 tokenId) public view returns (string memory) {258 return false;323 return false;259 }324 }260325326 // @notice Function to mint token.261 // `token_id` should be obtained with `next_token_id` method,327 // @dev `tokenId` should be obtained with `nextTokenId` method,262 // unlike standard, you can't specify it manually328 // unlike standard, you can't specify it manually329 // @param to The new owner330 // @param tokenId ID of the minted NFT263 //331 //264 // Selector: mint(address,uint256) 40c10f19332 // Selector: mint(address,uint256) 40c10f19265 function mint(address to, uint256 tokenId) public returns (bool) {333 function mint(address to, uint256 tokenId) public returns (bool) {270 return false;338 return false;271 }339 }272340341 // @notice Function to mint token with the given tokenUri.273 // `token_id` should be obtained with `next_token_id` method,342 // @dev `tokenId` should be obtained with `nextTokenId` method,274 // unlike standard, you can't specify it manually343 // unlike standard, you can't specify it manually344 // @param to The new owner345 // @param tokenId ID of the minted NFT346 // @param tokenUri Token URI that would be stored in the NFT properties275 //347 //276 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f348 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f277 function mintWithTokenURI(349 function mintWithTokenURI(287 return false;359 return false;288 }360 }289361290 // Not implemented362 // @dev Not implemented291 //363 //292 // Selector: finishMinting() 7d64bcb4364 // Selector: finishMinting() 7d64bcb4293 function finishMinting() public returns (bool) {365 function finishMinting() public returns (bool) {299371300// Selector: 780e9d63372// Selector: 780e9d63301contract ERC721Enumerable is Dummy, ERC165 {373contract ERC721Enumerable is Dummy, ERC165 {374 // @notice Enumerate valid NFTs375 // @param index A counter less than `totalSupply()`376 // @return The token identifier for the `index`th NFT,377 // (sort order not specified)378 //302 // Selector: tokenByIndex(uint256) 4f6ccce7379 // Selector: tokenByIndex(uint256) 4f6ccce7303 function tokenByIndex(uint256 index) public view returns (uint256) {380 function tokenByIndex(uint256 index) public view returns (uint256) {304 require(false, stub_error);381 require(false, stub_error);307 return 0;384 return 0;308 }385 }309386310 // Not implemented387 // @dev Not implemented311 //388 //312 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59389 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59313 function tokenOfOwnerByIndex(address owner, uint256 index)390 function tokenOfOwnerByIndex(address owner, uint256 index)322 return 0;399 return 0;323 }400 }324401402 // @notice Count NFTs tracked by this contract403 // @return A count of valid NFTs tracked by this contract, where each one of404 // them has an assigned and queryable owner not equal to the zero address405 //325 // Selector: totalSupply() 18160ddd406 // Selector: totalSupply() 18160ddd326 function totalSupply() public view returns (uint256) {407 function totalSupply() public view returns (uint256) {327 require(false, stub_error);408 require(false, stub_error);332413333// Selector: 7d9262e6414// Selector: 7d9262e6334contract Collection is Dummy, ERC165 {415contract Collection is Dummy, ERC165 {416 // Set collection property.417 //418 // @param key Property key.419 // @param value Propery value.420 //335 // Selector: setCollectionProperty(string,bytes) 2f073f66421 // Selector: setCollectionProperty(string,bytes) 2f073f66336 function setCollectionProperty(string memory key, bytes memory value)422 function setCollectionProperty(string memory key, bytes memory value)337 public423 public342 dummy = 0;428 dummy = 0;343 }429 }344430431 // Delete collection property.432 //433 // @param key Property key.434 //345 // Selector: deleteCollectionProperty(string) 7b7debce435 // Selector: deleteCollectionProperty(string) 7b7debce346 function deleteCollectionProperty(string memory key) public {436 function deleteCollectionProperty(string memory key) public {347 require(false, stub_error);437 require(false, stub_error);348 key;438 key;349 dummy = 0;439 dummy = 0;350 }440 }351441442 // Get collection property.443 //352 // Throws error if key not found444 // @dev Throws error if key not found.445 //446 // @param key Property key.447 // @return bytes The property corresponding to the key.353 //448 //354 // Selector: collectionProperty(string) cf24fd6d449 // Selector: collectionProperty(string) cf24fd6d355 function collectionProperty(string memory key)450 function collectionProperty(string memory key)363 return hex"";458 return hex"";364 }459 }365460461 // Set the sponsor of the collection.462 //463 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.464 //465 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.466 //366 // Selector: setCollectionSponsor(address) 7623402e467 // Selector: setCollectionSponsor(address) 7623402e367 function setCollectionSponsor(address sponsor) public {468 function setCollectionSponsor(address sponsor) public {368 require(false, stub_error);469 require(false, stub_error);369 sponsor;470 sponsor;370 dummy = 0;471 dummy = 0;371 }472 }372473474 // Collection sponsorship confirmation.475 //476 // @dev After setting the sponsor for the collection, it must be confirmed with this function.477 //373 // Selector: confirmCollectionSponsorship() 3c50e97a478 // Selector: confirmCollectionSponsorship() 3c50e97a374 function confirmCollectionSponsorship() public {479 function confirmCollectionSponsorship() public {375 require(false, stub_error);480 require(false, stub_error);376 dummy = 0;481 dummy = 0;377 }482 }378483484 // Set limits for the collection.485 // @dev Throws error if limit not found.486 // @param limit Name of the limit. Valid names:487 // "accountTokenOwnershipLimit",488 // "sponsoredDataSize",489 // "sponsoredDataRateLimit",490 // "tokenLimit",491 // "sponsorTransferTimeout",492 // "sponsorApproveTimeout"493 // @param value Value of the limit.494 //379 // Selector: setCollectionLimit(string,uint32) 6a3841db495 // Selector: setCollectionLimit(string,uint32) 6a3841db380 function setCollectionLimit(string memory limit, uint32 value) public {496 function setCollectionLimit(string memory limit, uint32 value) public {381 require(false, stub_error);497 require(false, stub_error);384 dummy = 0;500 dummy = 0;385 }501 }386502503 // Set limits for the collection.504 // @dev Throws error if limit not found.505 // @param limit Name of the limit. Valid names:506 // "ownerCanTransfer",507 // "ownerCanDestroy",508 // "transfersEnabled"509 // @param value Value of the limit.510 //387 // Selector: setCollectionLimit(string,bool) 993b7fba511 // Selector: setCollectionLimit(string,bool) 993b7fba388 function setCollectionLimit(string memory limit, bool value) public {512 function setCollectionLimit(string memory limit, bool value) public {389 require(false, stub_error);513 require(false, stub_error);392 dummy = 0;516 dummy = 0;393 }517 }394518519 // Get contract address.520 //395 // Selector: contractAddress() f6b4dfb4521 // Selector: contractAddress() f6b4dfb4396 function contractAddress() public view returns (address) {522 function contractAddress() public view returns (address) {397 require(false, stub_error);523 require(false, stub_error);398 dummy;524 dummy;399 return 0x0000000000000000000000000000000000000000;525 return 0x0000000000000000000000000000000000000000;400 }526 }401527528 // Add collection admin by substrate address.529 // @param new_admin Substrate administrator address.530 //402 // Selector: addCollectionAdminSubstrate(uint256) 5730062b531 // Selector: addCollectionAdminSubstrate(uint256) 5730062b403 function addCollectionAdminSubstrate(uint256 newAdmin) public view {532 function addCollectionAdminSubstrate(uint256 newAdmin) public {404 require(false, stub_error);533 require(false, stub_error);405 newAdmin;534 newAdmin;406 dummy;535 dummy = 0;407 }536 }408537538 // Remove collection admin by substrate address.539 // @param admin Substrate administrator address.540 //409 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9541 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9410 function removeCollectionAdminSubstrate(uint256 newAdmin) public view {542 function removeCollectionAdminSubstrate(uint256 admin) public {411 require(false, stub_error);543 require(false, stub_error);412 newAdmin;544 admin;413 dummy;545 dummy = 0;414 }546 }415547548 // Add collection admin.549 // @param new_admin Address of the added administrator.550 //416 // Selector: addCollectionAdmin(address) 92e462c7551 // Selector: addCollectionAdmin(address) 92e462c7417 function addCollectionAdmin(address newAdmin) public view {552 function addCollectionAdmin(address newAdmin) public {418 require(false, stub_error);553 require(false, stub_error);419 newAdmin;554 newAdmin;420 dummy;555 dummy = 0;421 }556 }422557558 // Remove collection admin.559 //560 // @param new_admin Address of the removed administrator.561 //423 // Selector: removeCollectionAdmin(address) fafd7b42562 // Selector: removeCollectionAdmin(address) fafd7b42424 function removeCollectionAdmin(address admin) public view {563 function removeCollectionAdmin(address admin) public {425 require(false, stub_error);564 require(false, stub_error);426 admin;565 admin;427 dummy;566 dummy = 0;428 }567 }429568569 // Toggle accessibility of collection nesting.570 //571 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'572 //430 // Selector: setCollectionNesting(bool) 112d4586573 // Selector: setCollectionNesting(bool) 112d4586431 function setCollectionNesting(bool enable) public {574 function setCollectionNesting(bool enable) public {432 require(false, stub_error);575 require(false, stub_error);433 enable;576 enable;434 dummy = 0;577 dummy = 0;435 }578 }436579580 // Toggle accessibility of collection nesting.581 //582 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'583 // @param collections Addresses of collections that will be available for nesting.584 //437 // Selector: setCollectionNesting(bool,address[]) 64872396585 // Selector: setCollectionNesting(bool,address[]) 64872396438 function setCollectionNesting(bool enable, address[] memory collections)586 function setCollectionNesting(bool enable, address[] memory collections)439 public587 public444 dummy = 0;592 dummy = 0;445 }593 }446594595 // Set the collection access method.596 // @param mode Access mode597 // 0 for Normal598 // 1 for AllowList599 //447 // Selector: setCollectionAccess(uint8) 41835d4c600 // Selector: setCollectionAccess(uint8) 41835d4c448 function setCollectionAccess(uint8 mode) public {601 function setCollectionAccess(uint8 mode) public {449 require(false, stub_error);602 require(false, stub_error);450 mode;603 mode;451 dummy = 0;604 dummy = 0;452 }605 }453606607 // Add the user to the allowed list.608 //609 // @param user Address of a trusted user.610 //454 // Selector: addToCollectionAllowList(address) 67844fe6611 // Selector: addToCollectionAllowList(address) 67844fe6455 function addToCollectionAllowList(address user) public view {612 function addToCollectionAllowList(address user) public {456 require(false, stub_error);613 require(false, stub_error);457 user;614 user;458 dummy;615 dummy = 0;459 }616 }460617618 // Remove the user from the allowed list.619 //620 // @param user Address of a removed user.621 //461 // Selector: removeFromCollectionAllowList(address) 85c51acb622 // Selector: removeFromCollectionAllowList(address) 85c51acb462 function removeFromCollectionAllowList(address user) public view {623 function removeFromCollectionAllowList(address user) public {463 require(false, stub_error);624 require(false, stub_error);464 user;625 user;465 dummy;626 dummy = 0;466 }627 }467628629 // Switch permission for minting.630 //631 // @param mode Enable if "true".632 //468 // Selector: setCollectionMintMode(bool) 00018e84633 // Selector: setCollectionMintMode(bool) 00018e84469 function setCollectionMintMode(bool mode) public {634 function setCollectionMintMode(bool mode) public {470 require(false, stub_error);635 require(false, stub_error);475640476// Selector: d74d154f641// Selector: d74d154f477contract ERC721UniqueExtensions is Dummy, ERC165 {642contract ERC721UniqueExtensions is Dummy, ERC165 {643 // @notice Transfer ownership of an NFT644 // @dev Throws unless `msg.sender` is the current owner. Throws if `to`645 // is the zero address. Throws if `tokenId` is not a valid NFT.646 // @param to The new owner647 // @param tokenId The NFT to transfer648 // @param _value Not used for an NFT649 //478 // Selector: transfer(address,uint256) a9059cbb650 // Selector: transfer(address,uint256) a9059cbb479 function transfer(address to, uint256 tokenId) public {651 function transfer(address to, uint256 tokenId) public {480 require(false, stub_error);652 require(false, stub_error);483 dummy = 0;655 dummy = 0;484 }656 }485657658 // @notice Burns a specific ERC721 token.659 // @dev Throws unless `msg.sender` is the current owner or an authorized660 // operator for this NFT. Throws if `from` is not the current owner. Throws661 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.662 // @param from The current owner of the NFT663 // @param tokenId The NFT to transfer664 // @param _value Not used for an NFT665 //486 // Selector: burnFrom(address,uint256) 79cc6790666 // Selector: burnFrom(address,uint256) 79cc6790487 function burnFrom(address from, uint256 tokenId) public {667 function burnFrom(address from, uint256 tokenId) public {488 require(false, stub_error);668 require(false, stub_error);491 dummy = 0;671 dummy = 0;492 }672 }493673674 // @notice Returns next free NFT ID.675 //494 // Selector: nextTokenId() 75794a3c676 // Selector: nextTokenId() 75794a3c495 function nextTokenId() public view returns (uint256) {677 function nextTokenId() public view returns (uint256) {496 require(false, stub_error);678 require(false, stub_error);497 dummy;679 dummy;498 return 0;680 return 0;499 }681 }500682683 // @notice Function to mint multiple tokens.684 // @dev `tokenIds` should be an array of consecutive numbers and first number685 // should be obtained with `nextTokenId` method686 // @param to The new owner687 // @param tokenIds IDs of the minted NFTs688 //501 // Selector: mintBulk(address,uint256[]) 44a9945e689 // Selector: mintBulk(address,uint256[]) 44a9945e502 function mintBulk(address to, uint256[] memory tokenIds)690 function mintBulk(address to, uint256[] memory tokenIds)503 public691 public510 return false;698 return false;511 }699 }512700701 // @notice Function to mint multiple tokens with the given tokenUris.702 // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive703 // numbers and first number should be obtained with `nextTokenId` method704 // @param to The new owner705 // @param tokens array of pairs of token ID and token URI for minted tokens706 //513 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006707 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006514 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)708 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)515 public709 publicpallets/nonfungible/src/weights.rsdiffbeforeafterboth3//! Autogenerated weights for pallet_nonfungible3//! Autogenerated weights for pallet_nonfungible4//!4//!5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev6//! DATE: 2022-06-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`6//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 10247//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024889// Executed Command:9// Executed Command:56 // Storage: Nonfungible TokenData (r:0 w:1)56 // Storage: Nonfungible TokenData (r:0 w:1)57 // Storage: Nonfungible Owned (r:0 w:1)57 // Storage: Nonfungible Owned (r:0 w:1)58 fn create_item() -> Weight {58 fn create_item() -> Weight {59 (24_135_000 as Weight)59 (20_328_000 as Weight)60 .saturating_add(T::DbWeight::get().reads(2 as Weight))60 .saturating_add(T::DbWeight::get().reads(2 as Weight))61 .saturating_add(T::DbWeight::get().writes(4 as Weight))61 .saturating_add(T::DbWeight::get().writes(4 as Weight))62 }62 }65 // Storage: Nonfungible TokenData (r:0 w:4)65 // Storage: Nonfungible TokenData (r:0 w:4)66 // Storage: Nonfungible Owned (r:0 w:4)66 // Storage: Nonfungible Owned (r:0 w:4)67 fn create_multiple_items(b: u32, ) -> Weight {67 fn create_multiple_items(b: u32, ) -> Weight {68 (21_952_000 as Weight)68 (10_134_000 as Weight)69 // Standard Error: 5_00069 // Standard Error: 3_00070 .saturating_add((4_727_000 as Weight).saturating_mul(b as Weight))70 .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))71 .saturating_add(T::DbWeight::get().reads(2 as Weight))71 .saturating_add(T::DbWeight::get().reads(2 as Weight))72 .saturating_add(T::DbWeight::get().writes(2 as Weight))72 .saturating_add(T::DbWeight::get().writes(2 as Weight))73 .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))73 .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))77 // Storage: Nonfungible TokenData (r:0 w:4)77 // Storage: Nonfungible TokenData (r:0 w:4)78 // Storage: Nonfungible Owned (r:0 w:4)78 // Storage: Nonfungible Owned (r:0 w:4)79 fn create_multiple_items_ex(b: u32, ) -> Weight {79 fn create_multiple_items_ex(b: u32, ) -> Weight {80 (10_432_000 as Weight)80 (5_710_000 as Weight)81 // Standard Error: 6_00081 // Standard Error: 4_00082 .saturating_add((7_383_000 as Weight).saturating_mul(b as Weight))82 .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))83 .saturating_add(T::DbWeight::get().reads(1 as Weight))83 .saturating_add(T::DbWeight::get().reads(1 as Weight))84 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))84 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))85 .saturating_add(T::DbWeight::get().writes(1 as Weight))85 .saturating_add(T::DbWeight::get().writes(1 as Weight))93 // Storage: Nonfungible Owned (r:0 w:1)93 // Storage: Nonfungible Owned (r:0 w:1)94 // Storage: Nonfungible TokenProperties (r:0 w:1)94 // Storage: Nonfungible TokenProperties (r:0 w:1)95 fn burn_item() -> Weight {95 fn burn_item() -> Weight {96 (29_798_000 as Weight)96 (28_433_000 as Weight)97 .saturating_add(T::DbWeight::get().reads(5 as Weight))97 .saturating_add(T::DbWeight::get().reads(5 as Weight))98 .saturating_add(T::DbWeight::get().writes(5 as Weight))98 .saturating_add(T::DbWeight::get().writes(5 as Weight))99 }99 }105 // Storage: Nonfungible Owned (r:0 w:1)105 // Storage: Nonfungible Owned (r:0 w:1)106 // Storage: Nonfungible TokenProperties (r:0 w:1)106 // Storage: Nonfungible TokenProperties (r:0 w:1)107 fn burn_recursively_self_raw() -> Weight {107 fn burn_recursively_self_raw() -> Weight {108 (37_955_000 as Weight)108 (34_435_000 as Weight)109 .saturating_add(T::DbWeight::get().reads(5 as Weight))109 .saturating_add(T::DbWeight::get().reads(5 as Weight))110 .saturating_add(T::DbWeight::get().writes(5 as Weight))110 .saturating_add(T::DbWeight::get().writes(5 as Weight))111 }111 }119 // Storage: Common CollectionById (r:1 w:0)119 // Storage: Common CollectionById (r:1 w:0)120 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {120 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {121 (0 as Weight)121 (0 as Weight)122 // Standard Error: 1_349_000122 // Standard Error: 1_539_000123 .saturating_add((275_145_000 as Weight).saturating_mul(b as Weight))123 .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))124 .saturating_add(T::DbWeight::get().reads(7 as Weight))124 .saturating_add(T::DbWeight::get().reads(7 as Weight))125 .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))125 .saturating_add(T::DbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))126 .saturating_add(T::DbWeight::get().writes(6 as Weight))126 .saturating_add(T::DbWeight::get().writes(6 as Weight))131 // Storage: Nonfungible Allowance (r:1 w:0)131 // Storage: Nonfungible Allowance (r:1 w:0)132 // Storage: Nonfungible Owned (r:0 w:2)132 // Storage: Nonfungible Owned (r:0 w:2)133 fn transfer() -> Weight {133 fn transfer() -> Weight {134 (27_867_000 as Weight)134 (24_376_000 as Weight)135 .saturating_add(T::DbWeight::get().reads(4 as Weight))135 .saturating_add(T::DbWeight::get().reads(4 as Weight))136 .saturating_add(T::DbWeight::get().writes(5 as Weight))136 .saturating_add(T::DbWeight::get().writes(5 as Weight))137 }137 }138 // Storage: Nonfungible TokenData (r:1 w:0)138 // Storage: Nonfungible TokenData (r:1 w:0)139 // Storage: Nonfungible Allowance (r:1 w:1)139 // Storage: Nonfungible Allowance (r:1 w:1)140 fn approve() -> Weight {140 fn approve() -> Weight {141 (18_824_000 as Weight)141 (15_890_000 as Weight)142 .saturating_add(T::DbWeight::get().reads(2 as Weight))142 .saturating_add(T::DbWeight::get().reads(2 as Weight))143 .saturating_add(T::DbWeight::get().writes(1 as Weight))143 .saturating_add(T::DbWeight::get().writes(1 as Weight))144 }144 }147 // Storage: Nonfungible AccountBalance (r:2 w:2)147 // Storage: Nonfungible AccountBalance (r:2 w:2)148 // Storage: Nonfungible Owned (r:0 w:2)148 // Storage: Nonfungible Owned (r:0 w:2)149 fn transfer_from() -> Weight {149 fn transfer_from() -> Weight {150 (32_879_000 as Weight)150 (28_634_000 as Weight)151 .saturating_add(T::DbWeight::get().reads(4 as Weight))151 .saturating_add(T::DbWeight::get().reads(4 as Weight))152 .saturating_add(T::DbWeight::get().writes(6 as Weight))152 .saturating_add(T::DbWeight::get().writes(6 as Weight))153 }153 }159 // Storage: Nonfungible Owned (r:0 w:1)159 // Storage: Nonfungible Owned (r:0 w:1)160 // Storage: Nonfungible TokenProperties (r:0 w:1)160 // Storage: Nonfungible TokenProperties (r:0 w:1)161 fn burn_from() -> Weight {161 fn burn_from() -> Weight {162 (37_061_000 as Weight)162 (32_201_000 as Weight)163 .saturating_add(T::DbWeight::get().reads(5 as Weight))163 .saturating_add(T::DbWeight::get().reads(5 as Weight))164 .saturating_add(T::DbWeight::get().writes(6 as Weight))164 .saturating_add(T::DbWeight::get().writes(6 as Weight))165 }165 }166 // Storage: Common CollectionPropertyPermissions (r:1 w:1)166 // Storage: Common CollectionPropertyPermissions (r:1 w:1)167 fn set_token_property_permissions(b: u32, ) -> Weight {167 fn set_token_property_permissions(b: u32, ) -> Weight {168 (0 as Weight)168 (0 as Weight)169 // Standard Error: 57_000169 // Standard Error: 57_000170 .saturating_add((15_149_000 as Weight).saturating_mul(b as Weight))170 .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))171 .saturating_add(T::DbWeight::get().reads(1 as Weight))171 .saturating_add(T::DbWeight::get().reads(1 as Weight))172 .saturating_add(T::DbWeight::get().writes(1 as Weight))172 .saturating_add(T::DbWeight::get().writes(1 as Weight))173 }173 }174 // Storage: Common CollectionPropertyPermissions (r:1 w:0)174 // Storage: Common CollectionPropertyPermissions (r:1 w:0)175 // Storage: Nonfungible TokenData (r:1 w:0)176 // Storage: Nonfungible TokenProperties (r:1 w:1)175 // Storage: Nonfungible TokenProperties (r:1 w:1)177 fn set_token_properties(b: u32, ) -> Weight {176 fn set_token_properties(b: u32, ) -> Weight {178 (0 as Weight)177 (0 as Weight)179 // Standard Error: 2_278_000178 // Standard Error: 1_648_000180 .saturating_add((409_613_000 as Weight).saturating_mul(b as Weight))179 .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))181 .saturating_add(T::DbWeight::get().reads(3 as Weight))180 .saturating_add(T::DbWeight::get().reads(2 as Weight))182 .saturating_add(T::DbWeight::get().writes(1 as Weight))181 .saturating_add(T::DbWeight::get().writes(1 as Weight))183 }182 }184 // Storage: Common CollectionPropertyPermissions (r:1 w:0)183 // Storage: Common CollectionPropertyPermissions (r:1 w:0)185 // Storage: Nonfungible TokenData (r:1 w:0)186 // Storage: Nonfungible TokenProperties (r:1 w:1)184 // Storage: Nonfungible TokenProperties (r:1 w:1)187 fn delete_token_properties(b: u32, ) -> Weight {185 fn delete_token_properties(b: u32, ) -> Weight {188 (0 as Weight)186 (0 as Weight)189 // Standard Error: 2_234_000187 // Standard Error: 1_632_000190 .saturating_add((408_185_000 as Weight).saturating_mul(b as Weight))188 .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))191 .saturating_add(T::DbWeight::get().reads(3 as Weight))189 .saturating_add(T::DbWeight::get().reads(2 as Weight))192 .saturating_add(T::DbWeight::get().writes(1 as Weight))190 .saturating_add(T::DbWeight::get().writes(1 as Weight))193 }191 }194}192}200 // Storage: Nonfungible TokenData (r:0 w:1)198 // Storage: Nonfungible TokenData (r:0 w:1)201 // Storage: Nonfungible Owned (r:0 w:1)199 // Storage: Nonfungible Owned (r:0 w:1)202 fn create_item() -> Weight {200 fn create_item() -> Weight {203 (24_135_000 as Weight)201 (20_328_000 as Weight)204 .saturating_add(RocksDbWeight::get().reads(2 as Weight))202 .saturating_add(RocksDbWeight::get().reads(2 as Weight))205 .saturating_add(RocksDbWeight::get().writes(4 as Weight))203 .saturating_add(RocksDbWeight::get().writes(4 as Weight))206 }204 }209 // Storage: Nonfungible TokenData (r:0 w:4)207 // Storage: Nonfungible TokenData (r:0 w:4)210 // Storage: Nonfungible Owned (r:0 w:4)208 // Storage: Nonfungible Owned (r:0 w:4)211 fn create_multiple_items(b: u32, ) -> Weight {209 fn create_multiple_items(b: u32, ) -> Weight {212 (21_952_000 as Weight)210 (10_134_000 as Weight)213 // Standard Error: 5_000211 // Standard Error: 3_000214 .saturating_add((4_727_000 as Weight).saturating_mul(b as Weight))212 .saturating_add((4_927_000 as Weight).saturating_mul(b as Weight))215 .saturating_add(RocksDbWeight::get().reads(2 as Weight))213 .saturating_add(RocksDbWeight::get().reads(2 as Weight))216 .saturating_add(RocksDbWeight::get().writes(2 as Weight))214 .saturating_add(RocksDbWeight::get().writes(2 as Weight))217 .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))215 .saturating_add(RocksDbWeight::get().writes((2 as Weight).saturating_mul(b as Weight)))221 // Storage: Nonfungible TokenData (r:0 w:4)219 // Storage: Nonfungible TokenData (r:0 w:4)222 // Storage: Nonfungible Owned (r:0 w:4)220 // Storage: Nonfungible Owned (r:0 w:4)223 fn create_multiple_items_ex(b: u32, ) -> Weight {221 fn create_multiple_items_ex(b: u32, ) -> Weight {224 (10_432_000 as Weight)222 (5_710_000 as Weight)225 // Standard Error: 6_000223 // Standard Error: 4_000226 .saturating_add((7_383_000 as Weight).saturating_mul(b as Weight))224 .saturating_add((7_578_000 as Weight).saturating_mul(b as Weight))227 .saturating_add(RocksDbWeight::get().reads(1 as Weight))225 .saturating_add(RocksDbWeight::get().reads(1 as Weight))228 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))226 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))229 .saturating_add(RocksDbWeight::get().writes(1 as Weight))227 .saturating_add(RocksDbWeight::get().writes(1 as Weight))237 // Storage: Nonfungible Owned (r:0 w:1)235 // Storage: Nonfungible Owned (r:0 w:1)238 // Storage: Nonfungible TokenProperties (r:0 w:1)236 // Storage: Nonfungible TokenProperties (r:0 w:1)239 fn burn_item() -> Weight {237 fn burn_item() -> Weight {240 (29_798_000 as Weight)238 (28_433_000 as Weight)241 .saturating_add(RocksDbWeight::get().reads(5 as Weight))239 .saturating_add(RocksDbWeight::get().reads(5 as Weight))242 .saturating_add(RocksDbWeight::get().writes(5 as Weight))240 .saturating_add(RocksDbWeight::get().writes(5 as Weight))243 }241 }249 // Storage: Nonfungible Owned (r:0 w:1)247 // Storage: Nonfungible Owned (r:0 w:1)250 // Storage: Nonfungible TokenProperties (r:0 w:1)248 // Storage: Nonfungible TokenProperties (r:0 w:1)251 fn burn_recursively_self_raw() -> Weight {249 fn burn_recursively_self_raw() -> Weight {252 (37_955_000 as Weight)250 (34_435_000 as Weight)253 .saturating_add(RocksDbWeight::get().reads(5 as Weight))251 .saturating_add(RocksDbWeight::get().reads(5 as Weight))254 .saturating_add(RocksDbWeight::get().writes(5 as Weight))252 .saturating_add(RocksDbWeight::get().writes(5 as Weight))255 }253 }263 // Storage: Common CollectionById (r:1 w:0)261 // Storage: Common CollectionById (r:1 w:0)264 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {262 fn burn_recursively_breadth_plus_self_plus_self_per_each_raw(b: u32, ) -> Weight {265 (0 as Weight)263 (0 as Weight)266 // Standard Error: 1_349_000264 // Standard Error: 1_539_000267 .saturating_add((275_145_000 as Weight).saturating_mul(b as Weight))265 .saturating_add((304_456_000 as Weight).saturating_mul(b as Weight))268 .saturating_add(RocksDbWeight::get().reads(7 as Weight))266 .saturating_add(RocksDbWeight::get().reads(7 as Weight))269 .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))267 .saturating_add(RocksDbWeight::get().reads((4 as Weight).saturating_mul(b as Weight)))270 .saturating_add(RocksDbWeight::get().writes(6 as Weight))268 .saturating_add(RocksDbWeight::get().writes(6 as Weight))275 // Storage: Nonfungible Allowance (r:1 w:0)273 // Storage: Nonfungible Allowance (r:1 w:0)276 // Storage: Nonfungible Owned (r:0 w:2)274 // Storage: Nonfungible Owned (r:0 w:2)277 fn transfer() -> Weight {275 fn transfer() -> Weight {278 (27_867_000 as Weight)276 (24_376_000 as Weight)279 .saturating_add(RocksDbWeight::get().reads(4 as Weight))277 .saturating_add(RocksDbWeight::get().reads(4 as Weight))280 .saturating_add(RocksDbWeight::get().writes(5 as Weight))278 .saturating_add(RocksDbWeight::get().writes(5 as Weight))281 }279 }282 // Storage: Nonfungible TokenData (r:1 w:0)280 // Storage: Nonfungible TokenData (r:1 w:0)283 // Storage: Nonfungible Allowance (r:1 w:1)281 // Storage: Nonfungible Allowance (r:1 w:1)284 fn approve() -> Weight {282 fn approve() -> Weight {285 (18_824_000 as Weight)283 (15_890_000 as Weight)286 .saturating_add(RocksDbWeight::get().reads(2 as Weight))284 .saturating_add(RocksDbWeight::get().reads(2 as Weight))287 .saturating_add(RocksDbWeight::get().writes(1 as Weight))285 .saturating_add(RocksDbWeight::get().writes(1 as Weight))288 }286 }291 // Storage: Nonfungible AccountBalance (r:2 w:2)289 // Storage: Nonfungible AccountBalance (r:2 w:2)292 // Storage: Nonfungible Owned (r:0 w:2)290 // Storage: Nonfungible Owned (r:0 w:2)293 fn transfer_from() -> Weight {291 fn transfer_from() -> Weight {294 (32_879_000 as Weight)292 (28_634_000 as Weight)295 .saturating_add(RocksDbWeight::get().reads(4 as Weight))293 .saturating_add(RocksDbWeight::get().reads(4 as Weight))296 .saturating_add(RocksDbWeight::get().writes(6 as Weight))294 .saturating_add(RocksDbWeight::get().writes(6 as Weight))297 }295 }303 // Storage: Nonfungible Owned (r:0 w:1)301 // Storage: Nonfungible Owned (r:0 w:1)304 // Storage: Nonfungible TokenProperties (r:0 w:1)302 // Storage: Nonfungible TokenProperties (r:0 w:1)305 fn burn_from() -> Weight {303 fn burn_from() -> Weight {306 (37_061_000 as Weight)304 (32_201_000 as Weight)307 .saturating_add(RocksDbWeight::get().reads(5 as Weight))305 .saturating_add(RocksDbWeight::get().reads(5 as Weight))308 .saturating_add(RocksDbWeight::get().writes(6 as Weight))306 .saturating_add(RocksDbWeight::get().writes(6 as Weight))309 }307 }310 // Storage: Common CollectionPropertyPermissions (r:1 w:1)308 // Storage: Common CollectionPropertyPermissions (r:1 w:1)311 fn set_token_property_permissions(b: u32, ) -> Weight {309 fn set_token_property_permissions(b: u32, ) -> Weight {312 (0 as Weight)310 (0 as Weight)313 // Standard Error: 57_000311 // Standard Error: 57_000314 .saturating_add((15_149_000 as Weight).saturating_mul(b as Weight))312 .saturating_add((15_232_000 as Weight).saturating_mul(b as Weight))315 .saturating_add(RocksDbWeight::get().reads(1 as Weight))313 .saturating_add(RocksDbWeight::get().reads(1 as Weight))316 .saturating_add(RocksDbWeight::get().writes(1 as Weight))314 .saturating_add(RocksDbWeight::get().writes(1 as Weight))317 }315 }318 // Storage: Common CollectionPropertyPermissions (r:1 w:0)316 // Storage: Common CollectionPropertyPermissions (r:1 w:0)319 // Storage: Nonfungible TokenData (r:1 w:0)320 // Storage: Nonfungible TokenProperties (r:1 w:1)317 // Storage: Nonfungible TokenProperties (r:1 w:1)321 fn set_token_properties(b: u32, ) -> Weight {318 fn set_token_properties(b: u32, ) -> Weight {322 (0 as Weight)319 (0 as Weight)323 // Standard Error: 2_278_000320 // Standard Error: 1_648_000324 .saturating_add((409_613_000 as Weight).saturating_mul(b as Weight))321 .saturating_add((288_654_000 as Weight).saturating_mul(b as Weight))325 .saturating_add(RocksDbWeight::get().reads(3 as Weight))322 .saturating_add(RocksDbWeight::get().reads(2 as Weight))326 .saturating_add(RocksDbWeight::get().writes(1 as Weight))323 .saturating_add(RocksDbWeight::get().writes(1 as Weight))327 }324 }328 // Storage: Common CollectionPropertyPermissions (r:1 w:0)325 // Storage: Common CollectionPropertyPermissions (r:1 w:0)329 // Storage: Nonfungible TokenData (r:1 w:0)330 // Storage: Nonfungible TokenProperties (r:1 w:1)326 // Storage: Nonfungible TokenProperties (r:1 w:1)331 fn delete_token_properties(b: u32, ) -> Weight {327 fn delete_token_properties(b: u32, ) -> Weight {332 (0 as Weight)328 (0 as Weight)333 // Standard Error: 2_234_000329 // Standard Error: 1_632_000334 .saturating_add((408_185_000 as Weight).saturating_mul(b as Weight))330 .saturating_add((289_190_000 as Weight).saturating_mul(b as Weight))335 .saturating_add(RocksDbWeight::get().reads(3 as Weight))331 .saturating_add(RocksDbWeight::get().reads(2 as Weight))336 .saturating_add(RocksDbWeight::get().writes(1 as Weight))332 .saturating_add(RocksDbWeight::get().writes(1 as Weight))337 }333 }338}334}pallets/refungible/CHANGELOG.mddiffbeforeafterbothno changes
pallets/refungible/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "pallet-refungible"2name = "pallet-refungible"3version = "0.1.0"3version = "0.1.2"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"6611version = '3.1.2'11version = '3.1.2'121213[dependencies]13[dependencies]14evm-coder = { default-features = false, path = '../../crates/evm-coder' }15pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }16pallet-common = { default-features = false, path = '../common' }17pallet-structure = { default-features = false, path = '../structure' }18struct-versioning = { path = "../../crates/struct-versioning" }19up-data-structs = { default-features = false, path = '../../primitives/data-structs' }2021ethereum = { version = "0.12.0", default-features = false }22scale-info = { version = "2.0.1", default-features = false, features = ["derive",] }2324frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }14frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }25frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }15frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }26frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }27pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }28sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }16sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }29sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }17sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }30sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }18sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }19pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.24" }20pallet-common = { default-features = false, path = '../common' }21pallet-structure = { default-features = false, path = '../structure' }22up-data-structs = { default-features = false, path = '../../primitives/data-structs' }23frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24" }24scale-info = { version = "2.0.1", default-features = false, features = [25 "derive",26] }27struct-versioning = { path = "../../crates/struct-versioning" }283129[features]32[features]30default = ["std"]33default = ["std"]31std = [34std = [35 "ethereum/std",36 "evm-coder/std",37 'frame-benchmarking/std',32 "frame-support/std",38 "frame-support/std",33 "frame-system/std",39 "frame-system/std",34 "sp-runtime/std",40 "pallet-common/std",35 "sp-std/std",41 "pallet-evm/std",36 "up-data-structs/std",37 "pallet-common/std",42 "pallet-evm-coder-substrate/std",38 "pallet-structure/std",43 "pallet-structure/std",39 'frame-benchmarking/std',44 "sp-runtime/std",40 "pallet-evm/std",45 "sp-std/std",46 "up-data-structs/std",41]47]42runtime-benchmarks = [48runtime-benchmarks = [43 'frame-benchmarking',49 'frame-benchmarking',44 'frame-support/runtime-benchmarks',50 'frame-support/runtime-benchmarks',45 'frame-system/runtime-benchmarks',51 'frame-system/runtime-benchmarks',52 'up-data-structs/runtime-benchmarks',46]53]4754pallets/refungible/Changelog.mddiffbeforeafterbothno changes
pallets/refungible/src/benchmarking.rsdiffbeforeafterboth18use crate::{Pallet, Config, RefungibleHandle};18use crate::{Pallet, Config, RefungibleHandle};191920use sp_std::prelude::*;20use sp_std::prelude::*;21use pallet_common::benchmarking::{create_collection_raw, create_data};21use pallet_common::benchmarking::{create_collection_raw, property_key, property_value, create_data};22use frame_benchmarking::{benchmarks, account};22use frame_benchmarking::{benchmarks, account};23use up_data_structs::{CollectionMode, MAX_ITEMS_PER_BATCH, CUSTOM_DATA_LIMIT, budget::Unlimited};23use up_data_structs::{24 CollectionMode, MAX_ITEMS_PER_BATCH, MAX_PROPERTIES_PER_ITEM, CUSTOM_DATA_LIMIT,25 budget::Unlimited,26};24use pallet_common::bench_init;27use pallet_common::bench_init;25use core::convert::TryInto;28use core::convert::TryInto;38 .collect::<BTreeMap<_, _>>()41 .collect::<BTreeMap<_, _>>()39 .try_into()42 .try_into()40 .unwrap(),43 .unwrap(),44 properties: Default::default(),41 }45 }42}46}43fn create_max_item<T: Config>(47fn create_max_item<T: Config>(204 <Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;208 <Pallet<T>>::set_allowance(&collection, &sender, &burner, item, 200)?;205 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}209 }: {<Pallet<T>>::burn_from(&collection, &burner, &sender, item, 200, &Unlimited)?}210211 set_token_property_permissions {212 let b in 0..MAX_PROPERTIES_PER_ITEM;213 bench_init!{214 owner: sub; collection: collection(owner);215 owner: cross_from_sub;216 };217 let perms = (0..b).map(|k| PropertyKeyPermission {218 key: property_key(k as usize),219 permission: PropertyPermission {220 mutable: false,221 collection_admin: false,222 token_owner: false,223 },224 }).collect::<Vec<_>>();225 }: {<Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?}226227 set_token_properties {228 let b in 0..MAX_PROPERTIES_PER_ITEM;229 bench_init!{230 owner: sub; collection: collection(owner);231 owner: cross_from_sub;232 };233 let perms = (0..b).map(|k| PropertyKeyPermission {234 key: property_key(k as usize),235 permission: PropertyPermission {236 mutable: false,237 collection_admin: true,238 token_owner: true,239 },240 }).collect::<Vec<_>>();241 <Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;242 let props = (0..b).map(|k| Property {243 key: property_key(k as usize),244 value: property_value(),245 }).collect::<Vec<_>>();246 let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;247 }: {<Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?}248249 delete_token_properties {250 let b in 0..MAX_PROPERTIES_PER_ITEM;251 bench_init!{252 owner: sub; collection: collection(owner);253 owner: cross_from_sub;254 };255 let perms = (0..b).map(|k| PropertyKeyPermission {256 key: property_key(k as usize),257 permission: PropertyPermission {258 mutable: true,259 collection_admin: true,260 token_owner: true,261 },262 }).collect::<Vec<_>>();263 <Pallet<T>>::set_token_property_permissions(&collection, &owner, perms)?;264 let props = (0..b).map(|k| Property {265 key: property_key(k as usize),266 value: property_value(),267 }).collect::<Vec<_>>();268 let item = create_max_item(&collection, &owner, [(owner.clone(), 200)])?;269 <Pallet<T>>::set_token_properties(&collection, &owner, item, props.into_iter(), false, &Unlimited)?;270 let to_delete = (0..b).map(|k| property_key(k as usize)).collect::<Vec<_>>();271 }: {<Pallet<T>>::delete_token_properties(&collection, &owner, item, to_delete.into_iter(), &Unlimited)?}206272207 repartition_item {273 repartition_item {208 bench_init!{274 bench_init!{pallets/refungible/src/common.rsdiffbeforeafterboth20use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};20use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, fail, weights::Weight, traits::Get};21use up_data_structs::{21use up_data_structs::{22 CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,22 CollectionId, TokenId, CreateItemExData, CreateRefungibleExData, budget::Budget, Property,23 PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData,23 PropertyKey, PropertyValue, PropertyKeyPermission, CreateItemData, CollectionPropertiesVec,24};24};25use pallet_common::{CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight};25use pallet_common::{26 CommonCollectionOperations, CommonWeightInfo, RefungibleExtensions, with_weight,27 weights::WeightInfo as _,28};26use pallet_structure::Error as StructureError;29use pallet_structure::Error as StructureError;27use sp_runtime::{DispatchError};30use sp_runtime::{DispatchError};41 };44 };42}45}4647fn properties_weight<T: Config>(properties: &CollectionPropertiesVec) -> u64 {48 if properties.len() > 0 {49 <CommonWeights<T>>::set_token_properties(properties.len() as u32)50 } else {51 052 }53}435444pub struct CommonWeights<T: Config>(PhantomData<T>);55pub struct CommonWeights<T: Config>(PhantomData<T>);45impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {56impl<T: Config> CommonWeightInfo<T::CrossAccountId> for CommonWeights<T> {48 }59 }496050 fn create_multiple_items(data: &[CreateItemData]) -> Weight {61 fn create_multiple_items(data: &[CreateItemData]) -> Weight {51 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32)62 <SelfWeightOf<T>>::create_multiple_items(data.len() as u32).saturating_add(63 data.iter()64 .map(|data| match data {65 CreateItemData::ReFungible(rft_data) => {66 properties_weight::<T>(&rft_data.properties)67 }68 _ => 0,69 })70 .fold(0, |a, b| a.saturating_add(b)),71 )52 }72 }537354 fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {74 fn create_multiple_items_ex(call: &CreateItemExData<T::CrossAccountId>) -> Weight {55 match call {75 match call {56 CreateItemExData::RefungibleMultipleOwners(i) => {76 CreateItemExData::RefungibleMultipleOwners(i) => {57 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)77 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_owners(i.users.len() as u32)78 .saturating_add(properties_weight::<T>(&i.properties))58 }79 }59 CreateItemExData::RefungibleMultipleItems(i) => {80 CreateItemExData::RefungibleMultipleItems(i) => {60 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)81 <SelfWeightOf<T>>::create_multiple_items_ex_multiple_items(i.len() as u32)82 .saturating_add(83 i.iter()84 .map(|d| properties_weight::<T>(&d.properties))85 .fold(0, |a, b| a.saturating_add(b)),86 )61 }87 }62 _ => 0,88 _ => 0,63 }89 }67 max_weight_of!(burn_item_partial(), burn_item_fully())93 max_weight_of!(burn_item_partial(), burn_item_fully())68 }94 }699570 fn set_collection_properties(_amount: u32) -> Weight {96 fn set_collection_properties(amount: u32) -> Weight {71 // Error97 <pallet_common::SelfWeightOf<T>>::set_collection_properties(amount)72 073 }98 }749975 fn delete_collection_properties(_amount: u32) -> Weight {100 fn delete_collection_properties(amount: u32) -> Weight {76 // Error101 <pallet_common::SelfWeightOf<T>>::delete_collection_properties(amount)77 078 }102 }7910380 fn set_token_properties(_amount: u32) -> Weight {104 fn set_token_properties(amount: u32) -> Weight {81 // Error105 <SelfWeightOf<T>>::set_token_properties(amount)82 083 }106 }8410785 fn delete_token_properties(_amount: u32) -> Weight {108 fn delete_token_properties(amount: u32) -> Weight {86 // Error109 <SelfWeightOf<T>>::delete_token_properties(amount)87 088 }110 }8911190 fn set_token_property_permissions(_amount: u32) -> Weight {112 fn set_token_property_permissions(amount: u32) -> Weight {91 // Error113 <SelfWeightOf<T>>::set_token_property_permissions(amount)92 093 }114 }9411595 fn transfer() -> Weight {116 fn transfer() -> Weight {140 out.insert(to.clone(), data.pieces);161 out.insert(to.clone(), data.pieces);141 out.try_into().expect("limit > 0")162 out.try_into().expect("limit > 0")142 },163 },164 properties: data.properties,143 }),165 }),144 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),166 _ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),145 }167 }146}168}147169170/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete171/// methods and adds weight info.148impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {172impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {149 fn create_item(173 fn create_item(150 &self,174 &self,295319296 fn set_collection_properties(320 fn set_collection_properties(297 &self,321 &self,298 _sender: T::CrossAccountId,322 sender: T::CrossAccountId,299 _property: Vec<Property>,323 properties: Vec<Property>,300 ) -> DispatchResultWithPostInfo {324 ) -> DispatchResultWithPostInfo {325 let weight = <CommonWeights<T>>::set_collection_properties(properties.len() as u32);326301 fail!(<Error<T>>::SettingPropertiesNotAllowed)327 with_weight(328 <Pallet<T>>::set_collection_properties(self, &sender, properties),329 weight,330 )302 }331 }303332304 fn delete_collection_properties(333 fn delete_collection_properties(305 &self,334 &self,306 _sender: &T::CrossAccountId,335 sender: &T::CrossAccountId,307 _property_keys: Vec<PropertyKey>,336 property_keys: Vec<PropertyKey>,308 ) -> DispatchResultWithPostInfo {337 ) -> DispatchResultWithPostInfo {338 let weight = <CommonWeights<T>>::delete_collection_properties(property_keys.len() as u32);339309 fail!(<Error<T>>::SettingPropertiesNotAllowed)340 with_weight(341 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),342 weight,343 )310 }344 }311345312 fn set_token_properties(346 fn set_token_properties(313 &self,347 &self,314 _sender: T::CrossAccountId,348 sender: T::CrossAccountId,315 _token_id: TokenId,349 token_id: TokenId,316 _property: Vec<Property>,350 properties: Vec<Property>,317 _nesting_budget: &dyn Budget,351 nesting_budget: &dyn Budget,318 ) -> DispatchResultWithPostInfo {352 ) -> DispatchResultWithPostInfo {353 let weight = <CommonWeights<T>>::set_token_properties(properties.len() as u32);354319 fail!(<Error<T>>::SettingPropertiesNotAllowed)355 with_weight(356 <Pallet<T>>::set_token_properties(357 self,358 &sender,359 token_id,360 properties.into_iter(),361 false,362 nesting_budget,363 ),364 weight,365 )320 }366 }321367322 fn set_token_property_permissions(368 fn set_token_property_permissions(323 &self,369 &self,324 _sender: &T::CrossAccountId,370 sender: &T::CrossAccountId,325 _property_permissions: Vec<PropertyKeyPermission>,371 property_permissions: Vec<PropertyKeyPermission>,326 ) -> DispatchResultWithPostInfo {372 ) -> DispatchResultWithPostInfo {373 let weight =374 <CommonWeights<T>>::set_token_property_permissions(property_permissions.len() as u32);375327 fail!(<Error<T>>::SettingPropertiesNotAllowed)376 with_weight(377 <Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),378 weight,379 )328 }380 }329381330 fn delete_token_properties(382 fn delete_token_properties(331 &self,383 &self,332 _sender: T::CrossAccountId,384 sender: T::CrossAccountId,333 _token_id: TokenId,385 token_id: TokenId,334 _property_keys: Vec<PropertyKey>,386 property_keys: Vec<PropertyKey>,335 _nesting_budget: &dyn Budget,387 nesting_budget: &dyn Budget,336 ) -> DispatchResultWithPostInfo {388 ) -> DispatchResultWithPostInfo {389 let weight = <CommonWeights<T>>::delete_token_properties(property_keys.len() as u32);390337 fail!(<Error<T>>::SettingPropertiesNotAllowed)391 with_weight(392 <Pallet<T>>::delete_token_properties(393 self,394 &sender,395 token_id,396 property_keys.into_iter(),397 nesting_budget,398 ),399 weight,400 )338 }401 }339402371 TokenId(<TokensMinted<T>>::get(self.id))434 TokenId(<TokensMinted<T>>::get(self.id))372 }435 }373436374 fn token_owner(&self, _token: TokenId) -> Option<T::CrossAccountId> {437 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId> {375 None438 <Pallet<T>>::token_owner(self.id, token)376 }439 }440441 /// Returns 10 token in no particular order.442 fn token_owners(&self, token: TokenId) -> Vec<T::CrossAccountId> {443 <Pallet<T>>::token_owners(self.id, token).unwrap_or_default()444 }377445378 fn token_property(&self, _token_id: TokenId, _key: &PropertyKey) -> Option<PropertyValue> {446 fn token_property(&self, _token_id: TokenId, _key: &PropertyKey) -> Option<PropertyValue> {379 None447 Nonepallets/refungible/src/erc.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617extern crate alloc;17use up_data_structs::TokenId;18use evm_coder::{generate_stubgen, solidity_interface, types::*};1918use pallet_common::erc::CommonEvmHandler;20use pallet_common::{CollectionHandle, erc::CollectionCall, erc::CommonEvmHandler};2119use pallet_evm::PrecompileHandle;22use pallet_evm::PrecompileHandle;23use pallet_evm_coder_substrate::call;202421use crate::{Config, RefungibleHandle};25use crate::{Config, RefungibleHandle};222627#[solidity_interface(28 name = "UniqueRFT",29 is(via("CollectionHandle<T>", common_mut, Collection),)30)]23impl<T: Config> CommonEvmHandler for RefungibleHandle<T> {31impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> {}24 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueRefungible.raw");322533// Not a tests, but code generators26 fn call(34generate_stubgen!(gen_impl, UniqueRFTCall<()>, true);27 self,28 _handle: &mut impl PrecompileHandle,29 ) -> Option<pallet_common::erc::PrecompileResult> {30 // TODO: Implement RFT variant of ERC72131 None32 }33}3435pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);35generate_stubgen!(gen_iface, UniqueRFTCall<()>, false);363637impl<T: Config> CommonEvmHandler for RefungibleTokenHandle<T> {37impl<T: Config> CommonEvmHandler for RefungibleHandle<T>38where39 T::AccountId: From<[u8; 32]>,40{38 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueRefungibleToken.raw");41 const CODE: &'static [u8] = include_bytes!("./stubs/UniqueRefungible.raw");3940 fn call(42 fn call(41 self,43 self,42 _handle: &mut impl PrecompileHandle,44 handle: &mut impl PrecompileHandle,43 ) -> Option<pallet_common::erc::PrecompileResult> {45 ) -> Option<pallet_common::erc::PrecompileResult> {44 // TODO: Implement RFT variant of ERC2046 call::<T, UniqueRFTCall<T>, _, _>(handle, self)45 None46 }47 }47}48}4849pallets/refungible/src/erc_token.rsdiffbeforeafterbothno changes
pallets/refungible/src/lib.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617//! # Refungible Pallet18//!19//! The Refungible pallet provides functionality for handling refungible collections and tokens.20//!21//! - [`Config`]22//! - [`RefungibleHandle`]23//! - [`Pallet`]24//! - [`CommonWeights`](common::CommonWeights)25//!26//! ## Overview27//!28//! The Refungible pallet provides functions for:29//!30//! - RFT collection creation and removal31//! - Minting and burning of RFT tokens32//! - Partition and repartition of RFT tokens33//! - Retrieving number of pieces of RFT token34//! - Retrieving account balances35//! - Transfering RFT token pieces36//! - Burning RFT token pieces37//! - Setting and checking allowance for RFT tokens38//!39//! ### Terminology40//!41//! - **RFT token:** Non fungible token that was partitioned to pieces. If an account owns all42//! of the RFT token pieces than it owns the RFT token and can repartition it.43//!44//! - **RFT Collection:** A collection of RFT tokens. All RFT tokens are part of a collection.45//! Each collection has its own settings and set of permissions.46//!47//! - **RFT token piece:** A fungible part of an RFT token.48//!49//! - **Balance:** RFT token pieces owned by an account50//!51//! - **Allowance:** Maximum number of RFT token pieces that one account is allowed to52//! transfer from the balance of another account53//!54//! - **Burning:** The process of “deleting” a token from a collection or removing token pieces from55//! an account balance.56//!57//! ### Implementations58//!59//! The Refungible pallet provides implementations for the following traits. If these traits provide60//! the functionality that you need, then you can avoid coupling with the Refungible pallet.61//!62//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight63//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing64//! with collections65//! - [`RefungibleExtensions`](pallet_common::RefungibleExtensions): Functions specific for refungible66//! collection67//!68//! ## Interface69//!70//! ### Dispatchable Functions71//!72//! - `init_collection` - Create RFT collection. RFT collection can be configured to allow or deny access for73//! some accounts.74//! - `destroy_collection` - Destroy exising RFT collection. There should be no tokens in the collection.75//! - `burn` - Burn some amount of RFT token pieces owned by account. Burns the RFT token if no pieces left.76//! - `transfer` - Transfer some amount of RFT token pieces. Transfers should be enabled for RFT collection.77//! Nests the RFT token if RFT token pieces are sent to another token.78//! - `create_item` - Mint RFT token in collection. Sender should have permission to mint tokens.79//! - `set_allowance` - Set allowance for another account to transfer balance from sender's account.80//! - `repartition` - Repartition token to selected number of pieces. Sender should own all existing pieces.81//!82//! ## Assumptions83//!84//! * Total number of pieces for one token shouldn't exceed `up_data_structs::MAX_REFUNGIBLE_PIECES`.85//! * Total number of tokens of all types shouldn't be greater than `up_data_structs::MAX_TOKEN_PREFIX_LENGTH`.86//! * Sender should be in collection's allow list to perform operations on tokens.8717#![cfg_attr(not(feature = "std"), no_std)]88#![cfg_attr(not(feature = "std"), no_std)]188919use frame_support::{ensure, BoundedVec};90use crate::erc_token::ERC20Events;9192use codec::{Encode, Decode, MaxEncodedLen};20use up_data_structs::{93use core::ops::Deref;94use evm_coder::ToLog;21 AccessMode, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,95use frame_support::{BoundedVec, ensure, fail, storage::with_transaction, transactional};96use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};97use pallet_evm_coder_substrate::WithRecorder;98use pallet_common::{22 CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping, budget::Budget,99 CommonCollectionOperations, Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,23};100};24use pallet_evm::account::CrossAccountId;25use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon};26use pallet_structure::Pallet as PalletStructure;101use pallet_structure::Pallet as PalletStructure;27use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};102use scale_info::TypeInfo;103use sp_core::H160;104use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};28use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};105use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};29use core::ops::Deref;106use up_data_structs::{107 AccessMode, budget::Budget, CollectionId, CreateCollectionData, CreateRefungibleExData,30use codec::{Encode, Decode, MaxEncodedLen};108 CustomDataLimit, mapping::TokenAddressMapping, MAX_REFUNGIBLE_PIECES, TokenId, Property,31use scale_info::TypeInfo;109 PropertyKey, PropertyKeyPermission, PropertyPermission, PropertyScope, PropertyValue,110 TrySetProperty,111};3211233pub use pallet::*;113pub use pallet::*;34#[cfg(feature = "runtime-benchmarks")]114#[cfg(feature = "runtime-benchmarks")]35pub mod benchmarking;115pub mod benchmarking;36pub mod common;116pub mod common;37pub mod erc;117pub mod erc;118pub mod erc_token;38pub mod weights;119pub mod weights;39pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;120pub(crate) type SelfWeightOf<T> = <T as Config>::WeightInfo;4012141/// Token data, stored independently from other data used to describe it.122/// Token data, stored independently from other data used to describe it42/// Notably contains the token metadata.123/// for the convenience of database access. Notably contains the token metadata.43#[struct_versioning::versioned(version = 2, upper)]124#[struct_versioning::versioned(version = 2, upper)]44#[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen)]125#[derive(Encode, Decode, Default, TypeInfo, MaxEncodedLen)]45pub struct ItemData {126pub struct ItemData {108189109 /// Amount of pieces a refungible token is split into.190 /// Amount of pieces a refungible token is split into.110 #[pallet::storage]191 #[pallet::storage]192 #[pallet::getter(fn token_properties)]193 pub type TokenProperties<T: Config> = StorageNMap<194 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),195 Value = up_data_structs::Properties,196 QueryKind = ValueQuery,197 OnEmpty = up_data_structs::TokenProperties,198 >;199200 /// Total amount of pieces for token201 #[pallet::storage]111 pub type TotalSupply<T: Config> = StorageNMap<202 pub type TotalSupply<T: Config> = StorageNMap<112 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),203 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),113 Value = u128,204 Value = u128,138 QueryKind = ValueQuery,229 QueryKind = ValueQuery,139 >;230 >;140231141 /// Amount of pieces of a token owned by an account.232 /// Amount of token pieces owned by account.142 #[pallet::storage]233 #[pallet::storage]143 pub type Balance<T: Config> = StorageNMap<234 pub type Balance<T: Config> = StorageNMap<144 Key = (235 Key = (151 QueryKind = ValueQuery,242 QueryKind = ValueQuery,152 >;243 >;153244154 /// todo:doc245 /// Allowance set by a token owner for another user to perform one of certain transactions on a number of pieces of a token.155 #[pallet::storage]246 #[pallet::storage]156 pub type Allowance<T: Config> = StorageNMap<247 pub type Allowance<T: Config> = StorageNMap<157 Key = (248 Key = (188 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {279 pub fn into_inner(self) -> pallet_common::CollectionHandle<T> {189 self.0280 self.0190 }281 }282 pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle<T> {283 &mut self.0284 }191}285}286192impl<T: Config> Deref for RefungibleHandle<T> {287impl<T: Config> Deref for RefungibleHandle<T> {193 type Target = pallet_common::CollectionHandle<T>;288 type Target = pallet_common::CollectionHandle<T>;194289197 }292 }198}293}199294295impl<T: Config> WithRecorder<T> for RefungibleHandle<T> {296 fn recorder(&self) -> &pallet_evm_coder_substrate::SubstrateRecorder<T> {297 self.0.recorder()298 }299 fn into_recorder(self) -> pallet_evm_coder_substrate::SubstrateRecorder<T> {300 self.0.into_recorder()301 }302}303200impl<T: Config> Pallet<T> {304impl<T: Config> Pallet<T> {305 /// Get number of RFT tokens in collection201 pub fn total_supply(collection: &RefungibleHandle<T>) -> u32 {306 pub fn total_supply(collection: &RefungibleHandle<T>) -> u32 {202 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)307 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)203 }308 }309310 /// Check that RFT token exists311 ///312 /// - `token`: Token ID.204 pub fn token_exists(collection: &RefungibleHandle<T>, token: TokenId) -> bool {313 pub fn token_exists(collection: &RefungibleHandle<T>, token: TokenId) -> bool {205 <TotalSupply<T>>::contains_key((collection.id, token))314 <TotalSupply<T>>::contains_key((collection.id, token))206 }315 }316317 pub fn set_scoped_token_property(318 collection_id: CollectionId,319 token_id: TokenId,320 scope: PropertyScope,321 property: Property,322 ) -> DispatchResult {323 TokenProperties::<T>::try_mutate((collection_id, token_id), |properties| {324 properties.try_scoped_set(scope, property.key, property.value)325 })326 .map_err(<CommonError<T>>::from)?;327328 Ok(())329 }330331 pub fn set_scoped_token_properties(332 collection_id: CollectionId,333 token_id: TokenId,334 scope: PropertyScope,335 properties: impl Iterator<Item = Property>,336 ) -> DispatchResult {337 TokenProperties::<T>::try_mutate((collection_id, token_id), |stored_properties| {338 stored_properties.try_scoped_set_from_iter(scope, properties)339 })340 .map_err(<CommonError<T>>::from)?;341342 Ok(())343 }207}344}208345209// unchecked calls skips any permission checks346// unchecked calls skips any permission checks210impl<T: Config> Pallet<T> {347impl<T: Config> Pallet<T> {348 /// Create RFT collection349 ///350 /// `init_collection` will take non-refundable deposit for collection creation.351 ///352 /// - `data`: Contains settings for collection limits and permissions.211 pub fn init_collection(353 pub fn init_collection(212 owner: T::CrossAccountId,354 owner: T::CrossAccountId,213 data: CreateCollectionData<T::AccountId>,355 data: CreateCollectionData<T::AccountId>,214 ) -> Result<CollectionId, DispatchError> {356 ) -> Result<CollectionId, DispatchError> {215 <PalletCommon<T>>::init_collection(owner, data, false)357 <PalletCommon<T>>::init_collection(owner, data, false)216 }358 }359360 /// Destroy RFT collection361 ///362 /// `destroy_collection` will throw error if collection contains any tokens.363 /// Only owner can destroy collection.217 pub fn destroy_collection(364 pub fn destroy_collection(218 collection: RefungibleHandle<T>,365 collection: RefungibleHandle<T>,219 sender: &T::CrossAccountId,366 sender: &T::CrossAccountId,245 .is_some()392 .is_some()246 }393 }247394248 pub fn burn_token(collection: &RefungibleHandle<T>, token_id: TokenId) -> DispatchResult {395 pub fn burn_token_unchecked(396 collection: &RefungibleHandle<T>,397 token_id: TokenId,398 ) -> DispatchResult {249 let burnt = <TokensBurnt<T>>::get(collection.id)399 let burnt = <TokensBurnt<T>>::get(collection.id)250 .checked_add(1)400 .checked_add(1)251 .ok_or(ArithmeticError::Overflow)?;401 .ok_or(ArithmeticError::Overflow)?;252402253 <TokensBurnt<T>>::insert(collection.id, burnt);403 <TokensBurnt<T>>::insert(collection.id, burnt);254 <TokenData<T>>::remove((collection.id, token_id));404 <TokenData<T>>::remove((collection.id, token_id));405 <TokenProperties<T>>::remove((collection.id, token_id));255 <TotalSupply<T>>::remove((collection.id, token_id));406 <TotalSupply<T>>::remove((collection.id, token_id));256 <Balance<T>>::remove_prefix((collection.id, token_id), None);407 <Balance<T>>::remove_prefix((collection.id, token_id), None);257 <Allowance<T>>::remove_prefix((collection.id, token_id), None);408 <Allowance<T>>::remove_prefix((collection.id, token_id), None);258 // TODO: ERC721 transfer event409 // TODO: ERC721 transfer event259 Ok(())410 Ok(())260 }411 }261412413 /// Burn RFT token pieces414 ///415 /// `burn` will decrease total amount of token pieces and amount owned by sender.416 /// `burn` can be called even if there are multiple owners of the RFT token.417 /// If sender wouldn't have any pieces left after `burn` than she will stop being418 /// one of the owners of the token. If there is no account that owns any pieces of419 /// the token than token will be burned too.420 ///421 /// - `amount`: Amount of token pieces to burn.422 /// - `token`: Token who's pieces should be burned423 /// - `collection`: Collection that contains the token262 pub fn burn(424 pub fn burn(263 collection: &RefungibleHandle<T>,425 collection: &RefungibleHandle<T>,264 owner: &T::CrossAccountId,426 owner: &T::CrossAccountId,286 <Owned<T>>::remove((collection.id, owner, token));448 <Owned<T>>::remove((collection.id, owner, token));287 <PalletStructure<T>>::unnest_if_nested(owner, collection.id, token);449 <PalletStructure<T>>::unnest_if_nested(owner, collection.id, token);288 <AccountBalance<T>>::insert((collection.id, owner), account_balance);450 <AccountBalance<T>>::insert((collection.id, owner), account_balance);289 Self::burn_token(collection, token)?;451 Self::burn_token_unchecked(collection, token)?;290 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(452 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(291 collection.id,453 collection.id,292 token,454 token,319 <Balance<T>>::insert((collection.id, token, owner), balance);481 <Balance<T>>::insert((collection.id, token, owner), balance);320 }482 }321 <TotalSupply<T>>::insert((collection.id, token), total_supply);483 <TotalSupply<T>>::insert((collection.id, token), total_supply);484322 // TODO: ERC20 transfer event485 <PalletEvm<T>>::deposit_log(486 ERC20Events::Transfer {487 from: *owner.as_eth(),488 to: H160::default(),489 value: amount.into(),490 }491 .to_log(T::EvmTokenAddressMapping::token_to_address(492 collection.id,493 token,494 )),495 );323 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(496 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(324 collection.id,497 collection.id,325 token,498 token,329 Ok(())502 Ok(())330 }503 }331504505 #[transactional]506 fn modify_token_properties(507 collection: &RefungibleHandle<T>,508 sender: &T::CrossAccountId,509 token_id: TokenId,510 properties: impl Iterator<Item = (PropertyKey, Option<PropertyValue>)>,511 is_token_create: bool,512 nesting_budget: &dyn Budget,513 ) -> DispatchResult {514 let is_collection_admin = || collection.is_owner_or_admin(sender);515 let is_token_owner = || -> Result<bool, DispatchError> {516 let balance = collection.balance(sender.clone(), token_id);517 let total_pieces: u128 =518 Self::total_pieces(collection.id, token_id).unwrap_or(u128::MAX);519 if balance != total_pieces {520 return Ok(false);521 }522523 let is_bundle_owner = <PalletStructure<T>>::check_indirectly_owned(524 sender.clone(),525 collection.id,526 token_id,527 None,528 nesting_budget,529 )?;530531 Ok(is_bundle_owner)532 };533534 for (key, value) in properties {535 let permission = <PalletCommon<T>>::property_permissions(collection.id)536 .get(&key)537 .cloned()538 .unwrap_or_else(PropertyPermission::none);539540 let is_property_exists = TokenProperties::<T>::get((collection.id, token_id))541 .get(&key)542 .is_some();543544 match permission {545 PropertyPermission { mutable: false, .. } if is_property_exists => {546 return Err(<CommonError<T>>::NoPermission.into());547 }548549 PropertyPermission {550 collection_admin,551 token_owner,552 ..553 } => {554 //TODO: investigate threats during public minting.555 let is_token_create =556 is_token_create && (collection_admin || token_owner) && value.is_some();557 if !(is_token_create558 || (collection_admin && is_collection_admin())559 || (token_owner && is_token_owner()?))560 {561 fail!(<CommonError<T>>::NoPermission);562 }563 }564 }565566 match value {567 Some(value) => {568 <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {569 properties.try_set(key.clone(), value)570 })571 .map_err(<CommonError<T>>::from)?;572573 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertySet(574 collection.id,575 token_id,576 key,577 ));578 }579 None => {580 <TokenProperties<T>>::try_mutate((collection.id, token_id), |properties| {581 properties.remove(&key)582 })583 .map_err(<CommonError<T>>::from)?;584585 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(586 collection.id,587 token_id,588 key,589 ));590 }591 }592 }593594 Ok(())595 }596597 pub fn set_token_properties(598 collection: &RefungibleHandle<T>,599 sender: &T::CrossAccountId,600 token_id: TokenId,601 properties: impl Iterator<Item = Property>,602 is_token_create: bool,603 nesting_budget: &dyn Budget,604 ) -> DispatchResult {605 Self::modify_token_properties(606 collection,607 sender,608 token_id,609 properties.map(|p| (p.key, Some(p.value))),610 is_token_create,611 nesting_budget,612 )613 }614615 pub fn set_token_property(616 collection: &RefungibleHandle<T>,617 sender: &T::CrossAccountId,618 token_id: TokenId,619 property: Property,620 nesting_budget: &dyn Budget,621 ) -> DispatchResult {622 let is_token_create = false;623624 Self::set_token_properties(625 collection,626 sender,627 token_id,628 [property].into_iter(),629 is_token_create,630 nesting_budget,631 )632 }633634 pub fn delete_token_properties(635 collection: &RefungibleHandle<T>,636 sender: &T::CrossAccountId,637 token_id: TokenId,638 property_keys: impl Iterator<Item = PropertyKey>,639 nesting_budget: &dyn Budget,640 ) -> DispatchResult {641 let is_token_create = false;642643 Self::modify_token_properties(644 collection,645 sender,646 token_id,647 property_keys.into_iter().map(|key| (key, None)),648 is_token_create,649 nesting_budget,650 )651 }652653 pub fn delete_token_property(654 collection: &RefungibleHandle<T>,655 sender: &T::CrossAccountId,656 token_id: TokenId,657 property_key: PropertyKey,658 nesting_budget: &dyn Budget,659 ) -> DispatchResult {660 Self::delete_token_properties(661 collection,662 sender,663 token_id,664 [property_key].into_iter(),665 nesting_budget,666 )667 }668669 /// Transfer RFT token pieces from one account to another.670 ///671 /// If the sender is no longer owns any pieces after the `transfer` than she stops being an owner of the token.672 ///673 /// - `from`: Owner of token pieces to transfer.674 /// - `to`: Recepient of transfered token pieces.675 /// - `amount`: Amount of token pieces to transfer.676 /// - `token`: Token whos pieces should be transfered677 /// - `collection`: Collection that contains the token332 pub fn transfer(678 pub fn transfer(333 collection: &RefungibleHandle<T>,679 collection: &RefungibleHandle<T>,334 from: &T::CrossAccountId,680 from: &T::CrossAccountId,422 }768 }423 }769 }424770425 // TODO: ERC20 transfer event771 <PalletEvm<T>>::deposit_log(772 ERC20Events::Transfer {773 from: *from.as_eth(),774 to: *to.as_eth(),775 value: amount.into(),776 }777 .to_log(T::EvmTokenAddressMapping::token_to_address(778 collection.id,779 token,780 )),781 );426 <PalletCommon<T>>::deposit_event(CommonEvent::Transfer(782 <PalletCommon<T>>::deposit_event(CommonEvent::Transfer(427 collection.id,783 collection.id,428 token,784 token,433 Ok(())789 Ok(())434 }790 }435791792 /// Batched operation to create multiple RFT tokens.793 ///794 /// Same as `create_item` but creates multiple tokens.795 ///796 /// - `data`: Same as 'data` in `create_item` but contains data for multiple tokens.436 pub fn create_multiple_items(797 pub fn create_multiple_items(437 collection: &RefungibleHandle<T>,798 collection: &RefungibleHandle<T>,438 sender: &T::CrossAccountId,799 sender: &T::CrossAccountId,517878518 // =========879 // =========519880881 with_transaction(|| {882 for (i, data) in data.iter().enumerate() {883 let token_id = first_token_id + i as u32 + 1;884 <TotalSupply<T>>::insert((collection.id, token_id), totals[i]);885886 <TokenData<T>>::insert(887 (collection.id, token_id),888 ItemData {889 const_data: data.const_data.clone(),890 },891 );892893 for (user, amount) in data.users.iter() {894 if *amount == 0 {895 continue;896 }897 <Balance<T>>::insert((collection.id, token_id, &user), amount);898 <Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);899 <PalletStructure<T>>::nest_if_sent_to_token_unchecked(900 user,901 collection.id,902 TokenId(token_id),903 );904 }905906 if let Err(e) = Self::set_token_properties(907 collection,908 sender,909 TokenId(token_id),910 data.properties.clone().into_iter(),911 true,912 nesting_budget,913 ) {914 return TransactionOutcome::Rollback(Err(e));915 }916 }917 TransactionOutcome::Commit(Ok(()))918 })?;919520 <TokensMinted<T>>::insert(collection.id, tokens_minted);920 <TokensMinted<T>>::insert(collection.id, tokens_minted);921521 for (account, balance) in balances {922 for (account, balance) in balances {522 <AccountBalance<T>>::insert((collection.id, account), balance);923 <AccountBalance<T>>::insert((collection.id, account), balance);523 }924 }925524 for (i, token) in data.into_iter().enumerate() {926 for (i, token) in data.into_iter().enumerate() {525 let token_id = first_token_id + i as u32 + 1;927 let token_id = first_token_id + i as u32 + 1;526 <TotalSupply<T>>::insert((collection.id, token_id), totals[i]);527928528 <TokenData<T>>::insert(529 (collection.id, token_id),530 ItemData {531 const_data: token.const_data,532 },533 );534535 for (user, amount) in token.users.into_iter() {929 for (user, amount) in token.users.into_iter() {536 if amount == 0 {930 if amount == 0 {537 continue;931 continue;538 }932 }933539 <Balance<T>>::insert((collection.id, token_id, &user), amount);934 <PalletEvm<T>>::deposit_log(935 ERC20Events::Transfer {936 from: H160::default(),540 <Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);937 to: *user.as_eth(),541 <PalletStructure<T>>::nest_if_sent_to_token_unchecked(938 value: amount.into(),542 &user,939 }543 collection.id,940 .to_log(T::EvmTokenAddressMapping::token_to_address(941 collection.id,544 TokenId(token_id),942 TokenId(token_id),943 )),545 );944 );546547 // TODO: ERC20 transfer event548 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(945 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(549 collection.id,946 collection.id,550 TokenId(token_id),947 TokenId(token_id),568 } else {965 } else {569 <Allowance<T>>::insert((collection.id, token, sender, spender), amount);966 <Allowance<T>>::insert((collection.id, token, sender, spender), amount);570 }967 }968571 // TODO: ERC20 approval event969 <PalletEvm<T>>::deposit_log(970 ERC20Events::Approval {971 owner: *sender.as_eth(),972 spender: *spender.as_eth(),973 value: amount.into(),974 }975 .to_log(T::EvmTokenAddressMapping::token_to_address(976 collection.id,977 token,978 )),979 );572 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(980 <PalletCommon<T>>::deposit_event(CommonEvent::Approved(573 collection.id,981 collection.id,574 token,982 token,578 ))986 ))579 }987 }580988989 /// Set allowance for the spender to `transfer` or `burn` sender's token pieces.990 ///991 /// - `amount`: Amount of token pieces the spender is allowed to `transfer` or `burn.581 pub fn set_allowance(992 pub fn set_allowance(582 collection: &RefungibleHandle<T>,993 collection: &RefungibleHandle<T>,583 sender: &T::CrossAccountId,994 sender: &T::CrossAccountId,646 Ok(allowance)1057 Ok(allowance)647 }1058 }64810591060 /// Transfer RFT token pieces from one account to another.1061 ///1062 /// Same as the [`transfer`] but spender doesn't needs to be an owner of the token pieces.1063 /// The owner should set allowance for the spender to transfer pieces.1064 ///1065 /// [`transfer`]: struct.Pallet.html#method.transfer649 pub fn transfer_from(1066 pub fn transfer_from(650 collection: &RefungibleHandle<T>,1067 collection: &RefungibleHandle<T>,651 spender: &T::CrossAccountId,1068 spender: &T::CrossAccountId,667 Ok(())1084 Ok(())668 }1085 }66910861087 /// Burn RFT token pieces from the account.1088 ///1089 /// Same as the [`burn`] but spender doesn't need to be an owner of the token pieces. The owner should1090 /// set allowance for the spender to burn pieces1091 ///1092 /// [`burn`]: struct.Pallet.html#method.burn670 pub fn burn_from(1093 pub fn burn_from(671 collection: &RefungibleHandle<T>,1094 collection: &RefungibleHandle<T>,672 spender: &T::CrossAccountId,1095 spender: &T::CrossAccountId,687 Ok(())1110 Ok(())688 }1111 }6891112690 /// Delegated to `create_multiple_items`1113 /// Create RFT token.1114 ///1115 /// The sender should be the owner/admin of the collection or collection should be configured1116 /// to allow public minting.1117 ///1118 /// - `data`: Contains list of users who will become the owners of the token pieces and amount1119 /// of token pieces they will receive.691 pub fn create_item(1120 pub fn create_item(692 collection: &RefungibleHandle<T>,1121 collection: &RefungibleHandle<T>,693 sender: &T::CrossAccountId,1122 sender: &T::CrossAccountId,697 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)1126 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)698 }1127 }69911281129 /// Repartition RFT token.1130 ///1131 /// `repartition` will set token balance of the sender and total amount of token pieces.1132 /// Sender should own all of the token pieces. `repartition' could be done even if some1133 /// token pieces were burned before.1134 ///1135 /// - `amount`: Total amount of token pieces that the token will have after `repartition`.700 pub fn repartition(1136 pub fn repartition(701 collection: &RefungibleHandle<T>,1137 collection: &RefungibleHandle<T>,702 owner: &T::CrossAccountId,1138 owner: &T::CrossAccountId,709 );1145 );710 ensure!(amount > 0, <CommonError<T>>::TokenValueTooLow);1146 ensure!(amount > 0, <CommonError<T>>::TokenValueTooLow);711 // Ensure user owns all pieces1147 // Ensure user owns all pieces712 let total_supply = <TotalSupply<T>>::get((collection.id, token));1148 let total_pieces = Self::total_pieces(collection.id, token).unwrap_or(u128::MAX);713 let balance = <Balance<T>>::get((collection.id, token, owner));1149 let balance = <Balance<T>>::get((collection.id, token, owner));714 ensure!(1150 ensure!(715 total_supply == balance,1151 total_pieces == balance,716 <Error<T>>::RepartitionWhileNotOwningAllPieces1152 <Error<T>>::RepartitionWhileNotOwningAllPieces717 );1153 );7181154719 <Balance<T>>::insert((collection.id, token, owner), amount);1155 <Balance<T>>::insert((collection.id, token, owner), amount);720 <TotalSupply<T>>::insert((collection.id, token), amount);1156 <TotalSupply<T>>::insert((collection.id, token), amount);11571158 if amount > total_pieces {1159 let mint_amount = amount - total_pieces;1160 <PalletEvm<T>>::deposit_log(1161 ERC20Events::Transfer {1162 from: H160::default(),1163 to: *owner.as_eth(),1164 value: mint_amount.into(),1165 }1166 .to_log(T::EvmTokenAddressMapping::token_to_address(1167 collection.id,1168 token,1169 )),1170 );1171 <PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(1172 collection.id,1173 token,1174 owner.clone(),1175 mint_amount,1176 ));1177 } else if total_pieces > amount {1178 let burn_amount = total_pieces - amount;1179 <PalletEvm<T>>::deposit_log(1180 ERC20Events::Transfer {1181 from: *owner.as_eth(),1182 to: H160::default(),1183 value: burn_amount.into(),1184 }1185 .to_log(T::EvmTokenAddressMapping::token_to_address(1186 collection.id,1187 token,1188 )),1189 );1190 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(1191 collection.id,1192 token,1193 owner.clone(),1194 burn_amount,1195 ));1196 }1197721 Ok(())1198 Ok(())722 }1199 }72312001201 fn token_owner(collection_id: CollectionId, token_id: TokenId) -> Option<T::CrossAccountId> {1202 let mut owner = None;1203 let mut count = 0;1204 for key in Balance::<T>::iter_key_prefix((collection_id, token_id)) {1205 count += 1;1206 if count > 1 {1207 return None;1208 }1209 owner = Some(key);1210 }1211 owner1212 }1213724 fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128> {1214 fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option<u128> {725 <TotalSupply<T>>::try_get((collection_id, token_id)).ok()1215 <TotalSupply<T>>::try_get((collection_id, token_id)).ok()1216 }12171218 pub fn set_collection_properties(1219 collection: &RefungibleHandle<T>,1220 sender: &T::CrossAccountId,1221 properties: Vec<Property>,1222 ) -> DispatchResult {1223 <PalletCommon<T>>::set_collection_properties(collection, sender, properties)1224 }12251226 pub fn delete_collection_properties(1227 collection: &RefungibleHandle<T>,1228 sender: &T::CrossAccountId,1229 property_keys: Vec<PropertyKey>,1230 ) -> DispatchResult {1231 <PalletCommon<T>>::delete_collection_properties(collection, sender, property_keys)1232 }12331234 pub fn set_token_property_permissions(1235 collection: &RefungibleHandle<T>,1236 sender: &T::CrossAccountId,1237 property_permissions: Vec<PropertyKeyPermission>,1238 ) -> DispatchResult {1239 <PalletCommon<T>>::set_token_property_permissions(collection, sender, property_permissions)1240 }12411242 /// Returns 10 token in no particular order.1243 ///1244 /// There is no direct way to get token holders in ascending order,1245 /// since `iter_prefix` returns values in no particular order.1246 /// Therefore, getting the 10 largest holders with a large value of holders1247 /// can lead to impact memory allocation + sorting with `n * log (n)`.1248 pub fn token_owners(1249 collection_id: CollectionId,1250 token: TokenId,1251 ) -> Option<Vec<T::CrossAccountId>> {1252 let res: Vec<T::CrossAccountId> = <Balance<T>>::iter_prefix((collection_id, token))1253 .map(|(owner, _amount)| owner)1254 .take(10)1255 .collect();12561257 if res.is_empty() {1258 None1259 } else {1260 Some(res)1261 }726 }1262 }727}1263}7281264pallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterbothno changes
pallets/refungible/src/weights.rsdiffbeforeafterboth3//! Autogenerated weights for pallet_refungible3//! Autogenerated weights for pallet_refungible4//!4//!5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev6//! DATE: 2022-06-27, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`6//! DATE: 2022-07-20, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 10247//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024889// Executed Command:9// Executed Command:49 fn transfer_from_removing() -> Weight;49 fn transfer_from_removing() -> Weight;50 fn transfer_from_creating_removing() -> Weight;50 fn transfer_from_creating_removing() -> Weight;51 fn burn_from() -> Weight;51 fn burn_from() -> Weight;52 fn set_token_property_permissions(b: u32, ) -> Weight;53 fn set_token_properties(b: u32, ) -> Weight;54 fn delete_token_properties(b: u32, ) -> Weight;52 fn repartition_item() -> Weight;55 fn repartition_item() -> Weight;53}56}545762 // Storage: Refungible TokenData (r:0 w:1)65 // Storage: Refungible TokenData (r:0 w:1)63 // Storage: Refungible Owned (r:0 w:1)66 // Storage: Refungible Owned (r:0 w:1)64 fn create_item() -> Weight {67 fn create_item() -> Weight {65 (17_553_000 as Weight)68 (21_310_000 as Weight)66 .saturating_add(T::DbWeight::get().reads(2 as Weight))69 .saturating_add(T::DbWeight::get().reads(2 as Weight))67 .saturating_add(T::DbWeight::get().writes(6 as Weight))70 .saturating_add(T::DbWeight::get().writes(6 as Weight))68 }71 }73 // Storage: Refungible TokenData (r:0 w:4)76 // Storage: Refungible TokenData (r:0 w:4)74 // Storage: Refungible Owned (r:0 w:4)77 // Storage: Refungible Owned (r:0 w:4)75 fn create_multiple_items(b: u32, ) -> Weight {78 fn create_multiple_items(b: u32, ) -> Weight {76 (10_654_000 as Weight)79 (9_552_000 as Weight)77 // Standard Error: 1_00080 // Standard Error: 2_00078 .saturating_add((5_114_000 as Weight).saturating_mul(b as Weight))81 .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))79 .saturating_add(T::DbWeight::get().reads(2 as Weight))82 .saturating_add(T::DbWeight::get().reads(2 as Weight))80 .saturating_add(T::DbWeight::get().writes(2 as Weight))83 .saturating_add(T::DbWeight::get().writes(2 as Weight))81 .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))84 .saturating_add(T::DbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))87 // Storage: Refungible TokenData (r:0 w:4)90 // Storage: Refungible TokenData (r:0 w:4)88 // Storage: Refungible Owned (r:0 w:4)91 // Storage: Refungible Owned (r:0 w:4)89 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {92 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {90 (3_587_000 as Weight)93 (4_857_000 as Weight)91 // Standard Error: 2_00094 // Standard Error: 2_00092 .saturating_add((7_931_000 as Weight).saturating_mul(b as Weight))95 .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))93 .saturating_add(T::DbWeight::get().reads(1 as Weight))96 .saturating_add(T::DbWeight::get().reads(1 as Weight))94 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))97 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))95 .saturating_add(T::DbWeight::get().writes(1 as Weight))98 .saturating_add(T::DbWeight::get().writes(1 as Weight))102 // Storage: Refungible Balance (r:0 w:4)105 // Storage: Refungible Balance (r:0 w:4)103 // Storage: Refungible Owned (r:0 w:4)106 // Storage: Refungible Owned (r:0 w:4)104 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {107 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {105 (1_980_000 as Weight)108 (11_335_000 as Weight)106 // Standard Error: 2_000109 // Standard Error: 2_000107 .saturating_add((6_305_000 as Weight).saturating_mul(b as Weight))110 .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))108 .saturating_add(T::DbWeight::get().reads(1 as Weight))111 .saturating_add(T::DbWeight::get().reads(1 as Weight))109 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))112 .saturating_add(T::DbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))110 .saturating_add(T::DbWeight::get().writes(3 as Weight))113 .saturating_add(T::DbWeight::get().writes(3 as Weight))115 // Storage: Refungible AccountBalance (r:1 w:1)118 // Storage: Refungible AccountBalance (r:1 w:1)116 // Storage: Refungible Owned (r:0 w:1)119 // Storage: Refungible Owned (r:0 w:1)117 fn burn_item_partial() -> Weight {120 fn burn_item_partial() -> Weight {118 (21_010_000 as Weight)121 (21_239_000 as Weight)119 .saturating_add(T::DbWeight::get().reads(3 as Weight))122 .saturating_add(T::DbWeight::get().reads(3 as Weight))120 .saturating_add(T::DbWeight::get().writes(4 as Weight))123 .saturating_add(T::DbWeight::get().writes(4 as Weight))121 }124 }125 // Storage: Refungible TokensBurnt (r:1 w:1)128 // Storage: Refungible TokensBurnt (r:1 w:1)126 // Storage: Refungible TokenData (r:0 w:1)129 // Storage: Refungible TokenData (r:0 w:1)127 // Storage: Refungible Owned (r:0 w:1)130 // Storage: Refungible Owned (r:0 w:1)131 // Storage: Refungible TokenProperties (r:0 w:1)128 fn burn_item_fully() -> Weight {132 fn burn_item_fully() -> Weight {129 (28_413_000 as Weight)133 (29_426_000 as Weight)130 .saturating_add(T::DbWeight::get().reads(4 as Weight))134 .saturating_add(T::DbWeight::get().reads(4 as Weight))131 .saturating_add(T::DbWeight::get().writes(6 as Weight))135 .saturating_add(T::DbWeight::get().writes(7 as Weight))132 }136 }133 // Storage: Refungible Balance (r:2 w:2)137 // Storage: Refungible Balance (r:2 w:2)134 fn transfer_normal() -> Weight {138 fn transfer_normal() -> Weight {135 (17_513_000 as Weight)139 (17_743_000 as Weight)136 .saturating_add(T::DbWeight::get().reads(2 as Weight))140 .saturating_add(T::DbWeight::get().reads(2 as Weight))137 .saturating_add(T::DbWeight::get().writes(2 as Weight))141 .saturating_add(T::DbWeight::get().writes(2 as Weight))138 }142 }139 // Storage: Refungible Balance (r:2 w:2)143 // Storage: Refungible Balance (r:2 w:2)140 // Storage: Refungible AccountBalance (r:1 w:1)144 // Storage: Refungible AccountBalance (r:1 w:1)141 // Storage: Refungible Owned (r:0 w:1)145 // Storage: Refungible Owned (r:0 w:1)142 fn transfer_creating() -> Weight {146 fn transfer_creating() -> Weight {143 (20_469_000 as Weight)147 (20_699_000 as Weight)144 .saturating_add(T::DbWeight::get().reads(3 as Weight))148 .saturating_add(T::DbWeight::get().reads(3 as Weight))145 .saturating_add(T::DbWeight::get().writes(4 as Weight))149 .saturating_add(T::DbWeight::get().writes(4 as Weight))146 }150 }147 // Storage: Refungible Balance (r:2 w:2)151 // Storage: Refungible Balance (r:2 w:2)148 // Storage: Refungible AccountBalance (r:1 w:1)152 // Storage: Refungible AccountBalance (r:1 w:1)149 // Storage: Refungible Owned (r:0 w:1)153 // Storage: Refungible Owned (r:0 w:1)150 fn transfer_removing() -> Weight {154 fn transfer_removing() -> Weight {151 (22_472_000 as Weight)155 (22_833_000 as Weight)152 .saturating_add(T::DbWeight::get().reads(3 as Weight))156 .saturating_add(T::DbWeight::get().reads(3 as Weight))153 .saturating_add(T::DbWeight::get().writes(4 as Weight))157 .saturating_add(T::DbWeight::get().writes(4 as Weight))154 }158 }155 // Storage: Refungible Balance (r:2 w:2)159 // Storage: Refungible Balance (r:2 w:2)156 // Storage: Refungible AccountBalance (r:2 w:2)160 // Storage: Refungible AccountBalance (r:2 w:2)157 // Storage: Refungible Owned (r:0 w:2)161 // Storage: Refungible Owned (r:0 w:2)158 fn transfer_creating_removing() -> Weight {162 fn transfer_creating_removing() -> Weight {159 (24_866_000 as Weight)163 (24_936_000 as Weight)160 .saturating_add(T::DbWeight::get().reads(4 as Weight))164 .saturating_add(T::DbWeight::get().reads(4 as Weight))161 .saturating_add(T::DbWeight::get().writes(6 as Weight))165 .saturating_add(T::DbWeight::get().writes(6 as Weight))162 }166 }163 // Storage: Refungible Balance (r:1 w:0)167 // Storage: Refungible Balance (r:1 w:0)164 // Storage: Refungible Allowance (r:0 w:1)168 // Storage: Refungible Allowance (r:0 w:1)165 fn approve() -> Weight {169 fn approve() -> Weight {166 (13_475_000 as Weight)170 (13_446_000 as Weight)167 .saturating_add(T::DbWeight::get().reads(1 as Weight))171 .saturating_add(T::DbWeight::get().reads(1 as Weight))168 .saturating_add(T::DbWeight::get().writes(1 as Weight))172 .saturating_add(T::DbWeight::get().writes(1 as Weight))169 }173 }170 // Storage: Refungible Allowance (r:1 w:1)174 // Storage: Refungible Allowance (r:1 w:1)171 // Storage: Refungible Balance (r:2 w:2)175 // Storage: Refungible Balance (r:2 w:2)172 fn transfer_from_normal() -> Weight {176 fn transfer_from_normal() -> Weight {173 (24_707_000 as Weight)177 (24_777_000 as Weight)174 .saturating_add(T::DbWeight::get().reads(3 as Weight))178 .saturating_add(T::DbWeight::get().reads(3 as Weight))175 .saturating_add(T::DbWeight::get().writes(3 as Weight))179 .saturating_add(T::DbWeight::get().writes(3 as Weight))176 }180 }179 // Storage: Refungible AccountBalance (r:1 w:1)183 // Storage: Refungible AccountBalance (r:1 w:1)180 // Storage: Refungible Owned (r:0 w:1)184 // Storage: Refungible Owned (r:0 w:1)181 fn transfer_from_creating() -> Weight {185 fn transfer_from_creating() -> Weight {182 (27_812_000 as Weight)186 (28_483_000 as Weight)183 .saturating_add(T::DbWeight::get().reads(4 as Weight))187 .saturating_add(T::DbWeight::get().reads(4 as Weight))184 .saturating_add(T::DbWeight::get().writes(5 as Weight))188 .saturating_add(T::DbWeight::get().writes(5 as Weight))185 }189 }188 // Storage: Refungible AccountBalance (r:1 w:1)192 // Storage: Refungible AccountBalance (r:1 w:1)189 // Storage: Refungible Owned (r:0 w:1)193 // Storage: Refungible Owned (r:0 w:1)190 fn transfer_from_removing() -> Weight {194 fn transfer_from_removing() -> Weight {191 (29_966_000 as Weight)195 (29_896_000 as Weight)192 .saturating_add(T::DbWeight::get().reads(4 as Weight))196 .saturating_add(T::DbWeight::get().reads(4 as Weight))193 .saturating_add(T::DbWeight::get().writes(5 as Weight))197 .saturating_add(T::DbWeight::get().writes(5 as Weight))194 }198 }197 // Storage: Refungible AccountBalance (r:2 w:2)201 // Storage: Refungible AccountBalance (r:2 w:2)198 // Storage: Refungible Owned (r:0 w:2)202 // Storage: Refungible Owned (r:0 w:2)199 fn transfer_from_creating_removing() -> Weight {203 fn transfer_from_creating_removing() -> Weight {200 (31_660_000 as Weight)204 (32_070_000 as Weight)201 .saturating_add(T::DbWeight::get().reads(5 as Weight))205 .saturating_add(T::DbWeight::get().reads(5 as Weight))202 .saturating_add(T::DbWeight::get().writes(7 as Weight))206 .saturating_add(T::DbWeight::get().writes(7 as Weight))203 }207 }208 // Storage: Refungible TokensBurnt (r:1 w:1)212 // Storage: Refungible TokensBurnt (r:1 w:1)209 // Storage: Refungible TokenData (r:0 w:1)213 // Storage: Refungible TokenData (r:0 w:1)210 // Storage: Refungible Owned (r:0 w:1)214 // Storage: Refungible Owned (r:0 w:1)215 // Storage: Refungible TokenProperties (r:0 w:1)211 fn burn_from() -> Weight {216 fn burn_from() -> Weight {212 (36_248_000 as Weight)217 (36_789_000 as Weight)213 .saturating_add(T::DbWeight::get().reads(5 as Weight))218 .saturating_add(T::DbWeight::get().reads(5 as Weight))214 .saturating_add(T::DbWeight::get().writes(7 as Weight))219 .saturating_add(T::DbWeight::get().writes(8 as Weight))215 }220 }221 // Storage: Common CollectionPropertyPermissions (r:1 w:1)222 fn set_token_property_permissions(b: u32, ) -> Weight {223 (0 as Weight)224 // Standard Error: 62_000225 .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))226 .saturating_add(T::DbWeight::get().reads(1 as Weight))227 .saturating_add(T::DbWeight::get().writes(1 as Weight))228 }229 // Storage: Common CollectionPropertyPermissions (r:1 w:0)230 // Storage: Refungible TokenProperties (r:1 w:1)231 fn set_token_properties(b: u32, ) -> Weight {232 (0 as Weight)233 // Standard Error: 1_668_000234 .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))235 .saturating_add(T::DbWeight::get().reads(2 as Weight))236 .saturating_add(T::DbWeight::get().writes(1 as Weight))237 }238 // Storage: Common CollectionPropertyPermissions (r:1 w:0)239 // Storage: Refungible TokenProperties (r:1 w:1)240 fn delete_token_properties(b: u32, ) -> Weight {241 (0 as Weight)242 // Standard Error: 1_619_000243 .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))244 .saturating_add(T::DbWeight::get().reads(2 as Weight))245 .saturating_add(T::DbWeight::get().writes(1 as Weight))246 }216 // Storage: Refungible TotalSupply (r:1 w:1)247 // Storage: Refungible TotalSupply (r:1 w:1)217 // Storage: Refungible Balance (r:1 w:1)248 // Storage: Refungible Balance (r:1 w:1)218 fn repartition_item() -> Weight {249 fn repartition_item() -> Weight {219 (8_226_000 as Weight)250 (8_325_000 as Weight)220 .saturating_add(T::DbWeight::get().reads(2 as Weight))251 .saturating_add(T::DbWeight::get().reads(2 as Weight))221 .saturating_add(T::DbWeight::get().writes(2 as Weight))252 .saturating_add(T::DbWeight::get().writes(2 as Weight))222 }253 }231 // Storage: Refungible TokenData (r:0 w:1)262 // Storage: Refungible TokenData (r:0 w:1)232 // Storage: Refungible Owned (r:0 w:1)263 // Storage: Refungible Owned (r:0 w:1)233 fn create_item() -> Weight {264 fn create_item() -> Weight {234 (17_553_000 as Weight)265 (21_310_000 as Weight)235 .saturating_add(RocksDbWeight::get().reads(2 as Weight))266 .saturating_add(RocksDbWeight::get().reads(2 as Weight))236 .saturating_add(RocksDbWeight::get().writes(6 as Weight))267 .saturating_add(RocksDbWeight::get().writes(6 as Weight))237 }268 }242 // Storage: Refungible TokenData (r:0 w:4)273 // Storage: Refungible TokenData (r:0 w:4)243 // Storage: Refungible Owned (r:0 w:4)274 // Storage: Refungible Owned (r:0 w:4)244 fn create_multiple_items(b: u32, ) -> Weight {275 fn create_multiple_items(b: u32, ) -> Weight {245 (10_654_000 as Weight)276 (9_552_000 as Weight)246 // Standard Error: 1_000277 // Standard Error: 2_000247 .saturating_add((5_114_000 as Weight).saturating_mul(b as Weight))278 .saturating_add((7_056_000 as Weight).saturating_mul(b as Weight))248 .saturating_add(RocksDbWeight::get().reads(2 as Weight))279 .saturating_add(RocksDbWeight::get().reads(2 as Weight))249 .saturating_add(RocksDbWeight::get().writes(2 as Weight))280 .saturating_add(RocksDbWeight::get().writes(2 as Weight))250 .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))281 .saturating_add(RocksDbWeight::get().writes((4 as Weight).saturating_mul(b as Weight)))256 // Storage: Refungible TokenData (r:0 w:4)287 // Storage: Refungible TokenData (r:0 w:4)257 // Storage: Refungible Owned (r:0 w:4)288 // Storage: Refungible Owned (r:0 w:4)258 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {289 fn create_multiple_items_ex_multiple_items(b: u32, ) -> Weight {259 (3_587_000 as Weight)290 (4_857_000 as Weight)260 // Standard Error: 2_000291 // Standard Error: 2_000261 .saturating_add((7_931_000 as Weight).saturating_mul(b as Weight))292 .saturating_add((9_838_000 as Weight).saturating_mul(b as Weight))262 .saturating_add(RocksDbWeight::get().reads(1 as Weight))293 .saturating_add(RocksDbWeight::get().reads(1 as Weight))263 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))294 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))264 .saturating_add(RocksDbWeight::get().writes(1 as Weight))295 .saturating_add(RocksDbWeight::get().writes(1 as Weight))271 // Storage: Refungible Balance (r:0 w:4)302 // Storage: Refungible Balance (r:0 w:4)272 // Storage: Refungible Owned (r:0 w:4)303 // Storage: Refungible Owned (r:0 w:4)273 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {304 fn create_multiple_items_ex_multiple_owners(b: u32, ) -> Weight {274 (1_980_000 as Weight)305 (11_335_000 as Weight)275 // Standard Error: 2_000306 // Standard Error: 2_000276 .saturating_add((6_305_000 as Weight).saturating_mul(b as Weight))307 .saturating_add((6_784_000 as Weight).saturating_mul(b as Weight))277 .saturating_add(RocksDbWeight::get().reads(1 as Weight))308 .saturating_add(RocksDbWeight::get().reads(1 as Weight))278 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))309 .saturating_add(RocksDbWeight::get().reads((1 as Weight).saturating_mul(b as Weight)))279 .saturating_add(RocksDbWeight::get().writes(3 as Weight))310 .saturating_add(RocksDbWeight::get().writes(3 as Weight))284 // Storage: Refungible AccountBalance (r:1 w:1)315 // Storage: Refungible AccountBalance (r:1 w:1)285 // Storage: Refungible Owned (r:0 w:1)316 // Storage: Refungible Owned (r:0 w:1)286 fn burn_item_partial() -> Weight {317 fn burn_item_partial() -> Weight {287 (21_010_000 as Weight)318 (21_239_000 as Weight)288 .saturating_add(RocksDbWeight::get().reads(3 as Weight))319 .saturating_add(RocksDbWeight::get().reads(3 as Weight))289 .saturating_add(RocksDbWeight::get().writes(4 as Weight))320 .saturating_add(RocksDbWeight::get().writes(4 as Weight))290 }321 }294 // Storage: Refungible TokensBurnt (r:1 w:1)325 // Storage: Refungible TokensBurnt (r:1 w:1)295 // Storage: Refungible TokenData (r:0 w:1)326 // Storage: Refungible TokenData (r:0 w:1)296 // Storage: Refungible Owned (r:0 w:1)327 // Storage: Refungible Owned (r:0 w:1)328 // Storage: Refungible TokenProperties (r:0 w:1)297 fn burn_item_fully() -> Weight {329 fn burn_item_fully() -> Weight {298 (28_413_000 as Weight)330 (29_426_000 as Weight)299 .saturating_add(RocksDbWeight::get().reads(4 as Weight))331 .saturating_add(RocksDbWeight::get().reads(4 as Weight))300 .saturating_add(RocksDbWeight::get().writes(6 as Weight))332 .saturating_add(RocksDbWeight::get().writes(7 as Weight))301 }333 }302 // Storage: Refungible Balance (r:2 w:2)334 // Storage: Refungible Balance (r:2 w:2)303 fn transfer_normal() -> Weight {335 fn transfer_normal() -> Weight {304 (17_513_000 as Weight)336 (17_743_000 as Weight)305 .saturating_add(RocksDbWeight::get().reads(2 as Weight))337 .saturating_add(RocksDbWeight::get().reads(2 as Weight))306 .saturating_add(RocksDbWeight::get().writes(2 as Weight))338 .saturating_add(RocksDbWeight::get().writes(2 as Weight))307 }339 }308 // Storage: Refungible Balance (r:2 w:2)340 // Storage: Refungible Balance (r:2 w:2)309 // Storage: Refungible AccountBalance (r:1 w:1)341 // Storage: Refungible AccountBalance (r:1 w:1)310 // Storage: Refungible Owned (r:0 w:1)342 // Storage: Refungible Owned (r:0 w:1)311 fn transfer_creating() -> Weight {343 fn transfer_creating() -> Weight {312 (20_469_000 as Weight)344 (20_699_000 as Weight)313 .saturating_add(RocksDbWeight::get().reads(3 as Weight))345 .saturating_add(RocksDbWeight::get().reads(3 as Weight))314 .saturating_add(RocksDbWeight::get().writes(4 as Weight))346 .saturating_add(RocksDbWeight::get().writes(4 as Weight))315 }347 }316 // Storage: Refungible Balance (r:2 w:2)348 // Storage: Refungible Balance (r:2 w:2)317 // Storage: Refungible AccountBalance (r:1 w:1)349 // Storage: Refungible AccountBalance (r:1 w:1)318 // Storage: Refungible Owned (r:0 w:1)350 // Storage: Refungible Owned (r:0 w:1)319 fn transfer_removing() -> Weight {351 fn transfer_removing() -> Weight {320 (22_472_000 as Weight)352 (22_833_000 as Weight)321 .saturating_add(RocksDbWeight::get().reads(3 as Weight))353 .saturating_add(RocksDbWeight::get().reads(3 as Weight))322 .saturating_add(RocksDbWeight::get().writes(4 as Weight))354 .saturating_add(RocksDbWeight::get().writes(4 as Weight))323 }355 }324 // Storage: Refungible Balance (r:2 w:2)356 // Storage: Refungible Balance (r:2 w:2)325 // Storage: Refungible AccountBalance (r:2 w:2)357 // Storage: Refungible AccountBalance (r:2 w:2)326 // Storage: Refungible Owned (r:0 w:2)358 // Storage: Refungible Owned (r:0 w:2)327 fn transfer_creating_removing() -> Weight {359 fn transfer_creating_removing() -> Weight {328 (24_866_000 as Weight)360 (24_936_000 as Weight)329 .saturating_add(RocksDbWeight::get().reads(4 as Weight))361 .saturating_add(RocksDbWeight::get().reads(4 as Weight))330 .saturating_add(RocksDbWeight::get().writes(6 as Weight))362 .saturating_add(RocksDbWeight::get().writes(6 as Weight))331 }363 }332 // Storage: Refungible Balance (r:1 w:0)364 // Storage: Refungible Balance (r:1 w:0)333 // Storage: Refungible Allowance (r:0 w:1)365 // Storage: Refungible Allowance (r:0 w:1)334 fn approve() -> Weight {366 fn approve() -> Weight {335 (13_475_000 as Weight)367 (13_446_000 as Weight)336 .saturating_add(RocksDbWeight::get().reads(1 as Weight))368 .saturating_add(RocksDbWeight::get().reads(1 as Weight))337 .saturating_add(RocksDbWeight::get().writes(1 as Weight))369 .saturating_add(RocksDbWeight::get().writes(1 as Weight))338 }370 }339 // Storage: Refungible Allowance (r:1 w:1)371 // Storage: Refungible Allowance (r:1 w:1)340 // Storage: Refungible Balance (r:2 w:2)372 // Storage: Refungible Balance (r:2 w:2)341 fn transfer_from_normal() -> Weight {373 fn transfer_from_normal() -> Weight {342 (24_707_000 as Weight)374 (24_777_000 as Weight)343 .saturating_add(RocksDbWeight::get().reads(3 as Weight))375 .saturating_add(RocksDbWeight::get().reads(3 as Weight))344 .saturating_add(RocksDbWeight::get().writes(3 as Weight))376 .saturating_add(RocksDbWeight::get().writes(3 as Weight))345 }377 }348 // Storage: Refungible AccountBalance (r:1 w:1)380 // Storage: Refungible AccountBalance (r:1 w:1)349 // Storage: Refungible Owned (r:0 w:1)381 // Storage: Refungible Owned (r:0 w:1)350 fn transfer_from_creating() -> Weight {382 fn transfer_from_creating() -> Weight {351 (27_812_000 as Weight)383 (28_483_000 as Weight)352 .saturating_add(RocksDbWeight::get().reads(4 as Weight))384 .saturating_add(RocksDbWeight::get().reads(4 as Weight))353 .saturating_add(RocksDbWeight::get().writes(5 as Weight))385 .saturating_add(RocksDbWeight::get().writes(5 as Weight))354 }386 }357 // Storage: Refungible AccountBalance (r:1 w:1)389 // Storage: Refungible AccountBalance (r:1 w:1)358 // Storage: Refungible Owned (r:0 w:1)390 // Storage: Refungible Owned (r:0 w:1)359 fn transfer_from_removing() -> Weight {391 fn transfer_from_removing() -> Weight {360 (29_966_000 as Weight)392 (29_896_000 as Weight)361 .saturating_add(RocksDbWeight::get().reads(4 as Weight))393 .saturating_add(RocksDbWeight::get().reads(4 as Weight))362 .saturating_add(RocksDbWeight::get().writes(5 as Weight))394 .saturating_add(RocksDbWeight::get().writes(5 as Weight))363 }395 }366 // Storage: Refungible AccountBalance (r:2 w:2)398 // Storage: Refungible AccountBalance (r:2 w:2)367 // Storage: Refungible Owned (r:0 w:2)399 // Storage: Refungible Owned (r:0 w:2)368 fn transfer_from_creating_removing() -> Weight {400 fn transfer_from_creating_removing() -> Weight {369 (31_660_000 as Weight)401 (32_070_000 as Weight)370 .saturating_add(RocksDbWeight::get().reads(5 as Weight))402 .saturating_add(RocksDbWeight::get().reads(5 as Weight))371 .saturating_add(RocksDbWeight::get().writes(7 as Weight))403 .saturating_add(RocksDbWeight::get().writes(7 as Weight))372 }404 }377 // Storage: Refungible TokensBurnt (r:1 w:1)409 // Storage: Refungible TokensBurnt (r:1 w:1)378 // Storage: Refungible TokenData (r:0 w:1)410 // Storage: Refungible TokenData (r:0 w:1)379 // Storage: Refungible Owned (r:0 w:1)411 // Storage: Refungible Owned (r:0 w:1)412 // Storage: Refungible TokenProperties (r:0 w:1)380 fn burn_from() -> Weight {413 fn burn_from() -> Weight {381 (36_248_000 as Weight)414 (36_789_000 as Weight)382 .saturating_add(RocksDbWeight::get().reads(5 as Weight))415 .saturating_add(RocksDbWeight::get().reads(5 as Weight))383 .saturating_add(RocksDbWeight::get().writes(7 as Weight))416 .saturating_add(RocksDbWeight::get().writes(8 as Weight))417 }418 // Storage: Common CollectionPropertyPermissions (r:1 w:1)419 fn set_token_property_permissions(b: u32, ) -> Weight {420 (0 as Weight)421 // Standard Error: 62_000422 .saturating_add((15_803_000 as Weight).saturating_mul(b as Weight))423 .saturating_add(RocksDbWeight::get().reads(1 as Weight))424 .saturating_add(RocksDbWeight::get().writes(1 as Weight))425 }426 // Storage: Common CollectionPropertyPermissions (r:1 w:0)427 // Storage: Refungible TokenProperties (r:1 w:1)428 fn set_token_properties(b: u32, ) -> Weight {429 (0 as Weight)430 // Standard Error: 1_668_000431 .saturating_add((302_308_000 as Weight).saturating_mul(b as Weight))432 .saturating_add(RocksDbWeight::get().reads(2 as Weight))433 .saturating_add(RocksDbWeight::get().writes(1 as Weight))434 }435 // Storage: Common CollectionPropertyPermissions (r:1 w:0)436 // Storage: Refungible TokenProperties (r:1 w:1)437 fn delete_token_properties(b: u32, ) -> Weight {438 (0 as Weight)439 // Standard Error: 1_619_000440 .saturating_add((294_574_000 as Weight).saturating_mul(b as Weight))441 .saturating_add(RocksDbWeight::get().reads(2 as Weight))442 .saturating_add(RocksDbWeight::get().writes(1 as Weight))384 }443 }385 // Storage: Refungible TotalSupply (r:1 w:1)444 // Storage: Refungible TotalSupply (r:1 w:1)386 // Storage: Refungible Balance (r:1 w:1)445 // Storage: Refungible Balance (r:1 w:1)387 fn repartition_item() -> Weight {446 fn repartition_item() -> Weight {388 (8_226_000 as Weight)447 (8_325_000 as Weight)389 .saturating_add(RocksDbWeight::get().reads(2 as Weight))448 .saturating_add(RocksDbWeight::get().reads(2 as Weight))390 .saturating_add(RocksDbWeight::get().writes(2 as Weight))449 .saturating_add(RocksDbWeight::get().writes(2 as Weight))391 }450 }pallets/scheduler/src/lib.rsdiffbeforeafterboth24// you may not use this file except in compliance with the License.24// you may not use this file except in compliance with the License.25// You may obtain a copy of the License at25// You may obtain a copy of the License at26//26//27// http://www.apache.org/licenses/LICENSE-2.027// <http://www.apache.org/licenses/LICENSE-2.0>28//28//29// Unless required by applicable law or agreed to in writing, software29// Unless required by applicable law or agreed to in writing, software30// distributed under the License is distributed on an "AS IS" BASIS,30// distributed under the License is distributed on an "AS IS" BASIS,31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.32// See the License for the specific language governing permissions and32// See the License for the specific language governing permissions and33// limitations under the License.33// limitations under the License.343435//! # Schedulerdo_reschedule35//! # Unique scheduler36//! A Pallet for scheduling dispatches.37//!38//! - [`Config`]39//! - [`Call`]40//! - [`Pallet`]41//!42//! ## Overview36//!43//!37//! This Pallet exposes capabilities for scheduling dispatches to occur at a44//! This Pallet exposes capabilities for scheduling dispatches to occur at a38//! specified block number or at a specified period. These scheduled dispatches45//! specified block number or at a specified period. These scheduled dispatches39//! may be named or anonymous and may be canceled.46//! should be named and may be canceled.40//!47//!41//! **NOTE:** The scheduled calls will be dispatched with the default filter48//! **NOTE:** The unique scheduler is designed for deferred transaction calls by block number.42//! for the origin: namely `frame_system::Config::BaseCallFilter` for all origin49//! Any user can book a call of a certain transaction to a specific block number.43//! except root which will get no filter. And not the filter contained in origin50//! Also possible to book a call with a certain frequency.44//! use to call `fn schedule`.45//!51//!46//! If a call is scheduled using proxy or whatever mecanism which adds filter,52//! Key differences from the original pallet:47//! then those filter will not be used when dispatching the schedule call.53//! <https://crates.io/crates/pallet-scheduler>54//! Schedule Id restricted by 16 bytes. Identificator for booked call.55//! Priority limited by HARD DEADLINE (<= 63). Calls over maximum weight don't include to block.56//! The maximum weight that may be scheduled per block for any dispatchables of less priority than `schedule::HARD_DEADLINE`.57//! Maybe_periodic limit is 100 calls. Reserved for future sponsored transaction support.58//! At 100 calls reserved amount is not so much and this is avoid potential problems with balance locks.59//! Any account allowed to schedule any calls. Account withdraw implemented through default transaction logic.48//!60//!49//! ## Interface61//! ## Interface50//!62//!51//! ### Dispatchable Functions63//! ### Dispatchable Functions52//!64//!53//! * `schedule` - schedule a dispatch, which may be periodic, to occur at a specified block and54//! with a specified priority.55//! * `cancel` - cancel a scheduled dispatch, specified by block number and index.56//! * `schedule_named` - augments the `schedule` interface with an additional `Vec<u8>` parameter65//! * `schedule_named` - augments the `schedule` interface with an additional `Vec<u8>` parameter57//! that can be used for identification.66//! that can be used for identification.58//! * `cancel_named` - the named complement to the cancel function.67//! * `cancel_named` - the named complement to the cancel function.258267259 /// A Scheduler-Runtime interface for finer payment handling.268 /// A Scheduler-Runtime interface for finer payment handling.260 pub trait DispatchCall<T: frame_system::Config + Config, SelfContainedSignedInfo> {269 pub trait DispatchCall<T: frame_system::Config + Config, SelfContainedSignedInfo> {261 /// Reserve the maximum spendings on a call.270 /// Reserve (lock) the maximum spendings on a call, calculated from its weight and the repetition count.262 fn reserve_balance(271 fn reserve_balance(263 id: ScheduledId,272 id: ScheduledId,264 sponsor: <T as frame_system::Config>::AccountId,273 sponsor: <T as frame_system::Config>::AccountId,265 call: <T as Config>::Call,274 call: <T as Config>::Call,266 count: u32,275 count: u32,267 ) -> Result<(), DispatchError>;276 ) -> Result<(), DispatchError>;268277269 /// Pay for call dispatch (un-reserve) from the reserved funds, returning the change.278 /// Unreserve (unlock) a certain amount from the payer's reserved funds, returning the change.270 fn pay_for_call(279 fn pay_for_call(271 id: ScheduledId,280 id: ScheduledId,272 sponsor: <T as frame_system::Config>::AccountId,281 sponsor: <T as frame_system::Config>::AccountId,282 TransactionValidityError,291 TransactionValidityError,283 >;292 >;284293285 /// Release reserved funds.294 /// Release unspent reserved funds in case of a schedule cancel.286 fn cancel_reserve(295 fn cancel_reserve(287 id: ScheduledId,296 id: ScheduledId,288 sponsor: <T as frame_system::Config>::AccountId,297 sponsor: <T as frame_system::Config>::AccountId,441 // );450 // );442 // }451 // }443452453 // Execute transaction via chain default pipeline454 // That means dispatch will be processed like any user's extrinsic e.g. transaction fees will be taken444 let r = T::CallExecutor::dispatch_call(sender, call.clone());455 let r = T::CallExecutor::dispatch_call(sender, call.clone());445456446 let mut actual_call_weight: Weight = item_weight;457 let mut actual_call_weight: Weight = item_weight;485 Agenda::<T>::append(wake, Some(s));496 Agenda::<T>::append(wake, Some(s));486 }497 }487 }498 }499 // Total weight should be 0, because the transaction is already paid for488 0500 0489 //total_weight490 }501 }491 }502 }492503pallets/structure/src/benchmarking.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161use super::*;17use super::*;218pallets/structure/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Structure Pallet18//!19//! The Structure pallet provides functionality for handling tokens nesting an unnesting.20//!21//! - [`Config`]22//! - [`Pallet`]23//!24//! ## Overview25//!26//! The Structure pallet provides functions for:27//!28//! - Searching for token parents, children and owners. Actual implementation of searching for29//! parent/child is done by pallets corresponding to token's collection type.30//! - Nesting and unnesting tokens. Actual implementation of nesting is done by pallets corresponding31//! to token's collection type.32//!33//! ### Terminology34//!35//! - **Nesting:** Setting up parent-child relationship between tokens. Nested tokens are inhereting36//! owner from their parent. There could be multiple levels of nesting. Token couldn't be nested in37//! it's child token i.e. parent-child relationship graph shouldn't have38//!39//! - **Parent:** Token that current token is nested in.40//!41//! - **Owner:** Account that owns the token and all nested tokens.42//!43//! ## Interface44//!45//! ### Available Functions46//!47//! - `find_parent` - Find parent of the token. It could be an account or another token.48//! - `parent_chain` - Find chain of parents of the token.49//! - `find_topmost_owner` - Find account or token in the end of the chain of parents.50//! - `check_nesting` - Check if the token could be nested in the other token51//! - `nest_if_sent_to_token` - Nest the token in the other token52//! - `unnest_if_nested` - Unnest the token from the other token531#![cfg_attr(not(feature = "std"), no_std)]54#![cfg_attr(not(feature = "std"), no_std)]25582}135}8313684impl<T: Config> Pallet<T> {137impl<T: Config> Pallet<T> {138 /// Find account owning the `token` or a token that the `token` is nested in.139 ///140 /// Returns the enum that have three variants:141 /// - [`User`](crate::Parent<T>::User): Contains account.142 /// - [`Token`](crate::Parent<T>::Token): Contains token id and collection id.143 /// - [`TokenNotFound`](crate::Parent<T>::TokenNotFound): Indicates that parent was not found85 pub fn find_parent(144 pub fn find_parent(86 collection: CollectionId,145 collection: CollectionId,87 token: TokenId,146 token: TokenId,103 })162 })104 }163 }105164165 /// Get the chain of parents of a token in the nesting hierarchy166 ///167 /// Returns an iterator of addresses of the owning tokens and the owning account,168 /// starting from the immediate parent token, ending with the account.169 /// Returns error if cycle is detected.106 pub fn parent_chain(170 pub fn parent_chain(107 mut collection: CollectionId,171 mut collection: CollectionId,108 mut token: TokenId,172 mut token: TokenId,133 /// Try to dereference address, until finding top level owner197 /// Try to dereference address, until finding top level owner134 ///198 ///135 /// May return token address if parent token not yet exists199 /// May return token address if parent token not yet exists200 ///201 /// - `budget`: Limit for searching parents in depth.136 pub fn find_topmost_owner(202 pub fn find_topmost_owner(137 collection: CollectionId,203 collection: CollectionId,138 token: TokenId,204 token: TokenId,149 })215 })150 }216 }151217218 /// Find the topmost parent and check that assigning `for_nest` token as a child for219 /// `token` wouldn't create a cycle.220 ///221 /// - `budget`: Limit for searching parents in depth.152 pub fn get_checked_topmost_owner(222 pub fn get_checked_topmost_owner(153 collection: CollectionId,223 collection: CollectionId,154 token: TokenId,224 token: TokenId,177 Err(<Error<T>>::DepthLimit.into())247 Err(<Error<T>>::DepthLimit.into())178 }248 }179249250 /// Burn token and all of it's nested tokens251 ///252 /// - `self_budget`: Limit for searching children in depth.253 /// - `breadth_budget`: Limit of breadth of searching children.180 pub fn burn_item_recursively(254 pub fn burn_item_recursively(181 from: T::CrossAccountId,255 from: T::CrossAccountId,182 collection: CollectionId,256 collection: CollectionId,190 dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)264 dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)191 }265 }192266193 /// Check if token indirectly owned by specified user267 /// Check if `token` indirectly owned by `user`268 ///269 /// Returns `true` if `user` is `token`'s owner. Or If token is provided as `user` then270 /// check that `user` and `token` have same owner.271 /// Checks that assigning `for_nest` token as a child for `token` wouldn't create a cycle.272 ///273 /// - `budget`: Limit for searching parents in depth.194 pub fn check_indirectly_owned(274 pub fn check_indirectly_owned(195 user: T::CrossAccountId,275 user: T::CrossAccountId,196 collection: CollectionId,276 collection: CollectionId,207 .map(|indirect_owner| indirect_owner == target_parent)287 .map(|indirect_owner| indirect_owner == target_parent)208 }288 }209289290 /// Checks that `under` is valid token and that `token_id` could be nested under it291 /// and that `from` is `under`'s owner292 ///293 /// Returns OK if `under` is not a token294 ///295 /// - `nesting_budget`: Limit for searching parents in depth.210 pub fn check_nesting(296 pub fn check_nesting(211 from: T::CrossAccountId,297 from: T::CrossAccountId,212 under: &T::CrossAccountId,298 under: &T::CrossAccountId,219 })305 })220 }306 }221307308 /// Nests `token_id` under `under` token309 ///310 /// Returns OK if `under` is not a token. Checks that nesting is possible.311 ///312 /// - `nesting_budget`: Limit for searching parents in depth.222 pub fn nest_if_sent_to_token(313 pub fn nest_if_sent_to_token(223 from: T::CrossAccountId,314 from: T::CrossAccountId,224 under: &T::CrossAccountId,315 under: &T::CrossAccountId,235 })326 })236 }327 }237328329 /// Nests `token_id` under `owner` token330 ///331 /// Caller should check that nesting wouldn't cause recursion in nesting238 pub fn nest_if_sent_to_token_unchecked(332 pub fn nest_if_sent_to_token_unchecked(239 owner: &T::CrossAccountId,333 owner: &T::CrossAccountId,240 collection_id: CollectionId,334 collection_id: CollectionId,245 });339 });246 }340 }247341342 /// Unnests `token_id` from `owner`.248 pub fn unnest_if_nested(343 pub fn unnest_if_nested(249 owner: &T::CrossAccountId,344 owner: &T::CrossAccountId,250 collection_id: CollectionId,345 collection_id: CollectionId,pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
primitives/data-structs/Cargo.tomldiffbeforeafterboth6license = 'GPLv3'6license = 'GPLv3'7homepage = "https://unique.network"7homepage = "https://unique.network"8repository = 'https://github.com/UniqueNetwork/unique-chain'8repository = 'https://github.com/UniqueNetwork/unique-chain'9version = '0.1.0'9version = '0.1.1'101011[dependencies]11[dependencies]12scale-info = { version = "2.0.1", default-features = false, features = [12scale-info = { version = "2.0.1", default-features = false, features = [primitives/data-structs/Changelog.mddiffbeforeafterbothno changes
primitives/data-structs/src/lib.rsdiffbeforeafterboth566 /// Number of pieces the RFT is split into567 /// Number of pieces the RFT is split into567 pub pieces: u128,568 pub pieces: u128,569570 /// Key-value pairs used to describe the token as metadata571 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]572 #[derivative(Debug(format_with = "bounded::vec_debug"))]573 pub properties: CollectionPropertiesVec,568}574}569575570#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]576#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]601 pub const_data: BoundedVec<u8, CustomDataLimit>,607 pub const_data: BoundedVec<u8, CustomDataLimit>,602 #[derivative(Debug(format_with = "bounded::map_debug"))]608 #[derivative(Debug(format_with = "bounded::map_debug"))]603 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,609 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,610 #[derivative(Debug(format_with = "bounded::vec_debug"))]611 pub properties: CollectionPropertiesVec,604}612}605613606/// Explicit item creation data with meta parameters, namely the owner.614/// Explicit item creation data with meta parameters, namely the owner.primitives/rpc/CHANGELOG.mddiffbeforeafterbothno changes
primitives/rpc/Cargo.tomldiffbeforeafterboth1[package]1[package]2name = "up-rpc"2name = "up-rpc"3version = "0.1.0"3version = "0.1.1"4license = "GPLv3"4license = "GPLv3"5edition = "2021"5edition = "2021"66primitives/rpc/src/lib.rsdiffbeforeafterboth81 fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>>;81 fn next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Result<Option<u64>>;82 fn effective_collection_limits(collection_id: CollectionId) -> Result<Option<CollectionLimits>>;82 fn effective_collection_limits(collection_id: CollectionId) -> Result<Option<CollectionLimits>>;83 fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Result<Option<u128>>;83 fn total_pieces(collection_id: CollectionId, token_id: TokenId) -> Result<Option<u128>>;84 fn token_owners(collection: CollectionId, token: TokenId) -> Result<Vec<CrossAccountId>>;84 }85 }85}86}8687runtime/common/CHANGELOG.mddiffbeforeafterbothno changes
runtime/common/src/dispatch.rsdiffbeforeafterboth25pub use pallet_common::dispatch::CollectionDispatch;25pub use pallet_common::dispatch::CollectionDispatch;26use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};26use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};27use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};27use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};28use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle, erc::RefungibleTokenHandle};28use pallet_refungible::{29 Pallet as PalletRefungible, RefungibleHandle, erc_token::RefungibleTokenHandle,30};29use up_data_structs::{31use up_data_structs::{30 CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,32 CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,runtime/common/src/runtime_apis.rsdiffbeforeafterboth41 dispatch_unique_runtime!(collection.token_owner(token))41 dispatch_unique_runtime!(collection.token_owner(token))42 }42 }4344 fn token_owners(collection: CollectionId, token: TokenId) -> Result<Vec::<CrossAccountId>, DispatchError> {45 dispatch_unique_runtime!(collection.token_owners(token))46 }4743 fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {48 fn topmost_token_owner(collection: CollectionId, token: TokenId) -> Result<Option<CrossAccountId>, DispatchError> {44 let budget = up_data_structs::budget::Value::new(10);49 let budget = up_data_structs::budget::Value::new(10);runtime/tests/src/tests.rsdiffbeforeafterboth64 CreateReFungibleData {64 CreateReFungibleData {65 const_data: vec![1, 2, 3].try_into().unwrap(),65 const_data: vec![1, 2, 3].try_into().unwrap(),66 pieces: 1023,66 pieces: 1023,67 properties: vec![Property {68 key: b"test-prop".to_vec().try_into().unwrap(),69 value: b"test-nft-prop".to_vec().try_into().unwrap(),70 }]71 .try_into()72 .unwrap(),67 }73 }68}74}6975tests/CHANGELOG.mddiffbeforeafterbothno changes
tests/package.jsondiffbeforeafterboth80 "testLimits": "mocha --timeout 9999999 -r ts-node/register ./**/limits.test.ts",80 "testLimits": "mocha --timeout 9999999 -r ts-node/register ./**/limits.test.ts",81 "testEthCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createCollection.test.ts",81 "testEthCreateCollection": "mocha --timeout 9999999 -r ts-node/register ./**/eth/createCollection.test.ts",82 "testRFT": "mocha --timeout 9999999 -r ts-node/register ./**/refungible.test.ts",82 "testRFT": "mocha --timeout 9999999 -r ts-node/register ./**/refungible.test.ts",83 "testFT": "mocha --timeout 9999999 -r ts-node/register ./**/fungible.test.ts",84 "testRPC": "mocha --timeout 9999999 -r ts-node/register ./**/rpc.test.ts",83 "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",85 "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",84 "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --endpoint src/interfaces/metadata.json --input src/interfaces/ --package .",86 "polkadot-types-from-defs": "ts-node ./node_modules/.bin/polkadot-types-from-defs --endpoint src/interfaces/metadata.json --input src/interfaces/ --package .",85 "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint src/interfaces/metadata.json --output src/interfaces/ --package .",87 "polkadot-types-from-chain": "ts-node ./node_modules/.bin/polkadot-types-from-chain --endpoint src/interfaces/metadata.json --output src/interfaces/ --package .",tests/src/createMultipleItems.test.tsdiffbeforeafterboth376 // ReFungible376 // ReFungible377 const collectionIdReFungible =377 const collectionIdReFungible =378 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});378 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});379 {379 const argsReFungible = [380 const argsReFungible = [380 {ReFungible: ['1'.repeat(2049), 10]},381 {ReFungible: ['1'.repeat(2049), 10, []]},381 {ReFungible: ['2'.repeat(2049), 10]},382 {ReFungible: ['2'.repeat(2049), 10, []]},382 {ReFungible: ['3'.repeat(2049), 10]},383 {ReFungible: ['3'.repeat(2049), 10, []]},383 ];384 ];384 const createMultipleItemsTxFungible = api.tx.unique385 const createMultipleItemsTxFungible = api.tx.unique385 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);386 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);386 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;387 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;388 }389 {390 const argsReFungible = [391 {ReFungible: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},392 {ReFungible: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},393 {ReFungible: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},394 ];395 const createMultipleItemsTxFungible = api.tx.unique396 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);397 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;398 }387 });399 });388 });400 });389401tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth28 function burnFrom(address from, uint256 amount) external returns (bool);28 function burnFrom(address from, uint256 amount) external returns (bool);29}29}3031// Selector: 7d9262e632interface Collection is Dummy, ERC165 {33 // Set collection property.34 //35 // @param key Property key.36 // @param value Propery value.37 //38 // Selector: setCollectionProperty(string,bytes) 2f073f6639 function setCollectionProperty(string memory key, bytes memory value)40 external;4142 // Delete collection property.43 //44 // @param key Property key.45 //46 // Selector: deleteCollectionProperty(string) 7b7debce47 function deleteCollectionProperty(string memory key) external;4849 // Get collection property.50 //51 // @dev Throws error if key not found.52 //53 // @param key Property key.54 // @return bytes The property corresponding to the key.55 //56 // Selector: collectionProperty(string) cf24fd6d57 function collectionProperty(string memory key)58 external59 view60 returns (bytes memory);6162 // Set the sponsor of the collection.63 //64 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.65 //66 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.67 //68 // Selector: setCollectionSponsor(address) 7623402e69 function setCollectionSponsor(address sponsor) external;7071 // Collection sponsorship confirmation.72 //73 // @dev After setting the sponsor for the collection, it must be confirmed with this function.74 //75 // Selector: confirmCollectionSponsorship() 3c50e97a76 function confirmCollectionSponsorship() external;7778 // Set limits for the collection.79 // @dev Throws error if limit not found.80 // @param limit Name of the limit. Valid names:81 // "accountTokenOwnershipLimit",82 // "sponsoredDataSize",83 // "sponsoredDataRateLimit",84 // "tokenLimit",85 // "sponsorTransferTimeout",86 // "sponsorApproveTimeout"87 // @param value Value of the limit.88 //89 // Selector: setCollectionLimit(string,uint32) 6a3841db90 function setCollectionLimit(string memory limit, uint32 value) external;9192 // Set limits for the collection.93 // @dev Throws error if limit not found.94 // @param limit Name of the limit. Valid names:95 // "ownerCanTransfer",96 // "ownerCanDestroy",97 // "transfersEnabled"98 // @param value Value of the limit.99 //100 // Selector: setCollectionLimit(string,bool) 993b7fba101 function setCollectionLimit(string memory limit, bool value) external;102103 // Get contract address.104 //105 // Selector: contractAddress() f6b4dfb4106 function contractAddress() external view returns (address);107108 // Add collection admin by substrate address.109 // @param new_admin Substrate administrator address.110 //111 // Selector: addCollectionAdminSubstrate(uint256) 5730062b112 function addCollectionAdminSubstrate(uint256 newAdmin) external;113114 // Remove collection admin by substrate address.115 // @param admin Substrate administrator address.116 //117 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9118 function removeCollectionAdminSubstrate(uint256 admin) external;119120 // Add collection admin.121 // @param new_admin Address of the added administrator.122 //123 // Selector: addCollectionAdmin(address) 92e462c7124 function addCollectionAdmin(address newAdmin) external;125126 // Remove collection admin.127 //128 // @param new_admin Address of the removed administrator.129 //130 // Selector: removeCollectionAdmin(address) fafd7b42131 function removeCollectionAdmin(address admin) external;132133 // Toggle accessibility of collection nesting.134 //135 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'136 //137 // Selector: setCollectionNesting(bool) 112d4586138 function setCollectionNesting(bool enable) external;139140 // Toggle accessibility of collection nesting.141 //142 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'143 // @param collections Addresses of collections that will be available for nesting.144 //145 // Selector: setCollectionNesting(bool,address[]) 64872396146 function setCollectionNesting(bool enable, address[] memory collections)147 external;148149 // Set the collection access method.150 // @param mode Access mode151 // 0 for Normal152 // 1 for AllowList153 //154 // Selector: setCollectionAccess(uint8) 41835d4c155 function setCollectionAccess(uint8 mode) external;156157 // Add the user to the allowed list.158 //159 // @param user Address of a trusted user.160 //161 // Selector: addToCollectionAllowList(address) 67844fe6162 function addToCollectionAllowList(address user) external;163164 // Remove the user from the allowed list.165 //166 // @param user Address of a removed user.167 //168 // Selector: removeFromCollectionAllowList(address) 85c51acb169 function removeFromCollectionAllowList(address user) external;170171 // Switch permission for minting.172 //173 // @param mode Enable if "true".174 //175 // Selector: setCollectionMintMode(bool) 00018e84176 function setCollectionMintMode(bool mode) external;177}3017831// Selector: 942e8b22179// Selector: 942e8b2232interface ERC20 is Dummy, ERC165, ERC20Events {180interface ERC20 is Dummy, ERC165, ERC20Events {65 returns (uint256);213 returns (uint256);66}214}6768// Selector: c894dc3569interface Collection is Dummy, ERC165 {70 // Selector: setCollectionProperty(string,bytes) 2f073f6671 function setCollectionProperty(string memory key, bytes memory value)72 external;7374 // Selector: deleteCollectionProperty(string) 7b7debce75 function deleteCollectionProperty(string memory key) external;7677 // Throws error if key not found78 //79 // Selector: collectionProperty(string) cf24fd6d80 function collectionProperty(string memory key)81 external82 view83 returns (bytes memory);8485 // Selector: ethSetSponsor(address) 8f9af35686 function ethSetSponsor(address sponsor) external;8788 // Selector: ethConfirmSponsorship() a8580d1a89 function ethConfirmSponsorship() external;9091 // Selector: setLimit(string,uint32) 68db30ca92 function setLimit(string memory limit, uint32 value) external;9394 // Selector: setLimit(string,bool) ea67e4c295 function setLimit(string memory limit, bool value) external;9697 // Selector: contractAddress() f6b4dfb498 function contractAddress() external view returns (address);99}100215101interface UniqueFungible is216interface UniqueFungible is102 Dummy,217 Dummy,tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth444445// Selector: 4136937745// Selector: 4136937746interface TokenProperties is Dummy, ERC165 {46interface TokenProperties is Dummy, ERC165 {47 // @notice Set permissions for token property.48 // @dev Throws error if `msg.sender` is not admin or owner of the collection.49 // @param key Property key.50 // @param is_mutable Permission to mutate property.51 // @param collection_admin Permission to mutate property by collection admin if property is mutable.52 // @param token_owner Permission to mutate property by token owner if property is mutable.53 //47 // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa54 // Selector: setTokenPropertyPermission(string,bool,bool,bool) 222d97fa48 function setTokenPropertyPermission(55 function setTokenPropertyPermission(49 string memory key,56 string memory key,52 bool tokenOwner59 bool tokenOwner53 ) external;60 ) external;546162 // @notice Set token property value.63 // @dev Throws error if `msg.sender` has no permission to edit the property.64 // @param tokenId ID of the token.65 // @param key Property key.66 // @param value Property value.67 //55 // Selector: setProperty(uint256,string,bytes) 1752d67b68 // Selector: setProperty(uint256,string,bytes) 1752d67b56 function setProperty(69 function setProperty(57 uint256 tokenId,70 uint256 tokenId,58 string memory key,71 string memory key,59 bytes memory value72 bytes memory value60 ) external;73 ) external;617475 // @notice Delete token property value.76 // @dev Throws error if `msg.sender` has no permission to edit the property.77 // @param tokenId ID of the token.78 // @param key Property key.79 //62 // Selector: deleteProperty(uint256,string) 066111d180 // Selector: deleteProperty(uint256,string) 066111d163 function deleteProperty(uint256 tokenId, string memory key) external;81 function deleteProperty(uint256 tokenId, string memory key) external;648283 // @notice Get token property value.65 // Throws error if key not found84 // @dev Throws error if key not found85 // @param tokenId ID of the token.86 // @param key Property key.87 // @return Property value bytes66 //88 //67 // Selector: property(uint256,string) 7228c32789 // Selector: property(uint256,string) 7228c32768 function property(uint256 tokenId, string memory key)90 function property(uint256 tokenId, string memory key)739574// Selector: 42966c6896// Selector: 42966c6875interface ERC721Burnable is Dummy, ERC165 {97interface ERC721Burnable is Dummy, ERC165 {98 // @notice Burns a specific ERC721 token.99 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized100 // operator of the current owner.101 // @param tokenId The NFT to approve102 //76 // Selector: burn(uint256) 42966c68103 // Selector: burn(uint256) 42966c6877 function burn(uint256 tokenId) external;104 function burn(uint256 tokenId) external;78}105}7910680// Selector: 58800161107// Selector: 5880016181interface ERC721 is Dummy, ERC165, ERC721Events {108interface ERC721 is Dummy, ERC165, ERC721Events {109 // @notice Count all NFTs assigned to an owner110 // @dev NFTs assigned to the zero address are considered invalid, and this111 // function throws for queries about the zero address.112 // @param owner An address for whom to query the balance113 // @return The number of NFTs owned by `owner`, possibly zero114 //82 // Selector: balanceOf(address) 70a08231115 // Selector: balanceOf(address) 70a0823183 function balanceOf(address owner) external view returns (uint256);116 function balanceOf(address owner) external view returns (uint256);84117118 // @notice Find the owner of an NFT119 // @dev NFTs assigned to zero address are considered invalid, and queries120 // about them do throw.121 // @param tokenId The identifier for an NFT122 // @return The address of the owner of the NFT123 //85 // Selector: ownerOf(uint256) 6352211e124 // Selector: ownerOf(uint256) 6352211e86 function ownerOf(uint256 tokenId) external view returns (address);125 function ownerOf(uint256 tokenId) external view returns (address);8712688 // Not implemented127 // @dev Not implemented89 //128 //90 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672129 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a1167291 function safeTransferFromWithData(130 function safeTransferFromWithData(95 bytes memory data134 bytes memory data96 ) external;135 ) external;9713698 // Not implemented137 // @dev Not implemented99 //138 //100 // Selector: safeTransferFrom(address,address,uint256) 42842e0e139 // Selector: safeTransferFrom(address,address,uint256) 42842e0e101 function safeTransferFrom(140 function safeTransferFrom(104 uint256 tokenId143 uint256 tokenId105 ) external;144 ) external;106145146 // @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE147 // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE148 // THEY MAY BE PERMANENTLY LOST149 // @dev Throws unless `msg.sender` is the current owner or an authorized150 // operator for this NFT. Throws if `from` is not the current owner. Throws151 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.152 // @param from The current owner of the NFT153 // @param to The new owner154 // @param tokenId The NFT to transfer155 // @param _value Not used for an NFT156 //107 // Selector: transferFrom(address,address,uint256) 23b872dd157 // Selector: transferFrom(address,address,uint256) 23b872dd108 function transferFrom(158 function transferFrom(109 address from,159 address from,110 address to,160 address to,111 uint256 tokenId161 uint256 tokenId112 ) external;162 ) external;113163164 // @notice Set or reaffirm the approved address for an NFT165 // @dev The zero address indicates there is no approved address.166 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized167 // operator of the current owner.168 // @param approved The new approved NFT controller169 // @param tokenId The NFT to approve170 //114 // Selector: approve(address,uint256) 095ea7b3171 // Selector: approve(address,uint256) 095ea7b3115 function approve(address approved, uint256 tokenId) external;172 function approve(address approved, uint256 tokenId) external;116173117 // Not implemented174 // @dev Not implemented118 //175 //119 // Selector: setApprovalForAll(address,bool) a22cb465176 // Selector: setApprovalForAll(address,bool) a22cb465120 function setApprovalForAll(address operator, bool approved) external;177 function setApprovalForAll(address operator, bool approved) external;121178122 // Not implemented179 // @dev Not implemented123 //180 //124 // Selector: getApproved(uint256) 081812fc181 // Selector: getApproved(uint256) 081812fc125 function getApproved(uint256 tokenId) external view returns (address);182 function getApproved(uint256 tokenId) external view returns (address);126183127 // Not implemented184 // @dev Not implemented128 //185 //129 // Selector: isApprovedForAll(address,address) e985e9c5186 // Selector: isApprovedForAll(address,address) e985e9c5130 function isApprovedForAll(address owner, address operator)187 function isApprovedForAll(address owner, address operator)135192136// Selector: 5b5e139f193// Selector: 5b5e139f137interface ERC721Metadata is Dummy, ERC165 {194interface ERC721Metadata is Dummy, ERC165 {195 // @notice A descriptive name for a collection of NFTs in this contract196 //138 // Selector: name() 06fdde03197 // Selector: name() 06fdde03139 function name() external view returns (string memory);198 function name() external view returns (string memory);140199200 // @notice An abbreviated name for NFTs in this contract201 //141 // Selector: symbol() 95d89b41202 // Selector: symbol() 95d89b41142 function symbol() external view returns (string memory);203 function symbol() external view returns (string memory);143204205 // @notice A distinct Uniform Resource Identifier (URI) for a given asset.206 // @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC207 // 3986. The URI may point to a JSON file that conforms to the "ERC721208 // Metadata JSON Schema".144 // Returns token's const_metadata209 // @return token's const_metadata145 //210 //146 // Selector: tokenURI(uint256) c87b56dd211 // Selector: tokenURI(uint256) c87b56dd147 function tokenURI(uint256 tokenId) external view returns (string memory);212 function tokenURI(uint256 tokenId) external view returns (string memory);152 // Selector: mintingFinished() 05d2035b217 // Selector: mintingFinished() 05d2035b153 function mintingFinished() external view returns (bool);218 function mintingFinished() external view returns (bool);154219220 // @notice Function to mint token.155 // `token_id` should be obtained with `next_token_id` method,221 // @dev `tokenId` should be obtained with `nextTokenId` method,156 // unlike standard, you can't specify it manually222 // unlike standard, you can't specify it manually223 // @param to The new owner224 // @param tokenId ID of the minted NFT157 //225 //158 // Selector: mint(address,uint256) 40c10f19226 // Selector: mint(address,uint256) 40c10f19159 function mint(address to, uint256 tokenId) external returns (bool);227 function mint(address to, uint256 tokenId) external returns (bool);160228229 // @notice Function to mint token with the given tokenUri.161 // `token_id` should be obtained with `next_token_id` method,230 // @dev `tokenId` should be obtained with `nextTokenId` method,162 // unlike standard, you can't specify it manually231 // unlike standard, you can't specify it manually232 // @param to The new owner233 // @param tokenId ID of the minted NFT234 // @param tokenUri Token URI that would be stored in the NFT properties163 //235 //164 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f236 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f165 function mintWithTokenURI(237 function mintWithTokenURI(168 string memory tokenUri240 string memory tokenUri169 ) external returns (bool);241 ) external returns (bool);170242171 // Not implemented243 // @dev Not implemented172 //244 //173 // Selector: finishMinting() 7d64bcb4245 // Selector: finishMinting() 7d64bcb4174 function finishMinting() external returns (bool);246 function finishMinting() external returns (bool);175}247}176248177// Selector: 780e9d63249// Selector: 780e9d63178interface ERC721Enumerable is Dummy, ERC165 {250interface ERC721Enumerable is Dummy, ERC165 {251 // @notice Enumerate valid NFTs252 // @param index A counter less than `totalSupply()`253 // @return The token identifier for the `index`th NFT,254 // (sort order not specified)255 //179 // Selector: tokenByIndex(uint256) 4f6ccce7256 // Selector: tokenByIndex(uint256) 4f6ccce7180 function tokenByIndex(uint256 index) external view returns (uint256);257 function tokenByIndex(uint256 index) external view returns (uint256);181258182 // Not implemented259 // @dev Not implemented183 //260 //184 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59261 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59185 function tokenOfOwnerByIndex(address owner, uint256 index)262 function tokenOfOwnerByIndex(address owner, uint256 index)186 external263 external187 view264 view188 returns (uint256);265 returns (uint256);189266267 // @notice Count NFTs tracked by this contract268 // @return A count of valid NFTs tracked by this contract, where each one of269 // them has an assigned and queryable owner not equal to the zero address270 //190 // Selector: totalSupply() 18160ddd271 // Selector: totalSupply() 18160ddd191 function totalSupply() external view returns (uint256);272 function totalSupply() external view returns (uint256);192}273}193274194// Selector: 7d9262e6275// Selector: 7d9262e6195interface Collection is Dummy, ERC165 {276interface Collection is Dummy, ERC165 {277 // Set collection property.278 //279 // @param key Property key.280 // @param value Propery value.281 //196 // Selector: setCollectionProperty(string,bytes) 2f073f66282 // Selector: setCollectionProperty(string,bytes) 2f073f66197 function setCollectionProperty(string memory key, bytes memory value)283 function setCollectionProperty(string memory key, bytes memory value)198 external;284 external;199285286 // Delete collection property.287 //288 // @param key Property key.289 //200 // Selector: deleteCollectionProperty(string) 7b7debce290 // Selector: deleteCollectionProperty(string) 7b7debce201 function deleteCollectionProperty(string memory key) external;291 function deleteCollectionProperty(string memory key) external;202292293 // Get collection property.294 //203 // Throws error if key not found295 // @dev Throws error if key not found.296 //297 // @param key Property key.298 // @return bytes The property corresponding to the key.204 //299 //205 // Selector: collectionProperty(string) cf24fd6d300 // Selector: collectionProperty(string) cf24fd6d206 function collectionProperty(string memory key)301 function collectionProperty(string memory key)207 external302 external208 view303 view209 returns (bytes memory);304 returns (bytes memory);210305306 // Set the sponsor of the collection.307 //308 // @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.309 //310 // @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.311 //211 // Selector: setCollectionSponsor(address) 7623402e312 // Selector: setCollectionSponsor(address) 7623402e212 function setCollectionSponsor(address sponsor) external;313 function setCollectionSponsor(address sponsor) external;213314315 // Collection sponsorship confirmation.316 //317 // @dev After setting the sponsor for the collection, it must be confirmed with this function.318 //214 // Selector: confirmCollectionSponsorship() 3c50e97a319 // Selector: confirmCollectionSponsorship() 3c50e97a215 function confirmCollectionSponsorship() external;320 function confirmCollectionSponsorship() external;216321322 // Set limits for the collection.323 // @dev Throws error if limit not found.324 // @param limit Name of the limit. Valid names:325 // "accountTokenOwnershipLimit",326 // "sponsoredDataSize",327 // "sponsoredDataRateLimit",328 // "tokenLimit",329 // "sponsorTransferTimeout",330 // "sponsorApproveTimeout"331 // @param value Value of the limit.332 //217 // Selector: setCollectionLimit(string,uint32) 6a3841db333 // Selector: setCollectionLimit(string,uint32) 6a3841db218 function setCollectionLimit(string memory limit, uint32 value) external;334 function setCollectionLimit(string memory limit, uint32 value) external;219335336 // Set limits for the collection.337 // @dev Throws error if limit not found.338 // @param limit Name of the limit. Valid names:339 // "ownerCanTransfer",340 // "ownerCanDestroy",341 // "transfersEnabled"342 // @param value Value of the limit.343 //220 // Selector: setCollectionLimit(string,bool) 993b7fba344 // Selector: setCollectionLimit(string,bool) 993b7fba221 function setCollectionLimit(string memory limit, bool value) external;345 function setCollectionLimit(string memory limit, bool value) external;222346347 // Get contract address.348 //223 // Selector: contractAddress() f6b4dfb4349 // Selector: contractAddress() f6b4dfb4224 function contractAddress() external view returns (address);350 function contractAddress() external view returns (address);225351352 // Add collection admin by substrate address.353 // @param new_admin Substrate administrator address.354 //226 // Selector: addCollectionAdminSubstrate(uint256) 5730062b355 // Selector: addCollectionAdminSubstrate(uint256) 5730062b227 function addCollectionAdminSubstrate(uint256 newAdmin) external view;356 function addCollectionAdminSubstrate(uint256 newAdmin) external;228357358 // Remove collection admin by substrate address.359 // @param admin Substrate administrator address.360 //229 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9361 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9230 function removeCollectionAdminSubstrate(uint256 newAdmin) external view;362 function removeCollectionAdminSubstrate(uint256 admin) external;231363364 // Add collection admin.365 // @param new_admin Address of the added administrator.366 //232 // Selector: addCollectionAdmin(address) 92e462c7367 // Selector: addCollectionAdmin(address) 92e462c7233 function addCollectionAdmin(address newAdmin) external view;368 function addCollectionAdmin(address newAdmin) external;234369370 // Remove collection admin.371 //372 // @param new_admin Address of the removed administrator.373 //235 // Selector: removeCollectionAdmin(address) fafd7b42374 // Selector: removeCollectionAdmin(address) fafd7b42236 function removeCollectionAdmin(address admin) external view;375 function removeCollectionAdmin(address admin) external;237376377 // Toggle accessibility of collection nesting.378 //379 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'380 //238 // Selector: setCollectionNesting(bool) 112d4586381 // Selector: setCollectionNesting(bool) 112d4586239 function setCollectionNesting(bool enable) external;382 function setCollectionNesting(bool enable) external;240383384 // Toggle accessibility of collection nesting.385 //386 // @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'387 // @param collections Addresses of collections that will be available for nesting.388 //241 // Selector: setCollectionNesting(bool,address[]) 64872396389 // Selector: setCollectionNesting(bool,address[]) 64872396242 function setCollectionNesting(bool enable, address[] memory collections)390 function setCollectionNesting(bool enable, address[] memory collections)243 external;391 external;244392393 // Set the collection access method.394 // @param mode Access mode395 // 0 for Normal396 // 1 for AllowList397 //245 // Selector: setCollectionAccess(uint8) 41835d4c398 // Selector: setCollectionAccess(uint8) 41835d4c246 function setCollectionAccess(uint8 mode) external;399 function setCollectionAccess(uint8 mode) external;247400401 // Add the user to the allowed list.402 //403 // @param user Address of a trusted user.404 //248 // Selector: addToCollectionAllowList(address) 67844fe6405 // Selector: addToCollectionAllowList(address) 67844fe6249 function addToCollectionAllowList(address user) external view;406 function addToCollectionAllowList(address user) external;250407408 // Remove the user from the allowed list.409 //410 // @param user Address of a removed user.411 //251 // Selector: removeFromCollectionAllowList(address) 85c51acb412 // Selector: removeFromCollectionAllowList(address) 85c51acb252 function removeFromCollectionAllowList(address user) external view;413 function removeFromCollectionAllowList(address user) external;253414415 // Switch permission for minting.416 //417 // @param mode Enable if "true".418 //254 // Selector: setCollectionMintMode(bool) 00018e84419 // Selector: setCollectionMintMode(bool) 00018e84255 function setCollectionMintMode(bool mode) external;420 function setCollectionMintMode(bool mode) external;256}421}257422258// Selector: d74d154f423// Selector: d74d154f259interface ERC721UniqueExtensions is Dummy, ERC165 {424interface ERC721UniqueExtensions is Dummy, ERC165 {425 // @notice Transfer ownership of an NFT426 // @dev Throws unless `msg.sender` is the current owner. Throws if `to`427 // is the zero address. Throws if `tokenId` is not a valid NFT.428 // @param to The new owner429 // @param tokenId The NFT to transfer430 // @param _value Not used for an NFT431 //260 // Selector: transfer(address,uint256) a9059cbb432 // Selector: transfer(address,uint256) a9059cbb261 function transfer(address to, uint256 tokenId) external;433 function transfer(address to, uint256 tokenId) external;262434435 // @notice Burns a specific ERC721 token.436 // @dev Throws unless `msg.sender` is the current owner or an authorized437 // operator for this NFT. Throws if `from` is not the current owner. Throws438 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.439 // @param from The current owner of the NFT440 // @param tokenId The NFT to transfer441 // @param _value Not used for an NFT442 //263 // Selector: burnFrom(address,uint256) 79cc6790443 // Selector: burnFrom(address,uint256) 79cc6790264 function burnFrom(address from, uint256 tokenId) external;444 function burnFrom(address from, uint256 tokenId) external;265445446 // @notice Returns next free NFT ID.447 //266 // Selector: nextTokenId() 75794a3c448 // Selector: nextTokenId() 75794a3c267 function nextTokenId() external view returns (uint256);449 function nextTokenId() external view returns (uint256);268450451 // @notice Function to mint multiple tokens.452 // @dev `tokenIds` should be an array of consecutive numbers and first number453 // should be obtained with `nextTokenId` method454 // @param to The new owner455 // @param tokenIds IDs of the minted NFTs456 //269 // Selector: mintBulk(address,uint256[]) 44a9945e457 // Selector: mintBulk(address,uint256[]) 44a9945e270 function mintBulk(address to, uint256[] memory tokenIds)458 function mintBulk(address to, uint256[] memory tokenIds)271 external459 external272 returns (bool);460 returns (bool);273461462 // @notice Function to mint multiple tokens with the given tokenUris.463 // @dev `tokenIds` is array of pairs of token ID and token URI. Token IDs should be consecutive464 // numbers and first number should be obtained with `nextTokenId` method465 // @param to The new owner466 // @param tokens array of pairs of token ID and token URI for minted tokens467 //274 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006468 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006275 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)469 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)276 external470 externaltests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterbothno changes
tests/src/eth/fungibleAbi.jsondiffbeforeafterboth49 "name": "Transfer",49 "name": "Transfer",50 "type": "event"50 "type": "event"51 },51 },52 {53 "inputs": [54 { "internalType": "address", "name": "newAdmin", "type": "address" }55 ],56 "name": "addCollectionAdmin",57 "outputs": [],58 "stateMutability": "nonpayable",59 "type": "function"60 },61 {62 "inputs": [63 { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }64 ],65 "name": "addCollectionAdminSubstrate",66 "outputs": [],67 "stateMutability": "nonpayable",68 "type": "function"69 },70 {71 "inputs": [72 { "internalType": "address", "name": "user", "type": "address" }73 ],74 "name": "addToCollectionAllowList",75 "outputs": [],76 "stateMutability": "nonpayable",77 "type": "function"78 },52 {79 {53 "inputs": [80 "inputs": [54 { "internalType": "address", "name": "owner", "type": "address" },81 { "internalType": "address", "name": "owner", "type": "address" },95 "stateMutability": "view",122 "stateMutability": "view",96 "type": "function"123 "type": "function"97 },124 },125 {126 "inputs": [],127 "name": "confirmCollectionSponsorship",128 "outputs": [],129 "stateMutability": "nonpayable",130 "type": "function"131 },98 {132 {99 "inputs": [],133 "inputs": [],100 "name": "contractAddress",134 "name": "contractAddress",116 "stateMutability": "nonpayable",150 "stateMutability": "nonpayable",117 "type": "function"151 "type": "function"118 },152 },153 {154 "inputs": [],155 "name": "name",156 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],157 "stateMutability": "view",158 "type": "function"159 },160 {161 "inputs": [162 { "internalType": "address", "name": "admin", "type": "address" }163 ],164 "name": "removeCollectionAdmin",165 "outputs": [],166 "stateMutability": "nonpayable",167 "type": "function"168 },119 {169 {120 "inputs": [],170 "inputs": [171 { "internalType": "uint256", "name": "admin", "type": "uint256" }172 ],121 "name": "ethConfirmSponsorship",173 "name": "removeCollectionAdminSubstrate",122 "outputs": [],174 "outputs": [],123 "stateMutability": "nonpayable",175 "stateMutability": "nonpayable",124 "type": "function"176 "type": "function"125 },177 },126 {178 {127 "inputs": [179 "inputs": [128 { "internalType": "address", "name": "sponsor", "type": "address" }180 { "internalType": "address", "name": "user", "type": "address" }129 ],181 ],130 "name": "ethSetSponsor",182 "name": "removeFromCollectionAllowList",131 "outputs": [],183 "outputs": [],132 "stateMutability": "nonpayable",184 "stateMutability": "nonpayable",133 "type": "function"185 "type": "function"134 },186 },135 {187 {136 "inputs": [],188 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],189 "name": "setCollectionAccess",190 "outputs": [],191 "stateMutability": "nonpayable",192 "type": "function"193 },194 {195 "inputs": [137 "name": "name",196 { "internalType": "string", "name": "limit", "type": "string" },197 { "internalType": "uint32", "name": "value", "type": "uint32" }198 ],199 "name": "setCollectionLimit",138 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],200 "outputs": [],201 "stateMutability": "nonpayable",202 "type": "function"203 },204 {205 "inputs": [206 { "internalType": "string", "name": "limit", "type": "string" },207 { "internalType": "bool", "name": "value", "type": "bool" }208 ],209 "name": "setCollectionLimit",210 "outputs": [],139 "stateMutability": "view",211 "stateMutability": "nonpayable",140 "type": "function"212 "type": "function"141 },213 },214 {215 "inputs": [{ "internalType": "bool", "name": "mode", "type": "bool" }],216 "name": "setCollectionMintMode",217 "outputs": [],218 "stateMutability": "nonpayable",219 "type": "function"220 },221 {222 "inputs": [{ "internalType": "bool", "name": "enable", "type": "bool" }],223 "name": "setCollectionNesting",224 "outputs": [],225 "stateMutability": "nonpayable",226 "type": "function"227 },228 {229 "inputs": [230 { "internalType": "bool", "name": "enable", "type": "bool" },231 {232 "internalType": "address[]",233 "name": "collections",234 "type": "address[]"235 }236 ],237 "name": "setCollectionNesting",238 "outputs": [],239 "stateMutability": "nonpayable",240 "type": "function"241 },142 {242 {143 "inputs": [243 "inputs": [144 { "internalType": "string", "name": "key", "type": "string" },244 { "internalType": "string", "name": "key", "type": "string" },151 },251 },152 {252 {153 "inputs": [253 "inputs": [154 { "internalType": "string", "name": "limit", "type": "string" },254 { "internalType": "address", "name": "sponsor", "type": "address" }155 { "internalType": "uint32", "name": "value", "type": "uint32" }156 ],255 ],157 "name": "setLimit",256 "name": "setCollectionSponsor",158 "outputs": [],257 "outputs": [],159 "stateMutability": "nonpayable",258 "stateMutability": "nonpayable",160 "type": "function"259 "type": "function"161 },260 },162 {163 "inputs": [164 { "internalType": "string", "name": "limit", "type": "string" },165 { "internalType": "bool", "name": "value", "type": "bool" }166 ],167 "name": "setLimit",168 "outputs": [],169 "stateMutability": "nonpayable",170 "type": "function"171 },172 {261 {173 "inputs": [262 "inputs": [174 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }263 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth86 ],86 ],87 "name": "addCollectionAdmin",87 "name": "addCollectionAdmin",88 "outputs": [],88 "outputs": [],89 "stateMutability": "view",89 "stateMutability": "nonpayable",90 "type": "function"90 "type": "function"91 },91 },92 {92 {95 ],95 ],96 "name": "addCollectionAdminSubstrate",96 "name": "addCollectionAdminSubstrate",97 "outputs": [],97 "outputs": [],98 "stateMutability": "view",98 "stateMutability": "nonpayable",99 "type": "function"99 "type": "function"100 },100 },101 {101 {104 ],104 ],105 "name": "addToCollectionAllowList",105 "name": "addToCollectionAllowList",106 "outputs": [],106 "outputs": [],107 "stateMutability": "view",107 "stateMutability": "nonpayable",108 "type": "function"108 "type": "function"109 },109 },110 {110 {304 ],304 ],305 "name": "removeCollectionAdmin",305 "name": "removeCollectionAdmin",306 "outputs": [],306 "outputs": [],307 "stateMutability": "view",307 "stateMutability": "nonpayable",308 "type": "function"308 "type": "function"309 },309 },310 {310 {311 "inputs": [311 "inputs": [312 { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }312 { "internalType": "uint256", "name": "admin", "type": "uint256" }313 ],313 ],314 "name": "removeCollectionAdminSubstrate",314 "name": "removeCollectionAdminSubstrate",315 "outputs": [],315 "outputs": [],316 "stateMutability": "view",316 "stateMutability": "nonpayable",317 "type": "function"317 "type": "function"318 },318 },319 {319 {322 ],322 ],323 "name": "removeFromCollectionAllowList",323 "name": "removeFromCollectionAllowList",324 "outputs": [],324 "outputs": [],325 "stateMutability": "view",325 "stateMutability": "nonpayable",326 "type": "function"326 "type": "function"327 },327 },328 {328 {tests/src/eth/reFungibleToken.test.tsdiffbeforeafterbothno changes
tests/src/eth/reFungibleTokenAbi.jsondiffbeforeafterbothno changes
tests/src/fungible.test.tsdiffbeforeafterbothno changes
tests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth29 [key: string]: Codec;29 [key: string]: Codec;30 };30 };31 common: {31 common: {32 /**33 * Maximum admins per collection.34 **/32 collectionAdminsLimit: u32 & AugmentedConst<ApiType>;35 collectionAdminsLimit: u32 & AugmentedConst<ApiType>;36 /**37 * Set price to create a collection.38 **/33 collectionCreationPrice: u128 & AugmentedConst<ApiType>;39 collectionCreationPrice: u128 & AugmentedConst<ApiType>;34 /**40 /**35 * Generic const41 * Generic consttests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth284 * Tried to set data for fungible item.284 * Tried to set data for fungible item.285 **/285 **/286 FungibleItemsDontHaveData: AugmentedError<ApiType>;286 FungibleItemsDontHaveData: AugmentedError<ApiType>;287 /**287 /**288 * Not default id passed as TokenId argument.288 * Fungible tokens hold no ID, and the default value of TokenId for Fungible collection is 0.289 **/289 **/290 FungibleItemsHaveNoId: AugmentedError<ApiType>;290 FungibleItemsHaveNoId: AugmentedError<ApiType>;291 /**291 /**292 * Not Fungible item data used to mint in Fungible collection.292 * Not Fungible item data used to mint in Fungible collection.595 [key: string]: AugmentedError<ApiType>;595 [key: string]: AugmentedError<ApiType>;596 };596 };597 unique: {597 unique: {598 /**598 /**599 * Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.599 * Decimal_points parameter must be lower than [`up_data_structs::MAX_DECIMAL_POINTS`].600 **/600 **/601 CollectionDecimalPointLimitExceeded: AugmentedError<ApiType>;601 CollectionDecimalPointLimitExceeded: AugmentedError<ApiType>;602 /**602 /**603 * This address is not set as sponsor, use setCollectionSponsor first.603 * This address is not set as sponsor, use setCollectionSponsor first.607 * Length of items properties must be greater than 0.607 * Length of items properties must be greater than 0.608 **/608 **/609 EmptyArgument: AugmentedError<ApiType>;609 EmptyArgument: AugmentedError<ApiType>;610 /**610 /**611 * Repertition is only supported by refungible collection611 * Repertition is only supported by refungible collection.612 **/612 **/613 RepartitionCalledOnNonRefungibleCollection: AugmentedError<ApiType>;613 RepartitionCalledOnNonRefungibleCollection: AugmentedError<ApiType>;614 /**614 /**615 * Generic error615 * Generic errortests/src/interfaces/augment-api-events.tsdiffbeforeafterboth58 [key: string]: AugmentedEvent<ApiType>;58 [key: string]: AugmentedEvent<ApiType>;59 };59 };60 common: {60 common: {61 /**61 /**62 * Sponsoring allowance was approved.62 * Amount pieces of token owned by `sender` was approved for `spender`.63 * 63 **/64 * # Arguments65 * 66 * * collection_id - todo:doc flesh out67 * * item_id68 * * sender69 * * spender70 * * amount71 **/72 Approved: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;64 Approved: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;73 /**65 /**74 * New collection was created66 * New collection was created75 * 67 **/76 * # Arguments77 * 78 * * collection_id - Globally unique identifier of newly created collection.79 * * mode - [CollectionMode] converted into u8.80 * * account_id - Collection owner.81 **/82 CollectionCreated: AugmentedEvent<ApiType, [u32, u8, AccountId32]>;68 CollectionCreated: AugmentedEvent<ApiType, [u32, u8, AccountId32]>;83 /**69 /**84 * New collection was destroyed70 * New collection was destroyed85 * 71 **/86 * # Arguments87 * 88 * * collection_id - Globally unique identifier of collection that has been destroyed.89 **/90 CollectionDestroyed: AugmentedEvent<ApiType, [u32]>;72 CollectionDestroyed: AugmentedEvent<ApiType, [u32]>;91 /**73 /**92 * Collection property was deleted.74 * The property has been deleted.93 * 75 **/94 * # Arguments95 * 96 * * collection_id - ID of the collection, whose property was just deleted.97 * * property_key - Key of the property that was just deleted.98 **/99 CollectionPropertyDeleted: AugmentedEvent<ApiType, [u32, Bytes]>;76 CollectionPropertyDeleted: AugmentedEvent<ApiType, [u32, Bytes]>;100 /**77 /**101 * Collection property was added or edited.78 * The colletion property has been added or edited.102 * 79 **/103 * # Arguments104 * 105 * * collection_id - ID of the collection, whose property was just set.106 * * property_key - Key of the property that was just set.107 **/108 CollectionPropertySet: AugmentedEvent<ApiType, [u32, Bytes]>;80 CollectionPropertySet: AugmentedEvent<ApiType, [u32, Bytes]>;109 /**81 /**110 * New item was created.82 * New item was created.111 * 83 **/112 * # Arguments113 * 114 * * collection_id - ID of the collection where the item was created.115 * * item_id - ID of the item. Unique within the collection.116 * * recipient - Owner of the newly created item.117 * * amount - The amount of tokens that were created (always 1 for NFT).118 **/119 ItemCreated: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;84 ItemCreated: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;120 /**85 /**121 * Collection item was burned.86 * Collection item was burned.122 * 87 **/123 * # Arguments124 * 125 * * collection_id - Identifier of the collection to which the burned NFT belonged.126 * * item_id - Identifier of burned NFT.127 * * owner - Which user has destroyed their tokens.128 * * amount - Amount of tokens that were destroyed (always 1 for NFT).129 **/130 ItemDestroyed: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;88 ItemDestroyed: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;131 /**89 /**132 * Token property permission was added or updated for a collection.90 * The token property permission of a collection has been set.133 * 91 **/134 * # Arguments135 * 136 * * collection_id - ID of the collection, whose permissions were just set/updated.137 * * property_key - Key of the property of the set/updated permission.138 **/139 PropertyPermissionSet: AugmentedEvent<ApiType, [u32, Bytes]>;92 PropertyPermissionSet: AugmentedEvent<ApiType, [u32, Bytes]>;140 /**93 /**141 * Item property was deleted.94 * The token property has been deleted.142 * 95 **/143 * # Arguments144 * 145 * * collection_id - ID of the collection, whose token's property was just deleted.146 * * item_id - ID of the item, whose property was just deleted.147 * * property_key - Key of the property that was just deleted.148 **/149 TokenPropertyDeleted: AugmentedEvent<ApiType, [u32, u32, Bytes]>;96 TokenPropertyDeleted: AugmentedEvent<ApiType, [u32, u32, Bytes]>;150 /**97 /**151 * Item property was added or edited.98 * The token property has been added or edited.152 * 99 **/153 * # Arguments154 * 155 * * collection_id - ID of the collection, whose token's property was just set.156 * * item_id - ID of the item, whose property was just set.157 * * property_key - Key of the property that was just set.158 **/159 TokenPropertySet: AugmentedEvent<ApiType, [u32, u32, Bytes]>;100 TokenPropertySet: AugmentedEvent<ApiType, [u32, u32, Bytes]>;160 /**101 /**161 * Item was transferred.102 * Item was transferred162 * 103 **/163 * # Arguments164 * 165 * * collection_id - ID of the collection to which the item belongs.166 * * item_id - ID of the item transferred.167 * * sender - Original owner of the item.168 * * recipient - New owner of the item.169 * * amount - Amount of tokens that were transferred (always 1 for NFT).170 **/171 Transfer: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;104 Transfer: AugmentedEvent<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u128]>;172 /**105 /**173 * Generic event106 * Generic event565 [key: string]: AugmentedEvent<ApiType>;498 [key: string]: AugmentedEvent<ApiType>;566 };499 };567 unique: {500 unique: {568 /**501 /**569 * Address was added to the allow list502 * Address was added to the allow list570 * 503 * 571 * # Arguments504 * # Arguments572 * 505 * * collection_id: ID of the affected collection.573 * * collection_id: Globally unique collection identifier.506 * * user: Address of the added account.574 * 575 * * user: Address.507 **/576 **/577 AllowListAddressAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;508 AllowListAddressAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;578 /**509 /**579 * Address was removed from the allow list510 * Address was removed from the allow list580 * 511 * 581 * # Arguments512 * # Arguments582 * 513 * * collection_id: ID of the affected collection.583 * * collection_id: Globally unique collection identifier.514 * * user: Address of the removed account.584 * 585 * * user: Address.515 **/586 **/587 AllowListAddressRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;516 AllowListAddressRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;588 /**517 /**589 * Collection admin was added518 * Collection admin was added590 * 519 * 591 * # Arguments520 * # Arguments592 * 521 * * collection_id: ID of the affected collection.593 * * collection_id: Globally unique collection identifier.522 * * admin: Admin address.594 * 595 * * admin: Admin address.523 **/596 **/597 CollectionAdminAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;524 CollectionAdminAdded: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;598 /**525 /**599 * Collection admin was removed526 * Collection admin was removed600 * 527 * 601 * # Arguments528 * # Arguments602 * 529 * * collection_id: ID of the affected collection.603 * * collection_id: Globally unique collection identifier.530 * * admin: Removed admin address.604 * 605 * * admin: Admin address.531 **/606 **/607 CollectionAdminRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;532 CollectionAdminRemoved: AugmentedEvent<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;608 /**533 /**609 * Collection limits were set534 * Collection limits were set610 * 535 * 611 * # Arguments536 * # Arguments612 * 537 * * collection_id: ID of the affected collection.613 * * collection_id: Globally unique collection identifier.538 **/614 **/615 CollectionLimitSet: AugmentedEvent<ApiType, [u32]>;539 CollectionLimitSet: AugmentedEvent<ApiType, [u32]>;616 /**540 /**617 * Collection owned was changed541 * Collection owned was changed618 * 542 * 619 * # Arguments543 * # Arguments620 * 544 * * collection_id: ID of the affected collection.621 * * collection_id: Globally unique collection identifier.545 * * owner: New owner address.622 * 623 * * owner: New owner address.546 **/624 **/625 CollectionOwnedChanged: AugmentedEvent<ApiType, [u32, AccountId32]>;547 CollectionOwnedChanged: AugmentedEvent<ApiType, [u32, AccountId32]>;626 /**548 /**627 * Collection permissions were set549 * Collection permissions were set628 * 550 * 629 * # Arguments551 * # Arguments630 * 552 * * collection_id: ID of the affected collection.631 * * collection_id: Globally unique collection identifier.553 **/632 **/633 CollectionPermissionSet: AugmentedEvent<ApiType, [u32]>;554 CollectionPermissionSet: AugmentedEvent<ApiType, [u32]>;634 /**555 /**635 * Collection sponsor was removed556 * Collection sponsor was removed636 * 557 * 637 * # Arguments558 * # Arguments638 * 559 * * collection_id: ID of the affected collection.639 * * collection_id: Globally unique collection identifier.560 **/640 **/641 CollectionSponsorRemoved: AugmentedEvent<ApiType, [u32]>;561 CollectionSponsorRemoved: AugmentedEvent<ApiType, [u32]>;642 /**562 /**643 * Collection sponsor was set563 * Collection sponsor was set644 * 564 * 645 * # Arguments565 * # Arguments646 * 566 * * collection_id: ID of the affected collection.647 * * collection_id: Globally unique collection identifier.567 * * owner: New sponsor address.648 * 649 * * owner: New sponsor address.568 **/650 **/651 CollectionSponsorSet: AugmentedEvent<ApiType, [u32, AccountId32]>;569 CollectionSponsorSet: AugmentedEvent<ApiType, [u32, AccountId32]>;652 /**570 /**653 * New sponsor was confirm571 * New sponsor was confirm654 * 572 * 655 * # Arguments573 * # Arguments656 * 574 * * collection_id: ID of the affected collection.657 * * collection_id: Globally unique collection identifier.575 * * sponsor: New sponsor address.658 * 659 * * sponsor: New sponsor address.576 **/660 **/661 SponsorshipConfirmed: AugmentedEvent<ApiType, [u32, AccountId32]>;577 SponsorshipConfirmed: AugmentedEvent<ApiType, [u32, AccountId32]>;662 /**578 /**663 * Generic event579 * Generic eventtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth69 [key: string]: QueryableStorageEntry<ApiType>;69 [key: string]: QueryableStorageEntry<ApiType>;70 };70 };71 common: {71 common: {72 /**72 /**73 * Amount of collection admins73 * Storage of the amount of collection admins.74 **/74 **/75 adminAmount: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;75 adminAmount: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;76 /**76 /**77 * Allowlisted collection users77 * Allowlisted collection users.78 **/78 **/79 allowlist: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;79 allowlist: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;80 /**80 /**81 * Collection info81 * Storage of collection info.82 **/82 **/83 collectionById: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<UpDataStructsCollection>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;83 collectionById: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Option<UpDataStructsCollection>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;84 /**84 /**85 * Collection properties85 * Storage of collection properties.86 **/86 **/87 collectionProperties: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;87 collectionProperties: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;88 /**88 /**89 * Token permissions of a collection89 * Storage of token property permissions of a collection.90 **/90 **/91 collectionPropertyPermissions: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<BTreeMap<Bytes, UpDataStructsPropertyPermission>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;91 collectionPropertyPermissions: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<BTreeMap<Bytes, UpDataStructsPropertyPermission>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;92 /**92 /**93 * The number of created collections. Essentially contains the last collection ID.93 * Storage of the count of created collections. Essentially contains the last collection ID.94 **/94 **/95 createdCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;95 createdCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;96 /**96 /**97 * The number of destroyed collections97 * Storage of the count of deleted collections.98 **/98 **/99 destroyedCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;99 destroyedCollectionCount: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;100 /**100 /**101 * Not used by code, exists only to provide some types to metadata101 * Not used by code, exists only to provide some types to metadata.102 **/102 **/103 dummyStorageValue: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[UpDataStructsCollectionStats, u32, u32, UpDataStructsTokenChild, PhantomTypeUpDataStructs]>>>, []> & QueryableStorageEntry<ApiType, []>;103 dummyStorageValue: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[UpDataStructsCollectionStats, u32, u32, UpDataStructsTokenChild, PhantomTypeUpDataStructs]>>>, []> & QueryableStorageEntry<ApiType, []>;104 /**104 /**105 * List of collection admins105 * List of collection admins.106 **/106 **/107 isAdmin: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;107 isAdmin: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;108 /**108 /**109 * Generic query109 * Generic query199 [key: string]: QueryableStorageEntry<ApiType>;199 [key: string]: QueryableStorageEntry<ApiType>;200 };200 };201 fungible: {201 fungible: {202 /**202 /**203 * todo:doc203 * Storage for assets delegated to a limited extent to other users.204 **/204 **/205 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;205 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;206 /**206 /**207 * Amount of tokens owned by an account inside a collection.207 * Amount of tokens owned by an account inside a collection.243 [key: string]: QueryableStorageEntry<ApiType>;243 [key: string]: QueryableStorageEntry<ApiType>;244 };244 };245 nonfungible: {245 nonfungible: {246 /**246 /**247 * Amount of tokens owned in a collection.247 * Amount of tokens owned by an account in a collection.248 **/248 **/249 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;249 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;250 /**250 /**251 * todo:doc251 * Allowance set by a token owner for another user to perform one of certain transactions on a token.252 **/252 **/253 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletEvmAccountBasicCrossAccountIdRepr>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;253 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletEvmAccountBasicCrossAccountIdRepr>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;254 /**254 /**255 * Used to enumerate tokens owned by account.255 * Used to enumerate tokens owned by account.256 **/256 **/257 owned: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]>;257 owned: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg3: u32 | AnyNumber | Uint8Array) => Observable<bool>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]>;258 /**258 /**259 * Scoped, auxiliary properties of a token, primarily used for on-chain operations.259 * Custom data of a token that is serialized to bytes,260 **/260 * primarily reserved for on-chain operations,261 * normally obscured from the external users.262 * 263 * Auxiliary properties are slightly different from264 * usual [`TokenProperties`] due to an unlimited number265 * and separately stored and written-to key-value pairs.266 * 267 * Currently used to store RMRK data.268 **/261 tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;269 tokenAuxProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: UpDataStructsPropertyScope | 'None' | 'Rmrk' | number | Uint8Array, arg4: Bytes | string | Uint8Array) => Observable<Option<Bytes>>, [u32, u32, UpDataStructsPropertyScope, Bytes]> & QueryableStorageEntry<ApiType, [u32, u32, UpDataStructsPropertyScope, Bytes]>;262 /**270 /**263 * Used to enumerate token's children.271 * Used to enumerate token's children.267 * Token data, used to partially describe a token.275 * Token data, used to partially describe a token.268 **/276 **/269 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletNonfungibleItemData>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;277 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<Option<PalletNonfungibleItemData>>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;270 /**278 /**271 * Key-value pairs, describing the metadata of a token.279 * Map of key-value pairs, describing the metadata of a token.272 **/280 **/273 tokenProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;281 tokenProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;274 /**282 /**275 * Amount of burnt tokens in a collection.283 * Amount of burnt tokens in a collection.446 * Amount of tokens (not pieces) partially owned by an account within a collection.454 * Amount of tokens (not pieces) partially owned by an account within a collection.447 **/455 **/448 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;456 accountBalance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u32>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;449 /**457 /**450 * todo:doc458 * Allowance set by a token owner for another user to perform one of certain transactions on a number of pieces of a token.451 **/459 **/452 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg4: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;460 allowance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, arg4: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]>;453 /**461 /**454 * Amount of pieces of a token owned by an account.462 * Amount of token pieces owned by account.455 **/463 **/456 balance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]>;464 balance: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array, arg3: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => Observable<u128>, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry<ApiType, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]>;457 /**465 /**458 * Used to enumerate tokens owned by account.466 * Used to enumerate tokens owned by account.462 * Token data, used to partially describe a token.470 * Token data, used to partially describe a token.463 **/471 **/464 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<PalletRefungibleItemData>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;472 tokenData: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<PalletRefungibleItemData>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;473 /**474 * Amount of pieces a refungible token is split into.475 **/476 tokenProperties: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<UpDataStructsProperties>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;465 /**477 /**466 * Amount of tokens burnt in a collection.478 * Amount of tokens burnt in a collection.467 **/479 **/470 * Total amount of minted tokens in a collection.482 * Total amount of minted tokens in a collection.471 **/483 **/472 tokensMinted: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;484 tokensMinted: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<u32>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;473 /**485 /**474 * Amount of pieces a refungible token is split into.486 * Total amount of pieces for token475 **/487 **/476 totalSupply: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u128>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;488 totalSupply: AugmentedQuery<ApiType, (arg1: u32 | AnyNumber | Uint8Array, arg2: u32 | AnyNumber | Uint8Array) => Observable<u128>, [u32, u32]> & QueryableStorageEntry<ApiType, [u32, u32]>;477 /**489 /**478 * Generic query490 * Generic querytests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth672 * Get tokens contained within a collection672 * Get tokens contained within a collection673 **/673 **/674 collectionTokens: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<u32>>>;674 collectionTokens: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<u32>>>;675 /**676 * Get token constant metadata677 **/678 constMetadata: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Bytes>>;675 /**679 /**676 * Get effective collection limits680 * Get effective collection limits677 **/681 **/704 * Get the token owner708 * Get the token owner705 **/709 **/706 tokenOwner: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<PalletEvmAccountBasicCrossAccountIdRepr>>>;710 tokenOwner: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Option<PalletEvmAccountBasicCrossAccountIdRepr>>>;711 /**712 * Returns 10 tokens owners in no particular order713 **/714 tokenOwners: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Vec<PalletEvmAccountBasicCrossAccountIdRepr>>>;707 /**715 /**708 * Get token properties, optionally limited to the provided keys716 * Get token properties, optionally limited to the provided keys709 **/717 **/720 * Get the amount of distinctive tokens present in a collection728 * Get the amount of distinctive tokens present in a collection721 **/729 **/722 totalSupply: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u32>>;730 totalSupply: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<u32>>;731 /**732 * Get token variable metadata733 **/734 variableMetadata: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable<Bytes>>;723 };735 };724 web3: {736 web3: {725 /**737 /**tests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth729 [key: string]: SubmittableExtrinsicFunction<ApiType>;729 [key: string]: SubmittableExtrinsicFunction<ApiType>;730 };730 };731 unique: {731 unique: {732 /**732 /**733 * Adds an admin of the collection.733 * Add an admin to a collection.734 * NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.734 * 735 * NFT Collection can be controlled by multiple admin addresses736 * (some which can also be servers, for example). Admins can issue737 * and burn NFTs, as well as add and remove other admins,738 * but cannot change NFT or Collection ownership.735 * 739 * 736 * # Permissions740 * # Permissions737 * 741 * 738 * * Collection Owner742 * * Collection owner739 * * Collection Admin743 * * Collection admin740 * 744 * 741 * # Arguments745 * # Arguments742 * 746 * 743 * * collection_id - ID of the Collection to add admin for.747 * * `collection_id`: ID of the Collection to add an admin for.744 * * new_admin - Address of new admin to add.748 * * `new_admin`: Address of new admin to add.745 **/749 **/746 addCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newAdmin: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;750 addCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newAdmin: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;747 /**751 /**748 * Add an address to allow list.752 * Add an address to allow list.749 * 753 * 750 * # Permissions754 * # Permissions751 * 755 * 752 * * Collection Owner756 * * Collection owner753 * * Collection Admin757 * * Collection admin754 * 758 * 755 * # Arguments759 * # Arguments756 * 760 * 757 * * collection_id.761 * * `collection_id`: ID of the modified collection.758 * * address.762 * * `address`: ID of the address to be added to the allowlist.759 **/763 **/760 addToAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;764 addToAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;761 /**765 /**762 * Set, change, or remove approved address to transfer the ownership of the NFT.766 * Allow a non-permissioned address to transfer or burn an item.763 * 767 * 764 * # Permissions768 * # Permissions765 * 769 * 766 * * Collection Owner770 * * Collection owner767 * * Collection Admin771 * * Collection admin768 * * Current NFT owner772 * * Current item owner769 * 773 * 770 * # Arguments774 * # Arguments771 * 775 * 772 * * approved - Address that is approved to transfer this NFT or zero (if needed to remove approval).776 * * `spender`: Account to be approved to make specific transactions on non-owned tokens.773 * * collection_id.777 * * `collection_id`: ID of the collection the item belongs to.774 * * item_id - ID of the item.778 * * `item_id`: ID of the item transactions on which are now approved.775 **/779 * * `amount`: Number of pieces of the item approved for a transaction (maximum of 1 for NFTs).780 * Set to 0 to revoke the approval.781 **/776 approve: AugmentedSubmittable<(spender: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;782 approve: AugmentedSubmittable<(spender: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;777 /**783 /**778 * Destroy a concrete instance of NFT on behalf of the owner.784 * Destroy a token on behalf of the owner as a non-owner account.779 * See also: [`approve`]785 * 780 * 786 * See also: [`approve`][`Pallet::approve`].781 * # Permissions787 * 782 * 788 * After this method executes, one approval is removed from the total so that783 * * Collection Owner.789 * the approved address will not be able to transfer this item again from this owner.784 * * Collection Admin.790 * 785 * * Current NFT Owner.791 * # Permissions786 * 792 * 787 * # Arguments793 * * Collection owner788 * 794 * * Collection admin789 * * collection_id - ID of the collection.795 * * Current token owner790 * * item_id - ID of NFT to burn.796 * * Address approved by current item owner791 * * from - The owner of the item from whom it is taken away.797 * 792 **/798 * # Arguments799 * 800 * * `from`: The owner of the burning item.801 * * `collection_id`: ID of the collection to which the item belongs.802 * * `item_id`: ID of item to burn.803 * * `value`: Number of pieces to burn.804 * * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.805 * * Fungible Mode: The desired number of pieces to burn.806 * * Re-Fungible Mode: The desired number of pieces to burn.807 **/793 burnFrom: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, from: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32, u128]>;808 burnFrom: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, from: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32, u128]>;794 /**809 /**795 * Destroy a concrete instance of NFT.810 * Destroy an item.796 * 811 * 797 * # Permissions812 * # Permissions798 * 813 * 799 * * Collection Owner814 * * Collection owner800 * * Collection Admin815 * * Collection admin801 * * Current NFT Owner816 * * Current item owner802 * 817 * 803 * # Arguments818 * # Arguments804 * 819 * 805 * * collection_id - ID of the collection.820 * * `collection_id`: ID of the collection to which the item belongs.806 * * item_id - ID of NFT to burn.821 * * `item_id`: ID of item to burn.807 **/822 * * `value`: Number of pieces of the item to destroy.823 * * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.824 * * Fungible Mode: The desired number of pieces to burn.825 * * Re-Fungible Mode: The desired number of pieces to burn.826 **/808 burnItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u128]>;827 burnItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u128]>;809 /**828 /**810 * Change the owner of the collection.829 * Change the owner of the collection.811 * 830 * 812 * # Permissions831 * # Permissions813 * 832 * 814 * * Collection Owner833 * * Collection owner815 * 834 * 816 * # Arguments835 * # Arguments817 * 836 * 818 * * collection_id.837 * * `collection_id`: ID of the modified collection.819 * * new_owner.838 * * `new_owner`: ID of the account that will become the owner.820 **/839 **/821 changeCollectionOwner: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newOwner: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;840 changeCollectionOwner: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newOwner: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;822 /**841 /**823 * Confirm own sponsorship of a collection.842 * Confirm own sponsorship of a collection, becoming the sponsor.824 * 843 * 825 * # Permissions844 * An invitation must be pending, see [`set_collection_sponsor`][`Pallet::set_collection_sponsor`].826 * 845 * Sponsor can pay the fees of a transaction instead of the sender,827 * * Sponsor-to-be846 * but only within specified limits.828 * 847 * 829 * # Arguments848 * # Permissions830 * 849 * 831 * * collection_id.850 * * Sponsor-to-be832 **/851 * 852 * # Arguments853 * 854 * * `collection_id`: ID of the collection with the pending sponsor.855 **/833 confirmSponsorship: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;856 confirmSponsorship: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;834 /**857 /**835 * This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.858 * Create a collection of tokens.836 * 859 * 837 * # Permissions860 * Each Token may have multiple properties encoded as an array of bytes838 * 861 * of certain length. The initial owner of the collection is set839 * * Anyone.862 * to the address that signed the transaction and can be changed later.840 * 863 * 841 * # Arguments864 * Prefer the more advanced [`create_collection_ex`][`Pallet::create_collection_ex`] instead.842 * 865 * 843 * * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.866 * # Permissions844 * * collection_description - UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.867 * 845 * * token_prefix - UTF-8 string with token prefix.868 * * Anyone - becomes the owner of the new collection.846 * * mode - [CollectionMode] collection type and type dependent data.869 * 847 **/870 * # Arguments871 * 872 * * `collection_name`: Wide-character string with collection name873 * (limit [`MAX_COLLECTION_NAME_LENGTH`]).874 * * `collection_description`: Wide-character string with collection description875 * (limit [`MAX_COLLECTION_DESCRIPTION_LENGTH`]).876 * * `token_prefix`: Byte string containing the token prefix to mark a collection877 * to which a token belongs (limit [`MAX_TOKEN_PREFIX_LENGTH`]).878 * * `mode`: Type of items stored in the collection and type dependent data.879 **/848 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]>;880 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]>;849 /**881 /**850 * Create a collection with explicit parameters.882 * Create a collection with explicit parameters.851 * Prefer it to the deprecated [`created_collection`] method.883 * 884 * Prefer it to the deprecated [`create_collection`][`Pallet::create_collection`] method.852 * 885 * 853 * # Permissions886 * # Permissions854 * 887 * 855 * * Anyone.888 * * Anyone - becomes the owner of the new collection.856 * 889 * 857 * # Arguments890 * # Arguments858 * 891 * 859 * * data: explicit create-collection data.892 * * `data`: Explicit data of a collection used for its creation.860 **/893 **/861 createCollectionEx: AugmentedSubmittable<(data: UpDataStructsCreateCollectionData | { mode?: any; access?: any; name?: any; description?: any; tokenPrefix?: any; pendingSponsor?: any; limits?: any; permissions?: any; tokenPropertyPermissions?: any; properties?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [UpDataStructsCreateCollectionData]>;894 createCollectionEx: AugmentedSubmittable<(data: UpDataStructsCreateCollectionData | { mode?: any; access?: any; name?: any; description?: any; tokenPrefix?: any; pendingSponsor?: any; limits?: any; permissions?: any; tokenPropertyPermissions?: any; properties?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [UpDataStructsCreateCollectionData]>;862 /**895 /**863 * Create a concrete instance of NFT Collection created with CreateCollection method.896 * Mint an item within a collection.897 * 898 * A collection must exist first, see [`create_collection_ex`][`Pallet::create_collection_ex`].864 * 899 * 865 * # Permissions900 * # Permissions866 * 901 * 867 * * Collection Owner902 * * Collection owner868 * * Collection Admin903 * * Collection admin869 * * Anyone if904 * * Anyone if870 * * Allow List is enabled, and905 * * Allow List is enabled, and871 * * Address is added to allow list, and906 * * Address is added to allow list, and872 * * MintPermission is enabled (see SetMintPermission method)907 * * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])873 * 908 * 874 * # Arguments909 * # Arguments875 * 910 * 876 * * collection_id - ID of the collection.911 * * `collection_id`: ID of the collection to which an item would belong.877 * * owner - Address, initial owner of the NFT.912 * * `owner`: Address of the initial owner of the item.878 * * data - Token data to store on chain.913 * * `data`: Token data describing the item to store on chain.879 **/914 **/880 createItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, data: UpDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, UpDataStructsCreateItemData]>;915 createItem: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, data: UpDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, UpDataStructsCreateItemData]>;881 /**916 /**882 * Create multiple items in a collection created with CreateCollection method.917 * Create multiple items within a collection.918 * 919 * A collection must exist first, see [`create_collection_ex`][`Pallet::create_collection_ex`].883 * 920 * 884 * # Permissions921 * # Permissions885 * 922 * 886 * * Collection Owner923 * * Collection owner887 * * Collection Admin924 * * Collection admin888 * * Anyone if925 * * Anyone if889 * * Allow List is enabled, and926 * * Allow List is enabled, and890 * * Address is added to allow list, and927 * * Address is added to the allow list, and891 * * MintPermission is enabled (see SetMintPermission method)928 * * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])892 * 929 * 893 * # Arguments930 * # Arguments894 * 931 * 895 * * collection_id - ID of the collection.932 * * `collection_id`: ID of the collection to which the tokens would belong.896 * * owner - Address, initial owner of the NFT.933 * * `owner`: Address of the initial owner of the tokens.897 * * items_data - Array items properties. Each property is an array of bytes itself, see [`create_item`].934 * * `items_data`: Vector of data describing each item to be created.898 **/935 **/899 createMultipleItems: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemsData: Vec<UpDataStructsCreateItemData> | (UpDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, Vec<UpDataStructsCreateItemData>]>;936 createMultipleItems: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, owner: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, itemsData: Vec<UpDataStructsCreateItemData> | (UpDataStructsCreateItemData | { NFT: any } | { Fungible: any } | { ReFungible: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, Vec<UpDataStructsCreateItemData>]>;900 /**937 /**901 * Create multiple items inside a collection with explicitly specified initial parameters.938 * Create multiple items within a collection with explicitly specified initial parameters.902 * 939 * 903 * # Permissions940 * # Permissions904 * 941 * 905 * * Collection Owner942 * * Collection owner906 * * Collection Admin943 * * Collection admin907 * * Anyone if944 * * Anyone if908 * * Allow List is enabled, and945 * * Allow List is enabled, and909 * * Address is added to allow list, and946 * * Address is added to allow list, and910 * * MintPermission is enabled (see SetMintPermission method)947 * * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])911 * 948 * 912 * # Arguments949 * # Arguments913 * 950 * 914 * * collection_id - ID of the collection.951 * * `collection_id`: ID of the collection to which the tokens would belong.915 * * data - Explicit item creation data.952 * * `data`: Explicit item creation data.916 **/953 **/917 createMultipleItemsEx: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, data: UpDataStructsCreateItemExData | { NFT: any } | { Fungible: any } | { RefungibleMultipleItems: any } | { RefungibleMultipleOwners: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsCreateItemExData]>;954 createMultipleItemsEx: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, data: UpDataStructsCreateItemExData | { NFT: any } | { Fungible: any } | { RefungibleMultipleItems: any } | { RefungibleMultipleOwners: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsCreateItemExData]>;918 /**955 /**919 * Delete specified collection properties.956 * Delete specified collection properties.920 * 957 * 921 * # Permissions958 * # Permissions922 * 959 * 923 * * Collection Owner960 * * Collection Owner924 * * Collection Admin961 * * Collection Admin925 * 962 * 926 * # Arguments963 * # Arguments927 * 964 * 928 * * collection_id.965 * * `collection_id`: ID of the modified collection.929 * * property_keys - Vector of keys of the properties to be deleted.966 * * `property_keys`: Vector of keys of the properties to be deleted.967 * Keys support Latin letters, `-`, `_`, and `.` as symbols.930 **/968 **/931 deleteCollectionProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Bytes> | (Bytes | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, Vec<Bytes>]>;969 deleteCollectionProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Bytes> | (Bytes | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, Vec<Bytes>]>;932 /**970 /**933 * Delete specified token properties.971 * Delete specified token properties. Currently properties only work with NFTs.934 * 972 * 935 * # Permissions973 * # Permissions936 * 974 * 937 * * Depends on collection's token property permissions and specified property mutability:975 * * Depends on collection's token property permissions and specified property mutability:938 * * Collection Owner976 * * Collection owner939 * * Collection Admin977 * * Collection admin940 * * Token Owner978 * * Token owner941 * 979 * 942 * # Arguments980 * # Arguments943 * 981 * 944 * * collection_id.982 * * `collection_id`: ID of the collection to which the token belongs.945 * * token_id.983 * * `token_id`: ID of the modified token.946 * * property_keys - Vector of keys of the properties to be deleted.984 * * `property_keys`: Vector of keys of the properties to be deleted.985 * Keys support Latin letters, `-`, `_`, and `.` as symbols.947 **/986 **/948 deleteTokenProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Bytes> | (Bytes | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<Bytes>]>;987 deleteTokenProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, propertyKeys: Vec<Bytes> | (Bytes | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<Bytes>]>;949 /**988 /**950 * Destroy the collection if no tokens exist within.989 * Destroy a collection if no tokens exist within.951 * 990 * 952 * # Permissions991 * # Permissions953 * 992 * 954 * * Collection Owner993 * * Collection owner955 * 994 * 956 * # Arguments995 * # Arguments957 * 996 * 958 * * collection_id - collection to destroy.997 * * `collection_id`: Collection to destroy.959 **/998 **/960 destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;999 destroyCollection: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;961 /**1000 /**962 * Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.1001 * Remove admin of a collection.1002 * 1003 * An admin address can remove itself. List of admins may become empty,1004 * in which case only Collection Owner will be able to add an Admin.963 * 1005 * 964 * # Permissions1006 * # Permissions965 * 1007 * 966 * * Collection Owner1008 * * Collection owner967 * * Collection Admin1009 * * Collection admin968 * 1010 * 969 * # Arguments1011 * # Arguments970 * 1012 * 971 * * collection_id - ID of the Collection to remove admin for.1013 * * `collection_id`: ID of the collection to remove the admin for.972 * * account_id - Address of admin to remove.1014 * * `account_id`: Address of the admin to remove.973 **/1015 **/974 removeCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, accountId: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;1016 removeCollectionAdmin: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, accountId: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;975 /**1017 /**976 * Switch back to pay-per-own-transaction model.1018 * Remove a collection's a sponsor, making everyone pay for their own transactions.977 * 1019 * 978 * # Permissions1020 * # Permissions979 * 1021 * 980 * * Collection Owner1022 * * Collection owner981 * 1023 * 982 * # Arguments1024 * # Arguments983 * 1025 * 984 * * collection_id.1026 * * `collection_id`: ID of the collection with the sponsor to remove.985 **/1027 **/986 removeCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;1028 removeCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32]>;987 /**1029 /**988 * Remove an address from allow list.1030 * Remove an address from allow list.989 * 1031 * 990 * # Permissions1032 * # Permissions991 * 1033 * 992 * * Collection Owner1034 * * Collection owner993 * * Collection Admin1035 * * Collection admin994 * 1036 * 995 * # Arguments1037 * # Arguments996 * 1038 * 997 * * collection_id.1039 * * `collection_id`: ID of the modified collection.998 * * address.1040 * * `address`: ID of the address to be removed from the allowlist.999 **/1041 **/1000 removeFromAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;1042 removeFromAllowList: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, address: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, PalletEvmAccountBasicCrossAccountIdRepr]>;1001 /**1043 /**1002 * Re-partition a refungible token, while owning all of its parts.1044 * Re-partition a refungible token, while owning all of its parts/pieces.1003 * 1045 * 1004 * # Permissions1046 * # Permissions1005 * 1047 * 1006 * * Token Owner (must own every part)1048 * * Token owner (must own every part)1007 * 1049 * 1008 * # Arguments1050 * # Arguments1009 * 1051 * 1010 * * collection_id.1052 * * `collection_id`: ID of the collection the RFT belongs to.1011 * * token_id - ID of the RFT.1053 * * `token_id`: ID of the RFT.1012 * * amount - New number of parts into which the token shall be partitioned.1054 * * `amount`: New number of parts/pieces into which the token shall be partitioned.1013 **/1055 **/1014 repartition: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u128]>;1056 repartition: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, amount: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, u32, u128]>;1015 /**1057 /**1016 * Set specific limits of a collection. Empty, or None fields mean chain default.1058 * Set specific limits of a collection. Empty, or None fields mean chain default.1017 * 1059 * 1018 * # Permissions1060 * # Permissions1019 * 1061 * 1020 * * Collection Owner1062 * * Collection owner1021 * * Collection Admin1063 * * Collection admin1022 * 1064 * 1023 * # Arguments1065 * # Arguments1024 * 1066 * 1025 * * collection_id.1067 * * `collection_id`: ID of the modified collection.1026 * * new_limit - New limits of the collection. They will overwrite the current ones.1068 * * `new_limit`: New limits of the collection. Fields that are not set (None)1069 * will not overwrite the old ones.1027 **/1070 **/1028 setCollectionLimits: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newLimit: UpDataStructsCollectionLimits | { accountTokenOwnershipLimit?: any; sponsoredDataSize?: any; sponsoredDataRateLimit?: any; tokenLimit?: any; sponsorTransferTimeout?: any; sponsorApproveTimeout?: any; ownerCanTransfer?: any; ownerCanDestroy?: any; transfersEnabled?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsCollectionLimits]>;1071 setCollectionLimits: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newLimit: UpDataStructsCollectionLimits | { accountTokenOwnershipLimit?: any; sponsoredDataSize?: any; sponsoredDataRateLimit?: any; tokenLimit?: any; sponsorTransferTimeout?: any; sponsorApproveTimeout?: any; ownerCanTransfer?: any; ownerCanDestroy?: any; transfersEnabled?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsCollectionLimits]>;1029 /**1072 /**1030 * Set specific permissions of a collection. Empty, or None fields mean chain default.1073 * Set specific permissions of a collection. Empty, or None fields mean chain default.1031 * 1074 * 1032 * # Permissions1075 * # Permissions1033 * 1076 * 1034 * * Collection Owner1077 * * Collection owner1035 * * Collection Admin1078 * * Collection admin1036 * 1079 * 1037 * # Arguments1080 * # Arguments1038 * 1081 * 1039 * * collection_id.1082 * * `collection_id`: ID of the modified collection.1040 * * new_permission - New permissions of the collection. They will overwrite the current ones.1083 * * `new_permission`: New permissions of the collection. Fields that are not set (None)1084 * will not overwrite the old ones.1041 **/1085 **/1042 setCollectionPermissions: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newPermission: UpDataStructsCollectionPermissions | { access?: any; mintMode?: any; nesting?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsCollectionPermissions]>;1086 setCollectionPermissions: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newPermission: UpDataStructsCollectionPermissions | { access?: any; mintMode?: any; nesting?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, UpDataStructsCollectionPermissions]>;1043 /**1087 /**1044 * Add or change collection properties.1088 * Add or change collection properties.1045 * 1089 * 1046 * # Permissions1090 * # Permissions1047 * 1091 * 1048 * * Collection Owner1092 * * Collection owner1049 * * Collection Admin1093 * * Collection admin1050 * 1094 * 1051 * # Arguments1095 * # Arguments1052 * 1096 * 1053 * * collection_id.1097 * * `collection_id`: ID of the modified collection.1054 * * properties - Vector of key-value pairs stored as the collection's metadata. Keys support Latin letters, `-`, `_`, and `.` as symbols.1098 * * `properties`: Vector of key-value pairs stored as the collection's metadata.1099 * Keys support Latin letters, `-`, `_`, and `.` as symbols.1055 **/1100 **/1056 setCollectionProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, properties: Vec<UpDataStructsProperty> | (UpDataStructsProperty | { key?: any; value?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, Vec<UpDataStructsProperty>]>;1101 setCollectionProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, properties: Vec<UpDataStructsProperty> | (UpDataStructsProperty | { key?: any; value?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, Vec<UpDataStructsProperty>]>;1057 /**1102 /**1058 * Set (invite) a new collection sponsor. If successful, confirmation from the sponsor-to-be will be pending.1103 * Set (invite) a new collection sponsor.1104 * 1105 * If successful, confirmation from the sponsor-to-be will be pending.1059 * 1106 * 1060 * # Permissions1107 * # Permissions1061 * 1108 * 1062 * * Collection Owner1109 * * Collection owner1063 * * Collection Admin1110 * * Collection admin1064 * 1111 * 1065 * # Arguments1112 * # Arguments1066 * 1113 * 1067 * * collection_id.1114 * * `collection_id`: ID of the modified collection.1068 * * new_sponsor.1115 * * `new_sponsor`: ID of the account of the sponsor-to-be.1069 **/1116 **/1070 setCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newSponsor: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;1117 setCollectionSponsor: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, newSponsor: AccountId32 | string | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, AccountId32]>;1071 /**1118 /**1072 * Add or change token properties according to collection's permissions.1119 * Add or change token properties according to collection's permissions.1073 * 1120 * Currently properties only work with NFTs.1074 * # Permissions1121 * 1122 * # Permissions1075 * 1123 * 1076 * * Depends on collection's token property permissions and specified property mutability:1124 * * Depends on collection's token property permissions and specified property mutability:1077 * * Collection Owner1125 * * Collection owner1078 * * Collection Admin1126 * * Collection admin1079 * * Token Owner1127 * * Token owner1080 * 1128 * 1081 * # Arguments1129 * See [`set_token_property_permissions`][`Pallet::set_token_property_permissions`].1130 * 1131 * # Arguments1082 * 1132 * 1083 * * collection_id.1133 * * `collection_id: ID of the collection to which the token belongs.1084 * * token_id.1134 * * `token_id`: ID of the modified token.1085 * * properties - Vector of key-value pairs stored as the token's metadata. Keys support Latin letters, `-`, `_`, and `.` as symbols.1135 * * `properties`: Vector of key-value pairs stored as the token's metadata.1136 * Keys support Latin letters, `-`, `_`, and `.` as symbols.1086 **/1137 **/1087 setTokenProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, properties: Vec<UpDataStructsProperty> | (UpDataStructsProperty | { key?: any; value?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<UpDataStructsProperty>]>;1138 setTokenProperties: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, properties: Vec<UpDataStructsProperty> | (UpDataStructsProperty | { key?: any; value?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, u32, Vec<UpDataStructsProperty>]>;1088 /**1139 /**1089 * Add or change token property permissions of a collection.1140 * Add or change token property permissions of a collection.1090 * 1141 * 1091 * # Permissions1142 * Without a permission for a particular key, a property with that key1143 * cannot be created in a token.1144 * 1145 * # Permissions1092 * 1146 * 1093 * * Collection Owner1147 * * Collection owner1094 * * Collection Admin1148 * * Collection admin1095 * 1149 * 1096 * # Arguments1150 * # Arguments1097 * 1151 * 1098 * * collection_id.1152 * * `collection_id`: ID of the modified collection.1099 * * property_permissions - Vector of permissions for property keys. Keys support Latin letters, `-`, `_`, and `.` as symbols.1153 * * `property_permissions`: Vector of permissions for property keys.1154 * Keys support Latin letters, `-`, `_`, and `.` as symbols.1100 **/1155 **/1101 setTokenPropertyPermissions: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, propertyPermissions: Vec<UpDataStructsPropertyKeyPermission> | (UpDataStructsPropertyKeyPermission | { key?: any; permission?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, Vec<UpDataStructsPropertyKeyPermission>]>;1156 setTokenPropertyPermissions: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, propertyPermissions: Vec<UpDataStructsPropertyKeyPermission> | (UpDataStructsPropertyKeyPermission | { key?: any; permission?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [u32, Vec<UpDataStructsPropertyKeyPermission>]>;1102 /**1157 /**1103 * Set transfers_enabled value for particular collection.1158 * Completely allow or disallow transfers for a particular collection.1104 * 1159 * 1105 * # Permissions1160 * # Permissions1106 * 1161 * 1107 * * Collection Owner1162 * * Collection owner1108 * 1163 * 1109 * # Arguments1164 * # Arguments1110 * 1165 * 1111 * * collection_id - ID of the collection.1166 * * `collection_id`: ID of the collection.1112 * * value - New flag value.1167 * * `value`: New value of the flag, are transfers allowed?1113 **/1168 **/1114 setTransfersEnabledFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, bool]>;1169 setTransfersEnabledFlag: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, value: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>, [u32, bool]>;1115 /**1170 /**1116 * Change ownership of the token.1171 * Change ownership of the token.1117 * 1172 * 1118 * # Permissions1173 * # Permissions1119 * 1174 * 1120 * * Collection Owner1175 * * Collection owner1121 * * Collection Admin1176 * * Collection admin1122 * * Current NFT owner1177 * * Current token owner1123 * 1178 * 1124 * # Arguments1179 * # Arguments1125 * 1180 * 1126 * * recipient - Address of token recipient.1181 * * `recipient`: Address of token recipient.1127 * 1182 * * `collection_id`: ID of the collection the item belongs to.1128 * * collection_id.1129 * 1183 * * `item_id`: ID of the item.1130 * * item_id - ID of the item1184 * * Non-Fungible Mode: Required.1131 * * Non-Fungible Mode: Required.1185 * * Fungible Mode: Ignored.1132 * * Fungible Mode: Ignored.1186 * * Re-Fungible Mode: Required.1133 * * Re-Fungible Mode: Required.1187 * 1134 * 1188 * * `value`: Amount to transfer.1135 * * value - Amount to transfer.1189 * * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.1136 * * Non-Fungible Mode: Ignored1190 * * Fungible Mode: The desired number of pieces to transfer.1137 * * Fungible Mode: Must specify transferred amount1191 * * Re-Fungible Mode: The desired number of pieces to transfer.1138 * * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)1192 **/1139 **/1140 transfer: AugmentedSubmittable<(recipient: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;1193 transfer: AugmentedSubmittable<(recipient: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;1141 /**1194 /**1142 * Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.1195 * Change ownership of an item on behalf of the owner as a non-owner account.1196 * 1197 * See the [`approve`][`Pallet::approve`] method for additional information.1198 * 1199 * After this method executes, one approval is removed from the total so that1200 * the approved address will not be able to transfer this item again from this owner.1143 * 1201 * 1144 * # Permissions1202 * # Permissions1145 * 1203 * 1146 * * Collection Owner1204 * * Collection owner1147 * * Collection Admin1205 * * Collection admin1148 * * Current NFT owner1206 * * Current item owner1149 * * Address approved by current NFT owner1207 * * Address approved by current item owner1150 * 1208 * 1151 * # Arguments1209 * # Arguments1152 * 1210 * 1153 * * from - Address that currently owns the token.1211 * * `from`: Address that currently owns the token.1154 * * recipient - Address of the new token-owner-to-be.1212 * * `recipient`: Address of the new token-owner-to-be.1155 * * collection_id.1213 * * `collection_id`: ID of the collection the item.1156 * * item_id - ID of the item to be transferred.1214 * * `item_id`: ID of the item to be transferred.1157 * * value - Amount to transfer.1215 * * `value`: Amount to transfer.1216 * * Non-Fungible Mode: An NFT is indivisible, there is always 1 corresponding to an ID.1217 * * Fungible Mode: The desired number of pieces to transfer.1218 * * Re-Fungible Mode: The desired number of pieces to transfer.1158 **/1219 **/1159 transferFrom: AugmentedSubmittable<(from: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, recipient: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;1220 transferFrom: AugmentedSubmittable<(from: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, recipient: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, collectionId: u32 | AnyNumber | Uint8Array, itemId: u32 | AnyNumber | Uint8Array, value: u128 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>, [PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr, u32, u32, u128]>;1160 /**1221 /**1161 * Generic tx1222 * Generic txtests/src/interfaces/default/types.tsdiffbeforeafterboth2461export interface UpDataStructsCreateReFungibleData extends Struct {2461export interface UpDataStructsCreateReFungibleData extends Struct {2462 readonly constData: Bytes;2462 readonly constData: Bytes;2463 readonly pieces: u128;2463 readonly pieces: u128;2464 readonly properties: Vec<UpDataStructsProperty>;2464}2465}246524662466/** @name UpDataStructsCreateRefungibleExData */2467/** @name UpDataStructsCreateRefungibleExData */2467export interface UpDataStructsCreateRefungibleExData extends Struct {2468export interface UpDataStructsCreateRefungibleExData extends Struct {2468 readonly constData: Bytes;2469 readonly constData: Bytes;2469 readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;2470 readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;2471 readonly properties: Vec<UpDataStructsProperty>;2470}2472}247124732472/** @name UpDataStructsNestingPermissions */2474/** @name UpDataStructsNestingPermissions */tests/src/interfaces/lookup.tsdiffbeforeafterboth1502 **/1502 **/1503 UpDataStructsCreateReFungibleData: {1503 UpDataStructsCreateReFungibleData: {1504 constData: 'Bytes',1504 constData: 'Bytes',1505 pieces: 'u128'1505 pieces: 'u128',1506 properties: 'Vec<UpDataStructsProperty>'1506 },1507 },1507 /**1508 /**1508 * Lookup193: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1509 * Lookup193: up_data_structs::CreateItemExData<pallet_evm::account::BasicCrossAccountIdRepr<sp_core::crypto::AccountId32>>1527 **/1528 **/1528 UpDataStructsCreateRefungibleExData: {1529 UpDataStructsCreateRefungibleExData: {1529 constData: 'Bytes',1530 constData: 'Bytes',1530 users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>'1531 users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>',1532 properties: 'Vec<UpDataStructsProperty>'1531 },1533 },1532 /**1534 /**1533 * Lookup204: pallet_unique_scheduler::pallet::Call<T>1535 * Lookup204: pallet_unique_scheduler::pallet::Call<T>tests/src/interfaces/types-lookup.tsdiffbeforeafterboth1629 export interface UpDataStructsCreateReFungibleData extends Struct {1629 export interface UpDataStructsCreateReFungibleData extends Struct {1630 readonly constData: Bytes;1630 readonly constData: Bytes;1631 readonly pieces: u128;1631 readonly pieces: u128;1632 readonly properties: Vec<UpDataStructsProperty>;1632 }1633 }163316341634 /** @name UpDataStructsCreateItemExData (193) */1635 /** @name UpDataStructsCreateItemExData (193) */1654 export interface UpDataStructsCreateRefungibleExData extends Struct {1655 export interface UpDataStructsCreateRefungibleExData extends Struct {1655 readonly constData: Bytes;1656 readonly constData: Bytes;1656 readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;1657 readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;1658 readonly properties: Vec<UpDataStructsProperty>;1657 }1659 }165816601659 /** @name PalletUniqueSchedulerCall (204) */1661 /** @name PalletUniqueSchedulerCall (204) */tests/src/interfaces/unique/definitions.tsdiffbeforeafterboth63 [collectionParam, tokenParam], 63 [collectionParam, tokenParam], 64 `Option<${CROSS_ACCOUNT_ID_TYPE}>`,64 `Option<${CROSS_ACCOUNT_ID_TYPE}>`,65 ),65 ),66 tokenOwners: fun(67 'Returns 10 tokens owners in no particular order', 68 [collectionParam, tokenParam], 69 `Vec<${CROSS_ACCOUNT_ID_TYPE}>`70 ),66 tokenChildren: fun(71 tokenChildren: fun(67 'Get tokens nested directly into the token', 72 'Get tokens nested directly into the token', 68 [collectionParam, tokenParam], 73 [collectionParam, tokenParam], 85 'Vec<UpDataStructsPropertyKeyPermission>',90 'Vec<UpDataStructsPropertyKeyPermission>',86 ),91 ),9293 constMetadata: fun(94 'Get token constant metadata', 95 [collectionParam, tokenParam], 96 'Vec<u8>',97 ),98 variableMetadata: fun(99 'Get token variable metadata', 100 [collectionParam, tokenParam], 101 'Vec<u8>',102 ),8710388 tokenData: fun(104 tokenData: fun(89 'Get token data, including properties, optionally limited to the provided keys, and total pieces for an RFT',105 'Get token data, including properties, optionally limited to the provided keys, and total pieces for an RFT',tests/src/nesting/properties.test.tsdiffbeforeafterboth2import usingApi, {executeTransaction} from '../substrate/substrate-api';2import usingApi, {executeTransaction} from '../substrate/substrate-api';3import {3import {4 addCollectionAdminExpectSuccess,4 addCollectionAdminExpectSuccess,5 CollectionMode,5 createCollectionExpectSuccess,6 createCollectionExpectSuccess,6 setCollectionPermissionsExpectSuccess,7 setCollectionPermissionsExpectSuccess,7 createItemExpectSuccess,8 createItemExpectSuccess,23 });24 });24 });25 });252626 it('Makes sure collectionById supplies required fields', async () => {27 async function testMakeSureSuppliesRequired(mode: CollectionMode) {27 await usingApi(async api => {28 await usingApi(async api => {28 const collectionId = await createCollectionExpectSuccess();29 const collectionId = await createCollectionExpectSuccess({mode: mode});293030 const collectionOption = await api.rpc.unique.collectionById(collectionId);31 const collectionOption = await api.rpc.unique.collectionById(collectionId);31 expect(collectionOption.isSome).to.be.true;32 expect(collectionOption.isSome).to.be.true;57 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);58 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);58 expect(collection.properties.toHuman()).to.be.deep.equal(collectionProperties);59 expect(collection.properties.toHuman()).to.be.deep.equal(collectionProperties);59 });60 });61 }6263 it('Makes sure collectionById supplies required fields for NFT', async () => {64 await testMakeSureSuppliesRequired({type: 'NFT'});60 });65 });6667 it('Makes sure collectionById supplies required fields for ReFungible', async () => {68 await testMakeSureSuppliesRequired({type: 'ReFungible'});69 });61});70});627163// ---------- COLLECTION PROPERTIES72// ---------- COLLECTION PROPERTIES79 });88 });80 });89 });81909182 it('Sets properties for a collection', async () => {92 async function testSetsPropertiesForCollection(mode: string) {83 await usingApi(async api => {93 await usingApi(async api => {84 const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: 'NFT'}));94 const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: mode}));85 const {collectionId} = getCreateCollectionResult(events);95 const {collectionId} = getCreateCollectionResult(events);869687 // As owner97 // As owner106 {key: 'black_hole', value: ''},116 {key: 'black_hole', value: ''},107 ]);117 ]);108 });118 });119 }120 it('Sets properties for a NFT collection', async () => {121 await testSetsPropertiesForCollection('NFT');109 });122 });123 it('Sets properties for a ReFungible collection', async () => {124 await testSetsPropertiesForCollection('ReFungible');125 });110126111 it('Check valid names for collection properties keys', async () => {127 async function testCheckValidNames(mode: string) {112 await usingApi(async api => {128 await usingApi(async api => {113 const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: 'NFT'}));129 const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: mode}));114 const {collectionId} = getCreateCollectionResult(events);130 const {collectionId} = getCreateCollectionResult(events);115131 116 // alpha symbols132 // alpha symbols117 await expect(executeTransaction(133 await expect(executeTransaction(118 api, 134 api, 119 bob, 135 bob, 120 api.tx.unique.setCollectionProperties(collectionId, [{key: 'alpha'}]), 136 api.tx.unique.setCollectionProperties(collectionId, [{key: 'alpha'}]), 121 )).to.not.be.rejected;137 )).to.not.be.rejected;122138 123 // numeric symbols139 // numeric symbols124 await expect(executeTransaction(140 await expect(executeTransaction(125 api, 141 api, 126 bob, 142 bob, 127 api.tx.unique.setCollectionProperties(collectionId, [{key: '123'}]), 143 api.tx.unique.setCollectionProperties(collectionId, [{key: '123'}]), 128 )).to.not.be.rejected;144 )).to.not.be.rejected;129145 130 // underscore symbol146 // underscore symbol131 await expect(executeTransaction(147 await expect(executeTransaction(132 api, 148 api, 133 bob, 149 bob, 134 api.tx.unique.setCollectionProperties(collectionId, [{key: 'black_hole'}]), 150 api.tx.unique.setCollectionProperties(collectionId, [{key: 'black_hole'}]), 135 )).to.not.be.rejected;151 )).to.not.be.rejected;136152 137 // dash symbol153 // dash symbol138 await expect(executeTransaction(154 await expect(executeTransaction(139 api, 155 api, 140 bob, 156 bob, 141 api.tx.unique.setCollectionProperties(collectionId, [{key: 'semi-automatic'}]), 157 api.tx.unique.setCollectionProperties(collectionId, [{key: 'semi-automatic'}]), 142 )).to.not.be.rejected;158 )).to.not.be.rejected;143159 144 // underscore symbol160 // underscore symbol145 await expect(executeTransaction(161 await expect(executeTransaction(146 api, 162 api, 147 bob, 163 bob, 148 api.tx.unique.setCollectionProperties(collectionId, [{key: 'build.rs'}]), 164 api.tx.unique.setCollectionProperties(collectionId, [{key: 'build.rs'}]), 149 )).to.not.be.rejected;165 )).to.not.be.rejected;150166 151 const propertyKeys = ['alpha', '123', 'black_hole', 'semi-automatic', 'build.rs'];167 const propertyKeys = ['alpha', '123', 'black_hole', 'semi-automatic', 'build.rs'];152 const properties = (await api.rpc.unique.collectionProperties(collectionId, propertyKeys)).toHuman();168 const properties = (await api.rpc.unique.collectionProperties(collectionId, propertyKeys)).toHuman();153 expect(properties).to.be.deep.equal([169 expect(properties).to.be.deep.equal([158 {key: 'build.rs', value: ''},174 {key: 'build.rs', value: ''},159 ]);175 ]);160 });176 });177 }178 it('Check valid names for NFT collection properties keys', async () => {179 await testCheckValidNames('NFT');161 });180 });181 it('Check valid names for ReFungible collection properties keys', async () => {182 await testCheckValidNames('ReFungible');183 });162184163 it('Changes properties of a collection', async () => {185 async function testChangesProperties(mode: CollectionMode) {164 await usingApi(async api => {186 await usingApi(async api => {165 const collection = await createCollectionExpectSuccess();187 const collection = await createCollectionExpectSuccess({mode: mode});166188 167 await expect(executeTransaction(189 await expect(executeTransaction(168 api, 190 api, 169 alice, 191 alice, 170 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole'}]), 192 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole'}]), 171 )).to.not.be.rejected;193 )).to.not.be.rejected;172194 173 // Mutate the properties195 // Mutate the properties174 await expect(executeTransaction(196 await expect(executeTransaction(175 api, 197 api, 176 alice, 198 alice, 177 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'bonded'}, {key: 'black_hole', value: 'LIGO'}]), 199 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'bonded'}, {key: 'black_hole', value: 'LIGO'}]), 178 )).to.not.be.rejected;200 )).to.not.be.rejected;179201 180 const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();202 const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();181 expect(properties).to.be.deep.equal([203 expect(properties).to.be.deep.equal([182 {key: 'electron', value: 'bonded'},204 {key: 'electron', value: 'bonded'},183 {key: 'black_hole', value: 'LIGO'},205 {key: 'black_hole', value: 'LIGO'},184 ]);206 ]);185 });207 });208 }209 it('Changes properties of a NFT collection', async () => {210 await testChangesProperties({type: 'NFT'});186 });211 });212 it('Changes properties of a ReFungible collection', async () => {213 await testChangesProperties({type: 'ReFungible'});214 });187215188 it('Deletes properties of a collection', async () => {216 async function testDeleteProperties(mode: CollectionMode) {189 await usingApi(async api => {217 await usingApi(async api => {190 const collection = await createCollectionExpectSuccess();218 const collection = await createCollectionExpectSuccess({mode: mode});191219 192 await expect(executeTransaction(220 await expect(executeTransaction(193 api, 221 api, 194 alice, 222 alice, 195 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]), 223 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]), 196 )).to.not.be.rejected;224 )).to.not.be.rejected;197225 198 await expect(executeTransaction(226 await expect(executeTransaction(199 api, 227 api, 200 alice, 228 alice, 201 api.tx.unique.deleteCollectionProperties(collection, ['electron']), 229 api.tx.unique.deleteCollectionProperties(collection, ['electron']), 202 )).to.not.be.rejected;230 )).to.not.be.rejected;203231 204 const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();232 const properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black_hole'])).toHuman();205 expect(properties).to.be.deep.equal([233 expect(properties).to.be.deep.equal([206 {key: 'black_hole', value: 'LIGO'},234 {key: 'black_hole', value: 'LIGO'},207 ]);235 ]);208 });236 }); 237 }238 it('Deletes properties of a NFT collection', async () => {239 await testDeleteProperties({type: 'NFT'});209 });240 });241 it('Deletes properties of a ReFungible collection', async () => {242 await testDeleteProperties({type: 'ReFungible'});243 });210});244});211245212describe('Negative Integration Test: Collection Properties', () => {246describe('Negative Integration Test: Collection Properties', () => {217 });251 });218 });252 });219 253 220 it('Fails to set properties in a collection if not its onwer/administrator', async () => {254 async function testFailsSetPropertiesIfNotOwnerOrAdmin(mode: CollectionMode) {221 await usingApi(async api => {255 await usingApi(async api => {222 const collection = await createCollectionExpectSuccess();256 const collection = await createCollectionExpectSuccess({mode: mode});223257 224 await expect(executeTransaction(258 await expect(executeTransaction(225 api, 259 api, 226 bob, 260 bob, 230 const properties = (await api.query.common.collectionProperties(collection)).toJSON();264 const properties = (await api.query.common.collectionProperties(collection)).toJSON();231 expect(properties.map).to.be.empty;265 expect(properties.map).to.be.empty;232 expect(properties.consumedSpace).to.equal(0);266 expect(properties.consumedSpace).to.equal(0);233 });267 }); 268 }269 it('Fails to set properties in a NFT collection if not its onwer/administrator', async () => {270 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'NFT'});234 });271 });272 it('Fails to set properties in a ReFungible collection if not its onwer/administrator', async () => {273 await testFailsSetPropertiesIfNotOwnerOrAdmin({type: 'ReFungible'});274 });235 275 236 it('Fails to set properties that exceed the limits', async () => {276 async function testFailsSetPropertiesThatExeedLimits(mode: CollectionMode) {237 await usingApi(async api => {277 await usingApi(async api => {238 const collection = await createCollectionExpectSuccess();278 const collection = await createCollectionExpectSuccess({mode: mode});239 const spaceLimit = (await api.query.common.collectionProperties(collection)).toJSON().spaceLimit as number; 279 const spaceLimit = (await api.query.common.collectionProperties(collection)).toJSON().spaceLimit as number; 240280 241 // Mute the general tx parsing error, too many bytes to process281 // Mute the general tx parsing error, too many bytes to process242 {282 {243 console.error = () => {};283 console.error = () => {};247 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 9))}]), 287 api.tx.unique.setCollectionProperties(collection, [{key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 9))}]), 248 )).to.be.rejected;288 )).to.be.rejected;249 }289 }250290 251 let properties = (await api.rpc.unique.collectionProperties(collection, ['electron'])).toJSON();291 let properties = (await api.rpc.unique.collectionProperties(collection, ['electron'])).toJSON();252 expect(properties).to.be.empty;292 expect(properties).to.be.empty;253293 254 await expect(executeTransaction(294 await expect(executeTransaction(255 api, 295 api, 256 alice, 296 alice, 259 {key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))}, 299 {key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))}, 260 ]), 300 ]), 261 )).to.be.rejectedWith(/common\.NoSpaceForProperty/);301 )).to.be.rejectedWith(/common\.NoSpaceForProperty/);262302 263 properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black hole'])).toJSON();303 properties = (await api.rpc.unique.collectionProperties(collection, ['electron', 'black hole'])).toJSON();264 expect(properties).to.be.empty;304 expect(properties).to.be.empty;265 });305 }); 306 }307 it('Fails to set properties that exceed the limits (NFT)', async () => {308 await testFailsSetPropertiesThatExeedLimits({type: 'NFT'});266 });309 });310 it('Fails to set properties that exceed the limits (ReFungible)', async () => {311 await testFailsSetPropertiesThatExeedLimits({type: 'ReFungible'});312 });267 313 268 it('Fails to set more properties than it is allowed', async () => {314 async function testFailsSetMorePropertiesThanAllowed(mode: CollectionMode) {269 await usingApi(async api => {315 await usingApi(async api => {270 const collection = await createCollectionExpectSuccess();316 const collection = await createCollectionExpectSuccess({mode: mode});271317 272 const propertiesToBeSet = [];318 const propertiesToBeSet = [];273 for (let i = 0; i < 65; i++) {319 for (let i = 0; i < 65; i++) {274 propertiesToBeSet.push({320 propertiesToBeSet.push({275 key: 'electron_' + i,321 key: 'electron_' + i,276 value: Math.random() > 0.5 ? 'high' : 'low',322 value: Math.random() > 0.5 ? 'high' : 'low',277 });323 });278 }324 }279325 280 await expect(executeTransaction(326 await expect(executeTransaction(281 api, 327 api, 282 alice, 328 alice, 283 api.tx.unique.setCollectionProperties(collection, propertiesToBeSet), 329 api.tx.unique.setCollectionProperties(collection, propertiesToBeSet), 284 )).to.be.rejectedWith(/common\.PropertyLimitReached/);330 )).to.be.rejectedWith(/common\.PropertyLimitReached/);285331 286 const properties = (await api.query.common.collectionProperties(collection)).toJSON();332 const properties = (await api.query.common.collectionProperties(collection)).toJSON();287 expect(properties.map).to.be.empty;333 expect(properties.map).to.be.empty;288 expect(properties.consumedSpace).to.equal(0);334 expect(properties.consumedSpace).to.equal(0);289 });335 }); 336 }337 it('Fails to set more properties than it is allowed (NFT)', async () => {338 await testFailsSetMorePropertiesThanAllowed({type: 'NFT'});290 });339 });291292 it('Fails to set properties with invalid names', async () => {340 it('Fails to set more properties than it is allowed (ReFungible)', async () => {341 await testFailsSetMorePropertiesThanAllowed({type: 'ReFungible'});342 });343 344 async function testFailsSetPropertiesWithInvalidNames(mode: CollectionMode) {293 await usingApi(async api => {345 await usingApi(async api => {294 const collection = await createCollectionExpectSuccess();346 const collection = await createCollectionExpectSuccess({mode: mode});295347 296 const invalidProperties = [348 const invalidProperties = [297 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],349 [{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],298 [{key: 'Mr/Sandman', value: 'Bring me a gene'}],350 [{key: 'Mr/Sandman', value: 'Bring me a gene'}],299 [{key: 'déjà vu', value: 'hmm...'}],351 [{key: 'déjà vu', value: 'hmm...'}],300 ];352 ];301353 302 for (let i = 0; i < invalidProperties.length; i++) {354 for (let i = 0; i < invalidProperties.length; i++) {303 await expect(executeTransaction(355 await expect(executeTransaction(304 api, 356 api, 305 alice, 357 alice, 306 api.tx.unique.setCollectionProperties(collection, invalidProperties[i]), 358 api.tx.unique.setCollectionProperties(collection, invalidProperties[i]), 307 ), `on rejecting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);359 ), `on rejecting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);308 }360 }309361 310 await expect(executeTransaction(362 await expect(executeTransaction(311 api, 363 api, 312 alice, 364 alice, 313 api.tx.unique.setCollectionProperties(collection, [{key: '', value: 'nothing must not exist'}]), 365 api.tx.unique.setCollectionProperties(collection, [{key: '', value: 'nothing must not exist'}]), 314 ), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);366 ), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);315367 316 await expect(executeTransaction(368 await expect(executeTransaction(317 api, 369 api, 318 alice, 370 alice, 319 api.tx.unique.setCollectionProperties(collection, [371 api.tx.unique.setCollectionProperties(collection, [320 {key: 'CRISPR-Cas9', value: 'rewriting nature!'},372 {key: 'CRISPR-Cas9', value: 'rewriting nature!'},321 ]), 373 ]), 322 ), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;374 ), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;323375 324 const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat('CRISPR-Cas9').concat('');376 const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat('CRISPR-Cas9').concat('');325377 326 const properties = (await api.rpc.unique.collectionProperties(collection, keys)).toHuman();378 const properties = (await api.rpc.unique.collectionProperties(collection, keys)).toHuman();327 expect(properties).to.be.deep.equal([379 expect(properties).to.be.deep.equal([328 {key: 'CRISPR-Cas9', value: 'rewriting nature!'},380 {key: 'CRISPR-Cas9', value: 'rewriting nature!'},329 ]);381 ]);330382 331 for (let i = 0; i < invalidProperties.length; i++) {383 for (let i = 0; i < invalidProperties.length; i++) {332 await expect(executeTransaction(384 await expect(executeTransaction(333 api, 385 api, 336 ), `on trying to delete the non-existent badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);388 ), `on trying to delete the non-existent badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);337 }389 }338 });390 });391 }392 it('Fails to set properties with invalid names (NFT)', async () => {393 await testFailsSetPropertiesWithInvalidNames({type: 'NFT'});339 });394 });395 it('Fails to set properties with invalid names (ReFungible)', async () => {396 await testFailsSetPropertiesWithInvalidNames({type: 'ReFungible'});397 });340});398});341399342// ---------- ACCESS RIGHTS400// ---------- ACCESS RIGHTS357 });415 });358 });416 });359 417 360 it('Sets access rights to properties of a collection', async () => {418 async function testSetsAccessRightsToProperties(mode: CollectionMode) {361 await usingApi(async api => {419 await usingApi(async api => {362 const collection = await createCollectionExpectSuccess();420 const collection = await createCollectionExpectSuccess({mode: mode});363421 364 await expect(executeTransaction(422 await expect(executeTransaction(365 api, 423 api, 366 alice, 424 alice, 367 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true}}]), 425 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true}}]), 368 )).to.not.be.rejected;426 )).to.not.be.rejected;369427 370 await addCollectionAdminExpectSuccess(alice, collection, bob.address);428 await addCollectionAdminExpectSuccess(alice, collection, bob.address);371429 372 await expect(executeTransaction(430 await expect(executeTransaction(373 api, 431 api, 374 alice, 432 alice, 375 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'mindgame', permission: {collectionAdmin: true, tokenOwner: false}}]), 433 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'mindgame', permission: {collectionAdmin: true, tokenOwner: false}}]), 376 )).to.not.be.rejected;434 )).to.not.be.rejected;377435 378 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery', 'mindgame'])).toHuman();436 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery', 'mindgame'])).toHuman();379 expect(propertyRights).to.be.deep.equal([437 expect(propertyRights).to.be.deep.equal([380 {key: 'skullduggery', permission: {'mutable': true, 'collectionAdmin': false, 'tokenOwner': false}},438 {key: 'skullduggery', permission: {'mutable': true, 'collectionAdmin': false, 'tokenOwner': false}},381 {key: 'mindgame', permission: {'mutable': false, 'collectionAdmin': true, 'tokenOwner': false}},439 {key: 'mindgame', permission: {'mutable': false, 'collectionAdmin': true, 'tokenOwner': false}},382 ]);440 ]);383 });441 }); 442 }443 it('Sets access rights to properties of a collection (NFT)', async () => {444 await testSetsAccessRightsToProperties({type: 'NFT'});384 });445 });446 it('Sets access rights to properties of a collection (ReFungible)', async () => {447 await testSetsAccessRightsToProperties({type: 'ReFungible'});448 });385 449 386 it('Changes access rights to properties of a collection', async () => {450 async function testChangesAccessRightsToProperty(mode: CollectionMode) {387 await usingApi(async api => {451 await usingApi(async api => {388 const collection = await createCollectionExpectSuccess();452 const collection = await createCollectionExpectSuccess({mode: mode});389453 390 await expect(executeTransaction(454 await expect(executeTransaction(391 api, 455 api, 392 alice, 456 alice, 393 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]), 457 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}]), 394 )).to.not.be.rejected;458 )).to.not.be.rejected;395459 396 await expect(executeTransaction(460 await expect(executeTransaction(397 api, 461 api, 398 alice, 462 alice, 399 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]), 463 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]), 400 )).to.not.be.rejected;464 )).to.not.be.rejected;401465 402 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();466 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();403 expect(propertyRights).to.be.deep.equal([467 expect(propertyRights).to.be.deep.equal([404 {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},468 {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},405 ]);469 ]);406 });470 });471 }472 it('Changes access rights to properties of a NFT collection', async () => {473 await testChangesAccessRightsToProperty({type: 'NFT'});407 });474 });475 it('Changes access rights to properties of a ReFungible collection', async () => {476 await testChangesAccessRightsToProperty({type: 'ReFungible'});477 });408});478});409479410describe('Negative Integration Test: Access Rights to Token Properties', () => {480describe('Negative Integration Test: Access Rights to Token Properties', () => {415 });485 });416 });486 });417487418 it('Prevents from setting access rights to properties of a collection if not an onwer/admin', async () => {488 async function testPreventsFromSettingAccessRightsNotAdminOrOwner(mode: CollectionMode) {419 await usingApi(async api => {489 await usingApi(async api => {420 const collection = await createCollectionExpectSuccess();490 const collection = await createCollectionExpectSuccess({mode: mode});421491 422 await expect(executeTransaction(492 await expect(executeTransaction(423 api, 493 api, 424 bob, 494 bob, 425 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]), 495 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}]), 426 )).to.be.rejectedWith(/common\.NoPermission/);496 )).to.be.rejectedWith(/common\.NoPermission/);427497 428 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toJSON();498 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toJSON();429 expect(propertyRights).to.be.empty;499 expect(propertyRights).to.be.empty;430 });500 });501 }502 it('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async () => {503 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'NFT'});431 });504 });505 it('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', async () => {506 await testPreventsFromSettingAccessRightsNotAdminOrOwner({type: 'ReFungible'});507 });432508433 it('Prevents from adding too many possible properties', async () => {509 async function testPreventFromAddingTooManyPossibleProperties(mode: CollectionMode) {434 await usingApi(async api => {510 await usingApi(async api => {435 const collection = await createCollectionExpectSuccess();511 const collection = await createCollectionExpectSuccess({mode: mode});436512 437 const constitution = [];513 const constitution = [];438 for (let i = 0; i < 65; i++) {514 for (let i = 0; i < 65; i++) {439 constitution.push({515 constitution.push({440 key: 'property_' + i,516 key: 'property_' + i,441 permission: Math.random() > 0.5 ? {mutable: true, collectionAdmin: true, tokenOwner: true} : {},517 permission: Math.random() > 0.5 ? {mutable: true, collectionAdmin: true, tokenOwner: true} : {},442 });518 });443 }519 }444520 445 await expect(executeTransaction(521 await expect(executeTransaction(446 api, 522 api, 447 alice, 523 alice, 448 api.tx.unique.setTokenPropertyPermissions(collection, constitution), 524 api.tx.unique.setTokenPropertyPermissions(collection, constitution), 449 )).to.be.rejectedWith(/common\.PropertyLimitReached/);525 )).to.be.rejectedWith(/common\.PropertyLimitReached/);450526 451 const propertyRights = (await api.query.common.collectionPropertyPermissions(collection)).toJSON();527 const propertyRights = (await api.query.common.collectionPropertyPermissions(collection)).toJSON();452 expect(propertyRights).to.be.empty;528 expect(propertyRights).to.be.empty;453 });529 }); 530 }531 it('Prevents from adding too many possible properties (NFT)', async () => {532 await testPreventFromAddingTooManyPossibleProperties({type: 'NFT'});454 });533 });534 it('Prevents from adding too many possible properties (ReFungible)', async () => {535 await testPreventFromAddingTooManyPossibleProperties({type: 'ReFungible'});536 });455537456 it('Prevents access rights to be modified if constant', async () => {538 async function testPreventAccessRightsModifiedIfConstant(mode: CollectionMode) {457 await usingApi(async api => {539 await usingApi(async api => {458 const collection = await createCollectionExpectSuccess();540 const collection = await createCollectionExpectSuccess({mode: mode});459541 460 await expect(executeTransaction(542 await expect(executeTransaction(461 api, 543 api, 462 alice, 544 alice, 463 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]), 545 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}]), 464 )).to.not.be.rejected;546 )).to.not.be.rejected;465547 466 await expect(executeTransaction(548 await expect(executeTransaction(467 api, 549 api, 468 alice, 550 alice, 469 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {}}]), 551 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'skullduggery', permission: {}}]), 470 )).to.be.rejectedWith(/common\.NoPermission/);552 )).to.be.rejectedWith(/common\.NoPermission/);471553 472 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();554 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, ['skullduggery'])).toHuman();473 expect(propertyRights).to.deep.equal([555 expect(propertyRights).to.deep.equal([474 {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},556 {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}},475 ]);557 ]);476 });558 }); 559 }560 it('Prevents access rights to be modified if constant (NFT)', async () => {561 await testPreventAccessRightsModifiedIfConstant({type: 'NFT'});477 });562 });563 it('Prevents access rights to be modified if constant (ReFungible)', async () => {564 await testPreventAccessRightsModifiedIfConstant({type: 'ReFungible'});565 });478566479 it('Prevents adding properties with invalid names', async () => {567 async function testPreventsAddingPropertiesWithInvalidNames(mode: CollectionMode) {480 await usingApi(async api => {568 await usingApi(async api => {481 const collection = await createCollectionExpectSuccess();569 const collection = await createCollectionExpectSuccess({mode: mode});482570 483 const invalidProperties = [571 const invalidProperties = [484 [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],572 [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}],485 [{key: 'G#4', permission: {tokenOwner: true}}],573 [{key: 'G#4', permission: {tokenOwner: true}}],486 [{key: 'HÆMILTON', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}],574 [{key: 'HÆMILTON', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}],487 ];575 ];488576 489 for (let i = 0; i < invalidProperties.length; i++) {577 for (let i = 0; i < invalidProperties.length; i++) {490 await expect(executeTransaction(578 await expect(executeTransaction(491 api, 579 api, 492 alice, 580 alice, 493 api.tx.unique.setTokenPropertyPermissions(collection, invalidProperties[i]), 581 api.tx.unique.setTokenPropertyPermissions(collection, invalidProperties[i]), 494 ), `on setting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);582 ), `on setting the new badly-named property #${i}`).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/);495 }583 }496584 497 await expect(executeTransaction(585 await expect(executeTransaction(498 api, 586 api, 499 alice, 587 alice, 500 api.tx.unique.setTokenPropertyPermissions(collection, [{key: '', permission: {}}]), 588 api.tx.unique.setTokenPropertyPermissions(collection, [{key: '', permission: {}}]), 501 ), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);589 ), 'on rejecting an unnamed property').to.be.rejectedWith(/common\.EmptyPropertyKey/);502590 503 const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string591 const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string504 await expect(executeTransaction(592 await expect(executeTransaction(505 api, 593 api, 508 {key: correctKey, permission: {collectionAdmin: true}},596 {key: correctKey, permission: {collectionAdmin: true}},509 ]), 597 ]), 510 ), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;598 ), 'on setting the correctly-but-still-badly-named property').to.not.be.rejected;511599 512 const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat(correctKey).concat('');600 const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat(correctKey).concat('');513601 514 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, keys)).toHuman();602 const propertyRights = (await api.rpc.unique.propertyPermissions(collection, keys)).toHuman();515 expect(propertyRights).to.be.deep.equal([603 expect(propertyRights).to.be.deep.equal([516 {key: correctKey, permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},604 {key: correctKey, permission: {mutable: false, collectionAdmin: true, tokenOwner: false}},517 ]);605 ]);518 });606 });607 }608 it('Prevents adding properties with invalid names (NFT)', async () => {609 await testPreventsAddingPropertiesWithInvalidNames({type: 'NFT'});519 });610 });611 it('Prevents adding properties with invalid names (ReFungible)', async () => {612 await testPreventsAddingPropertiesWithInvalidNames({type: 'ReFungible'});613 });520});614});521615522// ---------- TOKEN PROPERTIES616// ---------- TOKEN PROPERTIES523617524describe('Integration Test: Token Properties', () => {618describe('Integration Test: Token Properties', () => {525 let collection: number;526 let token: number;527 let nestedToken: number;528 let permissions: {permission: any, signers: IKeyringPair[]}[];619 let permissions: {permission: any, signers: IKeyringPair[]}[];529620530 before(async () => {621 before(async () => {531 await usingApi(async (api, privateKeyWrapper) => {622 await usingApi(async (api, privateKeyWrapper) => {532 alice = privateKeyWrapper('//Alice');623 alice = privateKeyWrapper('//Alice'); // collection owner533 bob = privateKeyWrapper('//Bob');624 bob = privateKeyWrapper('//Bob'); // collection admin534 charlie = privateKeyWrapper('//Charlie');625 charlie = privateKeyWrapper('//Charlie'); // token owner535626536 permissions = [627 permissions = [537 {permission: {mutable: true, collectionAdmin: true}, signers: [alice, bob]},628 {permission: {mutable: true, collectionAdmin: true}, signers: [alice, bob]},543 ];634 ];544 });635 });545 });636 });546547 beforeEach(async () => {548 await usingApi(async () => {549 collection = await createCollectionExpectSuccess();550 await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});551552 token = await createItemExpectSuccess(alice, collection, 'NFT');553 nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});554555 await addCollectionAdminExpectSuccess(alice, collection, bob.address);556 await transferExpectSuccess(collection, token, alice, charlie);557 });558 });559 637 560 it('Reads yet empty properties of a token', async () => {638 async function testReadsYetEmptyProperties(mode: CollectionMode) {561 await usingApi(async api => {639 await usingApi(async api => {562 const collection = await createCollectionExpectSuccess();640 const collection = await createCollectionExpectSuccess({mode: mode});563 const token = await createItemExpectSuccess(alice, collection, 'NFT');641 const token = await createItemExpectSuccess(alice, collection, mode.type);564 642 565 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();643 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();566 expect(properties.map).to.be.empty;644 expect(properties.map).to.be.empty;567 expect(properties.consumedSpace).to.be.equal(0);645 expect(properties.consumedSpace).to.be.equal(0);568646 569 const tokenData = (await api.rpc.unique.tokenData(collection, token, ['anything'])).toJSON().properties;647 const tokenData = (await api.rpc.unique.tokenData(collection, token, ['anything'])).toJSON().properties;570 expect(tokenData).to.be.empty;648 expect(tokenData).to.be.empty;571 });649 });650 }651 it('Reads yet empty properties of a token (NFT)', async () => {652 await testReadsYetEmptyProperties({type: 'NFT'});572 });653 });654 it('Reads yet empty properties of a token (ReFungible)', async () => {655 await testReadsYetEmptyProperties({type: 'ReFungible'});656 });573657574 it('Assigns properties to a token according to permissions', async () => {658 async function testAssignPropertiesAccordingToPermissions(mode: CollectionMode, pieces: number) {575 await usingApi(async api => {659 await usingApi(async api => {660 const collection = await createCollectionExpectSuccess({mode: mode});661 const token = await createItemExpectSuccess(alice, collection, mode.type);662 await addCollectionAdminExpectSuccess(alice, collection, bob.address);663 await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);664576 const propertyKeys: string[] = [];665 const propertyKeys: string[] = [];577 let i = 0;666 let i = 0;578 for (const permission of permissions) {667 for (const permission of permissions) {603 expect(tokensData[i].value).to.be.equal('Serotonin increase');692 expect(tokensData[i].value).to.be.equal('Serotonin increase');604 }693 }605 });694 });695 }696 it('Assigns properties to a token according to permissions (NFT)', async () => {697 await testAssignPropertiesAccordingToPermissions({type: 'NFT'}, 1);606 });698 });699 it('Assigns properties to a token according to permissions (ReFungible)', async () => {700 await testAssignPropertiesAccordingToPermissions({type: 'ReFungible'}, 100);701 });607702608 it('Changes properties of a token according to permissions', async () => {703 async function testChangesPropertiesAccordingPermission(mode: CollectionMode, pieces: number) {609 await usingApi(async api => {704 await usingApi(async api => {705 const collection = await createCollectionExpectSuccess({mode: mode});706 const token = await createItemExpectSuccess(alice, collection, mode.type);707 await addCollectionAdminExpectSuccess(alice, collection, bob.address);708 await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);709610 const propertyKeys: string[] = [];710 const propertyKeys: string[] = [];611 let i = 0;711 let i = 0;612 for (const permission of permissions) {712 for (const permission of permissions) {615 for (const signer of permission.signers) {715 for (const signer of permission.signers) {616 const key = i + '_' + signer.address;716 const key = i + '_' + signer.address;617 propertyKeys.push(key);717 propertyKeys.push(key);618718 619 await expect(executeTransaction(719 await expect(executeTransaction(620 api, 720 api, 621 alice, 721 alice, 622 api.tx.unique.setTokenPropertyPermissions(collection, [{key: key, permission: permission.permission}]), 722 api.tx.unique.setTokenPropertyPermissions(collection, [{key: key, permission: permission.permission}]), 623 ), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;723 ), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;624724 625 await expect(executeTransaction(725 await expect(executeTransaction(626 api, 726 api, 627 signer, 727 signer, 628 api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin increase'}]), 728 api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin increase'}]), 629 ), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;729 ), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;630730 631 await expect(executeTransaction(731 await expect(executeTransaction(632 api, 732 api, 633 signer, 733 signer, 634 api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin stable'}]), 734 api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin stable'}]), 635 ), `on changing property ${i} by ${signer.address}`).to.not.be.rejected;735 ), `on changing property ${i} by ${signer.address}`).to.not.be.rejected;636 }736 }637737 638 i++;738 i++;639 }739 }640740 641 const properties = (await api.rpc.unique.tokenProperties(collection, token, propertyKeys)).toHuman() as any[];741 const properties = (await api.rpc.unique.tokenProperties(collection, token, propertyKeys)).toHuman() as any[];642 const tokensData = (await api.rpc.unique.tokenData(collection, token, propertyKeys)).toHuman().properties as any[];742 const tokensData = (await api.rpc.unique.tokenData(collection, token, propertyKeys)).toHuman().properties as any[];643 for (let i = 0; i < properties.length; i++) {743 for (let i = 0; i < properties.length; i++) {644 expect(properties[i].value).to.be.equal('Serotonin stable');744 expect(properties[i].value).to.be.equal('Serotonin stable');645 expect(tokensData[i].value).to.be.equal('Serotonin stable');745 expect(tokensData[i].value).to.be.equal('Serotonin stable');646 }746 }647 });747 });748 }749 it('Changes properties of a token according to permissions (NFT)', async () => {750 await testChangesPropertiesAccordingPermission({type: 'NFT'}, 1);648 });751 });752 it('Changes properties of a token according to permissions (ReFungible)', async () => {753 await testChangesPropertiesAccordingPermission({type: 'ReFungible'}, 100);754 });649755650 it('Deletes properties of a token according to permissions', async () => {756 async function testDeletePropertiesAccordingPermission(mode: CollectionMode, pieces: number) {651 await usingApi(async api => {757 await usingApi(async api => {758 const collection = await createCollectionExpectSuccess({mode: mode});759 const token = await createItemExpectSuccess(alice, collection, mode.type);760 await addCollectionAdminExpectSuccess(alice, collection, bob.address);761 await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);762652 const propertyKeys: string[] = [];763 const propertyKeys: string[] = [];653 let i = 0;764 let i = 0;654765 655 for (const permission of permissions) {766 for (const permission of permissions) {656 if (!permission.permission.mutable) continue;767 if (!permission.permission.mutable) continue;657 768 658 for (const signer of permission.signers) {769 for (const signer of permission.signers) {659 const key = i + '_' + signer.address;770 const key = i + '_' + signer.address;660 propertyKeys.push(key);771 propertyKeys.push(key);661772 662 await expect(executeTransaction(773 await expect(executeTransaction(663 api, 774 api, 664 alice, 775 alice, 665 api.tx.unique.setTokenPropertyPermissions(collection, [{key: key, permission: permission.permission}]), 776 api.tx.unique.setTokenPropertyPermissions(collection, [{key: key, permission: permission.permission}]), 666 ), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;777 ), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;667778 668 await expect(executeTransaction(779 await expect(executeTransaction(669 api, 780 api, 670 signer, 781 signer, 671 api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin increase'}]), 782 api.tx.unique.setTokenProperties(collection, token, [{key: key, value: 'Serotonin increase'}]), 672 ), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;783 ), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;673784 674 await expect(executeTransaction(785 await expect(executeTransaction(675 api, 786 api, 676 signer, 787 signer, 680 791 681 i++;792 i++;682 }793 }683794 684 const properties = (await api.rpc.unique.tokenProperties(collection, token, propertyKeys)).toJSON() as any[];795 const properties = (await api.rpc.unique.tokenProperties(collection, token, propertyKeys)).toJSON() as any[];685 expect(properties).to.be.empty;796 expect(properties).to.be.empty;686 const tokensData = (await api.rpc.unique.tokenData(collection, token, propertyKeys)).toJSON().properties as any[];797 const tokensData = (await api.rpc.unique.tokenData(collection, token, propertyKeys)).toJSON().properties as any[];687 expect(tokensData).to.be.empty;798 expect(tokensData).to.be.empty;688 expect((await api.query.nonfungible.tokenProperties(collection, token)).toJSON().consumedSpace).to.be.equal(0);799 expect((await api.query.nonfungible.tokenProperties(collection, token)).toJSON().consumedSpace).to.be.equal(0);689 });800 });801 }802 it('Deletes properties of a token according to permissions (NFT)', async () => {803 await testDeletePropertiesAccordingPermission({type: 'NFT'}, 1);690 });804 });805 it('Deletes properties of a token according to permissions (ReFungible)', async () => {806 await testDeletePropertiesAccordingPermission({type: 'ReFungible'}, 100);807 });691808692 it('Assigns properties to a nested token according to permissions', async () => {809 it('Assigns properties to a nested token according to permissions', async () => {693 await usingApi(async api => {810 await usingApi(async api => {811 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});812 await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});813 const token = await createItemExpectSuccess(alice, collection, 'NFT');814 const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});815 await addCollectionAdminExpectSuccess(alice, collection, bob.address);816 await transferExpectSuccess(collection, token, alice, charlie);817694 const propertyKeys: string[] = [];818 const propertyKeys: string[] = [];695 let i = 0;819 let i = 0;696 for (const permission of permissions) {820 for (const permission of permissions) {725849726 it('Changes properties of a nested token according to permissions', async () => {850 it('Changes properties of a nested token according to permissions', async () => {727 await usingApi(async api => {851 await usingApi(async api => {852 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});853 await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});854 const token = await createItemExpectSuccess(alice, collection, 'NFT');855 const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});856 await addCollectionAdminExpectSuccess(alice, collection, bob.address);857 await transferExpectSuccess(collection, token, alice, charlie);858728 const propertyKeys: string[] = [];859 const propertyKeys: string[] = [];729 let i = 0;860 let i = 0;730 for (const permission of permissions) {861 for (const permission of permissions) {767898768 it('Deletes properties of a nested token according to permissions', async () => {899 it('Deletes properties of a nested token according to permissions', async () => {769 await usingApi(async api => {900 await usingApi(async api => {901 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});902 await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});903 const token = await createItemExpectSuccess(alice, collection, 'NFT');904 const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});905 await addCollectionAdminExpectSuccess(alice, collection, bob.address);906 await transferExpectSuccess(collection, token, alice, charlie);907770 const propertyKeys: string[] = [];908 const propertyKeys: string[] = [];771 let i = 0;909 let i = 0;772910832 });970 });833 });971 });834972835 beforeEach(async () => {973 async function prepare(mode: CollectionMode, pieces: number) {836 collection = await createCollectionExpectSuccess();974 collection = await createCollectionExpectSuccess({mode: mode});837 token = await createItemExpectSuccess(alice, collection, 'NFT');975 token = await createItemExpectSuccess(alice, collection, mode.type);838 await addCollectionAdminExpectSuccess(alice, collection, bob.address);976 await addCollectionAdminExpectSuccess(alice, collection, bob.address);839 await transferExpectSuccess(collection, token, alice, charlie);977 await transferExpectSuccess(collection, token, alice, charlie, pieces, mode.type);840 978 841 await usingApi(async api => {979 await usingApi(async api => {842 let i = 0;980 let i = 0;848 alice, 986 alice, 849 api.tx.unique.setTokenPropertyPermissions(collection, [{key: `${i}`, permission: passage.permission}]), 987 api.tx.unique.setTokenPropertyPermissions(collection, [{key: `${i}`, permission: passage.permission}]), 850 ), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;988 ), `on setting permission ${i} by ${signer.address}`).to.not.be.rejected;851989 852 await expect(executeTransaction(990 await expect(executeTransaction(853 api, 991 api, 854 signer, 992 signer, 855 api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin increase'}]), 993 api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin increase'}]), 856 ), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;994 ), `on adding property ${i} by ${signer.address}`).to.not.be.rejected;857995 858 i++;996 i++;859 }997 }860998 861 originalSpace = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON().consumedSpace as number;999 originalSpace = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON().consumedSpace as number;862 });1000 }); 863 });1001 }8641002865 it('Forbids changing/deleting properties of a token if the user is outside of permissions', async () => {1003 async function testForbidsChangingDeletingPropertiesUserOutsideOfPermissions(mode: CollectionMode, pieces: number) {1004 await prepare(mode, pieces);1005 866 await usingApi(async api => {1006 await usingApi(async api => {867 let i = -1;1007 let i = -1;868 for (const forbiddance of constitution) {1008 for (const forbiddance of constitution) {869 i++;1009 i++;870 if (!forbiddance.permission.mutable) continue;1010 if (!forbiddance.permission.mutable) continue;8711011 872 await expect(executeTransaction(1012 await expect(executeTransaction(873 api, 1013 api, 874 forbiddance.sinner, 1014 forbiddance.sinner, 875 api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin down'}]), 1015 api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin down'}]), 876 ), `on failing to change property ${i} by ${forbiddance.sinner.address}`).to.be.rejectedWith(/common\.NoPermission/);1016 ), `on failing to change property ${i} by ${forbiddance.sinner.address}`).to.be.rejectedWith(/common\.NoPermission/);8771017 878 await expect(executeTransaction(1018 await expect(executeTransaction(879 api, 1019 api, 880 forbiddance.sinner, 1020 forbiddance.sinner, 881 api.tx.unique.deleteTokenProperties(collection, token, [`${i}`]), 1021 api.tx.unique.deleteTokenProperties(collection, token, [`${i}`]), 882 ), `on failing to delete property ${i} by ${forbiddance.sinner.address}`).to.be.rejectedWith(/common\.NoPermission/);1022 ), `on failing to delete property ${i} by ${forbiddance.sinner.address}`).to.be.rejectedWith(/common\.NoPermission/);883 }1023 }8841024 885 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();1025 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();886 expect(properties.consumedSpace).to.be.equal(originalSpace);1026 expect(properties.consumedSpace).to.be.equal(originalSpace);887 });1027 });1028 }1029 it('Forbids changing/deleting properties of a token if the user is outside of permissions (NFT)', async () => {1030 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'NFT'}, 1);888 });1031 });1032 it('Forbids changing/deleting properties of a token if the user is outside of permissions (ReFungible)', async () => {1033 await testForbidsChangingDeletingPropertiesUserOutsideOfPermissions({type: 'ReFungible'}, 100);1034 });8891035890 it('Forbids changing/deleting properties of a token if the property is permanent (immutable)', async () => {1036 async function testForbidsChangingDeletingPropertiesIfPropertyImmutable(mode: CollectionMode, pieces: number) {1037 await prepare(mode, pieces);1038 891 await usingApi(async api => {1039 await usingApi(async api => {892 let i = -1;1040 let i = -1;893 for (const permission of constitution) {1041 for (const permission of constitution) {894 i++;1042 i++;895 if (permission.permission.mutable) continue;1043 if (permission.permission.mutable) continue;8961044 897 await expect(executeTransaction(1045 await expect(executeTransaction(898 api, 1046 api, 899 permission.signers[0], 1047 permission.signers[0], 900 api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin down'}]), 1048 api.tx.unique.setTokenProperties(collection, token, [{key: `${i}`, value: 'Serotonin down'}]), 901 ), `on failing to change property ${i} by ${permission.signers[0].address}`).to.be.rejectedWith(/common\.NoPermission/);1049 ), `on failing to change property ${i} by ${permission.signers[0].address}`).to.be.rejectedWith(/common\.NoPermission/);9021050 903 await expect(executeTransaction(1051 await expect(executeTransaction(904 api, 1052 api, 905 permission.signers[0], 1053 permission.signers[0], 906 api.tx.unique.deleteTokenProperties(collection, token, [i.toString()]), 1054 api.tx.unique.deleteTokenProperties(collection, token, [i.toString()]), 907 ), `on failing to delete property ${i} by ${permission.signers[0].address}`).to.be.rejectedWith(/common\.NoPermission/);1055 ), `on failing to delete property ${i} by ${permission.signers[0].address}`).to.be.rejectedWith(/common\.NoPermission/);908 }1056 }9091057 910 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();1058 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();911 expect(properties.consumedSpace).to.be.equal(originalSpace);1059 expect(properties.consumedSpace).to.be.equal(originalSpace);912 });1060 }); 1061 }1062 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (NFT)', async () => {1063 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'NFT'}, 1);913 });1064 });1065 it('Forbids changing/deleting properties of a token if the property is permanent (immutable) (ReFungible)', async () => {1066 await testForbidsChangingDeletingPropertiesIfPropertyImmutable({type: 'ReFungible'}, 100);1067 });9141068915 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission', async () => {1069 async function testForbidsAddingPropertiesIfPropertyNotDeclared(mode: CollectionMode, pieces: number) {1070 await prepare(mode, pieces);1071916 await usingApi(async api => {1072 await usingApi(async api => {917 await expect(executeTransaction(1073 await expect(executeTransaction(925 alice, 1081 alice, 926 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'now-existent', permission: {}}]), 1082 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'now-existent', permission: {}}]), 927 ), 'on setting a new non-permitted property').to.not.be.rejected;1083 ), 'on setting a new non-permitted property').to.not.be.rejected;9281084 929 await expect(executeTransaction(1085 await expect(executeTransaction(930 api, 1086 api, 931 alice, 1087 alice, 932 api.tx.unique.setTokenProperties(collection, token, [{key: 'now-existent', value: 'I exist!'}]), 1088 api.tx.unique.setTokenProperties(collection, token, [{key: 'now-existent', value: 'I exist!'}]), 933 ), 'on failing to add a property forbidden by the \'None\' permission').to.be.rejectedWith(/common\.NoPermission/);1089 ), 'on failing to add a property forbidden by the \'None\' permission').to.be.rejectedWith(/common\.NoPermission/);9341090 935 expect((await api.rpc.unique.tokenProperties(collection, token, ['non-existent', 'now-existent'])).toJSON()).to.be.empty;1091 expect((await api.rpc.unique.tokenProperties(collection, token, ['non-existent', 'now-existent'])).toJSON()).to.be.empty;936 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();1092 const properties = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();937 expect(properties.consumedSpace).to.be.equal(originalSpace);1093 expect(properties.consumedSpace).to.be.equal(originalSpace);938 });1094 });1095 }1096 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);939 });1098 });1099 it('Forbids adding properties to a token if the property is not declared / forbidden with the \'None\' permission (ReFungible)', async () => {1100 await testForbidsAddingPropertiesIfPropertyNotDeclared({type: 'ReFungible'}, 100);1101 });9401102941 it('Forbids adding too many properties to a token', async () => {1103 async function testForbidsAddingTooManyProperties(mode: CollectionMode, pieces: number) {1104 await prepare(mode, pieces);1105942 await usingApi(async api => {1106 await usingApi(async api => {943 await expect(executeTransaction(1107 await expect(executeTransaction(948 {key: 'young_years', permission: {collectionAdmin: true, tokenOwner: true}},1112 {key: 'young_years', permission: {collectionAdmin: true, tokenOwner: true}},949 ]), 1113 ]), 950 ), 'on setting a new non-permitted property').to.not.be.rejected;1114 ), 'on setting a new non-permitted property').to.not.be.rejected;9511115 952 // Mute the general tx parsing error1116 // Mute the general tx parsing error953 {1117 {954 console.error = () => {};1118 console.error = () => {};958 api.tx.unique.setCollectionProperties(collection, [{key: 'a_holy_book', value: 'word '.repeat(6554)}]), 1122 api.tx.unique.setCollectionProperties(collection, [{key: 'a_holy_book', value: 'word '.repeat(6554)}]), 959 )).to.be.rejected;1123 )).to.be.rejected;960 }1124 }9611125 962 await expect(executeTransaction(1126 await expect(executeTransaction(963 api, 1127 api, 964 alice, 1128 alice, 967 {key: 'young_years', value: 'neverending'.repeat(1490)},1131 {key: 'young_years', value: 'neverending'.repeat(1490)},968 ]), 1132 ]), 969 )).to.be.rejectedWith(/common\.NoSpaceForProperty/);1133 )).to.be.rejectedWith(/common\.NoSpaceForProperty/);9701134 971 expect((await api.rpc.unique.tokenProperties(collection, token, ['a_holy_book', 'young_years'])).toJSON()).to.be.empty;1135 expect((await api.rpc.unique.tokenProperties(collection, token, ['a_holy_book', 'young_years'])).toJSON()).to.be.empty;972 const propertiesMap = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();1136 const propertiesMap = (await api.query.nonfungible.tokenProperties(collection, token)).toJSON();973 expect(propertiesMap.consumedSpace).to.be.equal(originalSpace);1137 expect(propertiesMap.consumedSpace).to.be.equal(originalSpace);1138 });1139 }1140 it('Forbids adding too many properties to a token (NFT)', async () => {1141 await testForbidsAddingTooManyProperties({type: 'NFT'}, 1);1142 });1143 it('Forbids adding too many properties to a token (ReFungible)', async () => {1144 await testForbidsAddingTooManyProperties({type: 'ReFungible'}, 100);1145 });1146});11471148describe('ReFungible token properties permissions tests', () => {1149 let collection: number;1150 let token: number;11511152 before(async () => {1153 await usingApi(async (api, privateKeyWrapper) => {1154 alice = privateKeyWrapper('//Alice');1155 bob = privateKeyWrapper('//Bob');1156 charlie = privateKeyWrapper('//Charlie');1157 });1158 });11591160 beforeEach(async () => {1161 await usingApi(async api => {1162 collection = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});1163 token = await createItemExpectSuccess(alice, collection, 'ReFungible');1164 await addCollectionAdminExpectSuccess(alice, collection, bob.address);11651166 await expect(executeTransaction(1167 api, 1168 alice, 1169 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'key', permission: {mutable:true, tokenOwner: true}}]), 1170 )).to.not.be.rejected;1171 });1172 });11731174 it('Forbids add token property with tokenOwher==true but signer have\'t all pieces', async () => {1175 await usingApi(async api => {1176 await transferExpectSuccess(collection, token, alice, charlie, 33, 'ReFungible');1177 1178 await expect(executeTransaction(1179 api, 1180 alice, 1181 api.tx.unique.setTokenProperties(collection, token, [1182 {key: 'key', value: 'word'}, 1183 ]), 1184 )).to.be.rejectedWith(/common\.NoPermission/);1185 });1186 });11871188 it('Forbids mutate token property with tokenOwher==true but signer have\'t all pieces', async () => {1189 await usingApi(async api => {1190 await expect(executeTransaction(1191 api, 1192 alice, 1193 api.tx.unique.setTokenPropertyPermissions(collection, [{key: 'key', permission: {mutable:true, tokenOwner: true}}]), 1194 )).to.not.be.rejected;1195 1196 await expect(executeTransaction(1197 api, 1198 alice, 1199 api.tx.unique.setTokenProperties(collection, token, [1200 {key: 'key', value: 'word'}, 1201 ]), 1202 )).to.be.not.rejected;12031204 await transferExpectSuccess(collection, token, alice, charlie, 33, 'ReFungible');1205 1206 await expect(executeTransaction(1207 api, 1208 alice, 1209 api.tx.unique.setTokenProperties(collection, token, [1210 {key: 'key', value: 'bad word'}, 1211 ]), 1212 )).to.be.rejectedWith(/common\.NoPermission/);1213 });1214 });12151216 it('Forbids delete token property with tokenOwher==true but signer have\'t all pieces', async () => {1217 await usingApi(async api => {1218 await expect(executeTransaction(1219 api, 1220 alice, 1221 api.tx.unique.setTokenProperties(collection, token, [1222 {key: 'key', value: 'word'}, 1223 ]), 1224 )).to.be.not.rejected;12251226 await transferExpectSuccess(collection, token, alice, charlie, 33, 'ReFungible');1227 1228 await expect(executeTransaction(1229 api, 1230 alice, 1231 api.tx.unique.deleteTokenProperties(collection, token, [1232 'key',1233 ]), 1234 )).to.be.rejectedWith(/common\.NoPermission/);974 });1235 });975 });1236 });976});1237});tests/src/refungible.test.tsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.161617import {default as usingApi} from './substrate/substrate-api';17import {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';19import {19import {20 createCollectionExpectSuccess,20 createCollectionExpectSuccess,30 transfer,30 transfer,31 burnItem,31 burnItem,32 repartitionRFT,32 repartitionRFT,33 createCollectionWithPropsExpectSuccess,34 getDetailedCollectionInfo,35 normalizeAccountId,36 CrossAccountId,37 getCreateItemsResult,38 getDestroyItemsResult,33} from './util/helpers';39} from './util/helpers';344035import chai from 'chai';41import chai from 'chai';51 it('Create refungible collection and token', async () => {57 it('Create refungible collection and token', async () => {52 await usingApi(async api => {58 await usingApi(async api => {53 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});59 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});54 expect(createCollectionResult.success).to.be.true; 60 expect(createCollectionResult.success).to.be.true;55 const collectionId = createCollectionResult.collectionId;61 const collectionId = createCollectionResult.collectionId;5662 57 const itemCountBefore = await getLastTokenId(api, collectionId);63 const itemCountBefore = await getLastTokenId(api, collectionId);58 const result = await createRefungibleToken(api, alice, collectionId, 100n);64 const result = await createRefungibleToken(api, alice, collectionId, 100n);5965 60 const itemCountAfter = await getLastTokenId(api, collectionId);66 const itemCountAfter = await getLastTokenId(api, collectionId);6167 62 // What to expect68 // What to expect63 // tslint:disable-next-line:no-unused-expression69 // tslint:disable-next-line:no-unused-expression64 expect(result.success).to.be.true;70 expect(result.success).to.be.true;67 expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());73 expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString());68 });74 });69 });75 });7076 77 it('RPC method tokenOnewrs for refungible collection and token', async () => {78 await usingApi(async (api, privateKeyWrapper) => {79 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};80 const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));81 82 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}});83 const collectionId = createCollectionResult.collectionId;84 85 const result = await createRefungibleToken(api, alice, collectionId, 10_000n);86 const aliceTokenId = result.itemId;87 88 89 await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);90 await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);91 92 for (let i = 0; i < 7; i++) {93 await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 50*(i+1));94 } 95 96 const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId);97 const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s));98 99 const aliceID = normalizeAccountId(alice);100 const bobId = normalizeAccountId(bob);101 102 // What to expect103 // tslint:disable-next-line:no-unused-expression104 expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);105 expect(owners.length).to.be.equal(10);106 107 const eleven = privateKeyWrapper('11');108 expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true;109 expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10);110 });111 });112 71 it('Transfer token pieces', async () => {113 it('Transfer token pieces', async () => {72 await usingApi(async api => {114 await usingApi(async api => {73 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;115 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;184226185 expect(await repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;227 expect(await repartitionRFT(api, collectionId, bob, tokenId, 150n)).to.be.true;186 await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;228 await expect(transfer(api, collectionId, tokenId, bob, alice, 160n)).to.eventually.be.rejected;229 });230 });231232 it('Repartition with increased amount', async () => {233 await usingApi(async api => {234 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;235 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;236237 const tx = api.tx.unique.repartition(collectionId, tokenId, 200n);238 const events = await submitTransactionAsync(alice, tx);239 const substrateEvents = getCreateItemsResult(events);240 expect(substrateEvents).to.include.deep.members([241 {242 success: true,243 collectionId,244 itemId: tokenId,245 recipient: {Substrate: alice.address},246 amount: 100,247 },248 ]);249 });250 });251252 it('Repartition with decreased amount', async () => {253 await usingApi(async api => {254 const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId;255 const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId;256257 const tx = api.tx.unique.repartition(collectionId, tokenId, 50n);258 const events = await submitTransactionAsync(alice, tx);259 const substrateEvents = getDestroyItemsResult(events);260 expect(substrateEvents).to.include.deep.members([261 {262 success: true,263 collectionId,264 itemId: tokenId,265 owner: {Substrate: alice.address},266 amount: 50,267 },268 ]);269 });270 });271});272273describe('Test Refungible properties:', () => {274 before(async () => {275 await usingApi(async (api, privateKeyWrapper) => {276 alice = privateKeyWrapper('//Alice');277 bob = privateKeyWrapper('//Bob');278 });279 });280 281 it('Сreate new collection with properties', async () => {282 await usingApi(async api => {283 const properties = [{key: 'key1', value: 'val1'}];284 const propertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}];285 const collectionId = await createCollectionWithPropsExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'ReFungible'},286 properties: properties,287 propPerm: propertyPermissions, 288 });289 const collection = (await getDetailedCollectionInfo(api, collectionId))!;290 expect(collection.properties.toHuman()).to.be.deep.equal(properties);291 expect(collection.tokenPropertyPermissions.toHuman()).to.be.deep.equal(propertyPermissions);187 });292 });188 });293 });189});294});tests/src/rpc.test.tsdiffbeforeafterboth1import {IKeyringPair} from '@polkadot/types/types';1import {expect} from 'chai';2import {expect} from 'chai';2import usingApi from './substrate/substrate-api';3import usingApi from './substrate/substrate-api';3import {createCollectionExpectSuccess, getTokenOwner} from './util/helpers';4import {createCollection, createCollectionExpectSuccess, createFungibleItemExpectSuccess, CrossAccountId, getTokenOwner, normalizeAccountId, transfer, U128_MAX} from './util/helpers';56let alice: IKeyringPair;7let bob: IKeyringPair;8495describe('getTokenOwner', () => {10describe('integration test: RPC methods', () => {11 before(async () => {12 await usingApi(async (api, privateKeyWrapper) => {13 alice = privateKeyWrapper('//Alice');14 bob = privateKeyWrapper('//Bob');15 });16 });1718 6 it('returns None for fungible collection', async () => {19 it('returns None for fungible collection', async () => {10 });23 });11 });24 });25 26 it('RPC method tokenOwners for fungible collection and token', async () => {27 await usingApi(async (api, privateKeyWrapper) => {28 const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'};29 const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString())));30 31 const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}});32 const collectionId = createCollectionResult.collectionId;33 const aliceTokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: U128_MAX}, alice.address);34 35 await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n);36 await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n);37 38 for (let i = 0; i < 7; i++) {39 await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 1);40 } 41 42 const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId);43 const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s));44 const aliceID = normalizeAccountId(alice);45 const bobId = normalizeAccountId(bob);4647 // What to expect48 // tslint:disable-next-line:no-unused-expression49 expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]);50 expect(owners.length == 10).to.be.true;51 52 const eleven = privateKeyWrapper('11');53 expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true;54 expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10);55 });56 });12});57});tests/src/util/helpers.tsdiffbeforeafterboth103 collectionId: number;103 collectionId: number;104 itemId: number;104 itemId: number;105 recipient?: CrossAccountId;105 recipient?: CrossAccountId;106 amount?: number;106}107}108109interface DestroyItemResult {110 success: boolean;111 collectionId: number;112 itemId: number;113 owner: CrossAccountId;114 amount: number;115}107116108interface TransferResult {117interface TransferResult {109 collectionId: number;118 collectionId: number;220 const collectionId = parseInt(data[0].toString(), 10);229 const collectionId = parseInt(data[0].toString(), 10);221 const itemId = parseInt(data[1].toString(), 10);230 const itemId = parseInt(data[1].toString(), 10);222 const recipient = normalizeAccountId(data[2].toJSON() as any);231 const recipient = normalizeAccountId(data[2].toJSON() as any);232 const amount = parseInt(data[3].toString(), 10);223233224 const itemRes: CreateItemResult = {234 const itemRes: CreateItemResult = {225 success: true,235 success: true,226 collectionId,236 collectionId,227 itemId,237 itemId,228 recipient,238 recipient,239 amount,229 };240 };230241231 results.push(itemRes);242 results.push(itemRes);255 return result;266 return result;256}267}268269export function getDestroyItemsResult(events: EventRecord[]): DestroyItemResult[] {270 const results: DestroyItemResult[] = [];271 272 const genericResult = getGenericResult<DestroyItemResult[]>(events, 'common', 'ItemDestroyed', (data) => {273 const collectionId = parseInt(data[0].toString(), 10);274 const itemId = parseInt(data[1].toString(), 10);275 const owner = normalizeAccountId(data[2].toJSON() as any);276 const amount = parseInt(data[3].toString(), 10);277278 const itemRes: DestroyItemResult = {279 success: true,280 collectionId,281 itemId,282 owner,283 amount,284 };285286 results.push(itemRes);287 return results;288 });289290 if (!genericResult.success) return [];291 return results;292}257293258export function getTransferResult(api: ApiPromise, events: EventRecord[]): TransferResult {294export function getTransferResult(api: ApiPromise, events: EventRecord[]): TransferResult {259 for (const {event} of events) {295 for (const {event} of events) {284 type: 'ReFungible';320 type: 'ReFungible';285}321}286322287type CollectionMode = Nft | Fungible | ReFungible;323export type CollectionMode = Nft | Fungible | ReFungible;288324289export type Property = {325export type Property = {290 key: any,326 key: any,1414 tx = api.tx.unique.createItem(collectionId, to, createData as any);1450 tx = api.tx.unique.createItem(collectionId, to, createData as any);1415 }1451 }141614521417 const events = await submitTransactionAsync(sender, tx);1453 const events = await executeTransaction(api, sender, tx);1418 const result = getCreateItemResult(events);1454 const result = getCreateItemResult(events);141914551420 const itemCountAfter = await getLastTokenId(api, collectionId);1456 const itemCountAfter = await getLastTokenId(api, collectionId);