difftreelog
feat Add `collection_admins` method to eth collection.
in: master
19 files changed
pallets/common/src/erc.rsdiffbeforeafterboth580580581 /// Get collection owner.581 /// Get collection owner.582 ///582 ///583 /// @return Tuble with sponsor address and his substrate mirror.583 /// @return Tuple with sponsor address and his substrate mirror.584 /// If address is canonical then substrate mirror is zero and vice versa.584 /// If address is canonical then substrate mirror is zero and vice versa.585 fn collection_owner(&self) -> Result<(address, uint256)> {585 fn collection_owner(&self) -> Result<(address, uint256)> {586 Ok(convert_cross_account_to_tuple::<T>(586 Ok(convert_cross_account_to_tuple::<T>(616 // .map_err(dispatch_to_evm::<T>)616 // .map_err(dispatch_to_evm::<T>)617 // }617 // }618618619 // TODO: need implement AbiWriter for &Vec<T>619 /// Get collection administrators620 // fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {620 ///621 // let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))621 /// @return Vector of tuples with admins address and his substrate mirror.622 // .map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))622 /// If address is canonical then substrate mirror is zero and vice versa.623 // .collect();623 fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {624 // Ok(result)624 let result = crate::IsAdmin::<T>::iter_prefix((self.id,))625 // }625 .map(|(admin, _)| crate::eth::convert_cross_account_to_tuple::<T>(&admin))626 .collect();627 Ok(result)628 }626}629}627630628/// ### Note631/// ### Notepallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth18}18}191920/// @title A contract that allows you to work with collections.20/// @title A contract that allows you to work with collections.21/// @dev the ERC-165 identifier for this interface is 0x62e2229021/// @dev the ERC-165 identifier for this interface is 0x3af103fb22contract Collection is Dummy, ERC165 {22contract Collection is Dummy, ERC165 {23 /// Set collection property.23 /// Set collection property.24 ///24 ///282282283 /// Get collection owner.283 /// Get collection owner.284 ///284 ///285 /// @return Tuble with sponsor address and his substrate mirror.285 /// @return Tuple with sponsor address and his substrate mirror.286 /// If address is canonical then substrate mirror is zero and vice versa.286 /// If address is canonical then substrate mirror is zero and vice versa.287 /// @dev EVM selector for this function is: 0xdf727d3b,287 /// @dev EVM selector for this function is: 0xdf727d3b,288 /// or in textual repr: collectionOwner()288 /// or in textual repr: collectionOwner()304 dummy = 0;304 dummy = 0;305 }305 }306307 /// Get collection administrators308 ///309 /// @return Vector of tuples with admins address and his substrate mirror.310 /// If address is canonical then substrate mirror is zero and vice versa.311 /// @dev EVM selector for this function is: 0x5813216b,312 /// or in textual repr: collectionAdmins()313 function collectionAdmins() public view returns (Tuple6[] memory) {314 require(false, stub_error);315 dummy;316 return new Tuple6[](0);317 }306}318}307319308/// @dev the ERC-165 identifier for this interface is 0x63034ac5320/// @dev the ERC-165 identifier for this interface is 0x63034ac5pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth91}91}929293/// @title A contract that allows you to work with collections.93/// @title A contract that allows you to work with collections.94/// @dev the ERC-165 identifier for this interface is 0x62e2229094/// @dev the ERC-165 identifier for this interface is 0x3af103fb95contract Collection is Dummy, ERC165 {95contract Collection is Dummy, ERC165 {96 /// Set collection property.96 /// Set collection property.97 ///97 ///355355356 /// Get collection owner.356 /// Get collection owner.357 ///357 ///358 /// @return Tuble with sponsor address and his substrate mirror.358 /// @return Tuple with sponsor address and his substrate mirror.359 /// If address is canonical then substrate mirror is zero and vice versa.359 /// If address is canonical then substrate mirror is zero and vice versa.360 /// @dev EVM selector for this function is: 0xdf727d3b,360 /// @dev EVM selector for this function is: 0xdf727d3b,361 /// or in textual repr: collectionOwner()361 /// or in textual repr: collectionOwner()377 dummy = 0;377 dummy = 0;378 }378 }379380 /// Get collection administrators381 ///382 /// @return Vector of tuples with admins address and his substrate mirror.383 /// If address is canonical then substrate mirror is zero and vice versa.384 /// @dev EVM selector for this function is: 0x5813216b,385 /// or in textual repr: collectionAdmins()386 function collectionAdmins() public view returns (Tuple17[] memory) {387 require(false, stub_error);388 dummy;389 return new Tuple17[](0);390 }379}391}380392381/// @dev anonymous struct393/// @dev anonymous structpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth91}91}929293/// @title A contract that allows you to work with collections.93/// @title A contract that allows you to work with collections.94/// @dev the ERC-165 identifier for this interface is 0x62e2229094/// @dev the ERC-165 identifier for this interface is 0x3af103fb95contract Collection is Dummy, ERC165 {95contract Collection is Dummy, ERC165 {96 /// Set collection property.96 /// Set collection property.97 ///97 ///355355356 /// Get collection owner.356 /// Get collection owner.357 ///357 ///358 /// @return Tuble with sponsor address and his substrate mirror.358 /// @return Tuple with sponsor address and his substrate mirror.359 /// If address is canonical then substrate mirror is zero and vice versa.359 /// If address is canonical then substrate mirror is zero and vice versa.360 /// @dev EVM selector for this function is: 0xdf727d3b,360 /// @dev EVM selector for this function is: 0xdf727d3b,361 /// or in textual repr: collectionOwner()361 /// or in textual repr: collectionOwner()377 dummy = 0;377 dummy = 0;378 }378 }379380 /// Get collection administrators381 ///382 /// @return Vector of tuples with admins address and his substrate mirror.383 /// If address is canonical then substrate mirror is zero and vice versa.384 /// @dev EVM selector for this function is: 0x5813216b,385 /// or in textual repr: collectionAdmins()386 function collectionAdmins() public view returns (Tuple17[] memory) {387 require(false, stub_error);388 dummy;389 return new Tuple17[](0);390 }379}391}380392381/// @dev anonymous struct393/// @dev anonymous structpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth13}13}141415/// @title A contract that allows you to work with collections.15/// @title A contract that allows you to work with collections.16/// @dev the ERC-165 identifier for this interface is 0x62e2229016/// @dev the ERC-165 identifier for this interface is 0x3af103fb17interface Collection is Dummy, ERC165 {17interface Collection is Dummy, ERC165 {18 /// Set collection property.18 /// Set collection property.19 ///19 ///184184185 /// Get collection owner.185 /// Get collection owner.186 ///186 ///187 /// @return Tuble with sponsor address and his substrate mirror.187 /// @return Tuple with sponsor address and his substrate mirror.188 /// If address is canonical then substrate mirror is zero and vice versa.188 /// If address is canonical then substrate mirror is zero and vice versa.189 /// @dev EVM selector for this function is: 0xdf727d3b,189 /// @dev EVM selector for this function is: 0xdf727d3b,190 /// or in textual repr: collectionOwner()190 /// or in textual repr: collectionOwner()198 /// or in textual repr: changeCollectionOwner(address)198 /// or in textual repr: changeCollectionOwner(address)199 function changeCollectionOwner(address newOwner) external;199 function changeCollectionOwner(address newOwner) external;200201 /// Get collection administrators202 ///203 /// @return Vector of tuples with admins address and his substrate mirror.204 /// If address is canonical then substrate mirror is zero and vice versa.205 /// @dev EVM selector for this function is: 0x5813216b,206 /// or in textual repr: collectionAdmins()207 function collectionAdmins() external view returns (Tuple6[] memory);200}208}201209202/// @dev the ERC-165 identifier for this interface is 0x63034ac5210/// @dev the ERC-165 identifier for this interface is 0x63034ac5tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth62}62}636364/// @title A contract that allows you to work with collections.64/// @title A contract that allows you to work with collections.65/// @dev the ERC-165 identifier for this interface is 0x62e2229065/// @dev the ERC-165 identifier for this interface is 0x3af103fb66interface Collection is Dummy, ERC165 {66interface Collection is Dummy, ERC165 {67 /// Set collection property.67 /// Set collection property.68 ///68 ///233233234 /// Get collection owner.234 /// Get collection owner.235 ///235 ///236 /// @return Tuble with sponsor address and his substrate mirror.236 /// @return Tuple with sponsor address and his substrate mirror.237 /// If address is canonical then substrate mirror is zero and vice versa.237 /// If address is canonical then substrate mirror is zero and vice versa.238 /// @dev EVM selector for this function is: 0xdf727d3b,238 /// @dev EVM selector for this function is: 0xdf727d3b,239 /// or in textual repr: collectionOwner()239 /// or in textual repr: collectionOwner()247 /// or in textual repr: changeCollectionOwner(address)247 /// or in textual repr: changeCollectionOwner(address)248 function changeCollectionOwner(address newOwner) external;248 function changeCollectionOwner(address newOwner) external;249250 /// Get collection administrators251 ///252 /// @return Vector of tuples with admins address and his substrate mirror.253 /// If address is canonical then substrate mirror is zero and vice versa.254 /// @dev EVM selector for this function is: 0x5813216b,255 /// or in textual repr: collectionAdmins()256 function collectionAdmins() external view returns (Tuple17[] memory);249}257}250258251/// @dev anonymous struct259/// @dev anonymous structtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth62}62}636364/// @title A contract that allows you to work with collections.64/// @title A contract that allows you to work with collections.65/// @dev the ERC-165 identifier for this interface is 0x62e2229065/// @dev the ERC-165 identifier for this interface is 0x3af103fb66interface Collection is Dummy, ERC165 {66interface Collection is Dummy, ERC165 {67 /// Set collection property.67 /// Set collection property.68 ///68 ///233233234 /// Get collection owner.234 /// Get collection owner.235 ///235 ///236 /// @return Tuble with sponsor address and his substrate mirror.236 /// @return Tuple with sponsor address and his substrate mirror.237 /// If address is canonical then substrate mirror is zero and vice versa.237 /// If address is canonical then substrate mirror is zero and vice versa.238 /// @dev EVM selector for this function is: 0xdf727d3b,238 /// @dev EVM selector for this function is: 0xdf727d3b,239 /// or in textual repr: collectionOwner()239 /// or in textual repr: collectionOwner()247 /// or in textual repr: changeCollectionOwner(address)247 /// or in textual repr: changeCollectionOwner(address)248 function changeCollectionOwner(address newOwner) external;248 function changeCollectionOwner(address newOwner) external;249250 /// Get collection administrators251 ///252 /// @return Vector of tuples with admins address and his substrate mirror.253 /// If address is canonical then substrate mirror is zero and vice versa.254 /// @dev EVM selector for this function is: 0x5813216b,255 /// or in textual repr: collectionAdmins()256 function collectionAdmins() external view returns (Tuple17[] memory);249}257}250258251/// @dev anonymous struct259/// @dev anonymous structtests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth14// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.14// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.151516import {IKeyringPair} from '@polkadot/types/types';16import {IKeyringPair} from '@polkadot/types/types';17import {IEthCrossAccountId} from '../util/playgrounds/types';17import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util';18import {usingEthPlaygrounds, itEth, expect, EthUniqueHelper} from './util';181919async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {20async function recordEthFee(helper: EthUniqueHelper, userAddress: string, call: () => Promise<any>) {73 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;75 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;74 });76 });7577 78 itEth.skip('Check adminlist', async ({helper}) => {79 const owner = await helper.eth.createAccountWithBalance(donor);80 81 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');82 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);83 84 const admin1 = helper.eth.createAccount();85 const [admin2] = await helper.arrange.createAccounts([10n], donor);86 await collectionEvm.methods.addCollectionAdmin(admin1).send();87 await collectionEvm.methods.addCollectionAdminSubstrate(admin2.addressRaw).send();8889 const adminListRpc = await helper.collection.getAdmins(collectionId);90 let adminListEth = await collectionEvm.methods.collectionAdmins().call();91 adminListEth = adminListEth.map((element: IEthCrossAccountId) => {92 return helper.address.convertCrossAccountFromEthCrossAcoount(element);93 });94 expect(adminListRpc).to.be.like(adminListEth);95 }); 96 76 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {97 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {77 const owner = await helper.eth.createAccountWithBalance(donor);98 const owner = await helper.eth.createAccountWithBalance(donor);tests/src/eth/fungibleAbi.jsondiffbeforeafterboth124 "stateMutability": "nonpayable",124 "stateMutability": "nonpayable",125 "type": "function"125 "type": "function"126 },126 },127 {128 "inputs": [],129 "name": "collectionAdmins",130 "outputs": [131 {132 "components": [133 { "internalType": "address", "name": "field_0", "type": "address" },134 { "internalType": "uint256", "name": "field_1", "type": "uint256" }135 ],136 "internalType": "struct Tuple6[]",137 "name": "",138 "type": "tuple[]"139 }140 ],141 "stateMutability": "view",142 "type": "function"143 },127 {144 {128 "inputs": [],145 "inputs": [],129 "name": "collectionOwner",146 "name": "collectionOwner",tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth154 "stateMutability": "nonpayable",154 "stateMutability": "nonpayable",155 "type": "function"155 "type": "function"156 },156 },157 {158 "inputs": [],159 "name": "collectionAdmins",160 "outputs": [161 {162 "components": [163 { "internalType": "address", "name": "field_0", "type": "address" },164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }165 ],166 "internalType": "struct Tuple17[]",167 "name": "",168 "type": "tuple[]"169 }170 ],171 "stateMutability": "view",172 "type": "function"173 },157 {174 {158 "inputs": [],175 "inputs": [],159 "name": "collectionOwner",176 "name": "collectionOwner",tests/src/eth/reFungibleAbi.jsondiffbeforeafterboth154 "stateMutability": "nonpayable",154 "stateMutability": "nonpayable",155 "type": "function"155 "type": "function"156 },156 },157 {158 "inputs": [],159 "name": "collectionAdmins",160 "outputs": [161 {162 "components": [163 { "internalType": "address", "name": "field_0", "type": "address" },164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }165 ],166 "internalType": "struct Tuple17[]",167 "name": "",168 "type": "tuple[]"169 }170 ],171 "stateMutability": "view",172 "type": "function"173 },157 {174 {158 "inputs": [],175 "inputs": [],159 "name": "collectionOwner",176 "name": "collectionOwner",tests/src/util/playgrounds/types.tsdiffbeforeafterboth70 ethereum?: TEthereumAccount;70 ethereum?: TEthereumAccount;71}71}7273export interface IEthCrossAccountId {74 0: TEthereumAccount;75 1: TSubstrateAccount;76 field_0: TEthereumAccount;77 field_1: TSubstrateAccount;78}727973export interface ICollectionLimits {80export interface ICollectionLimits {74 accountTokenOwnershipLimit?: number | null;81 accountTokenOwnershipLimit?: number | null;tests/src/util/playgrounds/unique.tsdiffbeforeafterboth778import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';8import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';11import {IKeyringPair} from '@polkadot/types/types';11import {IKeyringPair} from '@polkadot/types/types';12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, IForeignAssetMetadata, TNetworks, MoonbeamAssetInfo, DemocracyStandardAccountVote, AcalaAssetMetadata} from './types';12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, IForeignAssetMetadata, TNetworks, MoonbeamAssetInfo, DemocracyStandardAccountVote, AcalaAssetMetadata, IEthCrossAccountId} from './types';13import {hexToU8a} from '@polkadot/util/hex';14import {u8aConcat} from '@polkadot/util/u8a';131514export class CrossAccountId implements ICrossAccountId {16export class CrossAccountId implements ICrossAccountId {15 Substrate?: TSubstrateAccount;17 Substrate?: TSubstrateAccount;2310 return siblingPrefix + encodedParaId + suffix;2312 return siblingPrefix + encodedParaId + suffix;2311 }2313 }23142315 /**2316 * Encode key to substrate address2317 * @param key key for encoding address2318 * @param ss58Format prefix for encoding to the address of the corresponding network2319 * @returns encoded substrate address2320 */2321 encodeSubstrateAddress (key: Uint8Array | string | bigint, ss58Format = 42): string {2322 const u8a :Uint8Array = typeof key === 'string'2323 ? hexToU8a(key)2324 : typeof key === 'bigint'2325 ? hexToU8a(key.toString(16))2326 : key;2327 2328 if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) {2329 throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`);2330 }2331 2332 const allowedDecodedLengths = [1, 2, 4, 8, 32, 33];2333 if (!allowedDecodedLengths.includes(u8a.length)) {2334 throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(', ')}`);2335 }2336 2337 const u8aPrefix = ss58Format < 642338 ? new Uint8Array([ss58Format])2339 : new Uint8Array([2340 ((ss58Format & 0xfc) >> 2) | 0x40,2341 (ss58Format >> 8) | ((ss58Format & 0x03) << 6),2342 ]);23432344 const input = u8aConcat(u8aPrefix, u8a);2345 2346 return base58Encode(u8aConcat(2347 input,2348 blake2AsU8a(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1),2349 ));2350 }23512352 /**2353 * Restore substrate address from bigint representation2354 * @param number decimal representation of substrate address2355 * @returns substrate address2356 */2357 restoreCrossAccountFromBigInt(number: bigint): TSubstrateAccount {2358 if (this.helper.api === null) {2359 throw 'Not connected';2360 }2361 const res = this.helper.api.registry.createType('AccountId', '0x' + number.toString(16).padStart(64, '0')).toJSON();2362 if (res === undefined || res === null) {2363 throw 'Restore address error';2364 }2365 return res.toString();2366 }23672368 /**2369 * Convert etherium cross account id to substrate cross account id2370 * @param ethCrossAccount etherium cross account2371 * @returns substrate cross account id2372 */2373 convertCrossAccountFromEthCrossAcoount(ethCrossAccount: IEthCrossAccountId): ICrossAccountId {2374 if (ethCrossAccount.field_1 === '0') {2375 return {Ethereum: ethCrossAccount.field_0.toLocaleLowerCase()};2376 }2377 2378 const ss58 = this.restoreCrossAccountFromBigInt(BigInt(ethCrossAccount.field_1));2379 return {Substrate: ss58};2380 }2312}2381}231323822314class StakingGroup extends HelperGroup<UniqueHelper> {2383class StakingGroup extends HelperGroup<UniqueHelper> {