--- a/client/rpc/src/lib.rs +++ b/client/rpc/src/lib.rs @@ -248,8 +248,8 @@ ) -> Result>; /// Get whether an operator is approved by a given owner. - #[method(name = "unique_isApprovedForAll")] - fn is_approved_for_all( + #[method(name = "unique_allowanceForAll")] + fn allowance_for_all( &self, collection: CollectionId, owner: CrossAccountId, @@ -579,7 +579,7 @@ pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option, unique_api); pass_method!(total_pieces(collection_id: CollectionId, token_id: TokenId) -> Option => |o| o.map(|number| number.to_string()) , unique_api); pass_method!(token_owners(collection: CollectionId, token: TokenId) -> Vec, unique_api); - pass_method!(is_approved_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> bool, unique_api); + pass_method!(allowance_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> bool, unique_api); } impl --- a/pallets/common/src/lib.rs +++ b/pallets/common/src/lib.rs @@ -1535,7 +1535,7 @@ fn token_owner() -> Weight; /// The price of setting approval for all - fn set_approval_for_all() -> Weight; + fn set_allowance_for_all() -> Weight; } /// Weight info extension trait for refungible pallet. @@ -1844,11 +1844,11 @@ /// Get extension for RFT collection. fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions>; - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all tokens of the `owner` on their behalf. /// * `owner` - Token owner /// * `operator` - Operator /// * `approve` - Should operator status be granted or revoked? - fn set_approval_for_all( + fn set_allowance_for_all( &self, owner: T::CrossAccountId, operator: T::CrossAccountId, @@ -1856,7 +1856,7 @@ ) -> DispatchResultWithPostInfo; /// Tells whether the given `owner` approves the `operator`. - fn is_approved_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool; + fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool; } /// Extension for RFT collection. --- a/pallets/fungible/src/common.rs +++ b/pallets/fungible/src/common.rs @@ -108,7 +108,7 @@ Weight::zero() } - fn set_approval_for_all() -> Weight { + fn set_allowance_for_all() -> Weight { Weight::zero() } } @@ -429,7 +429,7 @@ >::try_get(self.id).ok() } - fn set_approval_for_all( + fn set_allowance_for_all( &self, _owner: T::CrossAccountId, _operator: T::CrossAccountId, @@ -438,7 +438,7 @@ fail!(>::SettingApprovalForAllNotAllowed) } - fn is_approved_for_all(&self, _owner: T::CrossAccountId, _operator: T::CrossAccountId) -> bool { + fn allowance_for_all(&self, _owner: T::CrossAccountId, _operator: T::CrossAccountId) -> bool { false } } --- a/pallets/nonfungible/src/benchmarking.rs +++ b/pallets/nonfungible/src/benchmarking.rs @@ -223,17 +223,17 @@ }: {collection.token_owner(item)} - set_approval_for_all { + set_allowance_for_all { bench_init!{ owner: sub; collection: collection(owner); operator: cross_from_sub(owner); owner: cross_sub; }; - }: {>::set_approval_for_all(&collection, &owner, &operator, true)} + }: {>::set_allowance_for_all(&collection, &owner, &operator, true)} - is_approved_for_all { + allowance_for_all { bench_init!{ owner: sub; collection: collection(owner); operator: cross_from_sub(owner); owner: cross_sub; }; - }: {>::is_approved_for_all(&collection, &owner, &operator)} + }: {>::allowance_for_all(&collection, &owner, &operator)} } --- a/pallets/nonfungible/src/common.rs +++ b/pallets/nonfungible/src/common.rs @@ -123,8 +123,8 @@ >::token_owner() } - fn set_approval_for_all() -> Weight { - >::set_approval_for_all() + fn set_allowance_for_all() -> Weight { + >::set_allowance_for_all() } } @@ -517,19 +517,19 @@ } } - fn set_approval_for_all( + fn set_allowance_for_all( &self, owner: T::CrossAccountId, operator: T::CrossAccountId, approve: bool, ) -> DispatchResultWithPostInfo { with_weight( - >::set_approval_for_all(self, &owner, &operator, approve), - >::set_approval_for_all(), + >::set_allowance_for_all(self, &owner, &operator, approve), + >::set_allowance_for_all(), ) } - fn is_approved_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool { - >::is_approved_for_all(self, &owner, &operator) + fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool { + >::allowance_for_all(self, &owner, &operator) } } --- a/pallets/nonfungible/src/erc.rs +++ b/pallets/nonfungible/src/erc.rs @@ -472,8 +472,8 @@ /// @notice Sets or unsets the approval of a given operator. /// The `operator` is allowed to transfer all tokens of the `caller` on their behalf. /// @param operator Operator - /// @param approved Is operator enabled or disabled - #[weight(>::set_approval_for_all())] + /// @param approved Should operator status be granted or revoked? + #[weight(>::set_allowance_for_all())] fn set_approval_for_all( &mut self, caller: caller, @@ -483,7 +483,7 @@ let caller = T::CrossAccountId::from_eth(caller); let operator = T::CrossAccountId::from_eth(operator); - >::set_approval_for_all(self, &caller, &operator, approved) + >::set_allowance_for_all(self, &caller, &operator, approved) .map_err(dispatch_to_evm::)?; Ok(()) } @@ -494,13 +494,13 @@ Err("not implemented".into()) } - /// @notice Tells whether an operator is approved by a given owner. - #[weight(>::is_approved_for_all())] + /// @notice Tells whether the given `owner` approves the `operator`. + #[weight(>::allowance_for_all())] fn is_approved_for_all(&self, owner: address, operator: address) -> Result { let owner = T::CrossAccountId::from_eth(owner); let operator = T::CrossAccountId::from_eth(operator); - Ok(>::is_approved_for_all(self, &owner, &operator)) + Ok(>::allowance_for_all(self, &owner, &operator)) } /// @notice Returns collection helper contract address --- a/pallets/nonfungible/src/lib.rs +++ b/pallets/nonfungible/src/lib.rs @@ -274,7 +274,7 @@ /// Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet. #[pallet::storage] - pub type WalletOperator = StorageNMap< + pub type CollectionAllowance = StorageNMap< Key = ( Key, Key, @@ -450,7 +450,7 @@ >::remove(id); let _ = >::clear_prefix((id,), u32::MAX, None); let _ = >::clear_prefix((id,), u32::MAX, None); - let _ = >::clear_prefix((id,), u32::MAX, None); + let _ = >::clear_prefix((id,), u32::MAX, None); Ok(()) } @@ -1206,7 +1206,7 @@ if >::get((collection.id, token)).as_ref() == Some(spender) { return Ok(()); } - if >::get((collection.id, from, spender)) == Some(true) { + if >::get((collection.id, from, spender)) { return Ok(()); } ensure!( @@ -1345,11 +1345,11 @@ /// Sets or unsets the approval of a given operator. /// - /// An operator is allowed to transfer all token pieces of the sender on their behalf. + /// The `operator` is allowed to transfer all token pieces of the `owner` on their behalf. /// - `owner`: Token owner /// - `operator`: Operator - /// - `approve`: Is operator enabled or disabled - pub fn set_approval_for_all( + /// - `approve`: Should operator status be granted or revoked? + pub fn set_allowance_for_all( collection: &NonfungibleHandle, owner: &T::CrossAccountId, operator: &T::CrossAccountId, @@ -1364,7 +1364,7 @@ // ========= - >::insert((collection.id, owner, operator), approve); + >::insert((collection.id, owner, operator), approve); >::deposit_log( ERC721Events::ApprovalForAll { owner: *owner.as_eth(), @@ -1382,12 +1382,12 @@ Ok(()) } - /// Tells whether an operator is approved by a given owner. - pub fn is_approved_for_all( + /// Tells whether the given `owner` approves the `operator`. + pub fn allowance_for_all( collection: &NonfungibleHandle, owner: &T::CrossAccountId, operator: &T::CrossAccountId, ) -> bool { - >::get((collection.id, owner, operator)).unwrap_or(false) + >::get((collection.id, owner, operator)) } } --- a/pallets/nonfungible/src/stubs/UniqueNFT.sol +++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol @@ -1021,9 +1021,9 @@ } /// @notice Sets or unsets the approval of a given operator. - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all tokens of the `caller` on their behalf. /// @param operator Operator - /// @param approved Is operator enabled or disabled + /// @param approved Should operator status be granted or revoked? /// @dev EVM selector for this function is: 0xa22cb465, /// or in textual repr: setApprovalForAll(address,bool) function setApprovalForAll(address operator, bool approved) public { @@ -1043,7 +1043,7 @@ return 0x0000000000000000000000000000000000000000; } - /// @notice Tells whether an operator is approved by a given owner. + /// @notice Tells whether the given `owner` approves the `operator`. /// @dev EVM selector for this function is: 0xe985e9c5, /// or in textual repr: isApprovedForAll(address,address) function isApprovedForAll(address owner, address operator) public view returns (bool) { --- a/pallets/nonfungible/src/weights.rs +++ b/pallets/nonfungible/src/weights.rs @@ -48,8 +48,8 @@ fn set_token_properties(b: u32, ) -> Weight; fn delete_token_properties(b: u32, ) -> Weight; fn token_owner() -> Weight; - fn set_approval_for_all() -> Weight; - fn is_approved_for_all() -> Weight; + fn set_allowance_for_all() -> Weight; + fn allowance_for_all() -> Weight; } /// Weights for pallet_nonfungible using the Substrate node and recommended hardware. @@ -199,12 +199,12 @@ .saturating_add(T::DbWeight::get().reads(1 as u64)) } // Storage: Nonfungible WalletOperator (r:0 w:1) - fn set_approval_for_all() -> Weight { + fn set_allowance_for_all() -> Weight { Weight::from_ref_time(16_231_000 as u64) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: Nonfungible WalletOperator (r:1 w:0) - fn is_approved_for_all() -> Weight { + fn allowance_for_all() -> Weight { Weight::from_ref_time(6_161_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) } @@ -356,12 +356,12 @@ .saturating_add(RocksDbWeight::get().reads(1 as u64)) } // Storage: Nonfungible WalletOperator (r:0 w:1) - fn set_approval_for_all() -> Weight { + fn set_allowance_for_all() -> Weight { Weight::from_ref_time(16_231_000 as u64) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } // Storage: Nonfungible WalletOperator (r:1 w:0) - fn is_approved_for_all() -> Weight { + fn allowance_for_all() -> Weight { Weight::from_ref_time(6_161_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) } --- a/pallets/refungible/src/benchmarking.rs +++ b/pallets/refungible/src/benchmarking.rs @@ -291,17 +291,17 @@ let item = create_max_item(&collection, &sender, [(owner.clone(), 100)])?; }: {>::token_owner(collection.id, item)} - set_approval_for_all { + set_allowance_for_all { bench_init!{ owner: sub; collection: collection(owner); operator: cross_from_sub(owner); owner: cross_sub; }; - }: {>::set_approval_for_all(&collection, &owner, &operator, true)} + }: {>::set_allowance_for_all(&collection, &owner, &operator, true)} - is_approved_for_all { + allowance_for_all { bench_init!{ owner: sub; collection: collection(owner); operator: cross_from_sub(owner); owner: cross_sub; }; - }: {>::is_approved_for_all(&collection, &owner, &operator)} + }: {>::allowance_for_all(&collection, &owner, &operator)} } --- a/pallets/refungible/src/common.rs +++ b/pallets/refungible/src/common.rs @@ -153,8 +153,8 @@ >::token_owner() } - fn set_approval_for_all() -> Weight { - >::set_approval_for_all() + fn set_allowance_for_all() -> Weight { + >::set_allowance_for_all() } } @@ -521,20 +521,20 @@ >::total_pieces(self.id, token) } - fn set_approval_for_all( + fn set_allowance_for_all( &self, owner: T::CrossAccountId, operator: T::CrossAccountId, approve: bool, ) -> DispatchResultWithPostInfo { with_weight( - >::set_approval_for_all(self, &owner, &operator, approve), - >::set_approval_for_all(), + >::set_allowance_for_all(self, &owner, &operator, approve), + >::set_allowance_for_all(), ) } - fn is_approved_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool { - >::is_approved_for_all(self, &owner, &operator) + fn allowance_for_all(&self, owner: T::CrossAccountId, operator: T::CrossAccountId) -> bool { + >::allowance_for_all(self, &owner, &operator) } } --- a/pallets/refungible/src/erc.rs +++ b/pallets/refungible/src/erc.rs @@ -462,10 +462,10 @@ } /// @notice Sets or unsets the approval of a given operator. - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all token pieces of the `caller` on their behalf. /// @param operator Operator - /// @param approved Is operator enabled or disabled - #[weight(>::set_approval_for_all())] + /// @param approved Should operator status be granted or revoked? + #[weight(>::set_allowance_for_all())] fn set_approval_for_all( &mut self, caller: caller, @@ -475,7 +475,7 @@ let caller = T::CrossAccountId::from_eth(caller); let operator = T::CrossAccountId::from_eth(operator); - >::set_approval_for_all(self, &caller, &operator, approved) + >::set_allowance_for_all(self, &caller, &operator, approved) .map_err(dispatch_to_evm::)?; Ok(()) } @@ -486,13 +486,13 @@ Err("not implemented".into()) } - /// @notice Tells whether an operator is approved by a given owner. - #[weight(>::is_approved_for_all())] + /// @notice Tells whether the given `owner` approves the `operator`. + #[weight(>::allowance_for_all())] fn is_approved_for_all(&self, owner: address, operator: address) -> Result { let owner = T::CrossAccountId::from_eth(owner); let operator = T::CrossAccountId::from_eth(operator); - Ok(>::is_approved_for_all(self, &owner, &operator)) + Ok(>::allowance_for_all(self, &owner, &operator)) } /// @notice Returns collection helper contract address --- a/pallets/refungible/src/lib.rs +++ b/pallets/refungible/src/lib.rs @@ -275,14 +275,14 @@ /// Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet. #[pallet::storage] - pub type WalletOperator = StorageNMap< + pub type CollectionAllowance = StorageNMap< Key = ( Key, Key, Key, ), Value = bool, - QueryKind = OptionQuery, + QueryKind = ValueQuery, >; #[pallet::hooks] @@ -1174,8 +1174,8 @@ let allowance = >::get((collection.id, token, from, &spender)).checked_sub(amount); - // Allowance if any would be reduced if spender is also wallet operator - if >::get((collection.id, from, spender)) == Some(true) { + // Allowance (if any) would be reduced if spender is also wallet operator + if >::get((collection.id, from, spender)) { return Ok(allowance); } @@ -1408,11 +1408,11 @@ /// Sets or unsets the approval of a given operator. /// - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all token pieces of the `owner` on their behalf. /// - `owner`: Token owner /// - `operator`: Operator - /// - `approve`: Is operator enabled or disabled - pub fn set_approval_for_all( + /// - `approve`: Should operator status be granted or revoked? + pub fn set_allowance_for_all( collection: &RefungibleHandle, owner: &T::CrossAccountId, operator: &T::CrossAccountId, @@ -1427,7 +1427,7 @@ // ========= - >::insert((collection.id, owner, operator), approve); + >::insert((collection.id, owner, operator), approve); >::deposit_log( ERC721Events::ApprovalForAll { owner: *owner.as_eth(), @@ -1445,12 +1445,12 @@ Ok(()) } - /// Tells whether an operator is approved by a given owner. - pub fn is_approved_for_all( + /// Tells whether the given `owner` approves the `operator`. + pub fn allowance_for_all( collection: &RefungibleHandle, owner: &T::CrossAccountId, operator: &T::CrossAccountId, ) -> bool { - >::get((collection.id, owner, operator)).unwrap_or(false) + >::get((collection.id, owner, operator)) } } --- a/pallets/refungible/src/stubs/UniqueRefungible.sol +++ b/pallets/refungible/src/stubs/UniqueRefungible.sol @@ -1018,9 +1018,9 @@ } /// @notice Sets or unsets the approval of a given operator. - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all token pieces of the `caller` on their behalf. /// @param operator Operator - /// @param approved Is operator enabled or disabled + /// @param approved Should operator status be granted or revoked? /// @dev EVM selector for this function is: 0xa22cb465, /// or in textual repr: setApprovalForAll(address,bool) function setApprovalForAll(address operator, bool approved) public { @@ -1040,7 +1040,7 @@ return 0x0000000000000000000000000000000000000000; } - /// @notice Tells whether an operator is approved by a given owner. + /// @notice Tells whether the given `owner` approves the `operator`. /// @dev EVM selector for this function is: 0xe985e9c5, /// or in textual repr: isApprovedForAll(address,address) function isApprovedForAll(address owner, address operator) public view returns (bool) { --- a/pallets/refungible/src/weights.rs +++ b/pallets/refungible/src/weights.rs @@ -55,8 +55,8 @@ fn delete_token_properties(b: u32, ) -> Weight; fn repartition_item() -> Weight; fn token_owner() -> Weight; - fn set_approval_for_all() -> Weight; - fn is_approved_for_all() -> Weight; + fn set_allowance_for_all() -> Weight; + fn allowance_for_all() -> Weight; } /// Weights for pallet_refungible using the Substrate node and recommended hardware. @@ -263,12 +263,12 @@ .saturating_add(T::DbWeight::get().reads(2 as u64)) } // Storage: Refungible WalletOperator (r:0 w:1) - fn set_approval_for_all() -> Weight { + fn set_allowance_for_all() -> Weight { Weight::from_ref_time(16_150_000 as u64) .saturating_add(T::DbWeight::get().writes(1 as u64)) } // Storage: Refungible WalletOperator (r:1 w:0) - fn is_approved_for_all() -> Weight { + fn allowance_for_all() -> Weight { Weight::from_ref_time(5_901_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) } @@ -477,12 +477,12 @@ .saturating_add(RocksDbWeight::get().reads(2 as u64)) } // Storage: Refungible WalletOperator (r:0 w:1) - fn set_approval_for_all() -> Weight { + fn set_allowance_for_all() -> Weight { Weight::from_ref_time(16_150_000 as u64) .saturating_add(RocksDbWeight::get().writes(1 as u64)) } // Storage: Refungible WalletOperator (r:1 w:0) - fn is_approved_for_all() -> Weight { + fn allowance_for_all() -> Weight { Weight::from_ref_time(5_901_000 as u64) .saturating_add(RocksDbWeight::get().reads(1 as u64)) } --- a/pallets/unique/src/eth/mod.rs +++ b/pallets/unique/src/eth/mod.rs @@ -36,7 +36,7 @@ use sp_std::vec; use up_data_structs::{ CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix, - CreateCollectionData, CollectionId, + CreateCollectionData, }; use crate::{weights::WeightInfo, Config, SelfWeightOf}; --- a/pallets/unique/src/lib.rs +++ b/pallets/unique/src/lib.rs @@ -1129,15 +1129,15 @@ /// Sets or unsets the approval of a given operator. /// - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all tokens of the `owner` on their behalf. /// /// # Arguments /// /// * `owner`: Token owner /// * `operator`: Operator - /// * `approve`: Is operator enabled or disabled - #[weight = T::CommonWeightInfo::set_approval_for_all()] - pub fn set_approval_for_all( + /// * `approve`: Should operator status be granted or revoked? + #[weight = T::CommonWeightInfo::set_allowance_for_all()] + pub fn set_allowance_for_all( origin, collection_id: CollectionId, operator: T::CrossAccountId, @@ -1145,7 +1145,7 @@ ) -> DispatchResultWithPostInfo { let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); dispatch_tx::(collection_id, |d| { - d.set_approval_for_all(sender, operator, approve) + d.set_allowance_for_all(sender, operator, approve) }) } } --- a/primitives/rpc/src/lib.rs +++ b/primitives/rpc/src/lib.rs @@ -134,6 +134,6 @@ fn token_owners(collection: CollectionId, token: TokenId) -> Result>; /// Get whether an operator is approved by a given owner. - fn is_approved_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> Result; + fn allowance_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> Result; } } --- a/runtime/common/runtime_apis.rs +++ b/runtime/common/runtime_apis.rs @@ -188,8 +188,8 @@ dispatch_unique_runtime!(collection.total_pieces(token_id)) } - fn is_approved_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> Result { - dispatch_unique_runtime!(collection.is_approved_for_all(owner, operator)) + fn allowance_for_all(collection: CollectionId, owner: CrossAccountId, operator: CrossAccountId) -> Result { + dispatch_unique_runtime!(collection.allowance_for_all(owner, operator)) } } --- a/runtime/common/weights.rs +++ b/runtime/common/weights.rs @@ -121,8 +121,8 @@ max_weight_of!(token_owner()) } - fn set_approval_for_all() -> Weight { - max_weight_of!(set_approval_for_all()) + fn set_allowance_for_all() -> Weight { + max_weight_of!(set_allowance_for_all()) } } --- a/tests/src/approve.test.ts +++ b/tests/src/approve.test.ts @@ -617,26 +617,31 @@ itSub('[nft] Enable and disable approval', async ({helper}) => { const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}); - await helper.nft.mintToken(alice, {collectionId: collectionId, owner: alice.address}); - const checkBeforeApproval = await helper.nft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); + + const checkBeforeApproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); expect(checkBeforeApproval).to.be.false; - await helper.nft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, true); - const checkAfterApproval = await helper.nft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); + + await helper.nft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, true); + const checkAfterApproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); expect(checkAfterApproval).to.be.true; - await helper.nft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, false); - const checkAfterDisapproval = await helper.nft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); + + await helper.nft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, false); + const checkAfterDisapproval = await helper.nft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); expect(checkAfterDisapproval).to.be.false; }); itSub.ifWithPallets('[rft] Enable and disable approval', [Pallets.ReFungible], async ({helper}) => { const {collectionId} = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}); - const checkBeforeApproval = await helper.rft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); + + const checkBeforeApproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); expect(checkBeforeApproval).to.be.false; - await helper.rft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, true); - const checkAfterApproval = await helper.rft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); + + await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, true); + const checkAfterApproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); expect(checkAfterApproval).to.be.true; - await helper.rft.setApprovalForAll(alice, collectionId, {Substrate: bob.address}, false); - const checkAfterDisapproval = await helper.rft.isApprovedForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); + + await helper.rft.setAllowanceForAll(alice, collectionId, {Substrate: bob.address}, false); + const checkAfterDisapproval = await helper.rft.allowanceForAll(collectionId, {Substrate: alice.address}, {Substrate: bob.address}); expect(checkAfterDisapproval).to.be.false; }); }); --- a/tests/src/eth/api/UniqueNFT.sol +++ b/tests/src/eth/api/UniqueNFT.sol @@ -672,9 +672,9 @@ function approve(address approved, uint256 tokenId) external; /// @notice Sets or unsets the approval of a given operator. - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all tokens of the `caller` on their behalf. /// @param operator Operator - /// @param approved Is operator enabled or disabled + /// @param approved Should operator status be granted or revoked? /// @dev EVM selector for this function is: 0xa22cb465, /// or in textual repr: setApprovalForAll(address,bool) function setApprovalForAll(address operator, bool approved) external; @@ -684,7 +684,7 @@ /// or in textual repr: getApproved(uint256) function getApproved(uint256 tokenId) external view returns (address); - /// @notice Tells whether an operator is approved by a given owner. + /// @notice Tells whether the given `owner` approves the `operator`. /// @dev EVM selector for this function is: 0xe985e9c5, /// or in textual repr: isApprovedForAll(address,address) function isApprovedForAll(address owner, address operator) external view returns (bool); --- a/tests/src/eth/api/UniqueRefungible.sol +++ b/tests/src/eth/api/UniqueRefungible.sol @@ -669,9 +669,9 @@ function approve(address approved, uint256 tokenId) external; /// @notice Sets or unsets the approval of a given operator. - /// An operator is allowed to transfer all tokens of the sender on their behalf. + /// The `operator` is allowed to transfer all token pieces of the `caller` on their behalf. /// @param operator Operator - /// @param approved Is operator enabled or disabled + /// @param approved Should operator status be granted or revoked? /// @dev EVM selector for this function is: 0xa22cb465, /// or in textual repr: setApprovalForAll(address,bool) function setApprovalForAll(address operator, bool approved) external; @@ -681,7 +681,7 @@ /// or in textual repr: getApproved(uint256) function getApproved(uint256 tokenId) external view returns (address); - /// @notice Tells whether an operator is approved by a given owner. + /// @notice Tells whether the given `owner` approves the `operator`. /// @dev EVM selector for this function is: 0xe985e9c5, /// or in textual repr: isApprovedForAll(address,address) function isApprovedForAll(address owner, address operator) external view returns (bool); --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -935,48 +935,54 @@ let donor: IKeyringPair; let minter: IKeyringPair; let alice: IKeyringPair; - let bob: IKeyringPair; before(async function() { await usingEthPlaygrounds(async (helper, privateKey) => { donor = await privateKey({filename: __filename}); - [minter, alice, bob] = await helper.arrange.createAccounts([100n, 100n, 100n], donor); + [minter, alice] = await helper.arrange.createAccounts([100n, 100n], donor); }); }); itEth('[negative] Cant perform burn without approval', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); - const owner = bob; + const owner = await helper.eth.createAccountWithBalance(donor, 100n); const spender = await helper.eth.createAccountWithBalance(donor, 100n); - const token = await collection.mintToken(minter, {Substrate: owner.address}); + const token = await collection.mintToken(minter, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); const contract = helper.ethNativeContract.collection(address, 'nft'); - { - const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner); - await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected; - } + const ownerCross = helper.ethCrossAccount.fromAddress(owner); + await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected; + + await contract.methods.setApprovalForAll(spender, true).send({from: owner}); + await contract.methods.setApprovalForAll(spender, false).send({from: owner}); + + await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected; }); itEth('[negative] Cant perform transfer without approval', async ({helper}) => { const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'}); - const owner = bob; const receiver = alice; + const owner = await helper.eth.createAccountWithBalance(donor, 100n); const spender = await helper.eth.createAccountWithBalance(donor, 100n); - const token = await collection.mintToken(minter, {Substrate: owner.address}); + const token = await collection.mintToken(minter, {Ethereum: owner}); const address = helper.ethAddress.fromCollectionId(collection.collectionId); const contract = helper.ethNativeContract.collection(address, 'nft'); - { - const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner); - const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver); - await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; - } + const ownerCross = helper.ethCrossAccount.fromAddress(owner); + const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver); + + await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; + + await contract.methods.setApprovalForAll(spender, true).send({from: owner}); + await contract.methods.setApprovalForAll(spender, false).send({from: owner}); + + await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; }); }); --- a/tests/src/eth/reFungible.test.ts +++ b/tests/src/eth/reFungible.test.ts @@ -750,10 +750,14 @@ const address = helper.ethAddress.fromCollectionId(collection.collectionId); const contract = helper.ethNativeContract.collection(address, 'rft'); - { - const ownerCross = helper.ethCrossAccount.fromAddress(owner); - await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected; - } + const ownerCross = helper.ethCrossAccount.fromAddress(owner); + + await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected; + + await contract.methods.setApprovalForAll(spender, true).send({from: owner}); + await contract.methods.setApprovalForAll(spender, false).send({from: owner}); + + await expect(contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender})).to.be.rejected; }); itEth('[negative] Cant perform transfer without approval', async ({helper}) => { @@ -768,10 +772,14 @@ const address = helper.ethAddress.fromCollectionId(collection.collectionId); const contract = helper.ethNativeContract.collection(address, 'rft'); - { - const ownerCross = helper.ethCrossAccount.fromAddress(owner); - const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver); - await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; - } + const ownerCross = helper.ethCrossAccount.fromAddress(owner); + const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver); + + await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; + + await contract.methods.setApprovalForAll(spender, true).send({from: owner}); + await contract.methods.setApprovalForAll(spender, false).send({from: owner}); + + await expect(contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender})).to.be.rejected; }); }); --- a/tests/src/interfaces/augment-api-events.ts +++ b/tests/src/interfaces/augment-api-events.ts @@ -107,7 +107,7 @@ **/ Approved: AugmentedEvent; /** - * Amount pieces of token owned by `sender` was approved for `spender`. + * A `sender` approves operations on all owned tokens for `spender`. **/ ApprovedForAll: AugmentedEvent; /** --- a/tests/src/interfaces/augment-api-query.ts +++ b/tests/src/interfaces/augment-api-query.ts @@ -406,6 +406,10 @@ **/ allowance: AugmentedQuery Observable>, [u32, u32]> & QueryableStorageEntry; /** + * Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet. + **/ + collectionAllowance: AugmentedQuery Observable, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry; + /** * Used to enumerate tokens owned by account. **/ owned: AugmentedQuery Observable, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry; @@ -441,10 +445,6 @@ * Total amount of minted tokens in a collection. **/ tokensMinted: AugmentedQuery Observable, [u32]> & QueryableStorageEntry; - /** - * Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet. - **/ - walletOperator: AugmentedQuery Observable>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry; /** * Generic query **/ @@ -625,6 +625,10 @@ **/ balance: AugmentedQuery Observable, [u32, u32, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry; /** + * Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet. + **/ + collectionAllowance: AugmentedQuery Observable, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry; + /** * Used to enumerate tokens owned by account. **/ owned: AugmentedQuery Observable, [u32, PalletEvmAccountBasicCrossAccountIdRepr, u32]> & QueryableStorageEntry; @@ -648,10 +652,6 @@ * Total amount of pieces for token **/ totalSupply: AugmentedQuery Observable, [u32, u32]> & QueryableStorageEntry; - /** - * Operator set by a wallet owner that could perform certain transactions on all tokens in the wallet. - **/ - walletOperator: AugmentedQuery Observable>, [u32, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmAccountBasicCrossAccountIdRepr]> & QueryableStorageEntry; /** * Generic query **/ --- a/tests/src/interfaces/augment-api-rpc.ts +++ b/tests/src/interfaces/augment-api-rpc.ts @@ -684,6 +684,10 @@ **/ allowance: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, sender: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, spender: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, tokenId: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable>; /** + * Tells whether the given `owner` approves the `operator`. + **/ + allowanceForAll: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, owner: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, operator: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>>; + /** * Check if a user is allowed to operate within a collection **/ allowed: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, account: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>; @@ -719,10 +723,6 @@ * Get effective collection limits **/ effectiveCollectionLimits: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, at?: Hash | string | Uint8Array) => Observable>>; - /** - * Tells whether an operator is approved by a given owner. - **/ - isApprovedForAll: AugmentedRpc<(collection: u32 | AnyNumber | Uint8Array, owner: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, operator: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, at?: Hash | string | Uint8Array) => Observable>>; /** * Get the last token ID created in a collection **/ --- a/tests/src/interfaces/augment-api-tx.ts +++ b/tests/src/interfaces/augment-api-tx.ts @@ -1547,15 +1547,15 @@ /** * Sets or unsets the approval of a given operator. * - * An operator is allowed to transfer all tokens of the sender on their behalf. + * The `operator` is allowed to transfer all tokens of the `owner` on their behalf. * * # Arguments * * * `owner`: Token owner * * `operator`: Operator - * * `approve`: Is operator enabled or disabled + * * `approve`: Should operator status be granted or revoked? **/ - setApprovalForAll: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, operator: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, approve: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u32, PalletEvmAccountBasicCrossAccountIdRepr, bool]>; + setAllowanceForAll: AugmentedSubmittable<(collectionId: u32 | AnyNumber | Uint8Array, operator: PalletEvmAccountBasicCrossAccountIdRepr | { Substrate: any } | { Ethereum: any } | string | Uint8Array, approve: bool | boolean | Uint8Array) => SubmittableExtrinsic, [u32, PalletEvmAccountBasicCrossAccountIdRepr, bool]>; /** * Set specific limits of a collection. Empty, or None fields mean chain default. * --- a/tests/src/interfaces/default/types.ts +++ b/tests/src/interfaces/default/types.ts @@ -2312,13 +2312,13 @@ readonly tokenId: u32; readonly amount: u128; } & Struct; - readonly isSetApprovalForAll: boolean; - readonly asSetApprovalForAll: { + readonly isSetAllowanceForAll: boolean; + readonly asSetAllowanceForAll: { readonly collectionId: u32; readonly operator: PalletEvmAccountBasicCrossAccountIdRepr; readonly approve: bool; } & Struct; - readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetApprovalForAll'; + readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll'; } /** @name PalletUniqueError */ --- a/tests/src/interfaces/lookup.ts +++ b/tests/src/interfaces/lookup.ts @@ -2305,7 +2305,7 @@ tokenId: 'u32', amount: 'u128', }, - set_approval_for_all: { + set_allowance_for_all: { collectionId: 'u32', operator: 'PalletEvmAccountBasicCrossAccountIdRepr', approve: 'bool' --- a/tests/src/interfaces/types-lookup.ts +++ b/tests/src/interfaces/types-lookup.ts @@ -2541,13 +2541,13 @@ readonly tokenId: u32; readonly amount: u128; } & Struct; - readonly isSetApprovalForAll: boolean; - readonly asSetApprovalForAll: { + readonly isSetAllowanceForAll: boolean; + readonly asSetAllowanceForAll: { readonly collectionId: u32; readonly operator: PalletEvmAccountBasicCrossAccountIdRepr; readonly approve: bool; } & Struct; - readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetApprovalForAll'; + readonly type: 'CreateCollection' | 'CreateCollectionEx' | 'DestroyCollection' | 'AddToAllowList' | 'RemoveFromAllowList' | 'ChangeCollectionOwner' | 'AddCollectionAdmin' | 'RemoveCollectionAdmin' | 'SetCollectionSponsor' | 'ConfirmSponsorship' | 'RemoveCollectionSponsor' | 'CreateItem' | 'CreateMultipleItems' | 'SetCollectionProperties' | 'DeleteCollectionProperties' | 'SetTokenProperties' | 'DeleteTokenProperties' | 'SetTokenPropertyPermissions' | 'CreateMultipleItemsEx' | 'SetTransfersEnabledFlag' | 'BurnItem' | 'BurnFrom' | 'Transfer' | 'Approve' | 'TransferFrom' | 'SetCollectionLimits' | 'SetCollectionPermissions' | 'Repartition' | 'SetAllowanceForAll'; } /** @name UpDataStructsCollectionMode (240) */ --- a/tests/src/interfaces/unique/definitions.ts +++ b/tests/src/interfaces/unique/definitions.ts @@ -175,8 +175,8 @@ [collectionParam, tokenParam], 'Option', ), - isApprovedForAll: fun( - 'Tells whether an operator is approved by a given owner.', + allowanceForAll: fun( + 'Tells whether the given `owner` approves the `operator`.', [collectionParam, crossAccountParam('owner'), crossAccountParam('operator')], 'Option', ), --- a/tests/src/util/playgrounds/unique.ts +++ b/tests/src/util/playgrounds/unique.ts @@ -1415,26 +1415,26 @@ } /** - * Tells whether an operator is approved by a given owner. + * Tells whether the given `owner` approves the `operator`. * @param collectionId ID of collection * @param owner owner address - * @param operator operator addrees + * @param operator operator addrees * @returns true if operator is enabled */ - async isApprovedForAll(collectionId: number, owner: ICrossAccountId, operator: ICrossAccountId): Promise { - return (await this.helper.callRpc('api.rpc.unique.isApprovedForAll', [collectionId, owner, operator])).toJSON(); + async allowanceForAll(collectionId: number, owner: ICrossAccountId, operator: ICrossAccountId): Promise { + return (await this.helper.callRpc('api.rpc.unique.allowanceForAll', [collectionId, owner, operator])).toJSON(); } /** Sets or unsets the approval of a given operator. - * An operator is allowed to transfer all tokens of the sender on their behalf. - * @param operator Operator - * @param approved Is operator enabled or disabled + * The `operator` is allowed to transfer all tokens of the `caller` on their behalf. + * @param operator Operator + * @param approved Should operator status be granted or revoked? * @returns ```true``` if extrinsic success, otherwise ```false``` */ - async setApprovalForAll(signer: TSigner, collectionId: number, operator: ICrossAccountId, approved: boolean): Promise { + async setAllowanceForAll(signer: TSigner, collectionId: number, operator: ICrossAccountId, approved: boolean): Promise { const result = await this.helper.executeExtrinsic( signer, - 'api.tx.unique.setApprovalForAll', [collectionId, operator, approved], + 'api.tx.unique.setAllowanceForAll', [collectionId, operator, approved], true, ); return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'ApprovedForAll');