git.delta.rocks / unique-network / refs/commits / e684c8aafc35

difftreelog

Merge branch 'develop' into doc/architectural-changes

Farhad Hakimov2022-07-22parents: #5b3cd06 #26e74f7.patch.diff
in: master

80 files changed

modifiedCargo.lockdiffbeforeafterboth
57315731
5732[[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",
59535953
5954[[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",
61986198
6199[[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",
63206320
6321[[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",
1237412377
12375[[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",
1273312736
12734[[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",
1275112754
12752[[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",
modifiedMakefilediffbeforeafterboth
12NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs12NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs
13NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json13NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json
14
15REFUNGIBLE_EVM_STUBS=./pallets/refungible/src/stubs
16RENFUNGIBLE_EVM_ABI=./tests/src/eth/reFungibleAbi.json
17RENFUNGIBLE_TOKEN_EVM_ABI=./tests/src/eth/reFungibleTokenAbi.json
1418
15CONTRACT_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.json
21TESTS_API=./tests/src/eth/api/25TESTS_API=./tests/src/eth/api/
2226
23.PHONY: regenerate_solidity27.PHONY: regenerate_solidity
24regenerate_solidity: UniqueFungible.sol UniqueNFT.sol ContractHelpers.sol CollectionHelpers.sol28regenerate_solidity: UniqueFungible.sol UniqueNFT.sol UniqueRefungibleToken.sol ContractHelpers.sol CollectionHelpers.sol
2529
26UniqueFungible.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.sh
30UniqueNFT.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.sh
32 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.sh
37
38UniqueRefungibleToken.sol:
39 PACKAGE=pallet-refungible NAME=erc_token::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
40 PACKAGE=pallet-refungible NAME=erc_token::gen_impl OUTPUT=$(REFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
3341
34ContractHelpers.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.sh
47 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.sh
48 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.sh
57
58UniqueRefungibleToken: UniqueRefungibleToken.sol
59 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungibleToken.raw ./.maintain/scripts/compile_stub.sh
60 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(RENFUNGIBLE_TOKEN_EVM_ABI) ./.maintain/scripts/generate_abi.sh
4961
50ContractHelpers: ContractHelpers.sol62ContractHelpers: ContractHelpers.sol
51 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.sh
55 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.sh
56 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.sh
5769
58evm_stubs: UniqueFungible UniqueNFT ContractHelpers CollectionHelpers70evm_stubs: UniqueFungible UniqueNFT UniqueRefungibleToken ContractHelpers CollectionHelpers
5971
60.PHONY: _bench72.PHONY: _bench
61_bench:73_bench:
addedclient/rpc/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedclient/rpc/Cargo.tomldiffbeforeafterboth
1[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"
66
modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
77 at: Option<BlockHash>,77 at: Option<BlockHash>,
78 ) -> Result<Option<CrossAccountId>>;78 ) -> Result<Option<CrossAccountId>>;
79
80 /// 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>>;
7988
80 /// 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}
514524
515#[allow(deprecated)]525#[allow(deprecated)]
addedpallets/common/CHANGELOG.MDdiffbeforeafterboth

no changes

addedpallets/common/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedpallets/common/Cargo.tomldiffbeforeafterboth
1[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"
66
modifiedpallets/common/src/dispatch.rsdiffbeforeafterboth
1//! Module with interfaces for dispatching collections.
2
1use 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 pallets
21}23}
2224
23/// 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 result
65}70}
6671
72/// 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;
82
83 /// 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;
7388
89 /// 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;
93
94 /// Get the collection handle for the corresponding implementation.
75 fn into_inner(self) -> CollectionHandle<T>;95 fn into_inner(self) -> CollectionHandle<T>;
7696
97 /// Get the implementation of [`CommonCollectionOperations`].
77 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;98 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;
78}99}
79100
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! This module contains the implementation of pallet methods for evm.
1618
17use evm_coder::{19use evm_coder::{
18 solidity_interface, solidity, ToLog,20 solidity_interface, solidity, ToLog,
2931
30use crate::{Pallet, CollectionHandle, Config, CollectionProperties};32use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
3133
34/// 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,
42
43 /// Collection ID.
37 #[indexed]44 #[indexed]
38 collection_id: address,45 collection_id: address,
39 },46 },
40}47}
4148
42/// Does not always represent a full collection, for RFT it is either49/// Does not always represent a full collection, for RFT it is either
43/// 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];
4653
54 /// 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}
4957
58/// @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>
52where61where
53 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 }
7083
84 /// 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 }
7995
96 /// 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 }
91112
113 /// 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)?;
94120
98 save(self)124 save(self)
99 }125 }
100126
127 /// 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 !self
109 save(self)138 save(self)
110 }139 }
111140
141 /// 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 }
147186
187 /// 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 }
174220
221 /// 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 }
178225
226 /// 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 }
188241
242 /// 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 }
203257
258 /// 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 }
210266
267 /// 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 }
217276
277 /// 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 }
237299
300 /// 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 }
282348
349 /// Set the collection access method.
350 /// @param mode Access mode
351 /// 0 for Normal
352 /// 1 for AllowList
283 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 }
302372
373 /// 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 }
309382
383 /// 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 }
316392
393 /// 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}
353432
433/// 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()
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! The module contains a number of functions for converting and checking ethereum identifiers.
1618
17use 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];
2527
28/// 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}
37
38/// 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(&ETH_COLLECTION_PREFIX);41 out[0..16].copy_from_slice(&ETH_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}
4045
46/// 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_PREFIX
43}49}
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17//! # Common pallet
18//!
19//! The Common pallet provides functionality for handling collections.
20//!
21//! ## Overview
22//!
23//! The Common pallet provides an interface for common collection operations for different collection types
24//! (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//! ### Terminology
38//! **Collection sponsor** - For the collection, you can set a sponsor, at whose expense it will
39//! 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 various
44//! metadata can be placed.
45//!
46//! **Permissions on token properties** - For each property in the token can be set permission
47//! to change, see [`PropertyPermission`].
48//!
49//! **Collection administrator** - For a collection, you can set administrators who have the right
50//! to most actions on the collection.
51
52#![warn(missing_docs)]
17#![cfg_attr(not(feature = "std"), no_std)]53#![cfg_attr(not(feature = "std"), no_std)]
18
19extern crate alloc;54extern crate alloc;
2055
21use core::ops::{Deref, DerefMut};56use core::ops::{Deref, DerefMut};
90pub mod eth;125pub mod eth;
91pub mod weights;126pub mod weights;
92127
128/// Weight info.
93pub type SelfWeightOf<T> = <T as Config>::WeightInfo;129pub type SelfWeightOf<T> = <T as Config>::WeightInfo;
94130
131/// 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 id
97 pub id: CollectionId,140 pub id: CollectionId,
98 collection: Collection<T::AccountId>,141 collection: Collection<T::AccountId>,
142 /// Substrate recorder for counting consumed gas
99 pub recorder: SubstrateRecorder<T>,143 pub recorder: SubstrateRecorder<T>,
100}144}
145
101impl<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.recorder
106 self.recorder151 self.recorder
107 }152 }
108}153}
154
109impl<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 }
117164
165 /// 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 }
125173
174 /// 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 }
129179
180 /// 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 }
133184
185 /// 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.recorder
136 .consume_gas(T::GasWeightMapping::weight_to_gas(188 .consume_gas(T::GasWeightMapping::weight_to_gas(
140 ))192 ))
141 }193 }
142194
195 /// 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.recorder
145 .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 }
204
205 /// 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 }
155210
211 /// 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 }
160220
221 /// Confirm sponsorship
222 ///
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 }
169233
170 /// 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 }
179243
180 /// 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}
204268
205impl<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 }
275
276 /// 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 }
280
281 /// 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 }
286
287 /// 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 }
291
292 /// 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 }
296
297 /// 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 + TypeInfo
250 + account::Config325 + account::Config
251 {326 {
327 /// Weight information for functions of this pallet.
252 type WeightInfo: WeightInfo;328 type WeightInfo: WeightInfo;
329
330 /// 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>>;
254332
333 /// Handler of accounts and payment.
255 type Currency: Currency<Self::AccountId>;334 type Currency: Currency<Self::AccountId>;
256335
336 /// 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 >;
341
342 /// Dispatcher of operations on collections.
261 type CollectionDispatch: CollectionDispatch<Self>;343 type CollectionDispatch: CollectionDispatch<Self>;
262344
345 /// Account which holds the chain's treasury.
263 type TreasuryAccountId: Get<Self::AccountId>;346 type TreasuryAccountId: Get<Self::AccountId>;
347
348 /// Address under which the CollectionHelper contract would be available.
264 type ContractAddress: Get<H160>;349 type ContractAddress: Get<H160>;
265350
351 /// Mapper for token addresses to Ethereum addresses.
266 type EvmTokenAddressMapping: TokenAddressMapping<H160>;352 type EvmTokenAddressMapping: TokenAddressMapping<H160>;
353
354 /// Mapper for token addresses to [`CrossAccountId`].
267 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;355 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;
268 }356 }
269357
276364
277 #[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_LIMIT
281 }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 created
288 ///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 ),
295385
296 /// New collection was destroyed386 /// New collection was destroyed
297 ///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 ),
302391
303 /// 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 item
310 /// * amount - The amount of tokens that were created (always 1 for NFT).399 T::CrossAccountId,
400 /// Always 1 for NFT
311 ItemCreated(CollectionId, TokenId, T::CrossAccountId, u128),401 u128,
402 ),
312403
313 /// 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 ),
322415
323 /// Item was transferred.416 /// Item was transferred
324 ///
325 /// # Arguments
326 ///
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 ),
339429
340 /// Sponsoring allowance was approved.430 /// Amount pieces of token owned by `sender` was approved for `spender`.
341 ///
342 /// # Arguments
343 ///
344 /// * collection_id - todo:doc flesh out
345 /// * item_id
346 /// * sender
347 /// * spender
348 /// * amount
349 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 ),
356443
357 /// 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 ),
364451
365 /// 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 ),
372459
373 /// 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 ),
381469
382 /// 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 ),
390479
391 /// 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 }
399488
400 #[pallet::error]489 #[pallet::error]
482 CollectionIsInternal,571 CollectionIsInternal,
483 }572 }
484573
485 /// 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>;
488577
489 /// 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>;
493582
494 /// 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 >;
502591
503 /// 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 >;
513602
514 /// 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 >;
523612
524 /// 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 >;
532621
533 /// 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 >;
543632
544 /// 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 >;
554643
555 /// 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}
647736
648impl<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>>::AddressIsZero
654 );745 );
655 Ok(())746 Ok(())
656 }747 }
748
749 /// 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 }
755
756 /// 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 }
762
763 /// 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 }
767
768 /// 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 }
679778
779 /// 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 }
712812
813 /// 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}
786887
787impl<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 }
887993
994 /// 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 }
9151025
1026 /// 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 }
9331048
1049 /// 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 }
9461066
1067 /// 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 }
9591084
1085 /// 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 }
9721102
1103 /// 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 }
9921127
1128 /// 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 }
10051145
1006 // 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 }
10171162
1163 /// 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 }
10471197
1198 /// 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 }
10601215
1216 /// 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 }
10671223
1224 /// 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 }
10781235
1236 /// 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 }
11051263
1264 /// 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 }
11341293
1294 /// 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 }
11531313
1314 /// 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 }
11881349
1350 /// 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 }
12331395
1396 /// 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}
12471410
1411/// 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}
12541418
1255/// 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;
1423
1424 /// Weight of items creation.
1258 fn create_multiple_items(amount: &[CreateItemData]) -> Weight;1425 fn create_multiple_items(amount: &[CreateItemData]) -> Weight;
1426
1427 /// Weight of items creation.
1259 fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;1428 fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;
1429
1430 /// The weight of the burning item.
1260 fn burn_item() -> Weight;1431 fn burn_item() -> Weight;
1432
1433 /// 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;
1437
1438 /// 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;
1442
1443 /// 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;
1447
1448 /// 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;
1452
1453 /// 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;
1457
1458 /// Transfer price of the token or its parts.
1266 fn transfer() -> Weight;1459 fn transfer() -> Weight;
1460
1461 /// The price of setting the permission of the operation from another user.
1267 fn approve() -> Weight;1462 fn approve() -> Weight;
1463
1464 /// Transfer price from another user.
1268 fn transfer_from() -> Weight;1465 fn transfer_from() -> Weight;
1466
1467 /// The price of burning a token from another user.
1269 fn burn_from() -> Weight;1468 fn burn_from() -> Weight;
12701469
1271 /// 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 burn
1272 /// 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) instead
1275 fn burn_recursively_self_raw() -> Weight;1474 fn burn_recursively_self_raw() -> Weight;
1475
1276 /// 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) instead
1279 fn burn_recursively_breadth_raw(amount: u32) -> Weight;1479 fn burn_recursively_breadth_raw(amount: u32) -> Weight;
12801480
1481 /// 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}
12871491
1492/// 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}
12911497
1498/// Common collection operations.
1499///
1500/// It wraps methods in Fungible, Nonfungible and Refungible pallets
1501/// 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;
1516
1517 /// 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;
1530
1531 /// 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;
1543
1544 /// 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;
1555
1556 /// 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;
1569
1570 /// 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;
1579
1580 /// 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;
1589
1590 /// Set token properties.
1591 ///
1592 /// The appropriate [`PropertyPermission`] for the token property
1593 /// 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;
1606
1607 /// Remove token properties.
1608 ///
1609 /// The appropriate [`PropertyPermission`] for the token property
1610 /// 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;
1623
1624 /// 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;
1635
1636 /// 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;
1651
1652 /// 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;
1665
1666 /// 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;
1685
1686 /// 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;
13871703
1704 /// 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;
13951717
1718 /// 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));
13971723
1724 /// 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));
13991729
1730 /// 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>;
1734
1735 /// Get all the tokens in the collection.
1401 fn collection_tokens(&self) -> Vec<TokenId>;1736 fn collection_tokens(&self) -> Vec<TokenId>;
1737
1738 /// 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;
1742
1743 /// Get the id of the last minted token.
1403 fn last_token_id(&self) -> TokenId;1744 fn last_token_id(&self) -> TokenId;
14041745
1746 /// 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>;
1750
1751 /// 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>;
1755
1756 /// 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>;
1761
1407 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>;
1768
1408 /// Amount of unique collection tokens1769 /// Amount of unique collection tokens
1409 fn total_supply(&self) -> u32;1770 fn total_supply(&self) -> u32;
1771
1410 /// 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;
1776
1412 /// 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;
1779
1414 /// Amount of token pieces1780 /// Amount of token pieces
1415 fn total_pieces(&self, token: TokenId) -> Option<u128>;1781 fn total_pieces(&self, token: TokenId) -> Option<u128>;
1782
1783 /// 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;
1794
1795 /// 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}
14241798
1799/// Extension for RFT collection.
1425pub trait RefungibleExtensions<T>1800pub trait RefungibleExtensions<T>
1426where1801where
1427 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}
14361818
1437// 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),
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/fungible/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedpallets/fungible/Cargo.tomldiffbeforeafterboth
1[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"
66
modifiedpallets/fungible/src/common.rsdiffbeforeafterboth
105 }105 }
106}106}
107107
108/// Implementation of `CommonCollectionOperations` for `FungibleHandle`. It wraps FungibleHandle Pallete
109/// 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 None
361 }363 }
364
365 /// 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 }
362369
363 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 None
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! ERC-20 standart support implementation.
1618
17use core::char::{REPLACEMENT_CHARACTER, decode_utf16};19use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
18use core::convert::TryInto;20use core::convert::TryInto;
modifiedpallets/fungible/src/lib.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! # Fungible Pallet
18//!
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 tokens
31//!
32//! Fungible tokens or assets are divisible and non-unique. For instance,
33//! fiat currencies like the dollar are fungible: A $1 bill
34//! 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’s
37//! 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 equal
40//! 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 token
42//! that can be replaced by another identical coin or token, and they are
43//! both mutually interchangeable. A popular implementation of fungible tokens is
44//! the ERC-20 token standard.
45//!
46//! ### ERC-20
47//!
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 another
54//! * get the current token balance of an account
55//! * get the total supply of the token available on the network
56//! * approve whether an amount of token from an account can be spent by a third-party account
57//!
58//! ## Overview
59//!
60//! The module provides functionality for asset management of fungible asset, supports ERC-20 standart, includes:
61//!
62//! * Asset Issuance
63//! * Asset Transferal
64//! * Asset Destruction
65//! * Delegated Asset Transfers
66//!
67//! **NOTE:** The created fungible asset always has `token_id` = 0.
68//! So `tokenA` and `tokenB` will have different `collection_id`.
69//!
70//! ### Implementations
71//!
72//! The Fungible pallet provides implementations for the following traits.
73//!
74//! - [`WithRecorder`](pallet_evm_coder_substrate::WithRecorder): Trait for EVM support
75//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing with collections
76//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight
77//! - [`CommonEvmHandler`](pallet_common::erc::CommonEvmHandler): Function for handling EVM runtime calls
1678
17#![cfg_attr(not(feature = "std"), no_std)]79#![cfg_attr(not(feature = "std"), no_std)]
1880
33use 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};
3799
38pub use pallet::*;100pub use pallet::*;
39101
44pub mod erc;106pub mod erc;
45pub mod weights;107pub mod weights;
46108
47/// 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;
50111
58 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 >;
97158
98 /// 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}
110171
172/// 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>);
175
176/// 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 }
182
183 /// 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.0
118 }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.0
121 }190 }
136 }205 }
137}206}
138207
208/// Pallet implementation for fungible assets
139impl<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 }
217
218 /// 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 }
165238
239 ///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) != 0
168 }242 }
169243
244 /// Burns the specified amount of the token. If the token balance
245 /// 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 }
213290
291 /// Transfers the specified amount of tokens. Will check that
292 /// 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 token
214 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 }
283367
368 /// 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 }
384470
471 /// Set allowance for the spender to `transfer` or `burn` owner's tokens.
472 ///
473 /// - `collection`: Collection that contains the token
474 /// - `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 }
408500
501 /// 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 }
546
547 /// 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.
447551
448 pub fn transfer_from(552 pub fn transfer_from(
449 collection: &FungibleHandle<T>,553 collection: &FungibleHandle<T>,
464 Ok(())568 Ok(())
465 }569 }
466570
571 /// 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` should
574 /// 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 }
484593
485 /// 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 configured
597 /// to allow public minting.
598 ///
599 /// - `data`: Contains user who will become the owners of the tokens and amount
600 /// 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 }
614
615 /// Returns 10 tokens owners in no particular order
616 ///
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 holders
620 /// 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();
629
630 if res.is_empty() {
631 None
632 } else {
633 Some(res)
634 }
635 }
499}636}
500637
modifiedpallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
43 }43 }
44}44}
45
46// Selector: 7d9262e6
47contract 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) 2f073f66
54 function setCollectionProperty(string memory key, bytes memory value)
55 public
56 {
57 require(false, stub_error);
58 key;
59 value;
60 dummy = 0;
61 }
62
63 // Delete collection property.
64 //
65 // @param key Property key.
66 //
67 // Selector: deleteCollectionProperty(string) 7b7debce
68 function deleteCollectionProperty(string memory key) public {
69 require(false, stub_error);
70 key;
71 dummy = 0;
72 }
73
74 // 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) cf24fd6d
82 function collectionProperty(string memory key)
83 public
84 view
85 returns (bytes memory)
86 {
87 require(false, stub_error);
88 key;
89 dummy;
90 return hex"";
91 }
92
93 // 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) 7623402e
100 function setCollectionSponsor(address sponsor) public {
101 require(false, stub_error);
102 sponsor;
103 dummy = 0;
104 }
105
106 // Collection sponsorship confirmation.
107 //
108 // @dev After setting the sponsor for the collection, it must be confirmed with this function.
109 //
110 // Selector: confirmCollectionSponsorship() 3c50e97a
111 function confirmCollectionSponsorship() public {
112 require(false, stub_error);
113 dummy = 0;
114 }
115
116 // 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) 6a3841db
128 function setCollectionLimit(string memory limit, uint32 value) public {
129 require(false, stub_error);
130 limit;
131 value;
132 dummy = 0;
133 }
134
135 // 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) 993b7fba
144 function setCollectionLimit(string memory limit, bool value) public {
145 require(false, stub_error);
146 limit;
147 value;
148 dummy = 0;
149 }
150
151 // Get contract address.
152 //
153 // Selector: contractAddress() f6b4dfb4
154 function contractAddress() public view returns (address) {
155 require(false, stub_error);
156 dummy;
157 return 0x0000000000000000000000000000000000000000;
158 }
159
160 // Add collection admin by substrate address.
161 // @param new_admin Substrate administrator address.
162 //
163 // Selector: addCollectionAdminSubstrate(uint256) 5730062b
164 function addCollectionAdminSubstrate(uint256 newAdmin) public {
165 require(false, stub_error);
166 newAdmin;
167 dummy = 0;
168 }
169
170 // Remove collection admin by substrate address.
171 // @param admin Substrate administrator address.
172 //
173 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
174 function removeCollectionAdminSubstrate(uint256 admin) public {
175 require(false, stub_error);
176 admin;
177 dummy = 0;
178 }
179
180 // Add collection admin.
181 // @param new_admin Address of the added administrator.
182 //
183 // Selector: addCollectionAdmin(address) 92e462c7
184 function addCollectionAdmin(address newAdmin) public {
185 require(false, stub_error);
186 newAdmin;
187 dummy = 0;
188 }
189
190 // Remove collection admin.
191 //
192 // @param new_admin Address of the removed administrator.
193 //
194 // Selector: removeCollectionAdmin(address) fafd7b42
195 function removeCollectionAdmin(address admin) public {
196 require(false, stub_error);
197 admin;
198 dummy = 0;
199 }
200
201 // Toggle accessibility of collection nesting.
202 //
203 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
204 //
205 // Selector: setCollectionNesting(bool) 112d4586
206 function setCollectionNesting(bool enable) public {
207 require(false, stub_error);
208 enable;
209 dummy = 0;
210 }
211
212 // 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[]) 64872396
218 function setCollectionNesting(bool enable, address[] memory collections)
219 public
220 {
221 require(false, stub_error);
222 enable;
223 collections;
224 dummy = 0;
225 }
226
227 // Set the collection access method.
228 // @param mode Access mode
229 // 0 for Normal
230 // 1 for AllowList
231 //
232 // Selector: setCollectionAccess(uint8) 41835d4c
233 function setCollectionAccess(uint8 mode) public {
234 require(false, stub_error);
235 mode;
236 dummy = 0;
237 }
238
239 // Add the user to the allowed list.
240 //
241 // @param user Address of a trusted user.
242 //
243 // Selector: addToCollectionAllowList(address) 67844fe6
244 function addToCollectionAllowList(address user) public {
245 require(false, stub_error);
246 user;
247 dummy = 0;
248 }
249
250 // Remove the user from the allowed list.
251 //
252 // @param user Address of a removed user.
253 //
254 // Selector: removeFromCollectionAllowList(address) 85c51acb
255 function removeFromCollectionAllowList(address user) public {
256 require(false, stub_error);
257 user;
258 dummy = 0;
259 }
260
261 // Switch permission for minting.
262 //
263 // @param mode Enable if "true".
264 //
265 // Selector: setCollectionMintMode(bool) 00018e84
266 function setCollectionMintMode(bool mode) public {
267 require(false, stub_error);
268 mode;
269 dummy = 0;
270 }
271}
45272
46// Selector: 942e8b22273// Selector: 942e8b22
47contract ERC20 is Dummy, ERC165, ERC20Events {274contract ERC20 is Dummy, ERC165, ERC20Events {
127 }354 }
128}355}
129
130// Selector: c894dc35
131contract Collection is Dummy, ERC165 {
132 // Selector: setCollectionProperty(string,bytes) 2f073f66
133 function setCollectionProperty(string memory key, bytes memory value)
134 public
135 {
136 require(false, stub_error);
137 key;
138 value;
139 dummy = 0;
140 }
141
142 // Selector: deleteCollectionProperty(string) 7b7debce
143 function deleteCollectionProperty(string memory key) public {
144 require(false, stub_error);
145 key;
146 dummy = 0;
147 }
148
149 // Throws error if key not found
150 //
151 // Selector: collectionProperty(string) cf24fd6d
152 function collectionProperty(string memory key)
153 public
154 view
155 returns (bytes memory)
156 {
157 require(false, stub_error);
158 key;
159 dummy;
160 return hex"";
161 }
162
163 // Selector: ethSetSponsor(address) 8f9af356
164 function ethSetSponsor(address sponsor) public {
165 require(false, stub_error);
166 sponsor;
167 dummy = 0;
168 }
169
170 // Selector: ethConfirmSponsorship() a8580d1a
171 function ethConfirmSponsorship() public {
172 require(false, stub_error);
173 dummy = 0;
174 }
175
176 // Selector: setLimit(string,uint32) 68db30ca
177 function setLimit(string memory limit, uint32 value) public {
178 require(false, stub_error);
179 limit;
180 value;
181 dummy = 0;
182 }
183
184 // Selector: setLimit(string,bool) ea67e4c2
185 function setLimit(string memory limit, bool value) public {
186 require(false, stub_error);
187 limit;
188 value;
189 dummy = 0;
190 }
191
192 // Selector: contractAddress() f6b4dfb4
193 function contractAddress() public view returns (address) {
194 require(false, stub_error);
195 dummy;
196 return 0x0000000000000000000000000000000000000000;
197 }
198}
199356
200contract UniqueFungible is357contract UniqueFungible is
201 Dummy,358 Dummy,
modifiedpallets/inflation/src/lib.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! # Inflation
18//!
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//! ## Interface
24//!
25//! ### Dispatchable Functions
26//!
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 Treasury
29//! account if it does not exist and perform the first inflation deposit.
1630
17// #![recursion_limit = "1024"]31// #![recursion_limit = "1024"]
18#![cfg_attr(not(feature = "std"), no_std)]32#![cfg_attr(not(feature = "std"), no_std)]
addedpallets/nonfungible/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
1[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"
66
modifiedpallets/nonfungible/src/benchmarking.rsdiffbeforeafterboth
183 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)?}
187187
188 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}
212212
modifiedpallets/nonfungible/src/common.rsdiffbeforeafterboth
26 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};
3030
31use 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}
135135
136/// Implementation of `CommonCollectionOperations` for `NonfungibleHandle`. It wraps Nonfungible Pallete
137/// 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 }
424
425 /// 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 }
422429
423 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))
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! # Nonfungible Pallet EVM API
18//!
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.
1621
17extern crate alloc;22extern crate alloc;
18use core::{23use core::{
40 SelfWeightOf, weights::WeightInfo, TokenProperties,45 SelfWeightOf, weights::WeightInfo, TokenProperties,
41};46};
4247
48/// @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 }
7082
83 /// @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 }
98115
116 /// @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 }
113134
135 /// @notice Get token property value.
114 /// Throws error if key not found136 /// @dev Throws error if key not found
137 /// @param tokenId ID of the token.
138 /// @param key Property key.
139 /// @return Property value bytes
115 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)
127152
128#[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 destroyed
157 /// (`to` == 0). Exception: during contract creation, any number of NFTs
158 /// may be created and assigned without emitting Transfer. At the time of
159 /// 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 or
169 /// reaffirmed. The zero address indicates there is no approved address.
170 /// When a Transfer event emits, this also indicates that the approved
171 /// 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}
161197
198/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
199/// @dev See https://eips.ethereum.org/EIPS/eip-721
162#[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 contract
164 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 }
169208
209 /// @notice An abbreviated name for NFTs in this contract
170 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 }
173213
214 /// @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 RFC
216 /// 3986. The URI may point to a JSON file that conforms to the "ERC721
217 /// Metadata JSON Schema".
174 /// Returns token's const_metadata218 /// @return token's const_metadata
175 #[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}
194238
239/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
240/// @dev See https://eips.ethereum.org/EIPS/eip-721
195#[solidity_interface(name = "ERC721Enumerable")]241#[solidity_interface(name = "ERC721Enumerable")]
196impl<T: Config> NonfungibleHandle<T> {242impl<T: Config> NonfungibleHandle<T> {
243 /// @notice Enumerate valid NFTs
244 /// @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 }
200250
201 /// Not implemented251 /// @dev Not implemented
202 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 implemetable
204 Err("not implemented".into())254 Err("not implemented".into())
205 }255 }
206256
257 /// @notice Count NFTs tracked by this contract
258 /// @return A count of valid NFTs tracked by this contract, where each one of
259 /// them has an assigned and queryable owner not equal to the zero address
207 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}
212265
266/// @title ERC-721 Non-Fungible Token Standard
267/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
213#[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 owner
271 /// @dev NFTs assigned to the zero address are considered invalid, and this
272 /// function throws for queries about the zero address.
273 /// @param owner An address for whom to query the balance
274 /// @return The number of NFTs owned by `owner`, possibly zero
215 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 NFT
282 /// @dev NFTs assigned to zero address are considered invalid, and queries
283 /// about them do throw.
284 /// @param tokenId The identifier for an NFT
285 /// @return The address of the owner of the NFT
221 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 .owner
227 .as_eth())292 .as_eth())
228 }293 }
229 /// Not implemented294 /// @dev Not implemented
230 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 implemetable
239 Err("not implemented".into())304 Err("not implemented".into())
240 }305 }
241 /// Not implemented306 /// @dev Not implemented
242 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 }
252317
318 /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
319 /// TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
320 /// THEY MAY BE PERMANENTLY LOST
321 /// @dev Throws unless `msg.sender` is the current owner or an authorized
322 /// operator for this NFT. Throws if `from` is not the current owner. Throws
323 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
324 /// @param from The current owner of the NFT
325 /// @param to The new owner
326 /// @param tokenId The NFT to transfer
327 /// @param _value Not used for an NFT
253 #[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 }
274349
350 /// @notice Set or reaffirm the approved address for an NFT
351 /// @dev The zero address indicates there is no approved address.
352 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
353 /// operator of the current owner.
354 /// @param approved The new approved NFT controller
355 /// @param tokenId The NFT to approve
275 #[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 }
291372
292 /// Not implemented373 /// @dev Not implemented
293 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 }
302383
303 /// Not implemented384 /// @dev Not implemented
304 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 implemetable
306 Err("not implemented".into())387 Err("not implemented".into())
307 }388 }
308389
309 /// Not implemented390 /// @dev Not implemented
310 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 implemetable
312 Err("not implemented".into())393 Err("not implemented".into())
313 }394 }
314}395}
315396
397/// @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 authorized
402 /// operator of the current owner.
403 /// @param tokenId The NFT to approve
318 #[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}
327413
414/// @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 }
333420
421 /// @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 manually
424 /// @param to The new owner
425 /// @param tokenId ID of the minted NFT
336 #[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 }
366456
457 /// @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 manually
460 /// @param to The new owner
461 /// @param tokenId ID of the minted NFT
462 /// @param tokenUri Token URI that would be stored in the NFT properties
369 #[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 }
422516
423 /// Not implemented517 /// @dev Not implemented
424 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 false
450}544}
451545
546/// @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 NFT
550 /// @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 owner
553 /// @param tokenId The NFT to transfer
554 /// @param _value Not used for an NFT
454 #[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 }
472573
574 /// @notice Burns a specific ERC721 token.
575 /// @dev Throws unless `msg.sender` is the current owner or an authorized
576 /// operator for this NFT. Throws if `from` is not the current owner. Throws
577 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
578 /// @param from The current owner of the NFT
579 /// @param tokenId The NFT to transfer
580 /// @param _value Not used for an NFT
473 #[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 }
492600
601 /// @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 }
500609
610 /// @notice Function to mint multiple tokens.
611 /// @dev `tokenIds` should be an array of consecutive numbers and first number
612 /// should be obtained with `nextTokenId` method
613 /// @param to The new owner
614 /// @param tokenIds IDs of the minted NFTs
501 #[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 }
531645
646 /// @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 consecutive
648 /// numbers and first number should be obtained with `nextTokenId` method
649 /// @param to The new owner
650 /// @param tokens array of pairs of token ID and token URI for minted tokens
532 #[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(
modifiedpallets/nonfungible/src/lib.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! # Nonfungible Pallet
18//!
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//! ## Overview
27//!
28//! The Nonfungible pallet provides functions for:
29//!
30//! - NFT collection creation and removal
31//! - Minting and burning of NFT tokens
32//! - Retrieving account balances
33//! - Transfering NFT tokens
34//! - Setting and checking allowance for NFT tokens
35//! - Setting properties and permissions for NFT collections and tokens
36//! - Nesting and unnesting tokens
37//!
38//! ### Terminology
39//!
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 account
46//!
47//! - **Allowance:** NFT tokens owned by one account that another account is allowed to make operations on
48//!
49//! - **Burning:** The process of “deleting” a token from a collection and from
50//! an account balance of the owner.
51//!
52//! - **Nesting:** Setting up parent-child relationship between tokens. Nested tokens are inhereting
53//! owner from their parent. There could be multiple levels of nesting. Token couldn't be nested in
54//! 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 are
57//! attached to a collection. Set of permissions could be defined for each property.
58//!
59//! ### Implementations
60//!
61//! The Nonfungible pallet provides implementations for the following traits. If these traits provide
62//! 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 weight
65//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing
66//! with collections
67//!
68//! ## Interface
69//!
70//! ### Dispatchable Functions
71//!
72//! - `init_collection` - Create NFT collection. NFT collection can be configured to allow or deny access for
73//! 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//! ## Assumptions
88//!
89//! * To perform operations on tokens sender should be in collection's allow list if collection access mode is `AllowList`.
1690
17#![cfg_attr(not(feature = "std"), no_std)]91#![cfg_attr(not(feature = "std"), no_std)]
1892
56pub 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;
58132
59/// Token data, stored independently from other data used to describe it.133/// Token data, stored independently from other data used to describe it
60/// 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 >;
124198
125 /// 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 >;
134208
135 /// 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 >;
173255
174 /// 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 >;
184266
185 /// 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}
285367
286impl<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 }
373
374 /// 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 }
293380
381 /// 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 }
307397
398 /// 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 }
321412
413 /// 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 }
331425
426 /// 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 }
340435
436 /// 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 }
348446
447 /// Get ID of the last minted token
349 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}
353452
354// unchecked calls skips any permission checks453// unchecked calls skips any permission checks
355impl<T: Config> Pallet<T> {454impl<T: Config> Pallet<T> {
455 /// Create NFT collection
456 ///
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 }
467
468 /// Destroy NFT collection
469 ///
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 }
386495
496 /// Burn NFT token
497 ///
498 /// `burn` removes `token` from the `collection`, from it's owner and from the parent token
499 /// 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 burned
504 /// - `collection`: Collection that contains the token
387 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 }
455573
574 /// Same as [`burn`] but burns all the tokens that are nested in the token first
575 ///
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.burn
456 #[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 }
494618
619 /// Batch operation to add, edit or remove properties for the token
620 ///
621 /// All affected properties should have mutable permission and sender should have
622 /// 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 }
587719
720 /// Batch operation to add or edit properties for the token
721 ///
722 /// Same as [`modify_token_properties`] but doesn't allow to remove properties
723 ///
724 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties
588 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 }
605742
743 /// Add or edit single property for the token
744 ///
745 /// Calls [`set_token_properties`] internally
746 ///
747 /// [`set_token_properties`]: struct.Pallet.html#method.set_token_properties
606 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 }
624766
767 /// Batch operation to remove properties from the token
768 ///
769 /// Same as [`modify_token_properties`] but doesn't allow to add or edit properties
770 ///
771 /// [`modify_token_properties`]: struct.Pallet.html#method.modify_token_properties
625 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 }
643790
791 /// Remove single property from the token
792 ///
793 /// Calls [`delete_token_properties`] internally
794 ///
795 /// [`delete_token_properties`]: struct.Pallet.html#method.delete_token_properties
644 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 }
659811
812 /// Add or edit properties for the collection
660 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 }
667820
821 /// Remove properties from the collection
668 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 }
675829
830 /// 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 }
683840
841 /// 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 }
691851
852 /// 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 depth
692 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 }
782951
952 /// Batch operation to mint multiple NFT tokens.
953 ///
954 /// The sender should be the owner/admin of the collection or collection should be configured
955 /// to allow public minting.
956 /// Throws if amount of tokens reached it's limit for the collection or if caller reached
957 /// token ownership limit.
958 ///
959 /// - `data`: Contains list of token properties and users who will become the owners of the
960 /// corresponging tokens.
961 /// - `nesting_budget`: Limit for token nesting depth
783 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 }
9661145
1146 /// 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 }
9981180
1181 /// 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 }
10401223
1224 /// 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.transfer
1041 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 }
10561245
1246 /// 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 should
1249 /// set allowance for the spender to burn token.
1250 ///
1251 /// [`burn`]: struct.Pallet.html#method.burn
1057 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 }
10701265
1266 /// 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 }
11391336
1337 /// 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_items
1141 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,
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
5353
54// Selector: 4136937754// Selector: 41369377
55contract 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) 222d97fa
57 function setTokenPropertyPermission(64 function setTokenPropertyPermission(
58 string memory key,65 string memory key,
68 dummy = 0;75 dummy = 0;
69 }76 }
7077
78 // @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) 1752d67b
72 function setProperty(85 function setProperty(
73 uint256 tokenId,86 uint256 tokenId,
81 dummy = 0;94 dummy = 0;
82 }95 }
8396
97 // @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) 066111d1
85 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 }
91109
110 // @notice Get token property value.
92 // Throws error if key not found111 // @dev Throws error if key not found
112 // @param tokenId ID of the token.
113 // @param key Property key.
114 // @return Property value bytes
93 //115 //
94 // Selector: property(uint256,string) 7228c327116 // Selector: property(uint256,string) 7228c327
95 function property(uint256 tokenId, string memory key)117 function property(uint256 tokenId, string memory key)
107129
108// Selector: 42966c68130// Selector: 42966c68
109contract 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 authorized
134 // operator of the current owner.
135 // @param tokenId The NFT to approve
136 //
110 // Selector: burn(uint256) 42966c68137 // Selector: burn(uint256) 42966c68
111 function burn(uint256 tokenId) public {138 function burn(uint256 tokenId) public {
112 require(false, stub_error);139 require(false, stub_error);
117144
118// Selector: 58800161145// Selector: 58800161
119contract ERC721 is Dummy, ERC165, ERC721Events {146contract ERC721 is Dummy, ERC165, ERC721Events {
147 // @notice Count all NFTs assigned to an owner
148 // @dev NFTs assigned to the zero address are considered invalid, and this
149 // function throws for queries about the zero address.
150 // @param owner An address for whom to query the balance
151 // @return The number of NFTs owned by `owner`, possibly zero
152 //
120 // Selector: balanceOf(address) 70a08231153 // Selector: balanceOf(address) 70a08231
121 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 }
127160
161 // @notice Find the owner of an NFT
162 // @dev NFTs assigned to zero address are considered invalid, and queries
163 // about them do throw.
164 // @param tokenId The identifier for an NFT
165 // @return The address of the owner of the NFT
166 //
128 // Selector: ownerOf(uint256) 6352211e167 // Selector: ownerOf(uint256) 6352211e
129 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 }
135174
136 // Not implemented175 // @dev Not implemented
137 //176 //
138 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672177 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672
139 function safeTransferFromWithData(178 function safeTransferFromWithData(
150 dummy = 0;189 dummy = 0;
151 }190 }
152191
153 // Not implemented192 // @dev Not implemented
154 //193 //
155 // Selector: safeTransferFrom(address,address,uint256) 42842e0e194 // Selector: safeTransferFrom(address,address,uint256) 42842e0e
156 function safeTransferFrom(195 function safeTransferFrom(
165 dummy = 0;204 dummy = 0;
166 }205 }
167206
207 // @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
208 // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
209 // THEY MAY BE PERMANENTLY LOST
210 // @dev Throws unless `msg.sender` is the current owner or an authorized
211 // operator for this NFT. Throws if `from` is not the current owner. Throws
212 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
213 // @param from The current owner of the NFT
214 // @param to The new owner
215 // @param tokenId The NFT to transfer
216 // @param _value Not used for an NFT
217 //
168 // Selector: transferFrom(address,address,uint256) 23b872dd218 // Selector: transferFrom(address,address,uint256) 23b872dd
169 function transferFrom(219 function transferFrom(
170 address from,220 address from,
178 dummy = 0;228 dummy = 0;
179 }229 }
180230
231 // @notice Set or reaffirm the approved address for an NFT
232 // @dev The zero address indicates there is no approved address.
233 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
234 // operator of the current owner.
235 // @param approved The new approved NFT controller
236 // @param tokenId The NFT to approve
237 //
181 // Selector: approve(address,uint256) 095ea7b3238 // Selector: approve(address,uint256) 095ea7b3
182 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 }
188245
189 // Not implemented246 // @dev Not implemented
190 //247 //
191 // Selector: setApprovalForAll(address,bool) a22cb465248 // Selector: setApprovalForAll(address,bool) a22cb465
192 function setApprovalForAll(address operator, bool approved) public {249 function setApprovalForAll(address operator, bool approved) public {
196 dummy = 0;253 dummy = 0;
197 }254 }
198255
199 // Not implemented256 // @dev Not implemented
200 //257 //
201 // Selector: getApproved(uint256) 081812fc258 // Selector: getApproved(uint256) 081812fc
202 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 }
208265
209 // Not implemented266 // @dev Not implemented
210 //267 //
211 // Selector: isApprovedForAll(address,address) e985e9c5268 // Selector: isApprovedForAll(address,address) e985e9c5
212 function isApprovedForAll(address owner, address operator)269 function isApprovedForAll(address owner, address operator)
224281
225// Selector: 5b5e139f282// Selector: 5b5e139f
226contract ERC721Metadata is Dummy, ERC165 {283contract ERC721Metadata is Dummy, ERC165 {
284 // @notice A descriptive name for a collection of NFTs in this contract
285 //
227 // Selector: name() 06fdde03286 // Selector: name() 06fdde03
228 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 }
233292
293 // @notice An abbreviated name for NFTs in this contract
294 //
234 // Selector: symbol() 95d89b41295 // Selector: symbol() 95d89b41
235 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 }
240301
302 // @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 RFC
304 // 3986. The URI may point to a JSON file that conforms to the "ERC721
305 // Metadata JSON Schema".
241 // Returns token's const_metadata306 // @return token's const_metadata
242 //307 //
243 // Selector: tokenURI(uint256) c87b56dd308 // Selector: tokenURI(uint256) c87b56dd
244 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 }
260325
326 // @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 manually
329 // @param to The new owner
330 // @param tokenId ID of the minted NFT
263 //331 //
264 // Selector: mint(address,uint256) 40c10f19332 // Selector: mint(address,uint256) 40c10f19
265 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 }
272340
341 // @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 manually
344 // @param to The new owner
345 // @param tokenId ID of the minted NFT
346 // @param tokenUri Token URI that would be stored in the NFT properties
275 //347 //
276 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f348 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f
277 function mintWithTokenURI(349 function mintWithTokenURI(
287 return false;359 return false;
288 }360 }
289361
290 // Not implemented362 // @dev Not implemented
291 //363 //
292 // Selector: finishMinting() 7d64bcb4364 // Selector: finishMinting() 7d64bcb4
293 function finishMinting() public returns (bool) {365 function finishMinting() public returns (bool) {
299371
300// Selector: 780e9d63372// Selector: 780e9d63
301contract ERC721Enumerable is Dummy, ERC165 {373contract ERC721Enumerable is Dummy, ERC165 {
374 // @notice Enumerate valid NFTs
375 // @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) 4f6ccce7
303 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 }
309386
310 // Not implemented387 // @dev Not implemented
311 //388 //
312 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59389 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
313 function tokenOfOwnerByIndex(address owner, uint256 index)390 function tokenOfOwnerByIndex(address owner, uint256 index)
322 return 0;399 return 0;
323 }400 }
324401
402 // @notice Count NFTs tracked by this contract
403 // @return A count of valid NFTs tracked by this contract, where each one of
404 // them has an assigned and queryable owner not equal to the zero address
405 //
325 // Selector: totalSupply() 18160ddd406 // Selector: totalSupply() 18160ddd
326 function totalSupply() public view returns (uint256) {407 function totalSupply() public view returns (uint256) {
327 require(false, stub_error);408 require(false, stub_error);
332413
333// Selector: 7d9262e6414// Selector: 7d9262e6
334contract 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) 2f073f66
336 function setCollectionProperty(string memory key, bytes memory value)422 function setCollectionProperty(string memory key, bytes memory value)
337 public423 public
342 dummy = 0;428 dummy = 0;
343 }429 }
344430
431 // Delete collection property.
432 //
433 // @param key Property key.
434 //
345 // Selector: deleteCollectionProperty(string) 7b7debce435 // Selector: deleteCollectionProperty(string) 7b7debce
346 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 }
351441
442 // 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) cf24fd6d
355 function collectionProperty(string memory key)450 function collectionProperty(string memory key)
363 return hex"";458 return hex"";
364 }459 }
365460
461 // 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) 7623402e
367 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 }
372473
474 // 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() 3c50e97a
374 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 }
378483
484 // 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) 6a3841db
380 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 }
386502
503 // 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) 993b7fba
388 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 }
394518
519 // Get contract address.
520 //
395 // Selector: contractAddress() f6b4dfb4521 // Selector: contractAddress() f6b4dfb4
396 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 }
401527
528 // Add collection admin by substrate address.
529 // @param new_admin Substrate administrator address.
530 //
402 // Selector: addCollectionAdminSubstrate(uint256) 5730062b531 // Selector: addCollectionAdminSubstrate(uint256) 5730062b
403 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 }
408537
538 // Remove collection admin by substrate address.
539 // @param admin Substrate administrator address.
540 //
409 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9541 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
410 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 }
415547
548 // Add collection admin.
549 // @param new_admin Address of the added administrator.
550 //
416 // Selector: addCollectionAdmin(address) 92e462c7551 // Selector: addCollectionAdmin(address) 92e462c7
417 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 }
422557
558 // Remove collection admin.
559 //
560 // @param new_admin Address of the removed administrator.
561 //
423 // Selector: removeCollectionAdmin(address) fafd7b42562 // Selector: removeCollectionAdmin(address) fafd7b42
424 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 }
429568
569 // 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) 112d4586
431 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 }
436579
580 // 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[]) 64872396
438 function setCollectionNesting(bool enable, address[] memory collections)586 function setCollectionNesting(bool enable, address[] memory collections)
439 public587 public
444 dummy = 0;592 dummy = 0;
445 }593 }
446594
595 // Set the collection access method.
596 // @param mode Access mode
597 // 0 for Normal
598 // 1 for AllowList
599 //
447 // Selector: setCollectionAccess(uint8) 41835d4c600 // Selector: setCollectionAccess(uint8) 41835d4c
448 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 }
453606
607 // 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) 67844fe6
455 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 }
460617
618 // 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) 85c51acb
462 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 }
467628
629 // Switch permission for minting.
630 //
631 // @param mode Enable if "true".
632 //
468 // Selector: setCollectionMintMode(bool) 00018e84633 // Selector: setCollectionMintMode(bool) 00018e84
469 function setCollectionMintMode(bool mode) public {634 function setCollectionMintMode(bool mode) public {
470 require(false, stub_error);635 require(false, stub_error);
475640
476// Selector: d74d154f641// Selector: d74d154f
477contract ERC721UniqueExtensions is Dummy, ERC165 {642contract ERC721UniqueExtensions is Dummy, ERC165 {
643 // @notice Transfer ownership of an NFT
644 // @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 owner
647 // @param tokenId The NFT to transfer
648 // @param _value Not used for an NFT
649 //
478 // Selector: transfer(address,uint256) a9059cbb650 // Selector: transfer(address,uint256) a9059cbb
479 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 }
485657
658 // @notice Burns a specific ERC721 token.
659 // @dev Throws unless `msg.sender` is the current owner or an authorized
660 // operator for this NFT. Throws if `from` is not the current owner. Throws
661 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
662 // @param from The current owner of the NFT
663 // @param tokenId The NFT to transfer
664 // @param _value Not used for an NFT
665 //
486 // Selector: burnFrom(address,uint256) 79cc6790666 // Selector: burnFrom(address,uint256) 79cc6790
487 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 }
493673
674 // @notice Returns next free NFT ID.
675 //
494 // Selector: nextTokenId() 75794a3c676 // Selector: nextTokenId() 75794a3c
495 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 }
500682
683 // @notice Function to mint multiple tokens.
684 // @dev `tokenIds` should be an array of consecutive numbers and first number
685 // should be obtained with `nextTokenId` method
686 // @param to The new owner
687 // @param tokenIds IDs of the minted NFTs
688 //
501 // Selector: mintBulk(address,uint256[]) 44a9945e689 // Selector: mintBulk(address,uint256[]) 44a9945e
502 function mintBulk(address to, uint256[] memory tokenIds)690 function mintBulk(address to, uint256[] memory tokenIds)
503 public691 public
510 return false;698 return false;
511 }699 }
512700
701 // @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 consecutive
703 // numbers and first number should be obtained with `nextTokenId` method
704 // @param to The new owner
705 // @param tokens array of pairs of token ID and token URI for minted tokens
706 //
513 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006707 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
514 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)708 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
515 public709 public
modifiedpallets/nonfungible/src/weights.rsdiffbeforeafterboth
3//! Autogenerated weights for pallet_nonfungible3//! Autogenerated weights for pallet_nonfungible
4//!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-dev
6//! 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: 1024
88
9// 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_000
70 .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_000
82 .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_000
123 .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_000
170 .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_000
180 .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_000
190 .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_000
214 .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_000
226 .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_000
267 .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_000
314 .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_000
324 .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_000
334 .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}
addedpallets/refungible/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
1[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"
66
11version = '3.1.2'11version = '3.1.2'
1212
13[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' }
20
21ethereum = { version = "0.12.0", default-features = false }
22scale-info = { version = "2.0.1", default-features = false, features = ["derive",] }
23
24frame-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" }
2831
29[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]
4754
addedpallets/refungible/Changelog.mddiffbeforeafterboth

no changes

modifiedpallets/refungible/src/benchmarking.rsdiffbeforeafterboth
18use crate::{Pallet, Config, RefungibleHandle};18use crate::{Pallet, Config, RefungibleHandle};
1919
20use 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)?}
210
211 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)?}
226
227 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)?}
248
249 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)?}
206272
207 repartition_item {273 repartition_item {
208 bench_init!{274 bench_init!{
modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
20use 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}
46
47fn 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 0
52 }
53}
4354
44pub 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 }
4960
50 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 }
5373
54 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 }
6995
70 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 0
73 }98 }
7499
75 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 0
78 }102 }
79103
80 fn set_token_properties(_amount: u32) -> Weight {104 fn set_token_properties(amount: u32) -> Weight {
81 // Error105 <SelfWeightOf<T>>::set_token_properties(amount)
82 0
83 }106 }
84107
85 fn delete_token_properties(_amount: u32) -> Weight {108 fn delete_token_properties(amount: u32) -> Weight {
86 // Error109 <SelfWeightOf<T>>::delete_token_properties(amount)
87 0
88 }110 }
89111
90 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 0
93 }114 }
94115
95 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}
147169
170/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete
171/// 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,
295319
296 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);
326
301 fail!(<Error<T>>::SettingPropertiesNotAllowed)327 with_weight(
328 <Pallet<T>>::set_collection_properties(self, &sender, properties),
329 weight,
330 )
302 }331 }
303332
304 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);
339
309 fail!(<Error<T>>::SettingPropertiesNotAllowed)340 with_weight(
341 <Pallet<T>>::delete_collection_properties(self, sender, property_keys),
342 weight,
343 )
310 }344 }
311345
312 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);
354
319 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 }
321367
322 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);
375
327 fail!(<Error<T>>::SettingPropertiesNotAllowed)376 with_weight(
377 <Pallet<T>>::set_token_property_permissions(self, sender, property_permissions),
378 weight,
379 )
328 }380 }
329381
330 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);
390
337 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 }
339402
371 TokenId(<TokensMinted<T>>::get(self.id))434 TokenId(<TokensMinted<T>>::get(self.id))
372 }435 }
373436
374 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 }
440
441 /// 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 }
377445
378 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 None
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17extern crate alloc;
17use up_data_structs::TokenId;18use evm_coder::{generate_stubgen, solidity_interface, types::*};
19
18use pallet_common::erc::CommonEvmHandler;20use pallet_common::{CollectionHandle, erc::CollectionCall, erc::CommonEvmHandler};
21
19use pallet_evm::PrecompileHandle;22use pallet_evm::PrecompileHandle;
23use pallet_evm_coder_substrate::call;
2024
21use crate::{Config, RefungibleHandle};25use crate::{Config, RefungibleHandle};
2226
27#[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");32
2533// Not a tests, but code generators
26 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 ERC721
31 None
32 }
33}
34
35pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);35generate_stubgen!(gen_iface, UniqueRFTCall<()>, false);
3636
37impl<T: Config> CommonEvmHandler for RefungibleTokenHandle<T> {37impl<T: Config> CommonEvmHandler for RefungibleHandle<T>
38where
39 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");
39
40 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 None
46 }47 }
47}48}
4849
addedpallets/refungible/src/erc_token.rsdiffbeforeafterboth

no changes

modifiedpallets/refungible/src/lib.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17//! # Refungible Pallet
18//!
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//! ## Overview
27//!
28//! The Refungible pallet provides functions for:
29//!
30//! - RFT collection creation and removal
31//! - Minting and burning of RFT tokens
32//! - Partition and repartition of RFT tokens
33//! - Retrieving number of pieces of RFT token
34//! - Retrieving account balances
35//! - Transfering RFT token pieces
36//! - Burning RFT token pieces
37//! - Setting and checking allowance for RFT tokens
38//!
39//! ### Terminology
40//!
41//! - **RFT token:** Non fungible token that was partitioned to pieces. If an account owns all
42//! 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 account
50//!
51//! - **Allowance:** Maximum number of RFT token pieces that one account is allowed to
52//! transfer from the balance of another account
53//!
54//! - **Burning:** The process of “deleting” a token from a collection or removing token pieces from
55//! an account balance.
56//!
57//! ### Implementations
58//!
59//! The Refungible pallet provides implementations for the following traits. If these traits provide
60//! 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 weight
63//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing
64//! with collections
65//! - [`RefungibleExtensions`](pallet_common::RefungibleExtensions): Functions specific for refungible
66//! collection
67//!
68//! ## Interface
69//!
70//! ### Dispatchable Functions
71//!
72//! - `init_collection` - Create RFT collection. RFT collection can be configured to allow or deny access for
73//! 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//! ## Assumptions
83//!
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.
87
17#![cfg_attr(not(feature = "std"), no_std)]88#![cfg_attr(not(feature = "std"), no_std)]
1889
19use frame_support::{ensure, BoundedVec};90use crate::erc_token::ERC20Events;
91
92use 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};
32112
33pub 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;
40121
41/// Token data, stored independently from other data used to describe it.122/// Token data, stored independently from other data used to describe it
42/// 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 {
108189
109 /// 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 >;
199
200 /// Total amount of pieces for token
201 #[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 >;
140231
141 /// 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 >;
153244
154 /// 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.0
190 }281 }
282 pub fn common_mut(&mut self) -> &mut pallet_common::CollectionHandle<T> {
283 &mut self.0
284 }
191}285}
286
192impl<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>;
194289
197 }292 }
198}293}
199294
295impl<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}
303
200impl<T: Config> Pallet<T> {304impl<T: Config> Pallet<T> {
305 /// Get number of RFT tokens in collection
201 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 }
309
310 /// Check that RFT token exists
311 ///
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 }
316
317 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)?;
327
328 Ok(())
329 }
330
331 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)?;
341
342 Ok(())
343 }
207}344}
208345
209// unchecked calls skips any permission checks346// unchecked calls skips any permission checks
210impl<T: Config> Pallet<T> {347impl<T: Config> Pallet<T> {
348 /// Create RFT collection
349 ///
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 }
359
360 /// Destroy RFT collection
361 ///
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 }
247394
248 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)?;
252402
253 <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 event
259 Ok(())410 Ok(())
260 }411 }
261412
413 /// Burn RFT token pieces
414 ///
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 being
418 /// one of the owners of the token. If there is no account that owns any pieces of
419 /// 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 burned
423 /// - `collection`: Collection that contains the token
262 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);
484
322 // 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 }
331504
505 #[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 }
522
523 let is_bundle_owner = <PalletStructure<T>>::check_indirectly_owned(
524 sender.clone(),
525 collection.id,
526 token_id,
527 None,
528 nesting_budget,
529 )?;
530
531 Ok(is_bundle_owner)
532 };
533
534 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);
539
540 let is_property_exists = TokenProperties::<T>::get((collection.id, token_id))
541 .get(&key)
542 .is_some();
543
544 match permission {
545 PropertyPermission { mutable: false, .. } if is_property_exists => {
546 return Err(<CommonError<T>>::NoPermission.into());
547 }
548
549 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_create
558 || (collection_admin && is_collection_admin())
559 || (token_owner && is_token_owner()?))
560 {
561 fail!(<CommonError<T>>::NoPermission);
562 }
563 }
564 }
565
566 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)?;
572
573 <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)?;
584
585 <PalletCommon<T>>::deposit_event(CommonEvent::TokenPropertyDeleted(
586 collection.id,
587 token_id,
588 key,
589 ));
590 }
591 }
592 }
593
594 Ok(())
595 }
596
597 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 }
614
615 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;
623
624 Self::set_token_properties(
625 collection,
626 sender,
627 token_id,
628 [property].into_iter(),
629 is_token_create,
630 nesting_budget,
631 )
632 }
633
634 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;
642
643 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 }
652
653 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 }
668
669 /// 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 transfered
677 /// - `collection`: Collection that contains the token
332 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 }
424770
425 // 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 }
435791
792 /// 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,
517878
518 // =========879 // =========
519880
881 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]);
885
886 <TokenData<T>>::insert(
887 (collection.id, token_id),
888 ItemData {
889 const_data: data.const_data.clone(),
890 },
891 );
892
893 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 }
905
906 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 })?;
919
520 <TokensMinted<T>>::insert(collection.id, tokens_minted);920 <TokensMinted<T>>::insert(collection.id, tokens_minted);
921
521 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 }
925
524 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]);
527928
528 <TokenData<T>>::insert(
529 (collection.id, token_id),
530 ItemData {
531 const_data: token.const_data,
532 },
533 );
534
535 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 }
933
539 <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 );
546
547 // TODO: ERC20 transfer event
548 <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 }
968
571 // 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 }
580988
989 /// 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 }
6481059
1060 /// 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.transfer
649 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 }
6691086
1087 /// 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 should
1090 /// set allowance for the spender to burn pieces
1091 ///
1092 /// [`burn`]: struct.Pallet.html#method.burn
670 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 }
6891112
690 /// 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 configured
1116 /// to allow public minting.
1117 ///
1118 /// - `data`: Contains list of users who will become the owners of the token pieces and amount
1119 /// 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 }
6991128
1129 /// 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 some
1133 /// 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 pieces
712 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>>::RepartitionWhileNotOwningAllPieces
717 );1153 );
7181154
719 <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);
1157
1158 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 }
1197
721 Ok(())1198 Ok(())
722 }1199 }
7231200
1201 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 owner
1212 }
1213
724 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 }
1217
1218 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 }
1225
1226 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 }
1233
1234 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 }
1241
1242 /// 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 holders
1247 /// 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();
1256
1257 if res.is_empty() {
1258 None
1259 } else {
1260 Some(res)
1261 }
726 }1262 }
727}1263}
7281264
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth

no changes

modifiedpallets/refungible/src/weights.rsdiffbeforeafterboth
3//! Autogenerated weights for pallet_refungible3//! Autogenerated weights for pallet_refungible
4//!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-dev
6//! 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: 1024
88
9// 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}
5457
62 // 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_000
78 .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_000
92 .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_000
107 .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_000
225 .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_000
234 .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_000
243 .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_000
247 .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_000
261 .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_000
276 .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_000
422 .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_000
431 .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_000
440 .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 }
modifiedpallets/scheduler/src/lib.rsdiffbeforeafterboth
24// 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 at
26//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, software
30// 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 and
33// limitations under the License.33// limitations under the License.
3434
35//! # Schedulerdo_reschedule35//! # Unique scheduler
36//! A Pallet for scheduling dispatches.
37//!
38//! - [`Config`]
39//! - [`Call`]
40//! - [`Pallet`]
41//!
42//! ## Overview
36//!43//!
37//! This Pallet exposes capabilities for scheduling dispatches to occur at a44//! This Pallet exposes capabilities for scheduling dispatches to occur at a
38//! specified block number or at a specified period. These scheduled dispatches45//! specified block number or at a specified period. These scheduled dispatches
39//! 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//! ## Interface
50//!62//!
51//! ### Dispatchable Functions63//! ### Dispatchable Functions
52//!64//!
53//! * `schedule` - schedule a dispatch, which may be periodic, to occur at a specified block and
54//! 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>` parameter
57//! 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.
258267
259 /// 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>;
268277
269 /// 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 >;
284293
285 /// 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 // }
443452
453 // Execute transaction via chain default pipeline
454 // That means dispatch will be processed like any user's extrinsic e.g. transaction fees will be taken
444 let r = T::CallExecutor::dispatch_call(sender, call.clone());455 let r = T::CallExecutor::dispatch_call(sender, call.clone());
445456
446 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 for
488 0500 0
489 //total_weight
490 }501 }
491 }502 }
492503
modifiedpallets/structure/src/benchmarking.rsdiffbeforeafterboth
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
2// This file is part of Unique Network.
3
4// Unique Network is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Unique Network is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
1use super::*;17use super::*;
218
modifiedpallets/structure/src/lib.rsdiffbeforeafterboth
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
2// This file is part of Unique Network.
3
4// Unique Network is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Unique Network is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! # Structure Pallet
18//!
19//! The Structure pallet provides functionality for handling tokens nesting an unnesting.
20//!
21//! - [`Config`]
22//! - [`Pallet`]
23//!
24//! ## Overview
25//!
26//! The Structure pallet provides functions for:
27//!
28//! - Searching for token parents, children and owners. Actual implementation of searching for
29//! 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 corresponding
31//! to token's collection type.
32//!
33//! ### Terminology
34//!
35//! - **Nesting:** Setting up parent-child relationship between tokens. Nested tokens are inhereting
36//! owner from their parent. There could be multiple levels of nesting. Token couldn't be nested in
37//! it's child token i.e. parent-child relationship graph shouldn't have
38//!
39//! - **Parent:** Token that current token is nested in.
40//!
41//! - **Owner:** Account that owns the token and all nested tokens.
42//!
43//! ## Interface
44//!
45//! ### Available Functions
46//!
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 token
51//! - `nest_if_sent_to_token` - Nest the token in the other token
52//! - `unnest_if_nested` - Unnest the token from the other token
53
1#![cfg_attr(not(feature = "std"), no_std)]54#![cfg_attr(not(feature = "std"), no_std)]
255
82}135}
83136
84impl<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 found
85 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 }
105164
165 /// Get the chain of parents of a token in the nesting hierarchy
166 ///
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 owner
134 ///198 ///
135 /// May return token address if parent token not yet exists199 /// May return token address if parent token not yet exists
200 ///
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 }
151217
218 /// Find the topmost parent and check that assigning `for_nest` token as a child for
219 /// `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 }
179249
250 /// Burn token and all of it's nested tokens
251 ///
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 }
192266
193 /// 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` then
270 /// 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 }
209289
290 /// Checks that `under` is valid token and that `token_id` could be nested under it
291 /// and that `from` is `under`'s owner
292 ///
293 /// Returns OK if `under` is not a token
294 ///
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 }
221307
308 /// Nests `token_id` under `under` token
309 ///
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 }
237328
329 /// Nests `token_id` under `owner` token
330 ///
331 /// Caller should check that nesting wouldn't cause recursion in nesting
238 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 }
247341
342 /// 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,
modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedprimitives/data-structs/Cargo.tomldiffbeforeafterboth
6license = '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'
1010
11[dependencies]11[dependencies]
12scale-info = { version = "2.0.1", default-features = false, features = [12scale-info = { version = "2.0.1", default-features = false, features = [
addedprimitives/data-structs/Changelog.mddiffbeforeafterboth

no changes

modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
566 /// Number of pieces the RFT is split into567 /// Number of pieces the RFT is split into
567 pub pieces: u128,568 pub pieces: u128,
569
570 /// Key-value pairs used to describe the token as metadata
571 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
572 #[derivative(Debug(format_with = "bounded::vec_debug"))]
573 pub properties: CollectionPropertiesVec,
568}574}
569575
570#[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}
605613
606/// Explicit item creation data with meta parameters, namely the owner.614/// Explicit item creation data with meta parameters, namely the owner.
addedprimitives/rpc/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedprimitives/rpc/Cargo.tomldiffbeforeafterboth
1[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"
66
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
81 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}
8687
addedruntime/common/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedruntime/common/src/dispatch.rsdiffbeforeafterboth
25pub 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,
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
41 dispatch_unique_runtime!(collection.token_owner(token))41 dispatch_unique_runtime!(collection.token_owner(token))
42 }42 }
43
44 fn token_owners(collection: CollectionId, token: TokenId) -> Result<Vec::<CrossAccountId>, DispatchError> {
45 dispatch_unique_runtime!(collection.token_owners(token))
46 }
47
43 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);
modifiedruntime/tests/src/tests.rsdiffbeforeafterboth
64 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}
6975
addedtests/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedtests/package.jsondiffbeforeafterboth
80 "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 .",
modifiedtests/src/createMultipleItems.test.tsdiffbeforeafterboth
376 // ReFungible376 // ReFungible
377 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.unique
385 .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.unique
396 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);
397 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;
398 }
387 });399 });
388 });400 });
389401
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
28 function burnFrom(address from, uint256 amount) external returns (bool);28 function burnFrom(address from, uint256 amount) external returns (bool);
29}29}
30
31// Selector: 7d9262e6
32interface 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) 2f073f66
39 function setCollectionProperty(string memory key, bytes memory value)
40 external;
41
42 // Delete collection property.
43 //
44 // @param key Property key.
45 //
46 // Selector: deleteCollectionProperty(string) 7b7debce
47 function deleteCollectionProperty(string memory key) external;
48
49 // 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) cf24fd6d
57 function collectionProperty(string memory key)
58 external
59 view
60 returns (bytes memory);
61
62 // 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) 7623402e
69 function setCollectionSponsor(address sponsor) external;
70
71 // Collection sponsorship confirmation.
72 //
73 // @dev After setting the sponsor for the collection, it must be confirmed with this function.
74 //
75 // Selector: confirmCollectionSponsorship() 3c50e97a
76 function confirmCollectionSponsorship() external;
77
78 // 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) 6a3841db
90 function setCollectionLimit(string memory limit, uint32 value) external;
91
92 // 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) 993b7fba
101 function setCollectionLimit(string memory limit, bool value) external;
102
103 // Get contract address.
104 //
105 // Selector: contractAddress() f6b4dfb4
106 function contractAddress() external view returns (address);
107
108 // Add collection admin by substrate address.
109 // @param new_admin Substrate administrator address.
110 //
111 // Selector: addCollectionAdminSubstrate(uint256) 5730062b
112 function addCollectionAdminSubstrate(uint256 newAdmin) external;
113
114 // Remove collection admin by substrate address.
115 // @param admin Substrate administrator address.
116 //
117 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
118 function removeCollectionAdminSubstrate(uint256 admin) external;
119
120 // Add collection admin.
121 // @param new_admin Address of the added administrator.
122 //
123 // Selector: addCollectionAdmin(address) 92e462c7
124 function addCollectionAdmin(address newAdmin) external;
125
126 // Remove collection admin.
127 //
128 // @param new_admin Address of the removed administrator.
129 //
130 // Selector: removeCollectionAdmin(address) fafd7b42
131 function removeCollectionAdmin(address admin) external;
132
133 // Toggle accessibility of collection nesting.
134 //
135 // @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
136 //
137 // Selector: setCollectionNesting(bool) 112d4586
138 function setCollectionNesting(bool enable) external;
139
140 // 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[]) 64872396
146 function setCollectionNesting(bool enable, address[] memory collections)
147 external;
148
149 // Set the collection access method.
150 // @param mode Access mode
151 // 0 for Normal
152 // 1 for AllowList
153 //
154 // Selector: setCollectionAccess(uint8) 41835d4c
155 function setCollectionAccess(uint8 mode) external;
156
157 // Add the user to the allowed list.
158 //
159 // @param user Address of a trusted user.
160 //
161 // Selector: addToCollectionAllowList(address) 67844fe6
162 function addToCollectionAllowList(address user) external;
163
164 // Remove the user from the allowed list.
165 //
166 // @param user Address of a removed user.
167 //
168 // Selector: removeFromCollectionAllowList(address) 85c51acb
169 function removeFromCollectionAllowList(address user) external;
170
171 // Switch permission for minting.
172 //
173 // @param mode Enable if "true".
174 //
175 // Selector: setCollectionMintMode(bool) 00018e84
176 function setCollectionMintMode(bool mode) external;
177}
30178
31// Selector: 942e8b22179// Selector: 942e8b22
32interface ERC20 is Dummy, ERC165, ERC20Events {180interface ERC20 is Dummy, ERC165, ERC20Events {
65 returns (uint256);213 returns (uint256);
66}214}
67
68// Selector: c894dc35
69interface Collection is Dummy, ERC165 {
70 // Selector: setCollectionProperty(string,bytes) 2f073f66
71 function setCollectionProperty(string memory key, bytes memory value)
72 external;
73
74 // Selector: deleteCollectionProperty(string) 7b7debce
75 function deleteCollectionProperty(string memory key) external;
76
77 // Throws error if key not found
78 //
79 // Selector: collectionProperty(string) cf24fd6d
80 function collectionProperty(string memory key)
81 external
82 view
83 returns (bytes memory);
84
85 // Selector: ethSetSponsor(address) 8f9af356
86 function ethSetSponsor(address sponsor) external;
87
88 // Selector: ethConfirmSponsorship() a8580d1a
89 function ethConfirmSponsorship() external;
90
91 // Selector: setLimit(string,uint32) 68db30ca
92 function setLimit(string memory limit, uint32 value) external;
93
94 // Selector: setLimit(string,bool) ea67e4c2
95 function setLimit(string memory limit, bool value) external;
96
97 // Selector: contractAddress() f6b4dfb4
98 function contractAddress() external view returns (address);
99}
100215
101interface UniqueFungible is216interface UniqueFungible is
102 Dummy,217 Dummy,
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
4444
45// Selector: 4136937745// Selector: 41369377
46interface 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) 222d97fa
48 function setTokenPropertyPermission(55 function setTokenPropertyPermission(
49 string memory key,56 string memory key,
52 bool tokenOwner59 bool tokenOwner
53 ) external;60 ) external;
5461
62 // @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) 1752d67b
56 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 value
60 ) external;73 ) external;
6174
75 // @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) 066111d1
63 function deleteProperty(uint256 tokenId, string memory key) external;81 function deleteProperty(uint256 tokenId, string memory key) external;
6482
83 // @notice Get token property value.
65 // Throws error if key not found84 // @dev Throws error if key not found
85 // @param tokenId ID of the token.
86 // @param key Property key.
87 // @return Property value bytes
66 //88 //
67 // Selector: property(uint256,string) 7228c32789 // Selector: property(uint256,string) 7228c327
68 function property(uint256 tokenId, string memory key)90 function property(uint256 tokenId, string memory key)
7395
74// Selector: 42966c6896// Selector: 42966c68
75interface 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 authorized
100 // operator of the current owner.
101 // @param tokenId The NFT to approve
102 //
76 // Selector: burn(uint256) 42966c68103 // Selector: burn(uint256) 42966c68
77 function burn(uint256 tokenId) external;104 function burn(uint256 tokenId) external;
78}105}
79106
80// Selector: 58800161107// Selector: 58800161
81interface ERC721 is Dummy, ERC165, ERC721Events {108interface ERC721 is Dummy, ERC165, ERC721Events {
109 // @notice Count all NFTs assigned to an owner
110 // @dev NFTs assigned to the zero address are considered invalid, and this
111 // function throws for queries about the zero address.
112 // @param owner An address for whom to query the balance
113 // @return The number of NFTs owned by `owner`, possibly zero
114 //
82 // Selector: balanceOf(address) 70a08231115 // Selector: balanceOf(address) 70a08231
83 function balanceOf(address owner) external view returns (uint256);116 function balanceOf(address owner) external view returns (uint256);
84117
118 // @notice Find the owner of an NFT
119 // @dev NFTs assigned to zero address are considered invalid, and queries
120 // about them do throw.
121 // @param tokenId The identifier for an NFT
122 // @return The address of the owner of the NFT
123 //
85 // Selector: ownerOf(uint256) 6352211e124 // Selector: ownerOf(uint256) 6352211e
86 function ownerOf(uint256 tokenId) external view returns (address);125 function ownerOf(uint256 tokenId) external view returns (address);
87126
88 // Not implemented127 // @dev Not implemented
89 //128 //
90 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672129 // Selector: safeTransferFromWithData(address,address,uint256,bytes) 60a11672
91 function safeTransferFromWithData(130 function safeTransferFromWithData(
95 bytes memory data134 bytes memory data
96 ) external;135 ) external;
97136
98 // Not implemented137 // @dev Not implemented
99 //138 //
100 // Selector: safeTransferFrom(address,address,uint256) 42842e0e139 // Selector: safeTransferFrom(address,address,uint256) 42842e0e
101 function safeTransferFrom(140 function safeTransferFrom(
104 uint256 tokenId143 uint256 tokenId
105 ) external;144 ) external;
106145
146 // @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
147 // TO CONFIRM THAT `to` IS CAPABLE OF RECEIVING NFTS OR ELSE
148 // THEY MAY BE PERMANENTLY LOST
149 // @dev Throws unless `msg.sender` is the current owner or an authorized
150 // operator for this NFT. Throws if `from` is not the current owner. Throws
151 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
152 // @param from The current owner of the NFT
153 // @param to The new owner
154 // @param tokenId The NFT to transfer
155 // @param _value Not used for an NFT
156 //
107 // Selector: transferFrom(address,address,uint256) 23b872dd157 // Selector: transferFrom(address,address,uint256) 23b872dd
108 function transferFrom(158 function transferFrom(
109 address from,159 address from,
110 address to,160 address to,
111 uint256 tokenId161 uint256 tokenId
112 ) external;162 ) external;
113163
164 // @notice Set or reaffirm the approved address for an NFT
165 // @dev The zero address indicates there is no approved address.
166 // @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
167 // operator of the current owner.
168 // @param approved The new approved NFT controller
169 // @param tokenId The NFT to approve
170 //
114 // Selector: approve(address,uint256) 095ea7b3171 // Selector: approve(address,uint256) 095ea7b3
115 function approve(address approved, uint256 tokenId) external;172 function approve(address approved, uint256 tokenId) external;
116173
117 // Not implemented174 // @dev Not implemented
118 //175 //
119 // Selector: setApprovalForAll(address,bool) a22cb465176 // Selector: setApprovalForAll(address,bool) a22cb465
120 function setApprovalForAll(address operator, bool approved) external;177 function setApprovalForAll(address operator, bool approved) external;
121178
122 // Not implemented179 // @dev Not implemented
123 //180 //
124 // Selector: getApproved(uint256) 081812fc181 // Selector: getApproved(uint256) 081812fc
125 function getApproved(uint256 tokenId) external view returns (address);182 function getApproved(uint256 tokenId) external view returns (address);
126183
127 // Not implemented184 // @dev Not implemented
128 //185 //
129 // Selector: isApprovedForAll(address,address) e985e9c5186 // Selector: isApprovedForAll(address,address) e985e9c5
130 function isApprovedForAll(address owner, address operator)187 function isApprovedForAll(address owner, address operator)
135192
136// Selector: 5b5e139f193// Selector: 5b5e139f
137interface ERC721Metadata is Dummy, ERC165 {194interface ERC721Metadata is Dummy, ERC165 {
195 // @notice A descriptive name for a collection of NFTs in this contract
196 //
138 // Selector: name() 06fdde03197 // Selector: name() 06fdde03
139 function name() external view returns (string memory);198 function name() external view returns (string memory);
140199
200 // @notice An abbreviated name for NFTs in this contract
201 //
141 // Selector: symbol() 95d89b41202 // Selector: symbol() 95d89b41
142 function symbol() external view returns (string memory);203 function symbol() external view returns (string memory);
143204
205 // @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 RFC
207 // 3986. The URI may point to a JSON file that conforms to the "ERC721
208 // Metadata JSON Schema".
144 // Returns token's const_metadata209 // @return token's const_metadata
145 //210 //
146 // Selector: tokenURI(uint256) c87b56dd211 // Selector: tokenURI(uint256) c87b56dd
147 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() 05d2035b
153 function mintingFinished() external view returns (bool);218 function mintingFinished() external view returns (bool);
154219
220 // @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 manually
223 // @param to The new owner
224 // @param tokenId ID of the minted NFT
157 //225 //
158 // Selector: mint(address,uint256) 40c10f19226 // Selector: mint(address,uint256) 40c10f19
159 function mint(address to, uint256 tokenId) external returns (bool);227 function mint(address to, uint256 tokenId) external returns (bool);
160228
229 // @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 manually
232 // @param to The new owner
233 // @param tokenId ID of the minted NFT
234 // @param tokenUri Token URI that would be stored in the NFT properties
163 //235 //
164 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f236 // Selector: mintWithTokenURI(address,uint256,string) 50bb4e7f
165 function mintWithTokenURI(237 function mintWithTokenURI(
168 string memory tokenUri240 string memory tokenUri
169 ) external returns (bool);241 ) external returns (bool);
170242
171 // Not implemented243 // @dev Not implemented
172 //244 //
173 // Selector: finishMinting() 7d64bcb4245 // Selector: finishMinting() 7d64bcb4
174 function finishMinting() external returns (bool);246 function finishMinting() external returns (bool);
175}247}
176248
177// Selector: 780e9d63249// Selector: 780e9d63
178interface ERC721Enumerable is Dummy, ERC165 {250interface ERC721Enumerable is Dummy, ERC165 {
251 // @notice Enumerate valid NFTs
252 // @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) 4f6ccce7
180 function tokenByIndex(uint256 index) external view returns (uint256);257 function tokenByIndex(uint256 index) external view returns (uint256);
181258
182 // Not implemented259 // @dev Not implemented
183 //260 //
184 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59261 // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
185 function tokenOfOwnerByIndex(address owner, uint256 index)262 function tokenOfOwnerByIndex(address owner, uint256 index)
186 external263 external
187 view264 view
188 returns (uint256);265 returns (uint256);
189266
267 // @notice Count NFTs tracked by this contract
268 // @return A count of valid NFTs tracked by this contract, where each one of
269 // them has an assigned and queryable owner not equal to the zero address
270 //
190 // Selector: totalSupply() 18160ddd271 // Selector: totalSupply() 18160ddd
191 function totalSupply() external view returns (uint256);272 function totalSupply() external view returns (uint256);
192}273}
193274
194// Selector: 7d9262e6275// Selector: 7d9262e6
195interface 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) 2f073f66
197 function setCollectionProperty(string memory key, bytes memory value)283 function setCollectionProperty(string memory key, bytes memory value)
198 external;284 external;
199285
286 // Delete collection property.
287 //
288 // @param key Property key.
289 //
200 // Selector: deleteCollectionProperty(string) 7b7debce290 // Selector: deleteCollectionProperty(string) 7b7debce
201 function deleteCollectionProperty(string memory key) external;291 function deleteCollectionProperty(string memory key) external;
202292
293 // 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) cf24fd6d
206 function collectionProperty(string memory key)301 function collectionProperty(string memory key)
207 external302 external
208 view303 view
209 returns (bytes memory);304 returns (bytes memory);
210305
306 // 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) 7623402e
212 function setCollectionSponsor(address sponsor) external;313 function setCollectionSponsor(address sponsor) external;
213314
315 // 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() 3c50e97a
215 function confirmCollectionSponsorship() external;320 function confirmCollectionSponsorship() external;
216321
322 // 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) 6a3841db
218 function setCollectionLimit(string memory limit, uint32 value) external;334 function setCollectionLimit(string memory limit, uint32 value) external;
219335
336 // 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) 993b7fba
221 function setCollectionLimit(string memory limit, bool value) external;345 function setCollectionLimit(string memory limit, bool value) external;
222346
347 // Get contract address.
348 //
223 // Selector: contractAddress() f6b4dfb4349 // Selector: contractAddress() f6b4dfb4
224 function contractAddress() external view returns (address);350 function contractAddress() external view returns (address);
225351
352 // Add collection admin by substrate address.
353 // @param new_admin Substrate administrator address.
354 //
226 // Selector: addCollectionAdminSubstrate(uint256) 5730062b355 // Selector: addCollectionAdminSubstrate(uint256) 5730062b
227 function addCollectionAdminSubstrate(uint256 newAdmin) external view;356 function addCollectionAdminSubstrate(uint256 newAdmin) external;
228357
358 // Remove collection admin by substrate address.
359 // @param admin Substrate administrator address.
360 //
229 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9361 // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
230 function removeCollectionAdminSubstrate(uint256 newAdmin) external view;362 function removeCollectionAdminSubstrate(uint256 admin) external;
231363
364 // Add collection admin.
365 // @param new_admin Address of the added administrator.
366 //
232 // Selector: addCollectionAdmin(address) 92e462c7367 // Selector: addCollectionAdmin(address) 92e462c7
233 function addCollectionAdmin(address newAdmin) external view;368 function addCollectionAdmin(address newAdmin) external;
234369
370 // Remove collection admin.
371 //
372 // @param new_admin Address of the removed administrator.
373 //
235 // Selector: removeCollectionAdmin(address) fafd7b42374 // Selector: removeCollectionAdmin(address) fafd7b42
236 function removeCollectionAdmin(address admin) external view;375 function removeCollectionAdmin(address admin) external;
237376
377 // 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) 112d4586
239 function setCollectionNesting(bool enable) external;382 function setCollectionNesting(bool enable) external;
240383
384 // 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[]) 64872396
242 function setCollectionNesting(bool enable, address[] memory collections)390 function setCollectionNesting(bool enable, address[] memory collections)
243 external;391 external;
244392
393 // Set the collection access method.
394 // @param mode Access mode
395 // 0 for Normal
396 // 1 for AllowList
397 //
245 // Selector: setCollectionAccess(uint8) 41835d4c398 // Selector: setCollectionAccess(uint8) 41835d4c
246 function setCollectionAccess(uint8 mode) external;399 function setCollectionAccess(uint8 mode) external;
247400
401 // 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) 67844fe6
249 function addToCollectionAllowList(address user) external view;406 function addToCollectionAllowList(address user) external;
250407
408 // 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) 85c51acb
252 function removeFromCollectionAllowList(address user) external view;413 function removeFromCollectionAllowList(address user) external;
253414
415 // Switch permission for minting.
416 //
417 // @param mode Enable if "true".
418 //
254 // Selector: setCollectionMintMode(bool) 00018e84419 // Selector: setCollectionMintMode(bool) 00018e84
255 function setCollectionMintMode(bool mode) external;420 function setCollectionMintMode(bool mode) external;
256}421}
257422
258// Selector: d74d154f423// Selector: d74d154f
259interface ERC721UniqueExtensions is Dummy, ERC165 {424interface ERC721UniqueExtensions is Dummy, ERC165 {
425 // @notice Transfer ownership of an NFT
426 // @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 owner
429 // @param tokenId The NFT to transfer
430 // @param _value Not used for an NFT
431 //
260 // Selector: transfer(address,uint256) a9059cbb432 // Selector: transfer(address,uint256) a9059cbb
261 function transfer(address to, uint256 tokenId) external;433 function transfer(address to, uint256 tokenId) external;
262434
435 // @notice Burns a specific ERC721 token.
436 // @dev Throws unless `msg.sender` is the current owner or an authorized
437 // operator for this NFT. Throws if `from` is not the current owner. Throws
438 // if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
439 // @param from The current owner of the NFT
440 // @param tokenId The NFT to transfer
441 // @param _value Not used for an NFT
442 //
263 // Selector: burnFrom(address,uint256) 79cc6790443 // Selector: burnFrom(address,uint256) 79cc6790
264 function burnFrom(address from, uint256 tokenId) external;444 function burnFrom(address from, uint256 tokenId) external;
265445
446 // @notice Returns next free NFT ID.
447 //
266 // Selector: nextTokenId() 75794a3c448 // Selector: nextTokenId() 75794a3c
267 function nextTokenId() external view returns (uint256);449 function nextTokenId() external view returns (uint256);
268450
451 // @notice Function to mint multiple tokens.
452 // @dev `tokenIds` should be an array of consecutive numbers and first number
453 // should be obtained with `nextTokenId` method
454 // @param to The new owner
455 // @param tokenIds IDs of the minted NFTs
456 //
269 // Selector: mintBulk(address,uint256[]) 44a9945e457 // Selector: mintBulk(address,uint256[]) 44a9945e
270 function mintBulk(address to, uint256[] memory tokenIds)458 function mintBulk(address to, uint256[] memory tokenIds)
271 external459 external
272 returns (bool);460 returns (bool);
273461
462 // @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 consecutive
464 // numbers and first number should be obtained with `nextTokenId` method
465 // @param to The new owner
466 // @param tokens array of pairs of token ID and token URI for minted tokens
467 //
274 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006468 // Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
275 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)469 function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
276 external470 external
addedtests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth

no changes

modifiedtests/src/eth/fungibleAbi.jsondiffbeforeafterboth
49 "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" }
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
86 ],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 {
addedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth

no changes

addedtests/src/eth/reFungibleTokenAbi.jsondiffbeforeafterboth

no changes

addedtests/src/fungible.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth
29 [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 const
modifiedtests/src/interfaces/augment-api-errors.tsdiffbeforeafterboth
284 * 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 error
modifiedtests/src/interfaces/augment-api-events.tsdiffbeforeafterboth
58 [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 * # Arguments
65 *
66 * * collection_id - todo:doc flesh out
67 * * item_id
68 * * sender
69 * * spender
70 * * amount
71 **/
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 created
75 * 67 **/
76 * # Arguments
77 *
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 destroyed
85 * 71 **/
86 * # Arguments
87 *
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 * # Arguments
95 *
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 * # Arguments
104 *
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 * # Arguments
113 *
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 * # Arguments
124 *
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 * # Arguments
135 *
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 * # Arguments
144 *
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 * # Arguments
154 *
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 transferred
162 * 103 **/
163 * # Arguments
164 *
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 event
565 [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 list
570 * 503 *
571 * # Arguments504 * # Arguments
572 * 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 list
580 * 511 *
581 * # Arguments512 * # Arguments
582 * 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 added
590 * 519 *
591 * # Arguments520 * # Arguments
592 * 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 removed
600 * 527 *
601 * # Arguments528 * # Arguments
602 * 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 set
610 * 535 *
611 * # Arguments536 * # Arguments
612 * 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 changed
618 * 542 *
619 * # Arguments543 * # Arguments
620 * 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 set
628 * 550 *
629 * # Arguments551 * # Arguments
630 * 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 removed
636 * 557 *
637 * # Arguments558 * # Arguments
638 * 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 set
644 * 564 *
645 * # Arguments565 * # Arguments
646 * 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 confirm
654 * 572 *
655 * # Arguments573 * # Arguments
656 * 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 event
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
69 [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 query
199 [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 from
264 * usual [`TokenProperties`] due to an unlimited number
265 * 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 token
475 **/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 query
modifiedtests/src/interfaces/augment-api-rpc.tsdiffbeforeafterboth
672 * Get tokens contained within a collection672 * Get tokens contained within a collection
673 **/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 metadata
677 **/
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 limits
677 **/681 **/
704 * Get the token owner708 * Get the token owner
705 **/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 order
713 **/
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 keys
709 **/717 **/
720 * Get the amount of distinctive tokens present in a collection728 * Get the amount of distinctive tokens present in a collection
721 **/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 metadata
733 **/
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 /**
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
729 [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 addresses
736 * (some which can also be servers, for example). Admins can issue
737 * and burn NFTs, as well as add and remove other admins,
738 * but cannot change NFT or Collection ownership.
735 * 739 *
736 * # Permissions740 * # Permissions
737 * 741 *
738 * * Collection Owner742 * * Collection owner
739 * * Collection Admin743 * * Collection admin
740 * 744 *
741 * # Arguments745 * # Arguments
742 * 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 * # Permissions
751 * 755 *
752 * * Collection Owner756 * * Collection owner
753 * * Collection Admin757 * * Collection admin
754 * 758 *
755 * # Arguments759 * # Arguments
756 * 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 * # Permissions
765 * 769 *
766 * * Collection Owner770 * * Collection owner
767 * * Collection Admin771 * * Collection admin
768 * * Current NFT owner772 * * Current item owner
769 * 773 *
770 * # Arguments774 * # Arguments
771 * 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 that
783 * * 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 * # Permissions
786 * 792 *
787 * # Arguments793 * * Collection owner
788 * 794 * * Collection admin
789 * * collection_id - ID of the collection.795 * * Current token owner
790 * * item_id - ID of NFT to burn.796 * * Address approved by current item owner
791 * * from - The owner of the item from whom it is taken away.797 *
792 **/798 * # Arguments
799 *
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 * # Permissions
798 * 813 *
799 * * Collection Owner814 * * Collection owner
800 * * Collection Admin815 * * Collection admin
801 * * Current NFT Owner816 * * Current item owner
802 * 817 *
803 * # Arguments818 * # Arguments
804 * 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 * # Permissions
813 * 832 *
814 * * Collection Owner833 * * Collection owner
815 * 834 *
816 * # Arguments835 * # Arguments
817 * 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 * # Permissions
830 * 849 *
831 * * collection_id.850 * * Sponsor-to-be
832 **/851 *
852 * # Arguments
853 *
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 bytes
838 * 861 * of certain length. The initial owner of the collection is set
839 * * 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 * # Permissions
844 * * 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 * # Arguments
871 *
872 * * `collection_name`: Wide-character string with collection name
873 * (limit [`MAX_COLLECTION_NAME_LENGTH`]).
874 * * `collection_description`: Wide-character string with collection description
875 * (limit [`MAX_COLLECTION_DESCRIPTION_LENGTH`]).
876 * * `token_prefix`: Byte string containing the token prefix to mark a collection
877 * 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 * # Permissions
854 * 887 *
855 * * Anyone.888 * * Anyone - becomes the owner of the new collection.
856 * 889 *
857 * # Arguments890 * # Arguments
858 * 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 * # Permissions
866 * 901 *
867 * * Collection Owner902 * * Collection owner
868 * * Collection Admin903 * * Collection admin
869 * * Anyone if904 * * Anyone if
870 * * Allow List is enabled, and905 * * Allow List is enabled, and
871 * * Address is added to allow list, and906 * * Address is added to allow list, and
872 * * MintPermission is enabled (see SetMintPermission method)907 * * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])
873 * 908 *
874 * # Arguments909 * # Arguments
875 * 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 * # Permissions
885 * 922 *
886 * * Collection Owner923 * * Collection owner
887 * * Collection Admin924 * * Collection admin
888 * * Anyone if925 * * Anyone if
889 * * Allow List is enabled, and926 * * Allow List is enabled, and
890 * * Address is added to allow list, and927 * * Address is added to the allow list, and
891 * * MintPermission is enabled (see SetMintPermission method)928 * * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])
892 * 929 *
893 * # Arguments930 * # Arguments
894 * 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 * # Permissions
904 * 941 *
905 * * Collection Owner942 * * Collection owner
906 * * Collection Admin943 * * Collection admin
907 * * Anyone if944 * * Anyone if
908 * * Allow List is enabled, and945 * * Allow List is enabled, and
909 * * Address is added to allow list, and946 * * Address is added to allow list, and
910 * * MintPermission is enabled (see SetMintPermission method)947 * * MintPermission is enabled (see [`set_collection_permissions`][`Pallet::set_collection_permissions`])
911 * 948 *
912 * # Arguments949 * # Arguments
913 * 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 * # Permissions
922 * 959 *
923 * * Collection Owner960 * * Collection Owner
924 * * Collection Admin961 * * Collection Admin
925 * 962 *
926 * # Arguments963 * # Arguments
927 * 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 * # Permissions
936 * 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 owner
939 * * Collection Admin977 * * Collection admin
940 * * Token Owner978 * * Token owner
941 * 979 *
942 * # Arguments980 * # Arguments
943 * 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 * # Permissions
953 * 992 *
954 * * Collection Owner993 * * Collection owner
955 * 994 *
956 * # Arguments995 * # Arguments
957 * 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 * # Permissions
965 * 1007 *
966 * * Collection Owner1008 * * Collection owner
967 * * Collection Admin1009 * * Collection admin
968 * 1010 *
969 * # Arguments1011 * # Arguments
970 * 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 * # Permissions
979 * 1021 *
980 * * Collection Owner1022 * * Collection owner
981 * 1023 *
982 * # Arguments1024 * # Arguments
983 * 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 * # Permissions
991 * 1033 *
992 * * Collection Owner1034 * * Collection owner
993 * * Collection Admin1035 * * Collection admin
994 * 1036 *
995 * # Arguments1037 * # Arguments
996 * 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 * # Permissions
1005 * 1047 *
1006 * * Token Owner (must own every part)1048 * * Token owner (must own every part)
1007 * 1049 *
1008 * # Arguments1050 * # Arguments
1009 * 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 * # Permissions
1019 * 1061 *
1020 * * Collection Owner1062 * * Collection owner
1021 * * Collection Admin1063 * * Collection admin
1022 * 1064 *
1023 * # Arguments1065 * # Arguments
1024 * 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 * # Permissions
1033 * 1076 *
1034 * * Collection Owner1077 * * Collection owner
1035 * * Collection Admin1078 * * Collection admin
1036 * 1079 *
1037 * # Arguments1080 * # Arguments
1038 * 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 * # Permissions
1047 * 1091 *
1048 * * Collection Owner1092 * * Collection owner
1049 * * Collection Admin1093 * * Collection admin
1050 * 1094 *
1051 * # Arguments1095 * # Arguments
1052 * 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 * # Permissions
1061 * 1108 *
1062 * * Collection Owner1109 * * Collection owner
1063 * * Collection Admin1110 * * Collection admin
1064 * 1111 *
1065 * # Arguments1112 * # Arguments
1066 * 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 * # Permissions
1075 * 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 owner
1078 * * Collection Admin1126 * * Collection admin
1079 * * Token Owner1127 * * Token owner
1080 * 1128 *
1081 * # Arguments1129 * See [`set_token_property_permissions`][`Pallet::set_token_property_permissions`].
1130 *
1131 * # Arguments
1082 * 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 key
1143 * cannot be created in a token.
1144 *
1145 * # Permissions
1092 * 1146 *
1093 * * Collection Owner1147 * * Collection owner
1094 * * Collection Admin1148 * * Collection admin
1095 * 1149 *
1096 * # Arguments1150 * # Arguments
1097 * 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 * # Permissions
1106 * 1161 *
1107 * * Collection Owner1162 * * Collection owner
1108 * 1163 *
1109 * # Arguments1164 * # Arguments
1110 * 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 * # Permissions
1119 * 1174 *
1120 * * Collection Owner1175 * * Collection owner
1121 * * Collection Admin1176 * * Collection admin
1122 * * Current NFT owner1177 * * Current token owner
1123 * 1178 *
1124 * # Arguments1179 * # Arguments
1125 * 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 that
1200 * the approved address will not be able to transfer this item again from this owner.
1143 * 1201 *
1144 * # Permissions1202 * # Permissions
1145 * 1203 *
1146 * * Collection Owner1204 * * Collection owner
1147 * * Collection Admin1205 * * Collection admin
1148 * * Current NFT owner1206 * * Current item owner
1149 * * Address approved by current NFT owner1207 * * Address approved by current item owner
1150 * 1208 *
1151 * # Arguments1209 * # Arguments
1152 * 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 tx
modifiedtests/src/interfaces/default/types.tsdiffbeforeafterboth
2461export 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}
24652466
2466/** @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}
24712473
2472/** @name UpDataStructsNestingPermissions */2474/** @name UpDataStructsNestingPermissions */
modifiedtests/src/interfaces/lookup.tsdiffbeforeafterboth
1502 **/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>
modifiedtests/src/interfaces/types-lookup.tsdiffbeforeafterboth
1629 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 }
16331634
1634 /** @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 }
16581660
1659 /** @name PalletUniqueSchedulerCall (204) */1661 /** @name PalletUniqueSchedulerCall (204) */
modifiedtests/src/interfaces/unique/definitions.tsdiffbeforeafterboth
63 [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 ),
92
93 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 ),
87103
88 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',
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
2import 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 });
2526
26 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});
2930
30 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 }
62
63 it('Makes sure collectionById supplies required fields for NFT', async () => {
64 await testMakeSureSuppliesRequired({type: 'NFT'});
60 });65 });
66
67 it('Makes sure collectionById supplies required fields for ReFungible', async () => {
68 await testMakeSureSuppliesRequired({type: 'ReFungible'});
69 });
61});70});
6271
63// ---------- COLLECTION PROPERTIES72// ---------- COLLECTION PROPERTIES
79 });88 });
80 });89 });
8190
91
82 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);
8696
87 // As owner97 // As owner
106 {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 });
110126
111 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 symbols
117 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 symbols
124 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 symbol
131 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 symbol
138 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 symbol
145 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 });
162184
163 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 properties
174 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 });
187215
188 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});
211245
212describe('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 process
242 {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 });
291
292 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});
341399
342// ---------- ACCESS RIGHTS400// ---------- ACCESS RIGHTS
357 });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});
409479
410describe('Negative Integration Test: Access Rights to Token Properties', () => {480describe('Negative Integration Test: Access Rights to Token Properties', () => {
415 });485 });
416 });486 });
417487
418 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 });
432508
433 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 });
455537
456 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 });
478566
479 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-string
504 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});
521615
522// ---------- TOKEN PROPERTIES616// ---------- TOKEN PROPERTIES
523617
524describe('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[]}[];
529620
530 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 owner
533 bob = privateKeyWrapper('//Bob');624 bob = privateKeyWrapper('//Bob'); // collection admin
534 charlie = privateKeyWrapper('//Charlie');625 charlie = privateKeyWrapper('//Charlie'); // token owner
535626
536 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 });
546
547 beforeEach(async () => {
548 await usingApi(async () => {
549 collection = await createCollectionExpectSuccess();
550 await setCollectionPermissionsExpectSuccess(alice, collection, {nesting: {tokenOwner: true}});
551
552 token = await createItemExpectSuccess(alice, collection, 'NFT');
553 nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, token)});
554
555 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 });
573657
574 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);
664
576 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 });
607702
608 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);
709
610 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 });
649755
650 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);
762
652 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 });
691808
692 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);
817
694 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) {
725849
726 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);
858
728 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) {
767898
768 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);
907
770 const propertyKeys: string[] = [];908 const propertyKeys: string[] = [];
771 let i = 0;909 let i = 0;
772910
832 });970 });
833 });971 });
834972
835 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 }
8641002
865 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 });
8891035
890 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 });
9141068
915 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);
1071
916 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 });
9401102
941 it('Forbids adding too many properties to a token', async () => {1103 async function testForbidsAddingTooManyProperties(mode: CollectionMode, pieces: number) {
1104 await prepare(mode, pieces);
1105
942 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 error
953 {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});
1147
1148describe('ReFungible token properties permissions tests', () => {
1149 let collection: number;
1150 let token: number;
1151
1152 before(async () => {
1153 await usingApi(async (api, privateKeyWrapper) => {
1154 alice = privateKeyWrapper('//Alice');
1155 bob = privateKeyWrapper('//Bob');
1156 charlie = privateKeyWrapper('//Charlie');
1157 });
1158 });
1159
1160 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);
1165
1166 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 });
1173
1174 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 });
1187
1188 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;
1203
1204 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 });
1215
1216 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;
1225
1226 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});
modifiedtests/src/refungible.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {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';
3440
35import 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 expect
63 // tslint:disable-next-line:no-unused-expression69 // tslint:disable-next-line:no-unused-expression
64 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 expect
103 // tslint:disable-next-line:no-unused-expression
104 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;
184226
185 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 });
231
232 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;
236
237 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 });
251
252 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;
256
257 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});
272
273describe('Test Refungible properties:', () => {
274 before(async () => {
275 await usingApi(async (api, privateKeyWrapper) => {
276 alice = privateKeyWrapper('//Alice');
277 bob = privateKeyWrapper('//Bob');
278 });
279 });
280
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});
modifiedtests/src/rpc.test.tsdiffbeforeafterboth
1import {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';
5
6let alice: IKeyringPair;
7let bob: IKeyringPair;
8
49
5describe('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 });
17
18
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);
46
47 // What to expect
48 // tslint:disable-next-line:no-unused-expression
49 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});
modifiedtests/src/util/helpers.tsdiffbeforeafterboth
103 collectionId: number;103 collectionId: number;
104 itemId: number;104 itemId: number;
105 recipient?: CrossAccountId;105 recipient?: CrossAccountId;
106 amount?: number;
106}107}
108
109interface DestroyItemResult {
110 success: boolean;
111 collectionId: number;
112 itemId: number;
113 owner: CrossAccountId;
114 amount: number;
115}
107116
108interface 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);
223233
224 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 };
230241
231 results.push(itemRes);242 results.push(itemRes);
255 return result;266 return result;
256}267}
268
269export 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);
277
278 const itemRes: DestroyItemResult = {
279 success: true,
280 collectionId,
281 itemId,
282 owner,
283 amount,
284 };
285
286 results.push(itemRes);
287 return results;
288 });
289
290 if (!genericResult.success) return [];
291 return results;
292}
257293
258export 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}
286322
287type CollectionMode = Nft | Fungible | ReFungible;323export type CollectionMode = Nft | Fungible | ReFungible;
288324
289export 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 }
14161452
1417 const events = await submitTransactionAsync(sender, tx);1453 const events = await executeTransaction(api, sender, tx);
1418 const result = getCreateItemResult(events);1454 const result = getCreateItemResult(events);
14191455
1420 const itemCountAfter = await getLastTokenId(api, collectionId);1456 const itemCountAfter = await getLastTokenId(api, collectionId);