1234567891011121314151617import {itEth, usingEthPlaygrounds, expect} from './util';18import {IKeyringPair} from '@polkadot/types/types';19import {ITokenPropertyPermission} from '../util/playgrounds/types';20import {Pallets} from '../util';2122describe('EVM token properties', () => {23 let donor: IKeyringPair;24 let alice: IKeyringPair;2526 before(async function() {27 await usingEthPlaygrounds(async (helper, privateKey) => {28 donor = await privateKey({filename: __filename});29 [alice] = await helper.arrange.createAccounts([100n], donor);30 });31 });3233 itEth('Can be reconfigured', async({helper}) => {34 const caller = await helper.eth.createAccountWithBalance(donor);35 for(const [mutable,collectionAdmin, tokenOwner] of cartesian([], [false, true], [false, true], [false, true])) {36 const collection = await helper.nft.mintCollection(alice);37 await collection.addAdmin(alice, {Ethereum: caller});38 39 const address = helper.ethAddress.fromCollectionId(collection.collectionId);40 const contract = helper.ethNativeContract.collection(address, 'nft', caller);41 42 await contract.methods.setTokenPropertyPermission('testKey', mutable, collectionAdmin, tokenOwner).send({from: caller});43 44 expect(await collection.getPropertyPermissions()).to.be.deep.equal([{45 key: 'testKey',46 permission: {mutable, collectionAdmin, tokenOwner},47 }]);48 }49 });5051 itEth('Can be set', async({helper}) => {52 const caller = await helper.eth.createAccountWithBalance(donor);53 const collection = await helper.nft.mintCollection(alice, {54 tokenPropertyPermissions: [{55 key: 'testKey',56 permission: {57 collectionAdmin: true,58 },59 }],60 });61 const token = await collection.mintToken(alice);6263 await collection.addAdmin(alice, {Ethereum: caller});6465 const address = helper.ethAddress.fromCollectionId(collection.collectionId);66 const contract = helper.ethNativeContract.collection(address, 'nft', caller);6768 await contract.methods.setProperties(token.tokenId, [{key: 'testKey', value: Buffer.from('testValue')}]).send({from: caller});6970 const [{value}] = await token.getProperties(['testKey']);71 expect(value).to.equal('testValue');72 });7374 75 itEth('Property can be set', async({helper}) => {76 const caller = await helper.eth.createAccountWithBalance(donor);77 const collection = await helper.nft.mintCollection(alice, {78 tokenPropertyPermissions: [{79 key: 'testKey',80 permission: {81 collectionAdmin: true,82 },83 }],84 });85 const token = await collection.mintToken(alice);8687 await collection.addAdmin(alice, {Ethereum: caller});8889 const address = helper.ethAddress.fromCollectionId(collection.collectionId);90 const contract = helper.ethNativeContract.collection(address, 'nft', caller, true);9192 await contract.methods.setProperty(token.tokenId, 'testKey', Buffer.from('testValue')).send({from: caller});9394 const [{value}] = await token.getProperties(['testKey']);95 expect(value).to.equal('testValue');96 });97 98 itEth('Can be multiple set for NFT ', async({helper}) => {99 const caller = await helper.eth.createAccountWithBalance(donor);100 101 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });102 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true,103 collectionAdmin: true,104 mutable: true}}; });105 106 const collection = await helper.nft.mintCollection(alice, {107 tokenPrefix: 'ethp',108 tokenPropertyPermissions: permissions,109 });110 111 const token = await collection.mintToken(alice);112 113 const valuesBefore = await token.getProperties(properties.map(p => p.key));114 expect(valuesBefore).to.be.deep.equal([]);115 116 await collection.addAdmin(alice, {Ethereum: caller});117118 const address = helper.ethAddress.fromCollectionId(collection.collectionId);119 const contract = helper.ethNativeContract.collection(address, 'nft', caller);120121 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});122123 const values = await token.getProperties(properties.map(p => p.key));124 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; }));125 });126 127 itEth.ifWithPallets('Can be multiple set for RFT ', [Pallets.ReFungible], async({helper}) => {128 const caller = await helper.eth.createAccountWithBalance(donor);129 130 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });131 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true,132 collectionAdmin: true,133 mutable: true}}; });134 135 const collection = await helper.rft.mintCollection(alice, {136 tokenPrefix: 'ethp',137 tokenPropertyPermissions: permissions,138 });139 140 const token = await collection.mintToken(alice);141 142 const valuesBefore = await token.getProperties(properties.map(p => p.key));143 expect(valuesBefore).to.be.deep.equal([]);144 145 await collection.addAdmin(alice, {Ethereum: caller});146147 const address = helper.ethAddress.fromCollectionId(collection.collectionId);148 const contract = helper.ethNativeContract.collection(address, 'rft', caller);149150 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});151152 const values = await token.getProperties(properties.map(p => p.key));153 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; }));154 });155156 itEth('Can be deleted', async({helper}) => {157 const caller = await helper.eth.createAccountWithBalance(donor);158 const collection = await helper.nft.mintCollection(alice, {159 tokenPropertyPermissions: [{160 key: 'testKey',161 permission: {162 mutable: true,163 collectionAdmin: true,164 },165 },166 {167 key: 'testKey_1',168 permission: {169 mutable: true,170 collectionAdmin: true,171 },172 }],173 });174 175 const token = await collection.mintToken(alice);176 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}, {key: 'testKey_1', value: 'testValue_1'}]);177178 await collection.addAdmin(alice, {Ethereum: caller});179180 const address = helper.ethAddress.fromCollectionId(collection.collectionId);181 const contract = helper.ethNativeContract.collection(address, 'nft', caller);182183 await contract.methods.deleteProperties(token.tokenId, ['testKey', 'testKey_1']).send({from: caller});184185 const result = await token.getProperties(['testKey']);186 expect(result.length).to.equal(0);187 });188189 itEth('Can be read', async({helper}) => {190 const caller = helper.eth.createAccount();191 const collection = await helper.nft.mintCollection(alice, {192 tokenPropertyPermissions: [{193 key: 'testKey',194 permission: {195 collectionAdmin: true,196 },197 }],198 });199 200 const token = await collection.mintToken(alice);201 await token.setProperties(alice, [{key: 'testKey', value: 'testValue'}]);202203 const address = helper.ethAddress.fromCollectionId(collection.collectionId);204 const contract = helper.ethNativeContract.collection(address, 'nft', caller);205206 const value = await contract.methods.property(token.tokenId, 'testKey').call();207 expect(value).to.equal(helper.getWeb3().utils.toHex('testValue'));208 });209});210211212type ElementOf<A> = A extends readonly (infer T)[] ? T : never;213function* cartesian<T extends Array<Array<any>>, R extends Array<any>>(internalRest: [...R], ...args: [...T]): Generator<[...R, ...{[K in keyof T]: ElementOf<T[K]>}]> {214 if(args.length === 0) {215 yield internalRest as any;216 return;217 }218 for(const value of args[0]) {219 yield* cartesian([...internalRest, value], ...args.slice(1)) as any;220 }221}