From d6d6d43b7721ec8ed8029a0f308928e0952343e4 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Fri, 23 Dec 2022 09:24:21 +0000 Subject: [PATCH] Merge pull request #802 from UniqueNetwork/tests/eth-helpers --- --- a/tests/.eslintrc.json +++ b/tests/.eslintrc.json @@ -18,6 +18,9 @@ "mocha" ], "rules": { + "@typescript-eslint/no-floating-promises": [ + "error" + ], "indent": [ "error", 2, --- a/tests/package.json +++ b/tests/package.json @@ -11,8 +11,8 @@ "@types/chai-subset": "^1.3.3", "@types/mocha": "^10.0.0", "@types/node": "^18.11.2", - "@typescript-eslint/eslint-plugin": "^5.40.1", - "@typescript-eslint/parser": "^5.40.1", + "@typescript-eslint/eslint-plugin": "^5.47.0", + "@typescript-eslint/parser": "^5.47.0", "chai": "^4.3.6", "chai-subset": "^1.6.0", "eslint": "^8.25.0", --- a/tests/src/apiConsts.test.ts +++ b/tests/src/apiConsts.test.ts @@ -46,33 +46,33 @@ describe('integration test: API UNIQUE consts', () => { let api: ApiPromise; - + before(async () => { await usingPlaygrounds(async (helper) => { api = await helper.getApi(); }); }); - + itSub('DEFAULT_NFT_COLLECTION_LIMITS', () => { expect(api.consts.unique.nftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT); }); - + itSub('DEFAULT_RFT_COLLECTION_LIMITS', () => { expect(api.consts.unique.rftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT); }); - + itSub('DEFAULT_FT_COLLECTION_LIMITS', () => { expect(api.consts.unique.ftDefaultCollectionLimits.toHuman()).to.deep.equal(DEFAULT_COLLETCTION_LIMIT); }); - + itSub('MAX_COLLECTION_NAME_LENGTH', () => { checkConst(api.consts.unique.maxCollectionNameLength, MAX_COLLECTION_NAME_LENGTH); }); - + itSub('MAX_COLLECTION_DESCRIPTION_LENGTH', () => { checkConst(api.consts.unique.maxCollectionDescriptionLength, MAX_COLLECTION_DESCRIPTION_LENGTH); }); - + itSub('MAX_COLLECTION_PROPERTIES_SIZE', () => { checkConst(api.consts.unique.maxCollectionPropertiesSize, MAX_COLLECTION_PROPERTIES_SIZE); }); @@ -84,31 +84,31 @@ itSub('MAX_PROPERTY_KEY_LENGTH', () => { checkConst(api.consts.unique.maxPropertyKeyLength, MAX_PROPERTY_KEY_LENGTH); }); - + itSub('MAX_PROPERTY_VALUE_LENGTH', () => { checkConst(api.consts.unique.maxPropertyValueLength, MAX_PROPERTY_VALUE_LENGTH); }); - + itSub('MAX_PROPERTIES_PER_ITEM', () => { checkConst(api.consts.unique.maxPropertiesPerItem, MAX_PROPERTIES_PER_ITEM); }); - + itSub('NESTING_BUDGET', () => { checkConst(api.consts.unique.nestingBudget, NESTING_BUDGET); }); - + itSub('MAX_TOKEN_PROPERTIES_SIZE', () => { checkConst(api.consts.unique.maxTokenPropertiesSize, MAX_TOKEN_PROPERTIES_SIZE); }); - + itSub('COLLECTION_ADMINS_LIMIT', () => { checkConst(api.consts.unique.collectionAdminsLimit, COLLECTION_ADMINS_LIMIT); }); - + itSub('HELPERS_CONTRACT_ADDRESS', () => { expect(api.consts.evmContractHelpers.contractAddress.toString().toLowerCase()).to.be.equal(HELPERS_CONTRACT_ADDRESS.toLowerCase()); }); - + itSub('EVM_COLLECTION_HELPERS_ADDRESS', () => { expect(api.consts.common.contractAddress.toString().toLowerCase()).to.be.equal(EVM_COLLECTION_HELPERS_ADDRESS.toLowerCase()); }); --- a/tests/src/app-promotion.seqtest.ts +++ b/tests/src/app-promotion.seqtest.ts @@ -50,31 +50,31 @@ await expect(helper.signTransaction(nonAdmin, api.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address}))).to.be.rejected; await expect(helper.signTransaction(nonAdmin, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: nonAdmin.address})))).to.be.rejected; }); - + itSub('can be any valid CrossAccountId', async ({helper}) => { // We are not going to set an eth address as a sponsor, // but we do want to check, it doesn't break anything; const api = helper.getApi(); const [account] = await helper.arrange.createAccounts([10n], donor); - const ethAccount = helper.address.substrateToEth(account.address); + const ethAccount = helper.address.substrateToEth(account.address); // Alice sets Ethereum address as a sudo. Then Substrate address back... await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Ethereum: ethAccount})))).to.be.fulfilled; await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: palletAdmin.address})))).to.be.fulfilled; - + // ...It doesn't break anything; const collection = await helper.nft.mintCollection(account, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); await expect(helper.signTransaction(account, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected; }); - + itSub('can be reassigned', async ({helper}) => { const api = helper.getApi(); const [oldAdmin, newAdmin, collectionOwner] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'}); - + await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: oldAdmin.address})))).to.be.fulfilled; await expect(helper.signTransaction(superuser, api.tx.sudo.sudo(api.tx.appPromotion.setAdminAddress({Substrate: newAdmin.address})))).to.be.fulfilled; await expect(helper.signTransaction(oldAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.rejected; - + await expect(helper.signTransaction(newAdmin, api.tx.appPromotion.sponsorCollection(collection.collectionId))).to.be.fulfilled; }); }); --- a/tests/src/approve.test.ts +++ b/tests/src/approve.test.ts @@ -538,7 +538,7 @@ const approveTx = () => helper.rft.approveToken(alice, collectionId, 1, {Substrate: bob.address}); await expect(approveTx()).to.be.rejected; }); - + itSub('[nft] Approve transfer of a token that does not exist', async ({helper}) => { const {collectionId} = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}); const approveTx = () => helper.nft.approveToken(alice, collectionId, 2, {Substrate: bob.address}); @@ -639,7 +639,7 @@ 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.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/burnItem.test.ts +++ b/tests/src/burnItem.test.ts @@ -185,7 +185,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'Coll', description: 'Desc', tokenPrefix: 'T'}); const tokenAlice = await collection.mintToken(alice, {Substrate: alice.address}); const tokenBob = await collection.mintToken(alice, {Substrate: bob.address}); - + // 1. Zero burn of own tokens allowed: await helper.executeExtrinsic(alice, 'api.tx.unique.burnItem', [collection.collectionId, tokenAlice.tokenId, 0]); // 2. Zero burn of non-owned tokens not allowed: --- a/tests/src/calibrate.ts +++ b/tests/src/calibrate.ts @@ -295,6 +295,7 @@ } } +// eslint-disable-next-line @typescript-eslint/no-floating-promises (async () => { await usingEthPlaygrounds(async (helper: EthUniqueHelper, privateKey) => { // Subsequent runs reduce error, as price line is not actually straight, this is a curve --- a/tests/src/createCollection.test.ts +++ b/tests/src/createCollection.test.ts @@ -127,7 +127,7 @@ const mintCollectionTx = () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'A'.repeat(17)}); await expect(mintCollectionTx()).to.be.rejectedWith('Verification Error'); }); - + itSub('(!negative test!) fails when bad limits are set', async ({helper}) => { const mintCollectionTx = () => helper.nft.mintCollection(alice, {name: 'name', description: 'descr', tokenPrefix: 'COL', limits: {tokenLimit: 0}}); await expect(mintCollectionTx()).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/); --- a/tests/src/createMultipleItems.test.ts +++ b/tests/src/createMultipleItems.test.ts @@ -272,8 +272,8 @@ const types = ['NFT', 'Fungible', 'ReFungible']; await expect(helper.executeExtrinsic( - alice, - 'api.tx.unique.createMultipleItems', + alice, + 'api.tx.unique.createMultipleItems', [collectionId, {Substrate: alice.address}, types], )).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/); }); --- a/tests/src/eth/collectionSponsoring.test.ts +++ b/tests/src/eth/collectionSponsoring.test.ts @@ -101,11 +101,13 @@ expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true; await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor}); + let sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner}); + expect(helper.address.restoreCrossAccountFromBigInt(BigInt(sponsorTuple.sub))).to.be.eq(helper.address.ethToSubstrate(sponsor, true)); expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.false; await collectionEvm.methods.removeCollectionSponsor().send({from: owner}); - const sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner}); + sponsorTuple = await collectionEvm.methods.collectionSponsor().call({from: owner}); expect(sponsorTuple.eth).to.be.eq('0x0000000000000000000000000000000000000000'); })); --- a/tests/src/eth/createFTCollection.test.ts +++ b/tests/src/eth/createFTCollection.test.ts @@ -32,6 +32,7 @@ }); }); + // TODO move sponsorship tests to another file: // Soft-deprecated itEth('[eth] Set sponsorship', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); @@ -93,6 +94,11 @@ expect(await collectionHelpers .methods.isCollectionExist(collectionAddress).call()) .to.be.true; + + // check collectionOwner: + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true); + const collectionOwner = await collectionEvm.methods.collectionOwner().call(); + expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true)); }); itEth('destroyCollection', async ({helper}) => { --- a/tests/src/eth/createNFTCollection.test.ts +++ b/tests/src/eth/createNFTCollection.test.ts @@ -134,6 +134,11 @@ expect(await collectionHelpers .methods.isCollectionExist(collectionAddress).call()) .to.be.true; + + // check collectionOwner: + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true); + const collectionOwner = await collectionEvm.methods.collectionOwner().call(); + expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true)); }); }); --- a/tests/src/eth/createRFTCollection.test.ts +++ b/tests/src/eth/createRFTCollection.test.ts @@ -88,27 +88,6 @@ ]); }); - // this test will occasionally fail when in async environment. - itEth.skip('Check collection address exist', async ({helper}) => { - const owner = await helper.eth.createAccountWithBalance(donor); - - const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1; - const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId); - const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner); - - expect(await collectionHelpers.methods - .isCollectionExist(expectedCollectionAddress) - .call()).to.be.false; - - await collectionHelpers.methods - .createRFTCollection('A', 'A', 'A') - .send({value: Number(2n * helper.balance.getOneTokenNominal())}); - - expect(await collectionHelpers.methods - .isCollectionExist(expectedCollectionAddress) - .call()).to.be.true; - }); - // Soft-deprecated itEth('[eth] Set sponsorship', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); @@ -166,6 +145,11 @@ expect(await collectionHelpers .methods.isCollectionExist(collectionAddress).call()) .to.be.true; + + // check collectionOwner: + const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true); + const collectionOwner = await collectionEvm.methods.collectionOwner().call(); + expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true)); }); }); --- a/tests/src/eth/evmCoder.test.ts +++ b/tests/src/eth/evmCoder.test.ts @@ -62,7 +62,7 @@ donor = await privateKey({filename: __filename}); }); }); - + itEth('Call non-existing function', async ({helper}) => { const owner = await helper.eth.createAccountWithBalance(donor); const collection = await helper.eth.createNFTCollection(owner, 'EVMCODER', '', 'TEST'); --- a/tests/src/eth/nonFungible.test.ts +++ b/tests/src/eth/nonFungible.test.ts @@ -167,7 +167,6 @@ expect(event.returnValues.to).to.be.equal(receiver); expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI'); - console.log(await contract.methods.crossOwnerOf(tokenId).call()); expect(await contract.methods.crossOwnerOf(tokenId).call()).to.be.like([receiver, '0']); // TODO: this wont work right now, need release 919000 first // await helper.methods.setOffchainSchema(collectionIdAddress, 'https://offchain-service.local/token-info/{id}').send(); @@ -200,7 +199,6 @@ }, }; }); - const collection = await helper.nft.mintCollection(minter, { tokenPrefix: 'ethp', --- a/tests/src/eth/proxyContract.test.ts +++ b/tests/src/eth/proxyContract.test.ts @@ -31,11 +31,11 @@ const deployer = await helper.eth.createAccountWithBalance(donor); const caller = await helper.eth.createAccountWithBalance(donor); const proxyContract = await deployProxyContract(helper, deployer); - + const realContractV1 = await deployRealContractV1(helper, deployer); const realContractV1proxy = new helper.web3!.eth.Contract(realContractV1.options.jsonInterface, proxyContract.options.address, {from: caller, gas: helper.eth.DEFAULT_GAS}); await proxyContract.methods.updateVersion(realContractV1.options.address).send(); - + await realContractV1proxy.methods.flip().send(); await realContractV1proxy.methods.flip().send(); await realContractV1proxy.methods.flip().send(); --- a/tests/src/eth/scheduling.test.ts +++ b/tests/src/eth/scheduling.test.ts @@ -53,7 +53,7 @@ ); expect(await flipper.methods.getValue().call()).to.be.equal(initialValue); - + await helper.wait.newBlocks(waitForBlocks + 1); expect(await flipper.methods.getValue().call()).to.be.not.equal(initialValue); --- a/tests/src/eth/util/index.ts +++ b/tests/src/eth/util/index.ts @@ -58,9 +58,9 @@ silentConsole.disable(); } }; - + export function itEth(name: string, cb: (apis: { helper: EthUniqueHelper, privateKey: (seed: string | {filename: string}) => Promise }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) { - (opts.only ? it.only : + (opts.only ? it.only : opts.skip ? it.skip : it)(name, async function() { await usingEthPlaygrounds(async (helper, privateKey) => { if (opts.requiredPallets) { --- a/tests/src/fungible.test.ts +++ b/tests/src/fungible.test.ts @@ -43,7 +43,7 @@ expect(itemCountAfter).to.be.equal(defaultTokenId); expect(aliceBalance).to.be.equal(U128_MAX); }); - + itSub('RPC method tokenOnewrs for fungible collection and token', async ({helper}) => { const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; const facelessCrowd = (await helper.arrange.createAccounts(Array(7).fill(0n), donor)).map(keyring => {return {Substrate: keyring.address};}); @@ -54,22 +54,22 @@ await collection.transfer(alice, {Substrate: bob.address}, 1000n); await collection.transfer(alice, ethAcc, 900n); - + for (let i = 0; i < 7; i++) { await collection.transfer(alice, facelessCrowd[i], 1n); - } + } const owners = await collection.getTop10Owners(); // What to expect expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); expect(owners.length).to.be.equal(10); - + const [eleven] = await helper.arrange.createAccounts([0n], donor); expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; expect((await collection.getTop10Owners()).length).to.be.equal(10); }); - + itSub('Transfer token', async ({helper}) => { const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); @@ -108,7 +108,7 @@ expect(await collection.doesTokenExist(0)).to.be.true; expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n); }); - + itSub('Burn all tokens ', async ({helper}) => { const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); await collection.mint(alice, 500n); @@ -127,7 +127,7 @@ await collection.mint(alice, 100n); expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n); - + expect(await collection.approveTokens(alice, {Substrate: bob.address}, 60n)).to.be.true; expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n); expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n); @@ -169,11 +169,11 @@ // 1. Alice cannot transfer more than 0 tokens if balance low: await expect(collection.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow'); await expect(collection.transfer(alice, {Substrate: charlie.address}, 100n)).to.be.rejectedWith('common.TokenValueTooLow'); - + // 2. Alice cannot transfer non-existing token: await expect(nonExistingCollection.transfer(alice, {Substrate: charlie.address}, 0n)).to.be.rejectedWith('common.CollectionNotFound'); await expect(nonExistingCollection.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.CollectionNotFound'); - + // 3. Zero transfer allowed (EIP-20): await collection.transfer(bob, {Substrate: charlie.address}, 0n); // 3.1 even if the balance = 0 --- a/tests/src/inflation.seqtest.ts +++ b/tests/src/inflation.seqtest.ts @@ -26,7 +26,7 @@ superuser = await privateKey('//Alice'); }); }); - + itSub('First year inflation is 10%', async ({helper}) => { // Make sure non-sudo can't start inflation const [bob] = await helper.arrange.createAccounts([10n], superuser); --- a/tests/src/interfaces/unique/definitions.ts +++ b/tests/src/interfaces/unique/definitions.ts @@ -38,39 +38,39 @@ types: {}, rpc: { accountTokens: fun( - 'Get tokens owned by an account in a collection', - [collectionParam, crossAccountParam()], + 'Get tokens owned by an account in a collection', + [collectionParam, crossAccountParam()], 'Vec', ), collectionTokens: fun( - 'Get tokens contained within a collection', - [collectionParam], + 'Get tokens contained within a collection', + [collectionParam], 'Vec', ), tokenExists: fun( - 'Check if the token exists', - [collectionParam, tokenParam], + 'Check if the token exists', + [collectionParam, tokenParam], 'bool', ), tokenOwner: fun( - 'Get the token owner', - [collectionParam, tokenParam], + 'Get the token owner', + [collectionParam, tokenParam], `Option<${CROSS_ACCOUNT_ID_TYPE}>`, ), topmostTokenOwner: fun( - 'Get the topmost token owner in the hierarchy of a possibly nested token', - [collectionParam, tokenParam], + 'Get the topmost token owner in the hierarchy of a possibly nested token', + [collectionParam, tokenParam], `Option<${CROSS_ACCOUNT_ID_TYPE}>`, ), tokenOwners: fun( - 'Returns 10 tokens owners in no particular order', - [collectionParam, tokenParam], + 'Returns 10 tokens owners in no particular order', + [collectionParam, tokenParam], `Vec<${CROSS_ACCOUNT_ID_TYPE}>`, ), tokenChildren: fun( - 'Get tokens nested directly into the token', - [collectionParam, tokenParam], + 'Get tokens nested directly into the token', + [collectionParam, tokenParam], 'Vec', ), @@ -91,13 +91,13 @@ ), constMetadata: fun( - 'Get token constant metadata', - [collectionParam, tokenParam], + 'Get token constant metadata', + [collectionParam, tokenParam], 'Vec', ), variableMetadata: fun( - 'Get token variable metadata', - [collectionParam, tokenParam], + 'Get token variable metadata', + [collectionParam, tokenParam], 'Vec', ), @@ -107,77 +107,77 @@ 'UpDataStructsTokenData', ), totalSupply: fun( - 'Get the amount of distinctive tokens present in a collection', - [collectionParam], + 'Get the amount of distinctive tokens present in a collection', + [collectionParam], 'u32', ), accountBalance: fun( - 'Get the amount of any user tokens owned by an account', - [collectionParam, crossAccountParam()], + 'Get the amount of any user tokens owned by an account', + [collectionParam, crossAccountParam()], 'u32', ), balance: fun( - 'Get the amount of a specific token owned by an account', - [collectionParam, crossAccountParam(), tokenParam], + 'Get the amount of a specific token owned by an account', + [collectionParam, crossAccountParam(), tokenParam], 'u128', ), allowance: fun( - 'Get the amount of currently possible sponsored transactions on a token for the fee to be taken off a sponsor', - [collectionParam, crossAccountParam('sender'), crossAccountParam('spender'), tokenParam], + 'Get the amount of currently possible sponsored transactions on a token for the fee to be taken off a sponsor', + [collectionParam, crossAccountParam('sender'), crossAccountParam('spender'), tokenParam], 'u128', ), adminlist: fun( - 'Get the list of admin accounts of a collection', - [collectionParam], + 'Get the list of admin accounts of a collection', + [collectionParam], 'Vec', ), allowlist: fun( - 'Get the list of accounts allowed to operate within a collection', - [collectionParam], + 'Get the list of accounts allowed to operate within a collection', + [collectionParam], 'Vec', ), allowed: fun( - 'Check if a user is allowed to operate within a collection', - [collectionParam, crossAccountParam()], + 'Check if a user is allowed to operate within a collection', + [collectionParam, crossAccountParam()], 'bool', ), lastTokenId: fun( - 'Get the last token ID created in a collection', - [collectionParam], + 'Get the last token ID created in a collection', + [collectionParam], 'u32', ), collectionById: fun( - 'Get a collection by the specified ID', - [collectionParam], + 'Get a collection by the specified ID', + [collectionParam], 'Option', ), collectionStats: fun( - 'Get chain stats about collections', - [], + 'Get chain stats about collections', + [], 'UpDataStructsCollectionStats', ), nextSponsored: fun( - 'Get the number of blocks until sponsoring a transaction is available', - [collectionParam, crossAccountParam(), tokenParam], + 'Get the number of blocks until sponsoring a transaction is available', + [collectionParam, crossAccountParam(), tokenParam], 'Option', ), effectiveCollectionLimits: fun( - 'Get effective collection limits', - [collectionParam], + 'Get effective collection limits', + [collectionParam], 'Option', ), totalPieces: fun( - 'Get the total amount of pieces of an RFT', - [collectionParam, tokenParam], + 'Get the total amount of pieces of an RFT', + [collectionParam, tokenParam], 'Option', ), allowanceForAll: fun( - 'Tells whether the given `owner` approves the `operator`.', - [collectionParam, crossAccountParam('owner'), crossAccountParam('operator')], + 'Tells whether the given `owner` approves the `operator`.', + [collectionParam, crossAccountParam('owner'), crossAccountParam('operator')], 'Option', ), }, --- a/tests/src/limits.test.ts +++ b/tests/src/limits.test.ts @@ -30,7 +30,7 @@ itSub.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {}); await collection.setLimits(alice, {accountTokenOwnershipLimit: 20}); - + for(let i = 0; i < 10; i++){ await expect(collection.mintToken(alice)).to.be.not.rejected; } @@ -40,14 +40,14 @@ } await collection.burn(alice); }); - + itSub('Collection limits allow lower number than chain limits, collection limits are enforced', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {}); await collection.setLimits(alice, {accountTokenOwnershipLimit: 1}); await collection.mintToken(alice); await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/); - + await collection.burnToken(alice, 1); await expect(collection.burn(alice)).to.be.not.rejected; }); @@ -68,7 +68,7 @@ itSub.skip('Collection limits allow greater number than chain limits, chain limits are enforced', async ({helper}) => { const collection = await helper.rft.mintCollection(alice, {}); await collection.setLimits(alice, {accountTokenOwnershipLimit: 20}); - + for(let i = 0; i < 10; i++){ await expect(collection.mintToken(alice, 10n)).to.be.not.rejected; } @@ -85,7 +85,7 @@ await collection.mintToken(alice); await expect(collection.mintToken(alice)).to.be.rejectedWith(/common\.AccountTokenLimitExceeded/); - + await collection.burnToken(alice, 1); await expect(collection.burn(alice)).to.be.not.rejected; }); @@ -314,7 +314,7 @@ await collection.setSponsor(alice, alice.address); await collection.confirmSponsorship(alice); - + await token.transfer(alice, {Substrate: bob.address}); const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address); @@ -345,7 +345,7 @@ await collection.setSponsor(alice, alice.address); await collection.confirmSponsorship(alice); - + await collection.transfer(alice, {Substrate: bob.address}, 2n); const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address); @@ -387,7 +387,7 @@ await collection.setSponsor(alice, alice.address); await collection.confirmSponsorship(alice); - + await token.transfer(alice, {Substrate: bob.address}, 2n); const aliceBalanceBefore = await helper.balance.getSubstrate(alice.address); @@ -408,17 +408,17 @@ [alice] = await helper.arrange.createAccounts([10n], donor); }); }); - + itSub('Effective collection limits', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {}); - await collection.setLimits(alice, {ownerCanTransfer: true}); - - { + await collection.setLimits(alice, {ownerCanTransfer: true}); + + { // Check that limits are undefined const collectionInfo = await collection.getData(); const limits = collectionInfo?.raw.limits; expect(limits).to.be.any; - + expect(limits.accountTokenOwnershipLimit).to.be.null; expect(limits.sponsoredDataSize).to.be.null; expect(limits.sponsoredDataRateLimit).to.be.null; @@ -449,7 +449,7 @@ expect(limits.transfersEnabled).to.be.true; } - { + { // Check the values for collection limits await collection.setLimits(alice, { accountTokenOwnershipLimit: 99_999, --- a/tests/src/nesting/collectionProperties.seqtest.ts +++ b/tests/src/nesting/collectionProperties.seqtest.ts @@ -20,7 +20,7 @@ describe('Integration Test: Collection Properties with sudo', () => { let superuser: IKeyringPair; let alice: IKeyringPair; - + before(async () => { await usingPlaygrounds(async (helper, privateKey) => { superuser = await privateKey('//Alice'); @@ -32,7 +32,7 @@ [ {mode: 'nft' as const, requiredPallets: []}, {mode: 'ft' as const, requiredPallets: []}, - {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => { before(async function() { // eslint-disable-next-line require-await --- a/tests/src/nesting/collectionProperties.test.ts +++ b/tests/src/nesting/collectionProperties.test.ts @@ -20,14 +20,14 @@ describe('Integration Test: Collection Properties', () => { let alice: IKeyringPair; let bob: IKeyringPair; - + before(async () => { await usingPlaygrounds(async (helper, privateKey) => { const donor = await privateKey({filename: __filename}); [alice, bob] = await helper.arrange.createAccounts([200n, 10n], donor); }); }); - + itSub('Properties are initially empty', async ({helper}) => { const collection = await helper.nft.mintCollection(alice); expect(await collection.getProperties()).to.be.empty; @@ -36,7 +36,7 @@ [ {mode: 'nft' as const, requiredPallets: []}, {mode: 'ft' as const, requiredPallets: []}, - {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => { before(async function() { // eslint-disable-next-line require-await @@ -50,37 +50,37 @@ // As owner await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}])).to.be.fulfilled; - + await collection.addAdmin(alice, {Substrate: bob.address}); - + // As administrator await expect(collection.setProperties(bob, [{key: 'black_hole'}])).to.be.fulfilled; - + const properties = await collection.getProperties(); expect(properties).to.include.deep.members([ {key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}, ]); }); - + itSub('Check valid names for collection properties keys', async ({helper}) => { const collection = await helper[testSuite.mode].mintCollection(alice); // alpha symbols await expect(collection.setProperties(alice, [{key: 'answer'}])).to.be.fulfilled; - + // numeric symbols await expect(collection.setProperties(alice, [{key: '451'}])).to.be.fulfilled; - + // underscore symbol await expect(collection.setProperties(alice, [{key: 'black_hole'}])).to.be.fulfilled; - + // dash symbol await expect(collection.setProperties(alice, [{key: '-'}])).to.be.fulfilled; - + // dot symbol await expect(collection.setProperties(alice, [{key: 'once.in.a.long.long.while...', value: 'you get a little lost'}])).to.be.fulfilled; - + const properties = await collection.getProperties(); expect(properties).to.include.deep.members([ {key: 'answer', value: ''}, @@ -90,29 +90,29 @@ {key: 'once.in.a.long.long.while...', value: 'you get a little lost'}, ]); }); - + itSub('Changes properties of a collection', async ({helper}) => { const collection = await helper[testSuite.mode].mintCollection(alice); await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: ''}])).to.be.fulfilled; - + // Mutate the properties await expect(collection.setProperties(alice, [{key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled; - + const properties = await collection.getProperties(); expect(properties).to.include.deep.members([ {key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}, ]); }); - + itSub('Deletes properties of a collection', async ({helper}) => { const collection = await helper[testSuite.mode].mintCollection(alice); await expect(collection.setProperties(alice, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])).to.be.fulfilled; - + await expect(collection.deleteProperties(alice, ['electron'])).to.be.fulfilled; - + const properties = await collection.getProperties(['black_hole', 'electron']); expect(properties).to.be.deep.equal([ {key: 'black_hole', value: 'LIGO'}, @@ -201,11 +201,11 @@ }); })); }); - + describe('Negative Integration Test: Collection Properties', () => { let alice: IKeyringPair; let bob: IKeyringPair; - + before(async () => { await usingPlaygrounds(async (helper, privateKey) => { const donor = await privateKey({filename: __filename}); @@ -216,7 +216,7 @@ [ {mode: 'nft' as const, requiredPallets: []}, {mode: 'ft' as const, requiredPallets: []}, - {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => { before(async function() { // eslint-disable-next-line require-await @@ -224,21 +224,21 @@ requirePalletsOrSkip(this, helper, testSuite.requiredPallets); }); }); - + itSub('Fails to set properties in a collection if not its onwer/administrator', async ({helper}) => { const collection = await helper[testSuite.mode].mintCollection(alice); await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}])) .to.be.rejectedWith(/common\.NoPermission/); - + expect(await collection.getProperties()).to.be.empty; }); - + itSub('Fails to set properties that exceed the limits', async ({helper}) => { const collection = await helper[testSuite.mode].mintCollection(alice); const spaceLimit = (await (collection.helper!.api! as any).query.common.collectionProperties(collection.collectionId)).spaceLimit.toNumber(); - + // Mute the general tx parsing error, too many bytes to process { console.error = () => {}; @@ -246,17 +246,17 @@ {key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 9))}, ])).to.be.rejected; } - + expect(await collection.getProperties(['electron'])).to.be.empty; - + await expect(collection.setProperties(alice, [ - {key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 18))}, - {key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))}, + {key: 'electron', value: 'low high '.repeat(Math.ceil(spaceLimit! / 18))}, + {key: 'black_hole', value: '0'.repeat(Math.ceil(spaceLimit! / 2))}, ])).to.be.rejectedWith(/common\.NoSpaceForProperty/); - + expect(await collection.getProperties(['electron', 'black_hole'])).to.be.empty; }); - + itSub('Fails to set more properties than it is allowed', async ({helper}) => { const collection = await helper[testSuite.mode].mintCollection(alice); @@ -267,10 +267,10 @@ value: Math.random() > 0.5 ? 'high' : 'low', }); } - + await expect(collection.setProperties(alice, propertiesToBeSet)). to.be.rejectedWith(/common\.PropertyLimitReached/); - + expect(await collection.getProperties()).to.be.empty; }); @@ -282,34 +282,34 @@ [{key: 'Mr/Sandman', value: 'Bring me a gene'}], [{key: 'déjà vu', value: 'hmm...'}], ]; - + for (let i = 0; i < invalidProperties.length; i++) { await expect( - collection.setProperties(alice, invalidProperties[i]), + collection.setProperties(alice, invalidProperties[i]), `on rejecting the new badly-named property #${i}`, ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/); } - + await expect( - collection.setProperties(alice, [{key: '', value: 'nothing must not exist'}]), + collection.setProperties(alice, [{key: '', value: 'nothing must not exist'}]), 'on rejecting an unnamed property', ).to.be.rejectedWith(/common\.EmptyPropertyKey/); - + await expect( - collection.setProperties(alice, [{key: 'CRISPR-Cas9', value: 'rewriting nature!'}]), + collection.setProperties(alice, [{key: 'CRISPR-Cas9', value: 'rewriting nature!'}]), 'on setting the correctly-but-still-badly-named property', ).to.be.fulfilled; - + const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat('CRISPR-Cas9').concat(''); - + const properties = await collection.getProperties(keys); expect(properties).to.be.deep.equal([ {key: 'CRISPR-Cas9', value: 'rewriting nature!'}, ]); - + for (let i = 0; i < invalidProperties.length; i++) { await expect( - collection.deleteProperties(alice, invalidProperties[i].map(propertySet => propertySet.key)), + collection.deleteProperties(alice, invalidProperties[i].map(propertySet => propertySet.key)), `on trying to delete the non-existent badly-named property #${i}`, ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/); } @@ -326,4 +326,3 @@ }); })); }); - \ No newline at end of file --- a/tests/src/nesting/graphs.test.ts +++ b/tests/src/nesting/graphs.test.ts @@ -56,7 +56,7 @@ // to self await expect( tokens[0].nest(alice, tokens[0]), - 'first transaction', + 'first transaction', ).to.be.rejectedWith(/structure\.OuroborosDetected/); // to nested part of graph await expect( --- a/tests/src/nesting/nest.test.ts +++ b/tests/src/nesting/nest.test.ts @@ -36,7 +36,7 @@ const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount()); expect(await nestedToken.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address}); expect(await nestedToken.getOwner()).to.be.deep.equal(targetToken.nestingAccount().toLowerCase()); - + // Create a token to be nested const newToken = await collection.mintToken(alice); @@ -66,7 +66,7 @@ // Create a nested token const tokenC = await collection.mintToken(alice, tokenA.nestingAccount()); expect(await tokenC.getOwner()).to.be.deep.equal(tokenA.nestingAccount().toLowerCase()); - + // Transfer the nested token to another token await expect(tokenC.transferFrom(alice, tokenA.nestingAccount(), tokenB.nestingAccount())).to.be.fulfilled; expect(await tokenC.getTopmostOwner()).to.be.deep.equal({Substrate: alice.address}); @@ -76,7 +76,7 @@ itSub('Checks token children', async ({helper}) => { const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}}); const collectionB = await helper.ft.mintCollection(alice); - + const targetToken = await collectionA.mintToken(alice); expect((await targetToken.getChildren()).length).to.be.equal(0, 'Children length check at creation'); @@ -108,7 +108,7 @@ {tokenId: 0, collectionId: collectionB.collectionId}, ], 'Children contents check at nesting #4 (from another collection)') .and.be.length(2, 'Children length check at nesting #4 (from another collection)'); - + // Move part of the fungible token inside token A deeper in the nesting tree await collectionB.transferFrom(alice, targetToken.nestingAccount(), tokenA.nestingAccount(), 1n); expect(await targetToken.getChildren()).to.be.have.deep.members([ --- a/tests/src/nesting/propertyPermissions.test.ts +++ b/tests/src/nesting/propertyPermissions.test.ts @@ -21,94 +21,94 @@ describe('Integration Test: Access Rights to Token Properties', () => { let alice: IKeyringPair; let bob: IKeyringPair; - + before(async () => { await usingPlaygrounds(async (helper, privateKey) => { const donor = await privateKey({filename: __filename}); [alice, bob] = await helper.arrange.createAccounts([100n, 10n], donor); }); }); - + itSub('Reads access rights to properties of a collection', async ({helper}) => { const collection = await helper.nft.mintCollection(alice); const propertyRights = (await helper.callRpc('api.query.common.collectionPropertyPermissions', [collection.collectionId])).toJSON(); expect(propertyRights).to.be.empty; }); - - async function testSetsAccessRightsToProperties(collection: UniqueNFTCollection | UniqueRFTCollection) { + + async function testSetsAccessRightsToProperties(collection: UniqueNFTCollection | UniqueRFTCollection) { await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true}}])) .to.be.fulfilled; - + await collection.addAdmin(alice, {Substrate: bob.address}); - + await expect(collection.setTokenPropertyPermissions(bob, [{key: 'mindgame', permission: {collectionAdmin: true, tokenOwner: false}}])) .to.be.fulfilled; - + const propertyRights = await collection.getPropertyPermissions(['skullduggery', 'mindgame']); expect(propertyRights).to.include.deep.members([ {key: 'skullduggery', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}, {key: 'mindgame', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}, ]); } - + itSub('Sets access rights to properties of a collection (NFT)', async ({helper}) => { await testSetsAccessRightsToProperties(await helper.nft.mintCollection(alice)); }); - + itSub.ifWithPallets('Sets access rights to properties of a collection (ReFungible)', [Pallets.ReFungible], async ({helper}) => { await testSetsAccessRightsToProperties(await helper.rft.mintCollection(alice)); }); - + async function testChangesAccessRightsToProperty(collection: UniqueNFTCollection | UniqueRFTCollection) { await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: true, collectionAdmin: true}}])) .to.be.fulfilled; - + await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}])) .to.be.fulfilled; - + const propertyRights = await collection.getPropertyPermissions(); expect(propertyRights).to.be.deep.equal([ {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}}, ]); } - + itSub('Changes access rights to properties of a NFT collection', async ({helper}) => { await testChangesAccessRightsToProperty(await helper.nft.mintCollection(alice)); }); - + itSub.ifWithPallets('Changes access rights to properties of a ReFungible collection', [Pallets.ReFungible], async ({helper}) => { await testChangesAccessRightsToProperty(await helper.rft.mintCollection(alice)); }); }); - + describe('Negative Integration Test: Access Rights to Token Properties', () => { let alice: IKeyringPair; let bob: IKeyringPair; - + before(async () => { await usingPlaygrounds(async (helper, privateKey) => { const donor = await privateKey({filename: __filename}); [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor); }); }); - + async function testPreventsFromSettingAccessRightsNotAdminOrOwner(collection: UniqueNFTCollection | UniqueRFTCollection) { await expect(collection.setTokenPropertyPermissions(bob, [{key: 'skullduggery', permission: {mutable: true, tokenOwner: true}}])) .to.be.rejectedWith(/common\.NoPermission/); - + const propertyRights = await collection.getPropertyPermissions(['skullduggery']); expect(propertyRights).to.be.empty; } - + itSub('Prevents from setting access rights to properties of a NFT collection if not an onwer/admin', async ({helper}) => { await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.nft.mintCollection(alice)); }); - + itSub.ifWithPallets('Prevents from setting access rights to properties of a ReFungible collection if not an onwer/admin', [Pallets.ReFungible], async ({helper}) => { await testPreventsFromSettingAccessRightsNotAdminOrOwner(await helper.rft.mintCollection(alice)); }); - - async function testPreventFromAddingTooManyPossibleProperties(collection: UniqueNFTCollection | UniqueRFTCollection) { + + async function testPreventFromAddingTooManyPossibleProperties(collection: UniqueNFTCollection | UniqueRFTCollection) { const constitution = []; for (let i = 0; i < 65; i++) { constitution.push({ @@ -116,82 +116,82 @@ permission: Math.random() > 0.5 ? {mutable: true, collectionAdmin: true, tokenOwner: true} : {}, }); } - + await expect(collection.setTokenPropertyPermissions(alice, constitution)) .to.be.rejectedWith(/common\.PropertyLimitReached/); - + const propertyRights = await collection.getPropertyPermissions(); expect(propertyRights).to.be.empty; } - + itSub('Prevents from adding too many possible properties (NFT)', async ({helper}) => { await testPreventFromAddingTooManyPossibleProperties(await helper.nft.mintCollection(alice)); }); - + itSub.ifWithPallets('Prevents from adding too many possible properties (ReFungible)', [Pallets.ReFungible], async ({helper}) => { await testPreventFromAddingTooManyPossibleProperties(await helper.rft.mintCollection(alice)); }); - + async function testPreventAccessRightsModifiedIfConstant(collection: UniqueNFTCollection | UniqueRFTCollection) { await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {mutable: false, tokenOwner: true}}])) .to.be.fulfilled; - + await expect(collection.setTokenPropertyPermissions(alice, [{key: 'skullduggery', permission: {collectionAdmin: true}}])) .to.be.rejectedWith(/common\.NoPermission/); - + const propertyRights = await collection.getPropertyPermissions(['skullduggery']); expect(propertyRights).to.deep.equal([ {key: 'skullduggery', permission: {'mutable': false, 'collectionAdmin': false, 'tokenOwner': true}}, ]); } - + itSub('Prevents access rights to be modified if constant (NFT)', async ({helper}) => { await testPreventAccessRightsModifiedIfConstant(await helper.nft.mintCollection(alice)); }); - + itSub.ifWithPallets('Prevents access rights to be modified if constant (ReFungible)', [Pallets.ReFungible], async ({helper}) => { await testPreventAccessRightsModifiedIfConstant(await helper.rft.mintCollection(alice)); }); - + async function testPreventsAddingPropertiesWithInvalidNames(collection: UniqueNFTCollection | UniqueRFTCollection) { const invalidProperties = [ [{key: 'skullduggery', permission: {tokenOwner: true}}, {key: 'im possible', permission: {collectionAdmin: true}}], [{key: 'G#4', permission: {tokenOwner: true}}], [{key: 'HÆMILTON', permission: {mutable: false, collectionAdmin: true, tokenOwner: true}}], ]; - + for (let i = 0; i < invalidProperties.length; i++) { await expect( - collection.setTokenPropertyPermissions(alice, invalidProperties[i]), + collection.setTokenPropertyPermissions(alice, invalidProperties[i]), `on setting the new badly-named property #${i}`, ).to.be.rejectedWith(/common\.InvalidCharacterInPropertyKey/); } - + await expect( - collection.setTokenPropertyPermissions(alice, [{key: '', permission: {}}]), + collection.setTokenPropertyPermissions(alice, [{key: '', permission: {}}]), 'on rejecting an unnamed property', ).to.be.rejectedWith(/common\.EmptyPropertyKey/); - + const correctKey = '--0x03116e387820CA05'; // PolkadotJS would parse this as an already encoded hex-string await expect( collection.setTokenPropertyPermissions(alice, [ {key: correctKey, permission: {collectionAdmin: true}}, - ]), + ]), 'on setting the correctly-but-still-badly-named property', ).to.be.fulfilled; - + const keys = invalidProperties.flatMap(propertySet => propertySet.map(property => property.key)).concat(correctKey).concat(''); - + const propertyRights = await collection.getPropertyPermissions(keys); expect(propertyRights).to.be.deep.equal([ {key: correctKey, permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}, ]); } - + itSub('Prevents adding properties with invalid names (NFT)', async ({helper}) => { await testPreventsAddingPropertiesWithInvalidNames(await helper.nft.mintCollection(alice)); }); - + itSub.ifWithPallets('Prevents adding properties with invalid names (ReFungible)', [Pallets.ReFungible], async ({helper}) => { await testPreventsAddingPropertiesWithInvalidNames(await helper.rft.mintCollection(alice)); }); --- a/tests/src/nesting/tokenProperties.seqtest.ts +++ b/tests/src/nesting/tokenProperties.seqtest.ts @@ -31,7 +31,7 @@ [ {mode: 'nft' as const, pieces: undefined, requiredPallets: []}, - {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => { before(async function() { // eslint-disable-next-line require-await @@ -39,7 +39,7 @@ requirePalletsOrSkip(this, helper, testSuite.requiredPallets); }); }); - + itSub('force_repair_item preserves valid consumed space', async({helper}) => { const propKey = 'tok-prop'; --- a/tests/src/nesting/tokenProperties.test.ts +++ b/tests/src/nesting/tokenProperties.test.ts @@ -43,12 +43,12 @@ async function mintCollectionWithAllPermissionsAndToken(helper: UniqueHelper, mode: 'NFT' | 'RFT'): Promise<[UniqueNFToken | UniqueRFToken, bigint]> { const collection = await (mode == 'NFT' ? helper.nft : helper.rft).mintCollection(alice, { - tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => + tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})), }); return mode == 'NFT' ? [await collection.mintToken(alice), 1n] : [await collection.mintToken(alice, 100n), 100n]; } - + async function testReadsYetEmptyProperties(token: UniqueNFToken | UniqueRFToken) { const properties = await token.getProperties(); expect(properties).to.be.empty; @@ -84,7 +84,7 @@ propertyKeys.push(key); await expect( - token.setProperties(signer, [{key: key, value: 'Serotonin increase'}]), + token.setProperties(signer, [{key: key, value: 'Serotonin increase'}]), `on adding property #${i} by signer #${j}`, ).to.be.fulfilled; } @@ -117,7 +117,7 @@ for (const permission of permissions) { i++; if (!permission.permission.mutable) continue; - + let j = 0; for (const signer of permission.signers) { j++; @@ -125,12 +125,12 @@ propertyKeys.push(key); await expect( - token.setProperties(signer, [{key, value: 'Serotonin increase'}]), + token.setProperties(signer, [{key, value: 'Serotonin increase'}]), `on adding property #${i} by signer #${j}`, ).to.be.fulfilled; await expect( - token.setProperties(signer, [{key, value: 'Serotonin stable'}]), + token.setProperties(signer, [{key, value: 'Serotonin stable'}]), `on changing property #${i} by signer #${j}`, ).to.be.fulfilled; } @@ -164,7 +164,7 @@ for (const permission of permissions) { i++; if (!permission.permission.mutable) continue; - + let j = 0; for (const signer of permission.signers) { j++; @@ -172,12 +172,12 @@ propertyKeys.push(key); await expect( - token.setProperties(signer, [{key, value: 'Serotonin increase'}]), + token.setProperties(signer, [{key, value: 'Serotonin increase'}]), `on adding property #${i} by signer #${j}`, ).to.be.fulfilled; await expect( - token.deleteProperties(signer, [key]), + token.deleteProperties(signer, [key]), `on deleting property #${i} by signer #${j}`, ).to.be.fulfilled; } @@ -186,7 +186,7 @@ expect(await token.getProperties(propertyKeys)).to.be.empty; expect((await token.getData())!.properties).to.be.empty; } - + itSub('Deletes properties of a token according to permissions (NFT)', async ({helper}) => { const [token, amount] = await mintCollectionWithAllPermissionsAndToken(helper, 'NFT'); await testDeletePropertiesAccordingPermission(token, amount); @@ -200,7 +200,7 @@ itSub('Assigns properties to a nested token according to permissions', async ({helper}) => { const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}}); const collectionB = await helper.nft.mintCollection(alice, { - tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => + tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})), }); const targetToken = await collectionA.mintToken(alice); @@ -220,7 +220,7 @@ propertyKeys.push(key); await expect( - nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), + nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), `on adding property #${i} by signer #${j}`, ).to.be.fulfilled; } @@ -238,7 +238,7 @@ itSub('Changes properties of a nested token according to permissions', async ({helper}) => { const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}}); const collectionB = await helper.nft.mintCollection(alice, { - tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => + tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})), }); const targetToken = await collectionA.mintToken(alice); @@ -252,7 +252,7 @@ for (const permission of permissions) { i++; if (!permission.permission.mutable) continue; - + let j = 0; for (const signer of permission.signers) { j++; @@ -260,12 +260,12 @@ propertyKeys.push(key); await expect( - nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), + nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), `on adding property #${i} by signer #${j}`, ).to.be.fulfilled; await expect( - nestedToken.setProperties(signer, [{key, value: 'Serotonin stable'}]), + nestedToken.setProperties(signer, [{key, value: 'Serotonin stable'}]), `on changing property #${i} by signer #${j}`, ).to.be.fulfilled; } @@ -283,7 +283,7 @@ itSub('Deletes properties of a nested token according to permissions', async ({helper}) => { const collectionA = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}}); const collectionB = await helper.nft.mintCollection(alice, { - tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => + tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) => signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})), }); const targetToken = await collectionA.mintToken(alice); @@ -297,7 +297,7 @@ for (const permission of permissions) { i++; if (!permission.permission.mutable) continue; - + let j = 0; for (const signer of permission.signers) { j++; @@ -305,12 +305,12 @@ propertyKeys.push(key); await expect( - nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), + nestedToken.setProperties(signer, [{key, value: 'Serotonin increase'}]), `on adding property #${i} by signer #${j}`, ).to.be.fulfilled; await expect( - nestedToken.deleteProperties(signer, [key]), + nestedToken.deleteProperties(signer, [key]), `on deleting property #${i} by signer #${j}`, ).to.be.fulfilled; } @@ -323,7 +323,7 @@ [ {mode: 'nft' as const, storage: 'nonfungible' as const, pieces: undefined, requiredPallets: []}, - {mode: 'rft' as const, storage: 'refungible' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, storage: 'refungible' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, ].map(testCase => itSub.ifWithPallets(`Allows modifying a token property multiple times with the same size (${testCase.mode})`, testCase.requiredPallets, async({helper}) => { const propKey = 'tok-prop'; @@ -370,7 +370,7 @@ [ {mode: 'nft' as const, pieces: undefined, requiredPallets: []}, - {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, ].map(testCase => itSub.ifWithPallets(`Adding then removing a token property doesn't change the consumed space (${testCase.mode})`, testCase.requiredPallets, async({helper}) => { const propKey = 'tok-prop'; @@ -404,7 +404,7 @@ [ {mode: 'nft' as const, pieces: undefined, requiredPallets: []}, - {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, ].map(testCase => itSub.ifWithPallets(`Modifying a token property with different sizes correctly changes the consumed space (${testCase.mode})`, testCase.requiredPallets, async({helper}) => { const propKey = 'tok-prop'; @@ -497,12 +497,12 @@ i++; const signer = passage.signers[0]; await expect( - token.setProperties(signer, [{key: `${i}`, value: 'Serotonin increase'}]), + token.setProperties(signer, [{key: `${i}`, value: 'Serotonin increase'}]), `on adding property ${i} by ${signer.address}`, ).to.be.fulfilled; } - const originalSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); + const originalSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); return originalSpace; } @@ -515,17 +515,17 @@ if (!forbiddance.permission.mutable) continue; await expect( - token.setProperties(forbiddance.sinner, [{key: `${i}`, value: 'Serotonin down'}]), + token.setProperties(forbiddance.sinner, [{key: `${i}`, value: 'Serotonin down'}]), `on failing to change property ${i} by the malefactor`, ).to.be.rejectedWith(/common\.NoPermission/); await expect( - token.deleteProperties(forbiddance.sinner, [`${i}`]), + token.deleteProperties(forbiddance.sinner, [`${i}`]), `on failing to delete property ${i} by the malefactor`, ).to.be.rejectedWith(/common\.NoPermission/); } - const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); + const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); expect(consumedSpace).to.be.equal(originalSpace); } @@ -548,17 +548,17 @@ if (permission.permission.mutable) continue; await expect( - token.setProperties(permission.signers[0], [{key: `${i}`, value: 'Serotonin down'}]), + token.setProperties(permission.signers[0], [{key: `${i}`, value: 'Serotonin down'}]), `on failing to change property ${i} by signer #0`, ).to.be.rejectedWith(/common\.NoPermission/); await expect( - token.deleteProperties(permission.signers[0], [i.toString()]), + token.deleteProperties(permission.signers[0], [i.toString()]), `on failing to delete property ${i} by signer #0`, ).to.be.rejectedWith(/common\.NoPermission/); } - - const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); + + const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); expect(consumedSpace).to.be.equal(originalSpace); } @@ -576,23 +576,23 @@ const originalSpace = await prepare(token, pieces); await expect( - token.setProperties(alice, [{key: 'non-existent', value: 'I exist!'}]), + token.setProperties(alice, [{key: 'non-existent', value: 'I exist!'}]), 'on failing to add a previously non-existent property', ).to.be.rejectedWith(/common\.NoPermission/); - + await expect( - token.collection.setTokenPropertyPermissions(alice, [{key: 'now-existent', permission: {}}]), + token.collection.setTokenPropertyPermissions(alice, [{key: 'now-existent', permission: {}}]), 'on setting a new non-permitted property', ).to.be.fulfilled; await expect( - token.setProperties(alice, [{key: 'now-existent', value: 'I exist!'}]), + token.setProperties(alice, [{key: 'now-existent', value: 'I exist!'}]), 'on failing to add a property forbidden by the \'None\' permission', ).to.be.rejectedWith(/common\.NoPermission/); expect(await token.getProperties(['non-existent', 'now-existent'])).to.be.empty; - - const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); + + const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); expect(consumedSpace).to.be.equal(originalSpace); } @@ -611,9 +611,9 @@ await expect( token.collection.setTokenPropertyPermissions(alice, [ - {key: 'a_holy_book', permission: {collectionAdmin: true, tokenOwner: true}}, + {key: 'a_holy_book', permission: {collectionAdmin: true, tokenOwner: true}}, {key: 'young_years', permission: {collectionAdmin: true, tokenOwner: true}}, - ]), + ]), 'on setting new permissions for properties', ).to.be.fulfilled; @@ -625,12 +625,12 @@ } await expect(token.setProperties(alice, [ - {key: 'a_holy_book', value: 'word '.repeat(3277)}, + {key: 'a_holy_book', value: 'word '.repeat(3277)}, {key: 'young_years', value: 'neverending'.repeat(1490)}, ])).to.be.rejectedWith(/common\.NoSpaceForProperty/); - + expect(await token.getProperties(['a_holy_book', 'young_years'])).to.be.empty; - const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); + const consumedSpace = await getConsumedSpace(token.collection.helper.getApi(), token.collectionId, token.tokenId, pieces == 1n ? 'NFT' : 'RFT'); expect(consumedSpace).to.be.equal(originalSpace); } @@ -646,7 +646,7 @@ [ {mode: 'nft' as const, requiredPallets: []}, - {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, requiredPallets: [Pallets.ReFungible]}, ].map(testCase => itSub.ifWithPallets(`Forbids adding too many propeties to a token (${testCase.mode})`, testCase.requiredPallets, async({helper}) => { const collection = await helper[testCase.mode].mintCollection(alice); @@ -667,7 +667,7 @@ [ {mode: 'nft' as const, pieces: undefined, requiredPallets: []}, - {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, + {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]}, ].map(testCase => itSub.ifWithPallets(`Forbids force_repair_item from non-sudo (${testCase.mode})`, testCase.requiredPallets, async({helper}) => { const propKey = 'tok-prop'; @@ -712,10 +712,10 @@ async function prepare(helper: UniqueHelper): Promise { const collection = await helper.rft.mintCollection(alice); const token = await collection.mintToken(alice, 100n); - + await collection.addAdmin(alice, {Substrate: bob.address}); await collection.setTokenPropertyPermissions(alice, [{key: 'fractals', permission: {mutable: true, tokenOwner: true}}]); - + return token; } @@ -725,7 +725,7 @@ await token.transfer(alice, {Substrate: charlie.address}, 33n); await expect(token.setProperties(alice, [ - {key: 'fractals', value: 'multiverse'}, + {key: 'fractals', value: 'multiverse'}, ])).to.be.rejectedWith(/common\.NoPermission/); }); @@ -736,13 +736,13 @@ .to.be.fulfilled; await expect(token.setProperties(alice, [ - {key: 'fractals', value: 'multiverse'}, + {key: 'fractals', value: 'multiverse'}, ])).to.be.fulfilled; await token.transfer(alice, {Substrate: charlie.address}, 33n); await expect(token.setProperties(alice, [ - {key: 'fractals', value: 'want to rule the world'}, + {key: 'fractals', value: 'want to rule the world'}, ])).to.be.rejectedWith(/common\.NoPermission/); }); @@ -750,7 +750,7 @@ const token = await prepare(helper); await expect(token.setProperties(alice, [ - {key: 'fractals', value: 'one headline - why believe it'}, + {key: 'fractals', value: 'one headline - why believe it'}, ])).to.be.fulfilled; await token.transfer(alice, {Substrate: charlie.address}, 33n); @@ -768,7 +768,7 @@ .to.be.fulfilled; await expect(token.setProperties(alice, [ - {key: 'fractals', value: 'multiverse'}, + {key: 'fractals', value: 'multiverse'}, ])).to.be.fulfilled; }); }); --- a/tests/src/nesting/unnest.test.ts +++ b/tests/src/nesting/unnest.test.ts @@ -30,7 +30,7 @@ itSub('NFT: allows the owner to successfully unnest a token', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {permissions: {nesting: {tokenOwner: true}}}); const targetToken = await collection.mintToken(alice); - + // Create a nested token const nestedToken = await collection.mintToken(alice, targetToken.nestingAccount()); @@ -49,7 +49,7 @@ const targetToken = await collection.mintToken(alice); const collectionFT = await helper.ft.mintCollection(alice); - + // Nest and unnest await collectionFT.mint(alice, 10n, targetToken.nestingAccount()); await expect(collectionFT.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled; @@ -69,7 +69,7 @@ const targetToken = await collection.mintToken(alice); const collectionRFT = await helper.rft.mintCollection(alice); - + // Nest and unnest const token = await collectionRFT.mintToken(alice, 10n, targetToken.nestingAccount()); await expect(token.transferFrom(alice, targetToken.nestingAccount(), {Substrate: alice.address}, 9n), 'while unnesting').to.be.fulfilled; --- a/tests/src/nextSponsoring.test.ts +++ b/tests/src/nextSponsoring.test.ts @@ -39,7 +39,7 @@ // Check with Disabled sponsoring state expect(await token.getNextSponsored({Substrate: alice.address})).to.be.null; - + // Check with Unconfirmed sponsoring state await collection.setSponsor(alice, bob.address); expect(await token.getNextSponsored({Substrate: alice.address})).to.be.null; @@ -52,7 +52,7 @@ await token.transfer(alice, {Substrate: bob.address}); expect(await token.getNextSponsored({Substrate: alice.address})).to.be.lessThanOrEqual(SPONSORING_TIMEOUT); - // Non-existing token + // Non-existing token expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.null; }); @@ -65,7 +65,7 @@ await collection.setSponsor(alice, bob.address); await collection.confirmSponsorship(bob); - + // Check with Confirmed sponsoring state expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.equal(0); @@ -91,7 +91,7 @@ await token.transfer(alice, {Substrate: bob.address}); expect(await token.getNextSponsored({Substrate: alice.address})).to.be.lessThanOrEqual(SPONSORING_TIMEOUT); - // Non-existing token + // Non-existing token expect(await collection.getTokenNextSponsored(0, {Substrate: alice.address})).to.be.null; }); }); --- a/tests/src/refungible.test.ts +++ b/tests/src/refungible.test.ts @@ -32,36 +32,36 @@ [alice, bob] = await helper.arrange.createAccounts([100n, 10n], donor); }); }); - + itSub('Create refungible collection and token', async ({helper}) => { const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); const itemCountBefore = await collection.getLastTokenId(); const token = await collection.mintToken(alice, 100n); - + const itemCountAfter = await collection.getLastTokenId(); - + // What to expect expect(token?.tokenId).to.be.gte(itemCountBefore); expect(itemCountAfter).to.be.equal(itemCountBefore + 1); expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString()); }); - + itSub('Checking RPC methods when interacting with maximum allowed values (MAX_REFUNGIBLE_PIECES)', async ({helper}) => { const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - + const token = await collection.mintToken(alice, MAX_REFUNGIBLE_PIECES); - + expect(await collection.getTokenBalance(token.tokenId, {Substrate: alice.address})).to.be.equal(MAX_REFUNGIBLE_PIECES); - + await collection.transferToken(alice, token.tokenId, {Substrate: bob.address}, MAX_REFUNGIBLE_PIECES); expect(await collection.getTokenBalance(token.tokenId, {Substrate: bob.address})).to.be.equal(MAX_REFUNGIBLE_PIECES); expect(await token.getTotalPieces()).to.be.equal(MAX_REFUNGIBLE_PIECES); - + await expect(collection.mintToken(alice, MAX_REFUNGIBLE_PIECES + 1n)) .to.eventually.be.rejectedWith(/refungible\.WrongRefungiblePieces/); }); - + itSub('RPC method tokenOwners for refungible collection and token', async ({helper}) => { const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; const facelessCrowd = (await helper.arrange.createAccounts(Array(7).fill(0n), donor)).map(keyring => {return {Substrate: keyring.address};}); @@ -72,32 +72,32 @@ await token.transfer(alice, {Substrate: bob.address}, 1000n); await token.transfer(alice, ethAcc, 900n); - + for (let i = 0; i < 7; i++) { await token.transfer(alice, facelessCrowd[i], 50n * BigInt(i + 1)); - } + } const owners = await token.getTop10Owners(); // What to expect expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); expect(owners.length).to.be.equal(10); - + const [eleven] = await helper.arrange.createAccounts([0n], donor); expect(await token.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; expect((await token.getTop10Owners()).length).to.be.equal(10); }); - + itSub('Transfer token pieces', async ({helper}) => { const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); const token = await collection.mintToken(alice, 100n); expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; - + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n); expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n); - + await expect(token.transfer(alice, {Substrate: bob.address}, 41n)) .to.eventually.be.rejectedWith(/common\.TokenValueTooLow/); }); @@ -111,8 +111,8 @@ // {owner: {Substrate: alice.address}, pieces: 100n}, // ]); await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, [ - {pieces: 1n}, - {pieces: 2n}, + {pieces: 1n}, + {pieces: 2n}, {pieces: 100n}, ]); const lastTokenId = await collection.getLastTokenId(); @@ -133,7 +133,7 @@ itSub('Burn all pieces', async ({helper}) => { const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); const token = await collection.mintToken(alice, 100n); - + expect(await collection.doesTokenExist(token.tokenId)).to.be.true; expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); @@ -146,7 +146,7 @@ const token = await collection.mintToken(alice, 100n); expect(await collection.doesTokenExist(token.tokenId)).to.be.true; - + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; @@ -171,7 +171,7 @@ itSub('Set allowance for token', async ({helper}) => { const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); const token = await collection.mintToken(alice, 100n); - + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); expect(await token.approve(alice, {Substrate: bob.address}, 60n)).to.be.true; @@ -190,14 +190,14 @@ expect(await token.repartition(alice, 200n)).to.be.true; expect(await token.getBalance({Substrate: alice.address})).to.be.equal(200n); expect(await token.getTotalPieces()).to.be.equal(200n); - + expect(await token.transfer(alice, {Substrate: bob.address}, 110n)).to.be.true; expect(await token.getBalance({Substrate: alice.address})).to.be.equal(90n); expect(await token.getBalance({Substrate: bob.address})).to.be.equal(110n); - + await expect(token.repartition(alice, 80n)) .to.eventually.be.rejectedWith(/refungible\.RepartitionWhileNotOwningAllPieces/); - + expect(await token.transfer(alice, {Substrate: bob.address}, 90n)).to.be.true; expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n); expect(await token.getBalance({Substrate: bob.address})).to.be.equal(200n); @@ -220,7 +220,7 @@ data: [ collection.collectionId, token.tokenId, - {substrate: alice.address}, + {substrate: alice.address}, 100n, ], }); @@ -239,12 +239,12 @@ data: [ collection.collectionId, token.tokenId, - {substrate: alice.address}, + {substrate: alice.address}, 50n, ], }); }); - + itSub('Create new collection with properties', async ({helper}) => { const properties = [{key: 'key1', value: 'val1'}]; const tokenPropertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}]; @@ -280,7 +280,7 @@ await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow'); await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 10n)).to.be.rejectedWith('common.TokenValueTooLow'); await expect(tokenBob.transfer(alice, {Substrate: charlie.address}, 100n)).to.be.rejectedWith('common.TokenValueTooLow'); - + // 2. Alice cannot transfer non-existing token: await expect(collection.transferToken(alice, 100, {Substrate: charlie.address}, 0n)).to.be.rejectedWith('common.TokenValueTooLow'); await expect(collection.transferToken(alice, 100, {Substrate: charlie.address}, 1n)).to.be.rejectedWith('common.TokenValueTooLow'); --- a/tests/src/removeCollectionAdmin.test.ts +++ b/tests/src/removeCollectionAdmin.test.ts @@ -94,7 +94,7 @@ itSub('Admin can\'t remove collection admin.', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-4', tokenPrefix: 'RCA'}); - + await collection.addAdmin(alice, {Substrate: bob.address}); await collection.addAdmin(alice, {Substrate: charlie.address}); --- a/tests/src/rpc.test.ts +++ b/tests/src/rpc.test.ts @@ -35,20 +35,20 @@ const owner = (await helper.callRpc('api.rpc.unique.tokenOwner', [collection.collectionId, 0])).toJSON() as any; expect(owner).to.be.null; }); - + itSub('RPC method tokenOwners for fungible collection and token', async ({helper}) => { // Set-up a few token owners of all stripes const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; const facelessCrowd = (await helper.arrange.createAccounts([0n, 0n, 0n, 0n, 0n, 0n, 0n], donor)) .map(i => {return {Substrate: i.address};}); - + const collection = await helper.ft.mintCollection(alice, {name: 'RPC-2', tokenPrefix: 'RPC'}); // mint some maximum (u128) amounts of tokens possible await collection.mint(alice, (1n << 128n) - 1n); - + await collection.transfer(alice, {Substrate: bob.address}, 1000n); await collection.transfer(alice, ethAcc, 900n); - + for (let i = 0; i < facelessCrowd.length; i++) { await collection.transfer(alice, facelessCrowd[i], 1n); } @@ -59,7 +59,7 @@ expect(ids).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); expect(owners.length == 10).to.be.true; - + // Make sure only 10 results are returned with this RPC const [eleven] = await helper.arrange.createAccounts([0n], donor); expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; --- a/tests/src/scheduler.seqtest.ts +++ b/tests/src/scheduler.seqtest.ts @@ -47,7 +47,7 @@ const token = await collection.mintToken(alice); const scheduledId = scheduleKind == 'named' ? helper.arrange.makeScheduledId() : undefined; const blocksBeforeExecution = 4; - + await token.scheduleAfter(blocksBeforeExecution, {scheduledId}) .transfer(alice, {Substrate: bob.address}); const executionBlock = await helper.chain.getLatestBlockNumber() + blocksBeforeExecution + 1; @@ -156,7 +156,7 @@ const maxScheduledPerBlock = 50; let fillScheduledIds = new Array(maxScheduledPerBlock); let extraScheduledId = undefined; - + if (scheduleKind == 'named') { const scheduledIds = helper.arrange.makeScheduledIds(maxScheduledPerBlock + 1); fillScheduledIds = scheduledIds.slice(0, maxScheduledPerBlock); @@ -641,7 +641,7 @@ const balanceBefore = await helper.balance.getSubstrate(bob.address); const scheduled = helper.scheduler.scheduleAfter(waitForBlocks, {scheduledId, priority: 42}); - + await expect(scheduled.balance.transferToSubstrate(alice, bob.address, amount)) .to.be.rejectedWith(/BadOrigin/); --- a/tests/src/setCollectionLimits.test.ts +++ b/tests/src/setCollectionLimits.test.ts @@ -75,7 +75,7 @@ await collection.setLimits(alice, collectionLimits); const collectionInfo1 = await collection.getEffectiveLimits(); - + expect(collectionInfo1.tokenLimit).to.be.equal(tokenLimit); await collection.setLimits(alice, collectionLimits); @@ -108,7 +108,7 @@ [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor); }); }); - + itSub('execute setCollectionLimits for not exists collection', async ({helper}) => { const nonExistentCollectionId = (1 << 32) - 1; await expect(helper.collection.setLimits( @@ -180,7 +180,7 @@ itSub('Setting the higher token limit fails', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-4', tokenPrefix: 'SCL'}); - + const collectionLimits = { accountTokenOwnershipLimit: accountTokenOwnershipLimit, sponsoredMintSize: sponsoredDataSize, --- a/tests/src/setCollectionSponsor.test.ts +++ b/tests/src/setCollectionSponsor.test.ts @@ -37,7 +37,7 @@ Unconfirmed: bob.address, }); }); - + itSub('Set Fungible collection sponsor', async ({helper}) => { const collection = await helper.ft.mintCollection(alice, {name: 'SetCollectionSponsor-1-FT', tokenPrefix: 'SCS'}); await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected; @@ -75,7 +75,7 @@ Unconfirmed: charlie.address, }); }); - + itSub('Collection admin add sponsor', async ({helper}) => { const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-4', tokenPrefix: 'SCS'}); await collection.addAdmin(alice, {Substrate: bob.address}); --- a/tests/src/setPermissions.test.ts +++ b/tests/src/setPermissions.test.ts @@ -34,11 +34,11 @@ await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true, restricted: [1, 2]}}); await collection.setPermissions(alice, {access: 'AllowList', mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true, restricted: [1, 2]}}); - + const permissions = (await collection.getData())?.raw.permissions; expect(permissions).to.be.deep.equal({ - access: 'AllowList', - mintMode: true, + access: 'AllowList', + mintMode: true, nesting: {collectionAdmin: true, tokenOwner: true, restricted: [1, 2]}, }); }); @@ -49,16 +49,16 @@ await collection.setPermissions(alice, {access: 'AllowList', nesting: {collectionAdmin: false, tokenOwner: true, restricted: [1, 2]}}); expect((await collection.getData())?.raw.permissions).to.be.deep.equal({ - access: 'AllowList', - mintMode: false, + access: 'AllowList', + mintMode: false, nesting: {collectionAdmin: false, tokenOwner: true, restricted: [1, 2]}, }); await collection.setPermissions(alice, {access: 'Normal', mintMode: false, nesting: {}}); await collection.setPermissions(alice, {access: 'Normal', mintMode: false, nesting: {}}); expect((await collection.getData())?.raw.permissions).to.be.deep.equal({ - access: 'Normal', - mintMode: false, + access: 'Normal', + mintMode: false, nesting: {collectionAdmin: false, tokenOwner: false, restricted: null}, }); }); @@ -67,7 +67,7 @@ const collection = await helper.nft.mintCollection(alice, {name: 'SetPermissions-2', tokenPrefix: 'SP'}); await collection.addAdmin(alice, {Substrate: bob.address}); await collection.setPermissions(bob, {access: 'AllowList', mintMode: true}); - + expect((await collection.getData())?.raw.permissions.access).to.equal('AllowList'); expect((await collection.getData())?.raw.permissions.mintMode).to.equal(true); }); --- a/tests/src/transfer.nload.ts +++ b/tests/src/transfer.nload.ts @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . +/* eslint-disable @typescript-eslint/no-floating-promises */ import os from 'os'; import {IKeyringPair} from '@polkadot/types/types'; import {usingPlaygrounds} from './util'; --- a/tests/src/transfer.test.ts +++ b/tests/src/transfer.test.ts @@ -29,7 +29,7 @@ [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor); }); }); - + itSub('Balance transfers and check balance', async ({helper}) => { const alicesBalanceBefore = await helper.balance.getSubstrate(alice.address); const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address); @@ -162,7 +162,7 @@ await expect(collection.transfer(alice, {Substrate: bob.address})) .to.be.rejectedWith(/common\.CollectionNotFound/); }); - + itSub.ifWithPallets('[refungible] Transfer with deleted collection_id', [Pallets.ReFungible], async ({helper}) => { const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-1-RFT', description: '', tokenPrefix: 'T'}); const rft = await collection.mintToken(alice, 10n); @@ -279,7 +279,7 @@ donor = await privateKey({filename: __filename}); }); }); - + itEth('Transfers to self. In case of same frontend', async ({helper}) => { const [owner] = await helper.arrange.createAccounts([10n], donor); const collection = await helper.ft.mintCollection(owner, {}); --- a/tests/src/transferFrom.test.ts +++ b/tests/src/transferFrom.test.ts @@ -44,7 +44,7 @@ await collection.mint(alice, 10n); await collection.approveTokens(alice, {Substrate: bob.address}, 7n); expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n); - + await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n); expect(await collection.getBalance({Substrate: charlie.address})).to.be.equal(6n); expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(4n); @@ -56,7 +56,7 @@ const rft = await collection.mintToken(alice, 10n); await rft.approve(alice, {Substrate: bob.address}, 7n); expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n); - + await rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n); expect(await rft.getBalance({Substrate: charlie.address})).to.be.equal(6n); expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(4n); @@ -155,11 +155,11 @@ expect(await nft.isApproved({Substrate: bob.address})).to.be.true; await expect(helper.collection.transferTokenFrom( - bob, - collection.collectionId, - nft.tokenId, - {Substrate: alice.address}, - {Substrate: charlie.address}, + bob, + collection.collectionId, + nft.tokenId, + {Substrate: alice.address}, + {Substrate: charlie.address}, 2n, )).to.be.rejectedWith(/nonfungible\.NonfungibleItemsHaveNoAmount/); expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address}); @@ -202,7 +202,7 @@ await expect(nft.transferFrom( charlie, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address}); @@ -218,7 +218,7 @@ await expect(collection.transferFrom( charlie, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n); @@ -236,7 +236,7 @@ await expect(rft.transferFrom( charlie, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n); @@ -254,7 +254,7 @@ await expect(nft.transferFrom( bob, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); @@ -269,7 +269,7 @@ await expect(collection.transferFrom( alice, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.TokenValueTooLow/); }); @@ -284,7 +284,7 @@ await expect(rft.transferFrom( alice, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.TokenValueTooLow/); }); @@ -300,7 +300,7 @@ await expect(nft.transferFrom( bob, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); @@ -316,7 +316,7 @@ await expect(collection.transferFrom( bob, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.TokenValueTooLow/); }); @@ -332,7 +332,7 @@ await expect(rft.transferFrom( bob, - {Substrate: alice.address}, + {Substrate: alice.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); @@ -345,7 +345,7 @@ await expect(nft.transferFrom( alice, - {Substrate: bob.address}, + {Substrate: bob.address}, {Substrate: charlie.address}, )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); --- a/tests/src/util/globalSetup.ts +++ b/tests/src/util/globalSetup.ts @@ -17,10 +17,10 @@ // 2. Create donors for test files await fundFilenamesWithRetries(3) .then((result) => { - if (!result) Promise.reject(); + if (!result) throw Error('Some problems with fundFilenamesWithRetries'); }); - // 3. Configure App Promotion + // 3. Configure App Promotion const missingPallets = helper.fetchMissingPalletNames([Pallets.AppPromotion]); if (missingPallets.length === 0) { const superuser = await privateKey('//Alice'); @@ -38,7 +38,7 @@ } } catch (error) { console.error(error); - Promise.reject(); + throw Error('Error during globalSetup'); } }); }; @@ -78,7 +78,7 @@ if (aliceBalance < MINIMUM_DONOR_FUND * oneToken) { tx.push(helper.executeExtrinsic( - alice, + alice, 'api.tx.balances.transfer', [account.address, DONOR_FUNDING * oneToken], true, --- a/tests/src/util/index.ts +++ b/tests/src/util/index.ts @@ -41,7 +41,7 @@ else { const actualSeed = getTestSeed(seed.filename); let account = helper.util.fromSeed(actualSeed, ss58Format); - // here's to hoping that no + // here's to hoping that no if (!seed.ignoreFundsPresence && ((helper as any)['balance'] == undefined || await (helper as any).balance.getSubstrate(account.address) < MINIMUM_DONOR_FUND)) { console.warn(`${path.basename(seed.filename)}: Not enough funds present on the filename account. Using the default one as the donor instead.`); account = helper.util.fromSeed('//Alice', ss58Format); @@ -115,7 +115,7 @@ export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) { const missingPallets = helper.fetchMissingPalletNames(requiredPallets); - + if (missingPallets.length > 0) { const skipMsg = `\tSkipping test '${test.test?.title}'.\n\tThe following pallets are missing:\n\t- ${missingPallets.join('\n\t- ')}`; console.warn('\x1b[38:5:208m%s\x1b[0m', skipMsg); @@ -124,13 +124,13 @@ } export function itSub(name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) { - (opts.only ? it.only : + (opts.only ? it.only : opts.skip ? it.skip : it)(name, async function () { await usingPlaygrounds(async (helper, privateKey) => { if (opts.requiredPallets) { requirePalletsOrSkip(this, helper, opts.requiredPallets); } - + await cb({helper, privateKey}); }); }); --- a/tests/src/util/playgrounds/types.ts +++ b/tests/src/util/playgrounds/types.ts @@ -26,7 +26,7 @@ export interface ISubscribeBlockEventsData { number: number; hash: string; - timestamp: number; + timestamp: number; events: IEvent[]; } @@ -56,7 +56,7 @@ connected?: (...args: any[]) => any; disconnected?: (...args: any[]) => any; error?: (...args: any[]) => any; - ready?: (...args: any[]) => any; + ready?: (...args: any[]) => any; decorated?: (...args: any[]) => any; } --- a/tests/src/util/playgrounds/unique.dev.ts +++ b/tests/src/util/playgrounds/unique.dev.ts @@ -35,7 +35,7 @@ this.consoleWarn = console.warn; } - enable() { + enable() { const outFn = (printer: any) => (...args: any[]) => { for (const arg of args) { if (typeof arg !== 'string') @@ -45,7 +45,7 @@ } printer(...args); }; - + console.error = outFn(this.consoleErr.bind(console)); console.log = outFn(this.consoleLog.bind(console)); console.warn = outFn(this.consoleWarn.bind(console)); @@ -188,11 +188,11 @@ } /** - * Generates accounts with the specified UNQ token balance + * Generates accounts with the specified UNQ token balance * @param balances balances for generated accounts. Each balance will be multiplied by the token nominal. * @param donor donor account for balances * @returns array of newly created accounts - * @example const [acc1, acc2, acc3] = await createAccounts([0n, 10n, 20n], donor); + * @example const [acc1, acc2, acc3] = await createAccounts([0n, 10n, 20n], donor); */ createAccounts = async (balances: bigint[], donor: IKeyringPair): Promise => { let nonce = await this.helper.chain.getNonce(donor.address); @@ -212,7 +212,7 @@ } await Promise.all(transactions).catch(_e => {}); - + //#region TODO remove this region, when nonce problem will be solved const checkBalances = async () => { let isSuccess = true; @@ -242,7 +242,7 @@ }; // TODO combine this method and createAccounts into one - createCrowd = async (accountsToCreate: number, withBalance: bigint, donor: IKeyringPair): Promise => { + createCrowd = async (accountsToCreate: number, withBalance: bigint, donor: IKeyringPair): Promise => { const createAsManyAsCan = async () => { let transactions: any = []; const accounts: IKeyringPair[] = []; @@ -250,9 +250,9 @@ const tokenNominal = this.helper.balance.getOneTokenNominal(); for (let i = 0; i < accountsToCreate; i++) { if (i === 500) { // if there are too many accounts to create - await Promise.allSettled(transactions); // wait while first 500 (should be 100 for devnode) tx will be settled + await Promise.allSettled(transactions); // wait while first 500 (should be 100 for devnode) tx will be settled transactions = []; // - nonce = await this.helper.chain.getNonce(donor.address); // update nonce + nonce = await this.helper.chain.getNonce(donor.address); // update nonce } const recepient = this.helper.util.fromSeed(mnemonicGenerate()); accounts.push(recepient); @@ -262,7 +262,7 @@ nonce++; } } - + const fullfilledAccounts = []; await Promise.allSettled(transactions); for (const account of accounts) { @@ -274,7 +274,7 @@ return fullfilledAccounts; }; - + const crowd: IKeyringPair[] = []; // do up to 5 retries for (let index = 0; index < 5 && accountsToCreate !== 0; index++) { @@ -291,7 +291,7 @@ isDevNode = async () => { let blockNumber = (await this.helper.callRpc('api.query.system.number')).toJSON(); if (blockNumber == 0) { - await this.helper.wait.newBlocks(1); + await this.helper.wait.newBlocks(1); blockNumber = (await this.helper.callRpc('api.query.system.number')).toJSON(); } const block2 = await this.helper.callRpc('api.rpc.chain.getBlock', [await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockNumber])]); @@ -310,15 +310,15 @@ const block2date = await findCreationDate(block2); if(block2date! - block1date! < 9000) return true; }; - + async calculcateFee(payer: ICrossAccountId, promise: () => Promise): Promise { const address = payer.Substrate ? payer.Substrate : await this.helper.address.ethToSubstrate(payer.Ethereum!); - let balance = await this.helper.balance.getSubstrate(address); - + let balance = await this.helper.balance.getSubstrate(address); + await promise(); - + balance -= await this.helper.balance.getSubstrate(address); - + return balance; } @@ -335,7 +335,7 @@ const scheduledId = '0x' + '0'.repeat(prefixSize) + hexId; - return scheduledId; + return scheduledId; } const ids = []; @@ -424,7 +424,7 @@ /** * Wait for specified number of blocks * @param blocksCount number of blocks to wait - * @returns + * @returns */ async newBlocks(blocksCount = 1, timeout?: number): Promise { timeout = timeout ?? blocksCount * 60_000; @@ -457,7 +457,7 @@ await this.waitWithTimeout(promise, timeout); return promise; } - + async forRelayBlockNumber(blockNumber: bigint | number, timeout?: number) { timeout = timeout ?? 30 * 60 * 1000; // eslint-disable-next-line no-async-promise-executor @@ -476,7 +476,7 @@ noScheduledTasks() { const api = this.helper.getApi(); - + // eslint-disable-next-line no-async-promise-executor const promise = new Promise(async resolve => { const unsubscribe = await api.rpc.chain.subscribeNewHeads(async () => { @@ -486,7 +486,7 @@ unsubscribe(); resolve(); } - }); + }); }); return promise; @@ -500,16 +500,16 @@ const blockHash = header.hash; const eventIdStr = `${eventSection}.${eventMethod}`; const waitLimitStr = `wait blocks remaining: ${maxBlocksToWait}`; - + this.helper.logger.log(`[Block #${blockNumber}] Waiting for event \`${eventIdStr}\` (${waitLimitStr})`); - + const apiAt = await this.helper.getApi().at(blockHash); const eventRecords = (await apiAt.query.system.events()) as any; - + const neededEvent = eventRecords.toArray().find((r: FrameSystemEventRecord) => { return r.event.section == eventSection && r.event.method == eventMethod; }); - + if (neededEvent) { unsubscribe(); resolve(neededEvent); --- a/tests/src/util/playgrounds/unique.ts +++ b/tests/src/util/playgrounds/unique.ts @@ -1103,7 +1103,7 @@ async getPropertiesConsumedSpace(collectionId: number): Promise { const api = this.helper.getApi(); const props = (await api.query.common.collectionProperties(collectionId)).toJSON(); - + return (props! as any).consumedSpace; } @@ -2423,7 +2423,7 @@ /** * Get schedule for recepient of vested transfer * @param address Substrate address of recipient - * @returns + * @returns */ async getVestingSchedules(address: TSubstrateAccount): Promise<{start: bigint, period: bigint, periodCount: bigint, perPeriod: bigint}[]> { const schedule = (await this.helper.callRpc('api.query.vesting.vestingSchedules', [address])).toJSON(); @@ -2506,16 +2506,16 @@ : typeof key === 'bigint' ? hexToU8a(key.toString(16)) : key; - + if (ss58Format < 0 || ss58Format > 16383 || [46, 47].includes(ss58Format)) { throw new Error(`ss58Format is not valid, received ${typeof ss58Format} "${ss58Format}"`); } - + const allowedDecodedLengths = [1, 2, 4, 8, 32, 33]; if (!allowedDecodedLengths.includes(u8a.length)) { throw new Error(`key length is not valid, received ${u8a.length}, valid values are ${allowedDecodedLengths.join(', ')}`); } - + const u8aPrefix = ss58Format < 64 ? new Uint8Array([ss58Format]) : new Uint8Array([ @@ -2524,7 +2524,7 @@ ]); const input = u8aConcat(u8aPrefix, u8a); - + return base58Encode(u8aConcat( input, blake2AsU8a(input).subarray(0, [32, 33].includes(u8a.length) ? 2 : 1), @@ -2556,7 +2556,7 @@ if (ethCrossAccount.sub === '0') { return {Ethereum: ethCrossAccount.eth.toLocaleLowerCase()}; } - + const ss58 = this.restoreCrossAccountFromBigInt(BigInt(ethCrossAccount.sub)); return {Substrate: ss58}; } @@ -3074,14 +3074,14 @@ executeExtrinsic(sender: IKeyringPair, scheduledExtrinsic: string, scheduledParams: any[], expectSuccess?: boolean): Promise { const scheduledTx = this.constructApiCall(scheduledExtrinsic, scheduledParams); - + const mandatorySchedArgs = [ this.blocksNum, this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null, this.options.priority ?? null, scheduledTx, ]; - + let schedArgs; let scheduleFn; @@ -3301,7 +3301,7 @@ async getTokenPropertiesConsumedSpace(tokenId: number): Promise { const api = this.helper.getApi(); const props = (await api.query.nonfungible.tokenProperties(this.collectionId, tokenId)).toJSON(); - + return (props! as any).consumedSpace; } @@ -3419,7 +3419,7 @@ async getTokenPropertiesConsumedSpace(tokenId: number): Promise { const api = this.helper.getApi(); const props = (await api.query.refungible.tokenProperties(this.collectionId, tokenId)).toJSON(); - + return (props! as any).consumedSpace; } --- a/tests/src/vesting.test.ts +++ b/tests/src/vesting.test.ts @@ -73,7 +73,7 @@ expect(balanceRecepient.feeFrozen).to.eq(250n * nominal); expect(balanceRecepient.miscFrozen).to.eq(250n * nominal); expect(balanceRecepient.reserved).to.eq(0n); - + // Wait first schedule ends and first part od second schedule: await helper.wait.forRelayBlockNumber(SCHEDULE_2_START + SCHEDULE_2_PERIOD); await helper.balance.claim(recepient); @@ -84,7 +84,7 @@ expect(balanceRecepient.feeFrozen).to.eq(100n * nominal); expect(balanceRecepient.miscFrozen).to.eq(100n * nominal); expect(balanceRecepient.reserved).to.eq(0n); - + // Schedules list contain 1 vesting: schedule = await helper.balance.getVestingSchedules(recepient.address); expect(schedule).to.has.length(1); @@ -100,7 +100,7 @@ expect(balanceRecepient.feeFrozen).to.eq(0n); expect(balanceRecepient.miscFrozen).to.eq(0n); expect(balanceRecepient.reserved).to.eq(0n); - + // check sender balance does not changed: balanceSender = await helper.balance.getSubstrateFull(sender.address); expect(balanceSender.free / nominal).to.eq(699n); --- a/tests/src/xcm/xcmOpal.test.ts +++ b/tests/src/xcm/xcmOpal.test.ts @@ -37,12 +37,12 @@ const TRANSFER_AMOUNT = 1_000_000_000_000_000_000n; // 10,000.00 (ten thousands) USDT -const ASSET_AMOUNT = 1_000_000_000_000_000_000_000n; +const ASSET_AMOUNT = 1_000_000_000_000_000_000_000n; describeXCM('[XCM] Integration test: Exchanging USDT with Westmint', () => { let alice: IKeyringPair; let bob: IKeyringPair; - + let balanceStmnBefore: bigint; let balanceStmnAfter: bigint; @@ -66,7 +66,7 @@ await usingWestmintPlaygrounds(westmintUrl, async (helper) => { // 350.00 (three hundred fifty) DOT - const fundingAmount = 3_500_000_000_000n; + const fundingAmount = 3_500_000_000_000n; await helper.assets.create(alice, ASSET_ID, alice.address, ASSET_METADATA_MINIMAL_BALANCE); await helper.assets.setMetadata(alice, ASSET_ID, ASSET_METADATA_NAME, ASSET_METADATA_DESCRIPTION, ASSET_METADATA_DECIMALS); @@ -151,7 +151,7 @@ await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited'); }); - + }); itSub('Should connect and send USDT from Westmint to Opal', async ({helper}) => { @@ -190,7 +190,7 @@ }, { GeneralIndex: ASSET_ID, - }, + }, ]}, }, }, @@ -266,7 +266,7 @@ }, //10_000_000_000_000_000n, TRANSFER_AMOUNT, - ], + ], [ { NativeAssetId: 'Parent', @@ -278,16 +278,16 @@ const feeItem = 1; await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited'); - + // the commission has been paid in parachain native token balanceOpalFinal = await helper.balance.getSubstrate(alice.address); expect(balanceOpalAfter > balanceOpalFinal).to.be.true; await usingWestmintPlaygrounds(westmintUrl, async (helper) => { await helper.wait.newBlocks(3); - + // The USDT token never paid fees. Its amount not changed from begin value. - // Also check that xcm transfer has been succeeded + // Also check that xcm transfer has been succeeded expect((await helper.assets.account(ASSET_ID, alice.address))! == ASSET_AMOUNT).to.be.true; }); }); @@ -341,13 +341,13 @@ await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited'); }); - + await helper.wait.newBlocks(3); - balanceBobAfter = await helper.balance.getSubstrate(bob.address); + balanceBobAfter = await helper.balance.getSubstrate(bob.address); balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'}); - const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; + const wndFee = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; console.log( 'Relay (Westend) to Opal transaction fees: %s OPL', helper.util.bigIntToDecimals(balanceBobAfter - balanceBobBefore), --- a/tests/src/xcm/xcmQuartz.test.ts +++ b/tests/src/xcm/xcmQuartz.test.ts @@ -38,7 +38,7 @@ const TRANSFER_AMOUNT = 2000000000000000000000000n; -const FUNDING_AMOUNT = 3_500_000_0000_000_000n; +const FUNDING_AMOUNT = 3_500_000_0000_000_000n; const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n; @@ -52,7 +52,7 @@ describeXCM('[XCM] Integration test: Exchanging USDT with Statemine', () => { let alice: IKeyringPair; let bob: IKeyringPair; - + let balanceStmnBefore: bigint; let balanceStmnAfter: bigint; @@ -81,7 +81,7 @@ }); await usingStateminePlaygrounds(statemineUrl, async (helper) => { - const sovereignFundingAmount = 3_500_000_000n; + const sovereignFundingAmount = 3_500_000_000n; await helper.assets.create( alice, @@ -185,7 +185,7 @@ await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited'); }); - + }); itSub('Should connect and send USDT from Statemine to Quartz', async ({helper}) => { @@ -224,7 +224,7 @@ }, { GeneralIndex: USDT_ASSET_ID, - }, + }, ]}, }, }, @@ -267,7 +267,7 @@ console.log( '[Statemine -> Quartz] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(balanceQuartzAfter - balanceQuartzBefore), - ); + ); // commission has not paid in USDT token expect(free).to.be.equal(TRANSFER_AMOUNT); // ... and parachain native token @@ -299,7 +299,7 @@ ForeignAssetId: 0, }, TRANSFER_AMOUNT, - ], + ], [ { NativeAssetId: 'Parent', @@ -311,7 +311,7 @@ const feeItem = 1; await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited'); - + // the commission has been paid in parachain native token balanceQuartzFinal = await helper.balance.getSubstrate(alice.address); console.log('[Quartz -> Statemine] transaction fees on Quartz: %s QTZ', helper.util.bigIntToDecimals(balanceQuartzFinal - balanceQuartzAfter)); @@ -319,9 +319,9 @@ await usingStateminePlaygrounds(statemineUrl, async (helper) => { await helper.wait.newBlocks(3); - + // The USDT token never paid fees. Its amount not changed from begin value. - // Also check that xcm transfer has been succeeded + // Also check that xcm transfer has been succeeded expect((await helper.assets.account(USDT_ASSET_ID, alice.address))! == USDT_ASSET_AMOUNT).to.be.true; }); }); @@ -372,10 +372,10 @@ await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited'); }); - + await helper.wait.newBlocks(3); - balanceBobAfter = await helper.balance.getSubstrate(bob.address); + balanceBobAfter = await helper.balance.getSubstrate(bob.address); balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'}); const wndFeeOnQuartz = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; --- a/tests/src/xcm/xcmUnique.test.ts +++ b/tests/src/xcm/xcmUnique.test.ts @@ -38,7 +38,7 @@ const TRANSFER_AMOUNT = 2000000000000000000000000n; -const FUNDING_AMOUNT = 3_500_000_0000_000_000n; +const FUNDING_AMOUNT = 3_500_000_0000_000_000n; const TRANSFER_AMOUNT_RELAY = 50_000_000_000_000_000n; @@ -52,7 +52,7 @@ describeXCM('[XCM] Integration test: Exchanging USDT with Statemint', () => { let alice: IKeyringPair; let bob: IKeyringPair; - + let balanceStmnBefore: bigint; let balanceStmnAfter: bigint; @@ -81,7 +81,7 @@ }); await usingStatemintPlaygrounds(statemintUrl, async (helper) => { - const sovereignFundingAmount = 3_500_000_000n; + const sovereignFundingAmount = 3_500_000_000n; await helper.assets.create( alice, @@ -185,7 +185,7 @@ await helper.xcm.limitedReserveTransferAssets(alice, destination, beneficiary, assets, feeAssetItem, 'Unlimited'); }); - + }); itSub('Should connect and send USDT from Statemint to Unique', async ({helper}) => { @@ -224,7 +224,7 @@ }, { GeneralIndex: USDT_ASSET_ID, - }, + }, ]}, }, }, @@ -267,7 +267,7 @@ console.log( '[Statemint -> Unique] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(balanceUniqueAfter - balanceUniqueBefore), - ); + ); // commission has not paid in USDT token expect(free).to.be.equal(TRANSFER_AMOUNT); // ... and parachain native token @@ -299,7 +299,7 @@ ForeignAssetId: 0, }, TRANSFER_AMOUNT, - ], + ], [ { NativeAssetId: 'Parent', @@ -311,7 +311,7 @@ const feeItem = 1; await helper.xTokens.transferMulticurrencies(alice, currencies, feeItem, destination, 'Unlimited'); - + // the commission has been paid in parachain native token balanceUniqueFinal = await helper.balance.getSubstrate(alice.address); console.log('[Unique -> Statemint] transaction fees on Unique: %s UNQ', helper.util.bigIntToDecimals(balanceUniqueFinal - balanceUniqueAfter)); @@ -319,9 +319,9 @@ await usingStatemintPlaygrounds(statemintUrl, async (helper) => { await helper.wait.newBlocks(3); - + // The USDT token never paid fees. Its amount not changed from begin value. - // Also check that xcm transfer has been succeeded + // Also check that xcm transfer has been succeeded expect((await helper.assets.account(USDT_ASSET_ID, alice.address))! == USDT_ASSET_AMOUNT).to.be.true; }); }); @@ -372,10 +372,10 @@ await helper.xcm.limitedReserveTransferAssets(bob, destination, beneficiary, assets, feeAssetItem, 'Unlimited'); }); - + await helper.wait.newBlocks(3); - balanceBobAfter = await helper.balance.getSubstrate(bob.address); + balanceBobAfter = await helper.balance.getSubstrate(bob.address); balanceBobRelayTokenAfter = await helper.tokens.accounts(bob.address, {NativeAssetId: 'Parent'}); const wndFeeOnUnique = balanceBobRelayTokenAfter - TRANSFER_AMOUNT_RELAY - balanceBobRelayTokenBefore; @@ -909,7 +909,7 @@ const unqRandomAccountAsset = await helper.assets.account(assetId, randomAccountMoonbeam.address); expect(unqRandomAccountAsset).to.be.null; - + balanceForeignUnqTokenFinal = 0n; const unqOutcomeTransfer = balanceForeignUnqTokenMiddle - balanceForeignUnqTokenFinal; --- a/tests/yarn.lock +++ b/tests/yarn.lock @@ -1064,14 +1064,14 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@^5.40.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz#098abb4c9354e19f460d57ab18bff1f676a6cff0" - integrity sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA== +"@typescript-eslint/eslint-plugin@^5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.0.tgz#dadb79df3b0499699b155839fd6792f16897d910" + integrity sha512-AHZtlXAMGkDmyLuLZsRpH3p4G/1iARIwc/T0vIem2YB+xW6pZaXYXzCBnZSF/5fdM97R9QqZWZ+h3iW10XgevQ== dependencies: - "@typescript-eslint/scope-manager" "5.46.1" - "@typescript-eslint/type-utils" "5.46.1" - "@typescript-eslint/utils" "5.46.1" + "@typescript-eslint/scope-manager" "5.47.0" + "@typescript-eslint/type-utils" "5.47.0" + "@typescript-eslint/utils" "5.47.0" debug "^4.3.4" ignore "^5.2.0" natural-compare-lite "^1.4.0" @@ -1079,72 +1079,72 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.40.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.46.1.tgz#1fc8e7102c1141eb64276c3b89d70da8c0ba5699" - integrity sha512-RelQ5cGypPh4ySAtfIMBzBGyrNerQcmfA1oJvPj5f+H4jI59rl9xxpn4bonC0tQvUKOEN7eGBFWxFLK3Xepneg== +"@typescript-eslint/parser@^5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.0.tgz#62e83de93499bf4b500528f74bf2e0554e3a6c8d" + integrity sha512-udPU4ckK+R1JWCGdQC4Qa27NtBg7w020ffHqGyAK8pAgOVuNw7YaKXGChk+udh+iiGIJf6/E/0xhVXyPAbsczw== dependencies: - "@typescript-eslint/scope-manager" "5.46.1" - "@typescript-eslint/types" "5.46.1" - "@typescript-eslint/typescript-estree" "5.46.1" + "@typescript-eslint/scope-manager" "5.47.0" + "@typescript-eslint/types" "5.47.0" + "@typescript-eslint/typescript-estree" "5.47.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@5.46.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz#70af8425c79bbc1178b5a63fb51102ddf48e104a" - integrity sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA== +"@typescript-eslint/scope-manager@5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.0.tgz#f58144a6b0ff58b996f92172c488813aee9b09df" + integrity sha512-dvJab4bFf7JVvjPuh3sfBUWsiD73aiftKBpWSfi3sUkysDQ4W8x+ZcFpNp7Kgv0weldhpmMOZBjx1wKN8uWvAw== dependencies: - "@typescript-eslint/types" "5.46.1" - "@typescript-eslint/visitor-keys" "5.46.1" + "@typescript-eslint/types" "5.47.0" + "@typescript-eslint/visitor-keys" "5.47.0" -"@typescript-eslint/type-utils@5.46.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.46.1.tgz#195033e4b30b51b870dfcf2828e88d57b04a11cc" - integrity sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng== +"@typescript-eslint/type-utils@5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.0.tgz#2b440979c574e317d3473225ae781f292c99e55d" + integrity sha512-1J+DFFrYoDUXQE1b7QjrNGARZE6uVhBqIvdaXTe5IN+NmEyD68qXR1qX1g2u4voA+nCaelQyG8w30SAOihhEYg== dependencies: - "@typescript-eslint/typescript-estree" "5.46.1" - "@typescript-eslint/utils" "5.46.1" + "@typescript-eslint/typescript-estree" "5.47.0" + "@typescript-eslint/utils" "5.47.0" debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.46.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.46.1.tgz#4e9db2107b9a88441c4d5ecacde3bb7a5ebbd47e" - integrity sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w== +"@typescript-eslint/types@5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.0.tgz#67490def406eaa023dbbd8da42ee0d0c9b5229d3" + integrity sha512-eslFG0Qy8wpGzDdYKu58CEr3WLkjwC5Usa6XbuV89ce/yN5RITLe1O8e+WFEuxnfftHiJImkkOBADj58ahRxSg== -"@typescript-eslint/typescript-estree@5.46.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz#5358088f98a8f9939355e0996f9c8f41c25eced2" - integrity sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg== +"@typescript-eslint/typescript-estree@5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.0.tgz#ed971a11c5c928646d6ba7fc9dfdd6e997649aca" + integrity sha512-LxfKCG4bsRGq60Sqqu+34QT5qT2TEAHvSCCJ321uBWywgE2dS0LKcu5u+3sMGo+Vy9UmLOhdTw5JHzePV/1y4Q== dependencies: - "@typescript-eslint/types" "5.46.1" - "@typescript-eslint/visitor-keys" "5.46.1" + "@typescript-eslint/types" "5.47.0" + "@typescript-eslint/visitor-keys" "5.47.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.46.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.46.1.tgz#7da3c934d9fd0eb4002a6bb3429f33298b469b4a" - integrity sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA== +"@typescript-eslint/utils@5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.0.tgz#b5005f7d2696769a1fdc1e00897005a25b3a0ec7" + integrity sha512-U9xcc0N7xINrCdGVPwABjbAKqx4GK67xuMV87toI+HUqgXj26m6RBp9UshEXcTrgCkdGYFzgKLt8kxu49RilDw== dependencies: "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.46.1" - "@typescript-eslint/types" "5.46.1" - "@typescript-eslint/typescript-estree" "5.46.1" + "@typescript-eslint/scope-manager" "5.47.0" + "@typescript-eslint/types" "5.47.0" + "@typescript-eslint/typescript-estree" "5.47.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" semver "^7.3.7" -"@typescript-eslint/visitor-keys@5.46.1": - version "5.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz#126cc6fe3c0f83608b2b125c5d9daced61394242" - integrity sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg== +"@typescript-eslint/visitor-keys@5.47.0": + version "5.47.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.0.tgz#4aca4efbdf6209c154df1f7599852d571b80bb45" + integrity sha512-ByPi5iMa6QqDXe/GmT/hR6MZtVPi0SqMQPDx15FczCBXJo/7M8T88xReOALAfpBLm+zxpPfmhuEvPb577JRAEg== dependencies: - "@typescript-eslint/types" "5.46.1" + "@typescript-eslint/types" "5.47.0" eslint-visitor-keys "^3.3.0" abortcontroller-polyfill@^1.7.3: -- gitstuff