difftreelog
test upgrade for new logic
in: master
28 files changed
tests/src/benchmarks/mintFee/index.tsdiffbeforeafterboth72 ).toString();72 ).toString();737374 const donor = await privateKey('//Alice'); // Seed from account with balance on this network74 const donor = await privateKey('//Alice'); // Seed from account with balance on this network75 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);75 const ethSigner = await helper.eth.createAccountWithBalance(donor);767677 const contract = await helper.ethContract.deployByCode(77 const contract = await helper.ethContract.deployByCode(78 ethSigner,78 ethSigner,131}> {131}> {132 const donor = await privateKey('//Alice');132 const donor = await privateKey('//Alice');133 const substrateReceiver = await privateKey('//Bob');133 const substrateReceiver = await privateKey('//Bob');134 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);134 const ethSigner = await helper.eth.createAccountWithBalance(donor);135135136 const nominal = helper.balance.getOneTokenNominal();136 const nominal = helper.balance.getOneTokenNominal();137137205 setup: { propertiesNumber: number },205 setup: { propertiesNumber: number },206): Promise<IBenchmarkResultForProp> {206): Promise<IBenchmarkResultForProp> {207 const donor = await privateKey('//Alice'); // Seed from account with balance on this network207 const donor = await privateKey('//Alice'); // Seed from account with balance on this network208 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);208 const ethSigner = await helper.eth.createAccountWithBalance(donor);209209210 const susbstrateReceiver = await privateKey('//Bob');210 const susbstrateReceiver = await privateKey('//Bob');211 const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);211 const receiverEthAddress = helper.address.substrateToEth(susbstrateReceiver.address);tests/src/benchmarks/opsFee/index.tsdiffbeforeafterboth61 const res: IFunctionFee = {};61 const res: IFunctionFee = {};62 const donor = await privateKey('//Alice');62 const donor = await privateKey('//Alice');63 const [subReceiver] = await helper.arrange.createAccounts([10n], donor);63 const [subReceiver] = await helper.arrange.createAccounts([10n], donor);64 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);64 const ethSigner = await helper.eth.createAccountWithBalance(donor);65 const ethReceiver = await helper.eth.createAccountWithBalance(donor, 10n);65 const ethReceiver = await helper.eth.createAccountWithBalance(donor);66 const crossSigner = helper.ethCrossAccount.fromAddress(ethSigner);66 const crossSigner = helper.ethCrossAccount.fromAddress(ethSigner);67 const crossReceiver = helper.ethCrossAccount.fromAddress(ethReceiver);67 const crossReceiver = helper.ethCrossAccount.fromAddress(ethReceiver);68 const collection = (await createCollectionForBenchmarks(68 const collection = (await createCollectionForBenchmarks(521 const res: IFunctionFee = {};521 const res: IFunctionFee = {};522 const donor = await privateKey('//Alice');522 const donor = await privateKey('//Alice');523 const [subReceiver] = await helper.arrange.createAccounts([10n], donor);523 const [subReceiver] = await helper.arrange.createAccounts([10n], donor);524 const ethSigner = await helper.eth.createAccountWithBalance(donor, 100n);524 const ethSigner = await helper.eth.createAccountWithBalance(donor);525 const ethReceiver = await helper.eth.createAccountWithBalance(donor, 10n);525 const ethReceiver = await helper.eth.createAccountWithBalance(donor);526 const crossSigner = helper.ethCrossAccount.fromAddress(ethSigner);526 const crossSigner = helper.ethCrossAccount.fromAddress(ethSigner);527 const crossReceiver = helper.ethCrossAccount.fromAddress(ethReceiver);527 const crossReceiver = helper.ethCrossAccount.fromAddress(ethReceiver);528 const collection = (await createCollectionForBenchmarks(528 const collection = (await createCollectionForBenchmarks(tests/src/calibrate.tsdiffbeforeafterboth767677 sqrt() {77 sqrt() {78 if (this.a < 0n) {78 if (this.a < 0n) {79 throw 'square root of negative numbers is not supported';79 throw new Error('square root of negative numbers is not supported');80 }80 }818182 if (this.lt(new Fract(2n))) {82 if (this.lt(new Fract(2n))) {tests/src/collator-selection/collatorSelection.seqtest.tsdiffbeforeafterboth31 // In case there are too many invulnerables already, remove some of them, leaving space for Alice and Bob.31 // In case there are too many invulnerables already, remove some of them, leaving space for Alice and Bob.32 if (invulnerables.length + 2 >= helper.collatorSelection.maxCollators()) {32 if (invulnerables.length + 2 >= helper.collatorSelection.maxCollators()) {33 await Promise.all([33 await Promise.all([34 helper.getSudo().executeExtrinsic(superuser, 'api.tx.collatorSelection.removeInvulnerable', [invulnerables.pop()], true, {nonce: nonce++}),34 helper.getSudo().executeExtrinsic(superuser, 'api.tx.collatorSelection.removeInvulnerable', [invulnerables.pop()!], true, {nonce: nonce++}),35 helper.getSudo().executeExtrinsic(superuser, 'api.tx.collatorSelection.removeInvulnerable', [invulnerables.pop()], true, {nonce: nonce++}),35 helper.getSudo().executeExtrinsic(superuser, 'api.tx.collatorSelection.removeInvulnerable', [invulnerables.pop()!], true, {nonce: nonce++}),36 ]);36 ]);37 }37 }3838tests/src/collator-selection/identity.seqtest.tsdiffbeforeafterboth515152 itSub('Normal calls do not work', async ({helper}) => {52 itSub('Normal calls do not work', async ({helper}) => {53 // console.error = () => {};53 // console.error = () => {};54 await expect(helper.executeExtrinsic(superuser, 'api.tx.identity.setIdentity', [{info: {display: {Raw: 'Meowser'}}}]))54 await expect(helper.executeExtrinsic(superuser, 'api.tx.identity.setIdentity', [{info: {display: {Raw: 'Meowser'}}}] as any))55 .to.be.rejectedWith(/Transaction call is not expected/);55 .to.be.rejectedWith(/Transaction call is not expected/);56 });56 });575762 const crowdSize = 10;62 const crowdSize = 10;63 const crowd = await helper.arrange.createCrowd(crowdSize, 0n, superuser);63 const crowd = await helper.arrange.createCrowd(crowdSize, 0n, superuser);64 const identities = crowd.map((acc, i) => [acc.address, {info: {display: {Raw: `accounter #${i}`}}}]);64 const identities = crowd.map((acc, i) => [acc.address, {info: {display: {Raw: `accounter #${i}`}}}]);65 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities]);65 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities] as any);666667 expect((await getIdentityAccounts(helper)).length).to.be.equal(oldIdentitiesCount + crowdSize);67 expect((await getIdentityAccounts(helper)).length).to.be.equal(oldIdentitiesCount + crowdSize);68 });68 });737374 // insert a single identity74 // insert a single identity75 let singleIdentity = identities.pop()!;75 let singleIdentity = identities.pop()!;76 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [[singleIdentity]]);76 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [[singleIdentity]] as any);777778 const oldIdentitiesCount = (await getIdentityAccounts(helper)).length;78 const oldIdentitiesCount = (await getIdentityAccounts(helper)).length;797980 // change an identity and push it with a few new others80 // change an identity and push it with a few new others81 singleIdentity = [singleIdentity[0], {info: {display: {Raw: 'something special'}}}];81 singleIdentity = [singleIdentity[0], {info: {display: {Raw: 'something special'}}}];82 identities.push(singleIdentity);82 identities.push(singleIdentity);83 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities]);83 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities] as any);848485 // oldIdentitiesCount + 9 because one identity is overwritten, not inserted on top85 // oldIdentitiesCount + 9 because one identity is overwritten, not inserted on top86 expect((await getIdentityAccounts(helper)).length).to.be.equal(oldIdentitiesCount + 9);86 expect((await getIdentityAccounts(helper)).length).to.be.equal(oldIdentitiesCount + 9);91 itSub('Removes identities', async ({helper}) => {91 itSub('Removes identities', async ({helper}) => {92 const crowd = await helper.arrange.createCrowd(10, 0n, superuser);92 const crowd = await helper.arrange.createCrowd(10, 0n, superuser);93 const identities = crowd.map((acc, i) => [acc.address, {info: {display: {Raw: `accounter #${i}`}}}]);93 const identities = crowd.map((acc, i) => [acc.address, {info: {display: {Raw: `accounter #${i}`}}}]);94 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities]);94 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities] as any);95 const oldIdentities = await getIdentityAccounts(helper);95 const oldIdentities = await getIdentityAccounts(helper);969697 // delete a couple, check that they are no longer there97 // delete a couple, check that they are no longer there124 ]),124 ]),125 ],125 ],126 ]);126 ]);127 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo]);127 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo] as any);128128129 for (let i = 0; i < supers.length; i++) {129 for (let i = 0; i < supers.length; i++) {130 // check deposit130 // check deposit162 ]),162 ]),163 ],163 ],164 ]);164 ]);165 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo1]);165 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo1] as any);166166167 // change some sub-identities...167 // change some sub-identities...168 subs[2].pop(); subs[2].pop(); subs[2].push(...await helper.arrange.createAccounts([0n], superuser));168 subs[2].pop(); subs[2].pop(); subs[2].push(...await helper.arrange.createAccounts([0n], superuser));176 ]),176 ]),177 ],177 ],178 ]];178 ]];179 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo2]);179 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo2] as any);180180181 // make sure everything else is the same181 // make sure everything else is the same182 for (let i = 0; i < supers.length - 1; i++) {182 for (let i = 0; i < supers.length - 1; i++) {219 ]),219 ]),220 ],220 ],221 ]];221 ]];222 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo1]);222 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo1] as any);223223224 // empty sub-identities should delete the records224 // empty sub-identities should delete the records225 const subsInfo2 = [[225 const subsInfo2 = [[228 [],228 [],229 ],229 ],230 ]];230 ]];231 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo2]);231 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo2] as any);232232233 // check deposit233 // check deposit234 expect((await helper.getApi().query.identity.subsOf(sup.address)).toHuman()).to.be.deep.equal(['0', []]);234 expect((await helper.getApi().query.identity.subsOf(sup.address)).toHuman()).to.be.deep.equal(['0', []]);245245246 // insert identity246 // insert identity247 const identities = [[sup.address, {info: {display: {Raw: 'mental'}}}]];247 const identities = [[sup.address, {info: {display: {Raw: 'mental'}}}]];248 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities]);248 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceInsertIdentities', [identities] as any);249249250 // and its sub-identities250 // and its sub-identities251 const subsInfo = [[251 const subsInfo = [[256 ]),256 ]),257 ],257 ],258 ]];258 ]];259 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo]);259 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceSetSubs', [subsInfo] as any);260260261 // delete top identity261 // delete top identity262 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceRemoveIdentities', [[sup.address]]);262 await helper.getSudo().executeExtrinsic(superuser, 'api.tx.identity.forceRemoveIdentities', [[sup.address]]);tests/src/creditFeesToTreasury.seqtest.tsdiffbeforeafterboth88 expect(treasuryIncrease).to.be.equal(fee);88 expect(treasuryIncrease).to.be.equal(fee);89 });89 });909091 itSub('Treasury balance increased by failed tx fee', async ({helper}) => {91 itSub.only('Treasury balance increased by failed tx fee', async ({helper}) => {92 const api = helper.getApi();92 const api = helper.getApi();93 await helper.wait.newBlocks(1);93 await helper.wait.newBlocks(1);949495 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);95 const treasuryBalanceBefore = await helper.balance.getSubstrate(TREASURY);96 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);96 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);979798 await expect(helper.signTransaction(bob, api.tx.balances.setBalance(alice.address, 0, 0))).to.be.rejected;98 await expect(helper.signTransaction(bob, api.tx.balances.forceSetBalance(alice.address, 0))).to.be.rejected;9999100 const treasuryBalanceAfter = await helper.balance.getSubstrate(TREASURY);100 const treasuryBalanceAfter = await helper.balance.getSubstrate(TREASURY);101 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);101 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth18import {Pallets, requirePalletsOrSkip, usingPlaygrounds} from '../util/index';18import {Pallets, requirePalletsOrSkip, usingPlaygrounds} from '../util/index';19import {itEth, expect} from './util';19import {itEth, expect} from './util';202021describe('evm nft collection sponsoring', () => {21describe.only('evm nft collection sponsoring', () => {22 let donor: IKeyringPair;22 let donor: IKeyringPair;23 let alice: IKeyringPair;23 let alice: IKeyringPair;24 let nominal: bigint;24 let nominal: bigint;319 });319 });320});320});321321322describe('evm RFT collection sponsoring', () => {322describe.only('evm RFT collection sponsoring', () => {323 let donor: IKeyringPair;323 let donor: IKeyringPair;324 let alice: IKeyringPair;324 let alice: IKeyringPair;325 let nominal: bigint;325 let nominal: bigint;592 tokenId: '1',592 tokenId: '1',593 },593 },594 });594 });595 // FIXME: doesn't work595 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');596 expect(await collectionEvm.methods.tokenURI(tokenId).call({from: user})).to.be.equal('Test URI');596597597 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));598 const ownerBalanceAfter = await helper.balance.getSubstrate(helper.address.ethToSubstrate(owner));tests/src/eth/createFTCollection.seqtest.tsdiffbeforeafterboth202021const DECIMALS = 18;21const DECIMALS = 18;222223describe('Create FT collection from EVM', () => {23describe.only('Create FT collection from EVM', () => {24 let donor: IKeyringPair;24 let donor: IKeyringPair;252526 before(async function() {26 before(async function() {tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth222223const DECIMALS = 18;23const DECIMALS = 18;242425describe('Create FT collection from EVM', () => {25describe.only('Create FT collection from EVM', () => {26 let donor: IKeyringPair;26 let donor: IKeyringPair;272728 before(async function() {28 before(async function() {129 });129 });130});130});131131132describe('(!negative tests!) Create FT collection from EVM', () => {132describe.only('(!negative tests!) Create FT collection from EVM', () => {133 let donor: IKeyringPair;133 let donor: IKeyringPair;134 let nominal: bigint;134 let nominal: bigint;135135tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth21import {COLLECTION_HELPER} from '../util';21import {COLLECTION_HELPER} from '../util';2222232324describe('Create NFT collection from EVM', () => {24describe.only('Create NFT collection from EVM', () => {25 let donor: IKeyringPair;25 let donor: IKeyringPair;262627 before(async function () {27 before(async function () {143 });143 });144});144});145145146describe('(!negative tests!) Create NFT collection from EVM', () => {146describe.only('(!negative tests!) Create NFT collection from EVM', () => {147 let donor: IKeyringPair;147 let donor: IKeyringPair;148 let nominal: bigint;148 let nominal: bigint;149149199 // Soft-deprecated199 // Soft-deprecated200 itEth('(!negative test!) [eth] Check owner', async ({helper}) => {200 itEth('(!negative test!) [eth] Check owner', async ({helper}) => {201 const owner = await helper.eth.createAccountWithBalance(donor);201 const owner = await helper.eth.createAccountWithBalance(donor);202 // FIXME: do not give balance202 const malfeasant = helper.eth.createAccount();203 const malfeasant = await helper.eth.createAccountWithBalance(donor);203 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR');204 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR');204 const malfeasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant, true);205 const malfeasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant, true);205 const EXPECTED_ERROR = 'NoPermission';206 const EXPECTED_ERROR = 'NoPermission';tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth21import {CollectionLimitField} from './util/playgrounds/types';21import {CollectionLimitField} from './util/playgrounds/types';2222232324describe('Create RFT collection from EVM', () => {24describe.only('Create RFT collection from EVM', () => {25 let donor: IKeyringPair;25 let donor: IKeyringPair;262627 before(async function() {27 before(async function() {63 const baseUri = 'BaseURI';63 const baseUri = 'BaseURI';646465 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);65 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);66 // FIXME: caller is not needed66 const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft');67 const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);676868 const collection = helper.rft.getCollectionObject(collectionId);69 const collection = helper.rft.getCollectionObject(collectionId);69 const data = (await collection.getData())!;70 const data = (await collection.getData())!;153 });154 });154});155});155156156describe('(!negative tests!) Create RFT collection from EVM', () => {157describe.only('(!negative tests!) Create RFT collection from EVM', () => {157 let donor: IKeyringPair;158 let donor: IKeyringPair;158 let nominal: bigint;159 let nominal: bigint;159160tests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterboth80};80};8181828283describe('Fractionalizer contract usage', () => {83describe.only('Fractionalizer contract usage', () => {84 let donor: IKeyringPair;84 let donor: IKeyringPair;858586 before(async function() {86 before(async function() {91 });91 });929293 itEth('Set RFT collection', async ({helper}) => {93 itEth('Set RFT collection', async ({helper}) => {94 const owner = await helper.eth.createAccountWithBalance(donor, 10n);94 const owner = await helper.eth.createAccountWithBalance(donor);95 const fractionalizer = await deployContract(helper, owner);95 const fractionalizer = await deployContract(helper, owner);96 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');96 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');97 const rftContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);97 const rftContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);109 });109 });110110111 itEth('Mint RFT collection', async ({helper}) => {111 itEth('Mint RFT collection', async ({helper}) => {112 const owner = await helper.eth.createAccountWithBalance(donor, 10n);112 const owner = await helper.eth.createAccountWithBalance(donor);113 const fractionalizer = await deployContract(helper, owner);113 const fractionalizer = await deployContract(helper, owner);114 await helper.balance.transferToSubstrate(donor, evmToAddress(fractionalizer.options.address), 10n * helper.balance.getOneTokenNominal());114 await helper.balance.transferToSubstrate(donor, evmToAddress(fractionalizer.options.address), 10n * helper.balance.getOneTokenNominal());115115121 });121 });122122123 itEth('Set Allowlist', async ({helper}) => {123 itEth('Set Allowlist', async ({helper}) => {124 const owner = await helper.eth.createAccountWithBalance(donor, 20n);124 const owner = await helper.eth.createAccountWithBalance(donor);125 const {contract: fractionalizer} = await initContract(helper, owner);125 const {contract: fractionalizer} = await initContract(helper, owner);126 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');126 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');127127146 });146 });147147148 itEth('NFT to RFT', async ({helper}) => {148 itEth('NFT to RFT', async ({helper}) => {149 const owner = await helper.eth.createAccountWithBalance(donor, 20n);149 const owner = await helper.eth.createAccountWithBalance(donor);150150151 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');151 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');152 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);152 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);169 });169 });170 const rftTokenAddress = result.events.Fractionalized.returnValues._rftToken;170 const rftTokenAddress = result.events.Fractionalized.returnValues._rftToken;171171172 // FIXME: should work without the caller172 const rftTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress);173 const rftTokenContract = await helper.ethNativeContract.rftToken(rftTokenAddress, owner);173 expect(await rftTokenContract.methods.balanceOf(owner).call()).to.equal('100');174 expect(await rftTokenContract.methods.balanceOf(owner).call()).to.equal('100');174 });175 });175176176 itEth('RFT to NFT', async ({helper}) => {177 itEth('RFT to NFT', async ({helper}) => {177 const owner = await helper.eth.createAccountWithBalance(donor, 30n);178 const owner = await helper.eth.createAccountWithBalance(donor);178179179 const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);180 const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);180 const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await mintRFTToken(helper, owner, fractionalizer, 100n);181 const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await mintRFTToken(helper, owner, fractionalizer, 100n);197 });198 });198199199 itEth('Test fractionalizer NFT <-> RFT mapping ', async ({helper}) => {200 itEth('Test fractionalizer NFT <-> RFT mapping ', async ({helper}) => {200 const owner = await helper.eth.createAccountWithBalance(donor, 200n);201 const owner = await helper.eth.createAccountWithBalance(donor);201202202 const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);203 const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);203 const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await mintRFTToken(helper, owner, fractionalizer, 100n);204 const {rftTokenAddress, nftCollectionAddress, nftTokenId} = await mintRFTToken(helper, owner, fractionalizer, 100n);232 });233 });233234234 itEth('call setRFTCollection twice', async ({helper}) => {235 itEth('call setRFTCollection twice', async ({helper}) => {235 const owner = await helper.eth.createAccountWithBalance(donor, 20n);236 const owner = await helper.eth.createAccountWithBalance(donor);236 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');237 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');237 const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);238 const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);238239246 });247 });247248248 itEth('call setRFTCollection with NFT collection', async ({helper}) => {249 itEth('call setRFTCollection with NFT collection', async ({helper}) => {249 const owner = await helper.eth.createAccountWithBalance(donor, 20n);250 const owner = await helper.eth.createAccountWithBalance(donor);250 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');251 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');251 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);252 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);252253259 });260 });260261261 itEth('call setRFTCollection while not collection admin', async ({helper}) => {262 itEth('call setRFTCollection while not collection admin', async ({helper}) => {262 const owner = await helper.eth.createAccountWithBalance(donor, 20n);263 const owner = await helper.eth.createAccountWithBalance(donor);263 const fractionalizer = await deployContract(helper, owner);264 const fractionalizer = await deployContract(helper, owner);264 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');265 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');265266268 });269 });269270270 itEth('call setRFTCollection after createAndSetRFTCollection', async ({helper}) => {271 itEth('call setRFTCollection after createAndSetRFTCollection', async ({helper}) => {271 const owner = await helper.eth.createAccountWithBalance(donor, 20n);272 const owner = await helper.eth.createAccountWithBalance(donor);272 const fractionalizer = await deployContract(helper, owner);273 const fractionalizer = await deployContract(helper, owner);273 await helper.balance.transferToSubstrate(donor, evmToAddress(fractionalizer.options.address), 10n * helper.balance.getOneTokenNominal());274 await helper.balance.transferToSubstrate(donor, evmToAddress(fractionalizer.options.address), 10n * helper.balance.getOneTokenNominal());274275280 });281 });281282282 itEth('call nft2rft without setting RFT collection for contract', async ({helper}) => {283 itEth('call nft2rft without setting RFT collection for contract', async ({helper}) => {283 const owner = await helper.eth.createAccountWithBalance(donor, 20n);284 const owner = await helper.eth.createAccountWithBalance(donor);284285285 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');286 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');286 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);287 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);294 });295 });295296296 itEth('call nft2rft while not owner of NFT token', async ({helper}) => {297 itEth('call nft2rft while not owner of NFT token', async ({helper}) => {297 const owner = await helper.eth.createAccountWithBalance(donor, 20n);298 const owner = await helper.eth.createAccountWithBalance(donor);298 const nftOwner = await helper.eth.createAccountWithBalance(donor, 10n);299 const nftOwner = await helper.eth.createAccountWithBalance(donor);299300300 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');301 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');301 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);302 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);312 });313 });313314314 itEth('call nft2rft while not in list of allowed accounts', async ({helper}) => {315 itEth('call nft2rft while not in list of allowed accounts', async ({helper}) => {315 const owner = await helper.eth.createAccountWithBalance(donor, 20n);316 const owner = await helper.eth.createAccountWithBalance(donor);316317317 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');318 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');318 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);319 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);327 });328 });328329329 itEth('call nft2rft while fractionalizer doesnt have approval for nft token', async ({helper}) => {330 itEth('call nft2rft while fractionalizer doesnt have approval for nft token', async ({helper}) => {330 const owner = await helper.eth.createAccountWithBalance(donor, 20n);331 const owner = await helper.eth.createAccountWithBalance(donor);331332332 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');333 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');333 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);334 const nftContract = await helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);342 });343 });343344344 itEth('call rft2nft without setting RFT collection for contract', async ({helper}) => {345 itEth('call rft2nft without setting RFT collection for contract', async ({helper}) => {345 const owner = await helper.eth.createAccountWithBalance(donor, 20n);346 const owner = await helper.eth.createAccountWithBalance(donor);346347347 const fractionalizer = await deployContract(helper, owner);348 const fractionalizer = await deployContract(helper, owner);348 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');349 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');355 });356 });356357357 itEth('call rft2nft for RFT token that is not from configured RFT collection', async ({helper}) => {358 itEth('call rft2nft for RFT token that is not from configured RFT collection', async ({helper}) => {358 const owner = await helper.eth.createAccountWithBalance(donor, 20n);359 const owner = await helper.eth.createAccountWithBalance(donor);359360360 const {contract: fractionalizer} = await initContract(helper, owner);361 const {contract: fractionalizer} = await initContract(helper, owner);361 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');362 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');368 });369 });369370370 itEth('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({helper}) => {371 itEth('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({helper}) => {371 const owner = await helper.eth.createAccountWithBalance(donor, 20n);372 const owner = await helper.eth.createAccountWithBalance(donor);372 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');373 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');373 const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);374 const refungibleContract = await helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);374375386 });387 });387388388 itEth('call rft2nft without owning all RFT pieces', async ({helper}) => {389 itEth('call rft2nft without owning all RFT pieces', async ({helper}) => {389 const owner = await helper.eth.createAccountWithBalance(donor, 200n);390 const owner = await helper.eth.createAccountWithBalance(donor);390 const receiver = await helper.eth.createAccountWithBalance(donor, 10n);391 const receiver = await helper.eth.createAccountWithBalance(donor);391392392 const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);393 const {contract: fractionalizer, rftCollectionAddress} = await initContract(helper, owner);393 const {rftTokenAddress} = await mintRFTToken(helper, owner, fractionalizer, 100n);394 const {rftTokenAddress} = await mintRFTToken(helper, owner, fractionalizer, 100n);401 });402 });402403403 itEth('send QTZ/UNQ to contract from non owner', async ({helper}) => {404 itEth('send QTZ/UNQ to contract from non owner', async ({helper}) => {404 const owner = await helper.eth.createAccountWithBalance(donor, 20n);405 const owner = await helper.eth.createAccountWithBalance(donor);405 const payer = await helper.eth.createAccountWithBalance(donor, 10n);406 const payer = await helper.eth.createAccountWithBalance(donor);406407407 const fractionalizer = await deployContract(helper, owner);408 const fractionalizer = await deployContract(helper, owner);408 const amount = 10n * helper.balance.getOneTokenNominal();409 const amount = 10n * helper.balance.getOneTokenNominal();413 itEth('fractionalize NFT with NFT transfers disallowed', async ({helper}) => {414 itEth('fractionalize NFT with NFT transfers disallowed', async ({helper}) => {414 const nftCollection = await helper.nft.mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});415 const nftCollection = await helper.nft.mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});415416416 const owner = await helper.eth.createAccountWithBalance(donor, 20n);417 const owner = await helper.eth.createAccountWithBalance(donor);417 const nftToken = await nftCollection.mintToken(donor, {Ethereum: owner});418 const nftToken = await nftCollection.mintToken(donor, {Ethereum: owner});418 await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [nftCollection.collectionId, false], true);419 await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [nftCollection.collectionId, false], true);419 const nftCollectionAddress = helper.ethAddress.fromCollectionId(nftCollection.collectionId);420 const nftCollectionAddress = helper.ethAddress.fromCollectionId(nftCollection.collectionId);427 });428 });428429429 itEth('fractionalize NFT with RFT transfers disallowed', async ({helper}) => {430 itEth('fractionalize NFT with RFT transfers disallowed', async ({helper}) => {430 const owner = await helper.eth.createAccountWithBalance(donor, 20n);431 const owner = await helper.eth.createAccountWithBalance(donor);431432432 const rftCollection = await helper.rft.mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});433 const rftCollection = await helper.rft.mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});433 const rftCollectionAddress = helper.ethAddress.fromCollectionId(rftCollection.collectionId);434 const rftCollectionAddress = helper.ethAddress.fromCollectionId(rftCollection.collectionId);tests/src/eth/fungible.test.tsdiffbeforeafterboth205205206206207 itEth('Can perform burnFromCross()', async ({helper}) => {207 itEth('Can perform burnFromCross()', async ({helper}) => {208 const sender = await helper.eth.createAccountWithBalance(donor, 100n);208 const sender = await helper.eth.createAccountWithBalance(donor);209209210 const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);210 const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);211211382 });382 });383383384 itEth('Can perform transferFromCross()', async ({helper}) => {384 itEth('Can perform transferFromCross()', async ({helper}) => {385 const sender = await helper.eth.createAccountWithBalance(donor, 100n);385 const sender = await helper.eth.createAccountWithBalance(donor);386386387 const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);387 const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);388388603 });603 });604604605 itEth('Events emitted for transferFromCross()', async ({helper}) => {605 itEth('Events emitted for transferFromCross()', async ({helper}) => {606 const sender = await helper.eth.createAccountWithBalance(donor, 100n);606 const sender = await helper.eth.createAccountWithBalance(donor);607607608 const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);608 const collection = await helper.ft.mintCollection(owner, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);609609tests/src/eth/nonFungible.test.tsdiffbeforeafterboth303 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});303 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});304304305 const owner = await helper.eth.createAccountWithBalance(donor);305 const owner = await helper.eth.createAccountWithBalance(donor);306 const operator = await helper.eth.createAccountWithBalance(donor, 100n);306 const operator = await helper.eth.createAccountWithBalance(donor);307307308 const token = await collection.mintToken(minter, {Ethereum: owner});308 const token = await collection.mintToken(minter, {Ethereum: owner});309309366 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});366 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});367 const ownerSub = bob;367 const ownerSub = bob;368 const ownerCrossSub = helper.ethCrossAccount.fromKeyringPair(ownerSub);368 const ownerCrossSub = helper.ethCrossAccount.fromKeyringPair(ownerSub);369 const ownerEth = await helper.eth.createAccountWithBalance(donor, 100n);369 const ownerEth = await helper.eth.createAccountWithBalance(donor);370 const ownerCrossEth = helper.ethCrossAccount.fromAddress(ownerEth);370 const ownerCrossEth = helper.ethCrossAccount.fromAddress(ownerEth);371371372 const burnerEth = await helper.eth.createAccountWithBalance(donor, 100n);372 const burnerEth = await helper.eth.createAccountWithBalance(donor);373 const burnerCrossEth = helper.ethCrossAccount.fromAddress(burnerEth);373 const burnerCrossEth = helper.ethCrossAccount.fromAddress(burnerEth);374374375 const token1 = await collection.mintToken(minter, {Substrate: ownerSub.address});375 const token1 = await collection.mintToken(minter, {Substrate: ownerSub.address});411 // TODO combine all approve tests in one place411 // TODO combine all approve tests in one place412 itEth('Can perform approveCross()', async ({helper}) => {412 itEth('Can perform approveCross()', async ({helper}) => {413 // arrange: create accounts413 // arrange: create accounts414 const owner = await helper.eth.createAccountWithBalance(donor, 100n);414 const owner = await helper.eth.createAccountWithBalance(donor);415 const ownerCross = helper.ethCrossAccount.fromAddress(owner);415 const ownerCross = helper.ethCrossAccount.fromAddress(owner);416 const receiverSub = charlie;416 const receiverSub = charlie;417 const recieverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub);417 const recieverCrossSub = helper.ethCrossAccount.fromKeyringPair(receiverSub);418 const receiverEth = await helper.eth.createAccountWithBalance(donor, 100n);418 const receiverEth = await helper.eth.createAccountWithBalance(donor);419 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);419 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);420420421 // arrange: create collection and tokens:421 // arrange: create collection and tokens:469 });469 });470470471 itEth('Can reaffirm approved address', async ({helper}) => {471 itEth('Can reaffirm approved address', async ({helper}) => {472 const owner = await helper.eth.createAccountWithBalance(donor, 100n);472 const owner = await helper.eth.createAccountWithBalance(donor);473 const ownerCrossEth = helper.ethCrossAccount.fromAddress(owner);473 const ownerCrossEth = helper.ethCrossAccount.fromAddress(owner);474 const [receiver1, receiver2] = await helper.arrange.createAccounts([100n, 100n], donor);474 const [receiver1, receiver2] = await helper.arrange.createAccounts([100n, 100n], donor);475 const receiver1Cross = helper.ethCrossAccount.fromKeyringPair(receiver1);475 const receiver1Cross = helper.ethCrossAccount.fromKeyringPair(receiver1);743 const receiver = charlie;743 const receiver = charlie;744 const collection = await helper.nft.mintCollection(collectionMinter, {name: 'A', description: 'B', tokenPrefix: 'C'});744 const collection = await helper.nft.mintCollection(collectionMinter, {name: 'A', description: 'B', tokenPrefix: 'C'});745745746 const spender = await helper.eth.createAccountWithBalance(donor, 100n);746 const spender = await helper.eth.createAccountWithBalance(donor);747747748 const token = await collection.mintToken(collectionMinter, {Substrate: owner.address});748 const token = await collection.mintToken(collectionMinter, {Substrate: owner.address});749749929 });929 });930 });930 });931931932 itEth('Returns collection name', async ({helper}) => {932 itEth.only('Returns collection name', async ({helper}) => {933 // FIXME: should not have balance to use .call()933 const caller = await helper.eth.createAccountWithBalance(donor);934 const caller = await helper.eth.createAccountWithBalance(donor);934 const tokenPropertyPermissions = [{935 const tokenPropertyPermissions = [{935 key: 'URI',936 key: 'URI',995 itEth('[negative] Cant perform burn without approval', async ({helper}) => {996 itEth('[negative] Cant perform burn without approval', async ({helper}) => {996 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});997 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});997998998 const owner = await helper.eth.createAccountWithBalance(donor, 100n);999 const owner = await helper.eth.createAccountWithBalance(donor);999 const spender = await helper.eth.createAccountWithBalance(donor, 100n);1000 const spender = await helper.eth.createAccountWithBalance(donor);100010011001 const token = await collection.mintToken(minter, {Ethereum: owner});1002 const token = await collection.mintToken(minter, {Ethereum: owner});100210031016 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});1017 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});1017 const receiver = alice;1018 const receiver = alice;101810191019 const owner = await helper.eth.createAccountWithBalance(donor, 100n);1020 const owner = await helper.eth.createAccountWithBalance(donor);1020 const spender = await helper.eth.createAccountWithBalance(donor, 100n);1021 const spender = await helper.eth.createAccountWithBalance(donor);102110221022 const token = await collection.mintToken(minter, {Ethereum: owner});1023 const token = await collection.mintToken(minter, {Ethereum: owner});10231024tests/src/eth/payable.test.tsdiffbeforeafterboth41 expect(await contract.methods.getCollected().call()).to.be.equal('10000');41 expect(await contract.methods.getCollected().call()).to.be.equal('10000');42 });42 });434344 itEth('Evm contract can receive wei from substrate account', async ({helper}) => {44 itEth.only('Evm contract can receive wei from substrate account', async ({helper}) => {45 const deployer = await helper.eth.createAccountWithBalance(donor);45 const deployer = await helper.eth.createAccountWithBalance(donor);46 const contract = await helper.eth.deployCollectorContract(deployer);46 const contract = await helper.eth.deployCollectorContract(deployer);47 const [alice] = await helper.arrange.createAccounts([10n], donor);47 const [alice] = await helper.arrange.createAccounts([40n], donor);484849 const weiCount = '10000';49 const weiCount = '10000';5050tests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth178 itEth.skip('Can perform mintBulk()', async ({helper}) => {178 itEth.skip('Can perform mintBulk()', async ({helper}) => {179 const collection = await helper.nft.mintCollection(donor, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});179 const collection = await helper.nft.mintCollection(donor, {name: 'New', description: 'New collection', tokenPrefix: 'NEW'});180180181 const caller = await helper.eth.createAccountWithBalance(donor, 30n);181 const caller = await helper.eth.createAccountWithBalance(donor);182 const receiver = helper.eth.createAccount();182 const receiver = helper.eth.createAccount();183183184 const address = helper.ethAddress.fromCollectionId(collection.collectionId);184 const address = helper.ethAddress.fromCollectionId(collection.collectionId);tests/src/eth/reFungible.test.tsdiffbeforeafterboth177 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});177 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});178178179 const owner = await helper.eth.createAccountWithBalance(donor);179 const owner = await helper.eth.createAccountWithBalance(donor);180 const operator = await helper.eth.createAccountWithBalance(donor, 100n);180 const operator = await helper.eth.createAccountWithBalance(donor);181181182 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});182 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});183183206 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});206 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});207207208 const owner = await helper.eth.createAccountWithBalance(donor);208 const owner = await helper.eth.createAccountWithBalance(donor);209 const operator = await helper.eth.createAccountWithBalance(donor, 100n);209 const operator = await helper.eth.createAccountWithBalance(donor);210210211 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});211 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});212212331 itEth('Can perform burnFrom()', async ({helper}) => {331 itEth('Can perform burnFrom()', async ({helper}) => {332 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});332 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});333333334 const owner = await helper.eth.createAccountWithBalance(donor, 100n);334 const owner = await helper.eth.createAccountWithBalance(donor);335 const spender = await helper.eth.createAccountWithBalance(donor, 100n);335 const spender = await helper.eth.createAccountWithBalance(donor);336336337 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});337 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});338338365 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});365 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});366366367 const owner = bob;367 const owner = bob;368 const spender = await helper.eth.createAccountWithBalance(donor, 100n);368 const spender = await helper.eth.createAccountWithBalance(donor);369369370 const token = await collection.mintToken(minter, 100n, {Substrate: owner.address});370 const token = await collection.mintToken(minter, 100n, {Substrate: owner.address});371371397 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});397 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});398398399 const owner = bob;399 const owner = bob;400 const spender = await helper.eth.createAccountWithBalance(donor, 100n);400 const spender = await helper.eth.createAccountWithBalance(donor);401 const receiver = charlie;401 const receiver = charlie;402402403 const token = await collection.mintToken(minter, 100n, {Substrate: owner.address});403 const token = await collection.mintToken(minter, 100n, {Substrate: owner.address});679 });679 });680 });680 });681681682 itEth('Returns collection name', async ({helper}) => {682 itEth.only('Returns collection name', async ({helper}) => {683 // FIXME: should not have balance to use .call()683 const caller = helper.eth.createAccount();684 const caller = await helper.eth.createAccountWithBalance(alice);684 const tokenPropertyPermissions = [{685 const tokenPropertyPermissions = [{685 key: 'URI',686 key: 'URI',686 permission: {687 permission: {747 itEth('[negative] Cant perform burn without approval', async ({helper}) => {748 itEth('[negative] Cant perform burn without approval', async ({helper}) => {748 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});749 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});749750750 const owner = await helper.eth.createAccountWithBalance(donor, 100n);751 const owner = await helper.eth.createAccountWithBalance(donor);751 const spender = await helper.eth.createAccountWithBalance(donor, 100n);752 const spender = await helper.eth.createAccountWithBalance(donor);752753753 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});754 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});754755767768768 itEth('[negative] Cant perform transfer without approval', async ({helper}) => {769 itEth('[negative] Cant perform transfer without approval', async ({helper}) => {769 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});770 const collection = await helper.rft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});770 const owner = await helper.eth.createAccountWithBalance(donor, 100n);771 const owner = await helper.eth.createAccountWithBalance(donor);771 const receiver = alice;772 const receiver = alice;772773773 const spender = await helper.eth.createAccountWithBalance(donor, 100n);774 const spender = await helper.eth.createAccountWithBalance(donor);774775775 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});776 const token = await collection.mintToken(minter, 100n, {Ethereum: owner});776777tests/src/eth/tokenProperties.test.tsdiffbeforeafterboth29 before(async function() {29 before(async function() {30 await usingEthPlaygrounds(async (helper, privateKey) => {30 await usingEthPlaygrounds(async (helper, privateKey) => {31 donor = await privateKey({url: import.meta.url});31 donor = await privateKey({url: import.meta.url});32 [alice] = await helper.arrange.createAccounts([100n], donor);32 [alice] = await helper.arrange.createAccounts([1000n], donor);33 });33 });34 });34 });3535314 expect(result.length).to.equal(0);314 expect(result.length).to.equal(0);315 }));315 }));316316317 itEth('Can be read', async({helper}) => {317 itEth.only('Can be read', async({helper}) => {318 // FIXME: User with no balance should be able to call318 const caller = helper.eth.createAccount();319 const caller = await helper.eth.createAccountWithBalance(alice);319 const collection = await helper.nft.mintCollection(alice, {320 const collection = await helper.nft.mintCollection(alice, {320 tokenPropertyPermissions: [{321 tokenPropertyPermissions: [{321 key: 'testKey',322 key: 'testKey',tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth49 }49 }50}50}515152function unlimitedMoneyHack<C>(_contract: C): C {53 const contract = _contract as any;54 // Hack: fight against gasPrice override55 for (const method in contract.methods) {56 const _method = contract.methods[method];57 contract.methods[method] = function (...args: any) {58 const encodedCall = _method.call(this, ...args);59 const _call = encodedCall.call;60 encodedCall.call = function (...args: any) {61 if (args.length === 0) {62 return _call.call(this, {gasPrice: '0'});63 }64 // No support for callback/defaultBlock, they may be placed as first argument65 if (typeof args[0] !== 'object')66 throw new Error('only options are supported');67 args[0].gasPrice = '0';68 return _call.call(this, ...args);69 };70 return encodedCall;71 };72 }73 return contract;74}755276class ContractGroup extends EthGroupBase {53class ContractGroup extends EthGroupBase {77 async findImports(imports?: ContractImports[]){54 async findImports(imports?: ContractImports[]) {137 gas: gas ?? this.helper.eth.DEFAULT_GAS,114 gas: gas ?? this.helper.eth.DEFAULT_GAS,138 gasPrice: await this.getGasPrice(),115 gasPrice: await this.getGasPrice(),139 });116 });140 return unlimitedMoneyHack(await contract.deploy({data: object}).send({from: signer}));117 return await contract.deploy({data: object}).send({from: signer});141 }118 }142119143}120}146123147 async contractHelpers(caller: string): Promise<Contract> {124 async contractHelpers(caller: string): Promise<Contract> {148 const web3 = this.helper.getWeb3();125 const web3 = this.helper.getWeb3();149 return unlimitedMoneyHack(new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), {126 return new web3.eth.Contract(contractHelpersAbi as any, this.helper.getApi().consts.evmContractHelpers.contractAddress.toString(), {150 from: caller,127 from: caller,151 gas: this.helper.eth.DEFAULT_GAS,128 gas: this.helper.eth.DEFAULT_GAS,152 gasPrice: await this.getGasPrice(),129 gasPrice: await this.getGasPrice(),153 }));130 });154 }131 }155132156 async collectionHelpers(caller: string) {133 async collectionHelpers(caller: string) {157 const web3 = this.helper.getWeb3();134 const web3 = this.helper.getWeb3();158 return unlimitedMoneyHack(new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), {135 return new web3.eth.Contract(collectionHelpersAbi as any, this.helper.getApi().consts.common.contractAddress.toString(), {159 from: caller,136 from: caller,160 gas: this.helper.eth.DEFAULT_GAS,137 gas: this.helper.eth.DEFAULT_GAS,161 gasPrice: await this.getGasPrice(),138 gasPrice: await this.getGasPrice(),162 }));139 });163 }140 }164141165 async collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false) {142 async collection(address: string, mode: TCollectionMode, caller?: string, mergeDeprecated = false) {177 abi = [...abi,...deprecated];154 abi = [...abi, ...deprecated];178 }155 }179 const web3 = this.helper.getWeb3();156 const web3 = this.helper.getWeb3();180 return unlimitedMoneyHack(new web3.eth.Contract(abi as any, address, {157 return new web3.eth.Contract(abi as any, address, {181 gas: this.helper.eth.DEFAULT_GAS,158 gas: this.helper.eth.DEFAULT_GAS,182 gasPrice: await this.getGasPrice(),159 gasPrice: await this.getGasPrice(),183 ...(caller ? {from: caller} : {}),160 ...(caller ? {from: caller} : {}),184 }));161 });185 }162 }186163187 collectionById(collectionId: number, mode: 'nft' | 'rft' | 'ft', caller?: string, mergeDeprecated = false) {164 collectionById(collectionId: number, mode: 'nft' | 'rft' | 'ft', caller?: string, mergeDeprecated = false) {191 async rftToken(address: string, caller?: string, mergeDeprecated = false) {168 async rftToken(address: string, caller?: string, mergeDeprecated = false) {192 const web3 = this.helper.getWeb3();169 const web3 = this.helper.getWeb3();193 const abi = mergeDeprecated ? [...refungibleTokenAbi, ...refungibleTokenDeprecatedAbi] : refungibleTokenAbi;170 const abi = mergeDeprecated ? [...refungibleTokenAbi, ...refungibleTokenDeprecatedAbi] : refungibleTokenAbi;194 return unlimitedMoneyHack(new web3.eth.Contract(abi as any, address, {171 return new web3.eth.Contract(abi as any, address, {195 gas: this.helper.eth.DEFAULT_GAS,172 gas: this.helper.eth.DEFAULT_GAS,196 gasPrice: await this.getGasPrice(),173 gasPrice: await this.getGasPrice(),197 ...(caller ? {from: caller} : {}),174 ...(caller ? {from: caller} : {}),198 }));175 });199 }176 }200177201 rftTokenById(collectionId: number, tokenId: number, caller?: string, mergeDeprecated = false) {178 rftTokenById(collectionId: number, tokenId: number, caller?: string, mergeDeprecated = false) {214 return account.address;191 return account.address;215 }192 }216193217 async createAccountWithBalance(donor: IKeyringPair, amount=100n) {194 async createAccountWithBalance(donor: IKeyringPair, amount = 600n) {218 const account = this.createAccount();195 const account = this.createAccount();219 await this.transferBalanceFromSubstrate(donor, account, amount);196 await this.transferBalanceFromSubstrate(donor, account, amount);220197tests/src/maintenance.seqtest.tsdiffbeforeafterboth323 expect(await helper.preimage.getPreimageInfo(preimageHashes[0])).to.have.property('unrequested');325 expect(await helper.preimage.getPreimageInfo(preimageHashes[0])).to.have.property('unrequested');324 });326 });325327326 itSub('Does not allow execution of a preimage that would fail', async ({helper}) => {328 itSub.only('Does not allow execution of a preimage that would fail', async ({helper}) => {327 const [zeroAccount] = await helper.arrange.createAccounts([0n], superuser);329 const [zeroAccount] = await helper.arrange.createAccounts([0n], superuser);328330329 const preimage = helper.constructApiCall('api.tx.balances.forceTransfer', [331 const preimage = helper.constructApiCall('api.tx.balances.forceTransfer', [334336335 await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.executePreimage', [337 await expect(helper.getSudo().executeExtrinsic(superuser, 'api.tx.maintenance.executePreimage', [336 preimageHash, {refTime: 10000000000, proofSize: 10000},338 preimageHash, {refTime: 10000000000, proofSize: 10000},337 ])).to.be.rejectedWith(/balances\.InsufficientBalance/);339 ])).to.be.rejectedWith(/^Token: FundsUnavailable$/);338 });340 });339341340 itSub('Does not allow preimage execution with non-root', async ({helper}) => {342 itSub('Does not allow preimage execution with non-root', async ({helper}) => {tests/src/nesting/tokenProperties.seqtest.tsdiffbeforeafterboth30 });30 });313132 [32 [33 {mode: 'nft' as const, pieces: undefined, requiredPallets: []},33 {mode: 'nft' as const, pieces: undefined, requiredPallets: []} as const,34 {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},34 {mode: 'rft' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]} as const,35 ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {35 ].map(testSuite => describe(`${testSuite.mode.toUpperCase()}`, () => {36 before(async function() {36 before(async function() {37 // eslint-disable-next-line require-await37 // eslint-disable-next-line require-await53 });53 });54 const token = await (54 const token = await (55 testSuite.pieces55 testSuite.pieces56 ? collection.mintToken(alice, testSuite.pieces)56 ? collection.mintToken(alice, testSuite.pieces as any)57 : collection.mintToken(alice)57 : collection.mintToken(alice)58 );58 );5959tests/src/nesting/tokenProperties.test.tsdiffbeforeafterboth46 tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>46 tokenPropertyPermissions: permissions.flatMap(({permission, signers}, i) =>47 signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})),47 signers.map(signer => {return {key: `${i+1}_${signer.address}`, permission};})),48 });48 });49 return mode == 'NFT' ? [await collection.mintToken(alice), 1n] : [await collection.mintToken(alice, 100n), 100n];49 return mode == 'NFT' ? [await collection.mintToken(alice), 1n] : [await collection.mintToken(alice, 100n as any), 100n];50 }50 }515152 async function testReadsYetEmptyProperties(token: UniqueNFToken | UniqueRFToken) {52 async function testReadsYetEmptyProperties(token: UniqueNFToken | UniqueRFToken) {322 });322 });323323324 [324 [325 {mode: 'nft' as const, storage: 'nonfungible' as const, pieces: undefined, requiredPallets: []},325 {mode: 'nft' as const, storage: 'nonfungible' as const, pieces: undefined, requiredPallets: []} as const,326 {mode: 'rft' as const, storage: 'refungible' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]},326 {mode: 'rft' as const, storage: 'refungible' as const, pieces: 100n, requiredPallets: [Pallets.ReFungible]} as const,327 ].map(testCase =>327 ].map(testCase =>328 itSub.ifWithPallets(`Allows modifying a token property multiple times with the same size (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {328 itSub.ifWithPallets(`Allows modifying a token property multiple times with the same size (${testCase.mode})`, testCase.requiredPallets, async({helper}) => {329 const propKey = 'tok-prop';329 const propKey = 'tok-prop';349349350 const token = await (350 const token = await (351 testCase.pieces351 testCase.pieces352 ? collection.mintToken(alice, testCase.pieces)352 ? collection.mintToken(alice, testCase.pieces as any)353 : collection.mintToken(alice)353 : collection.mintToken(alice)354 );354 );355355386 });386 });387 const token = await (387 const token = await (388 testCase.pieces388 testCase.pieces389 ? collection.mintToken(alice, testCase.pieces)389 ? collection.mintToken(alice, testCase.pieces as any)390 : collection.mintToken(alice)390 : collection.mintToken(alice)391 );391 );392 const originalSpace = await token.getTokenPropertiesConsumedSpace();392 const originalSpace = await token.getTokenPropertiesConsumedSpace();421 });421 });422 const token = await (422 const token = await (423 testCase.pieces423 testCase.pieces424 ? collection.mintToken(alice, testCase.pieces)424 ? collection.mintToken(alice, testCase.pieces as any)425 : collection.mintToken(alice)425 : collection.mintToken(alice)426 );426 );427 const originalSpace = await token.getTokenPropertiesConsumedSpace();427 const originalSpace = await token.getTokenPropertiesConsumedSpace();479 const collection = await (mode == 'NFT' ? helper.nft : helper.rft).mintCollection(alice, {479 const collection = await (mode == 'NFT' ? helper.nft : helper.rft).mintCollection(alice, {480 tokenPropertyPermissions: constitution.map(({permission}, i) => {return {key: `${i+1}`, permission};}),480 tokenPropertyPermissions: constitution.map(({permission}, i) => {return {key: `${i+1}`, permission};}),481 });481 });482 return mode == 'NFT' ? [await collection.mintToken(alice), 1n] : [await collection.mintToken(alice, 100n), 100n];482 return mode == 'NFT' ? [await collection.mintToken(alice), 1n] : [await collection.mintToken(alice, 100n as any), 100n];483 }483 }484484485 async function getConsumedSpace(api: any, collectionId: number, tokenId: number, mode: 'NFT' | 'RFT'): Promise<number> {485 async function getConsumedSpace(api: any, collectionId: number, tokenId: number, mode: 'NFT' | 'RFT'): Promise<number> {680 });680 });681 const token = await (681 const token = await (682 testCase.pieces682 testCase.pieces683 ? collection.mintToken(alice, testCase.pieces)683 ? collection.mintToken(alice, testCase.pieces as any)684 : collection.mintToken(alice)684 : collection.mintToken(alice)685 );685 );686686tests/src/sub/appPromotion/appPromotion.test.tsdiffbeforeafterboth86 await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.rejected;86 await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.rejected;87 await helper.staking.stake(staker, 100n * nominal);87 await helper.staking.stake(staker, 100n * nominal);888889 // Staker balance is: miscFrozen: 100, feeFrozen: 100, reserved: 0n...89 // Staker balance is: frozen: 100, reserved: 0n...90 // ...so he can not transfer 90090 // ...so he can not transfer 90091 expect(await helper.balance.getSubstrateFull(staker.address)).to.contain({miscFrozen: 100n * nominal, feeFrozen: 100n * nominal, reserved: 0n});91 expect(await helper.balance.getSubstrateFull(staker.address)).to.contain({frozen: 100n * nominal, reserved: 0n});92 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'appstake', amount: 100n * nominal, reasons: 'All'}]);92 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'appstake', amount: 100n * nominal, reasons: 'All'}]);93 await expect(helper.balance.transferToSubstrate(staker, recepient.address, 900n * nominal)).to.be.rejectedWith('balances.LiquidityRestrictions');93 await expect(helper.balance.transferToSubstrate(staker, recepient.address, 900n * nominal)).to.be.rejectedWith(/^Token: Frozen$/);949495 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(100n * nominal);95 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(100n * nominal);96 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);96 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);151 // staker has tokens locked with vesting id:151 // staker has tokens locked with vesting id:152 await helper.balance.vestedTransfer(donor, staker.address, {start: 0n, period: 1n, periodCount: 1n, perPeriod: 200n * nominal});152 await helper.balance.vestedTransfer(donor, staker.address, {start: 0n, period: 1n, periodCount: 1n, perPeriod: 200n * nominal});153 expect(await helper.balance.getSubstrateFull(staker.address))153 expect(await helper.balance.getSubstrateFull(staker.address))154 .to.deep.contain({free: 1200n * nominal, miscFrozen: 200n * nominal, feeFrozen: 200n * nominal, reserved: 0n});154 .to.deep.contain({free: 1200n * nominal, frozen: 200n * nominal, reserved: 0n});155155156 // Locked balance can be staked. staker can stake 1200 tokens (minus fee):156 // Locked balance can be staked. staker can stake 1200 tokens (minus fee):157 await helper.staking.stake(staker, 1000n * nominal);157 await helper.staking.stake(staker, 1000n * nominal);158 await helper.staking.stake(staker, 199n * nominal);158 await helper.staking.stake(staker, 199n * nominal);159 // check balances159 // check balances160 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'ormlvest', amount: 200n * nominal, reasons: 'All'}, {id: 'appstake', amount: 1199n * nominal, reasons: 'All'}]);160 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'ormlvest', amount: 200n * nominal, reasons: 'All'}, {id: 'appstake', amount: 1199n * nominal, reasons: 'All'}]);161 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: 1199n * nominal, feeFrozen: 1199n * nominal});161 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 1199n * nominal});162 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(1199n);162 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(1199n);163 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(1199n * nominal);163 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(1199n * nominal);164164170170171 // check balances171 // check balances172 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'ormlvest', amount: 200n * nominal, reasons: 'All'}]);172 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'ormlvest', amount: 200n * nominal, reasons: 'All'}]);173 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: 200n * nominal, feeFrozen: 200n * nominal});173 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 200n * nominal});174 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(1199n);174 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(1199n);175 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(0n);175 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(0n);176176219 // Right after unstake tokens are still locked219 // Right after unstake tokens are still locked220 expect(await helper.staking.getStakesNumber({Substrate: staker.address})).to.eq(0);220 expect(await helper.staking.getStakesNumber({Substrate: staker.address})).to.eq(0);221 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'appstake', amount: STAKE_AMOUNT, reasons: 'All'}]);221 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([{id: 'appstake', amount: STAKE_AMOUNT, reasons: 'All'}]);222 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: STAKE_AMOUNT, feeFrozen: STAKE_AMOUNT});222 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: STAKE_AMOUNT});223 // Staker can not transfer223 // Staker can not transfer224 await expect(helper.balance.transferToSubstrate(staker, recepient.address, 100n * nominal)).to.be.rejectedWith('balances.LiquidityRestrictions');224 await expect(helper.balance.transferToSubstrate(staker, recepient.address, 100n * nominal)).to.be.rejectedWith(/^Token: Frozen$/);225 expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(STAKE_AMOUNT);225 expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.be.equal(STAKE_AMOUNT);226 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n);226 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n);227 expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore);227 expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore);242242243 // Wait for unstaking period. Balance now free ~1000; reserved, frozen, miscFrozeb: 0n243 // Wait for unstaking period. Balance now free ~1000; reserved, frozen, miscFrozeb: 0n244 await helper.wait.forParachainBlockNumber(pendingUnstake.block);244 await helper.wait.forParachainBlockNumber(pendingUnstake.block);245 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: 0n, feeFrozen: 0n});245 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 0n});246 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);246 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);247247248 // staker can transfer:248 // staker can transfer:283 expect(stakes).to.be.deep.equal([]);283 expect(stakes).to.be.deep.equal([]);284 expect(pendingUnstake[0].amount).to.equal(600n * nominal);284 expect(pendingUnstake[0].amount).to.equal(600n * nominal);285285286 expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, feeFrozen: 600n * nominal, miscFrozen: 600n * nominal});286 expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 600n * nominal});287 expect (await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);287 expect (await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);288 await helper.wait.forParachainBlockNumber(pendingUnstake[0].block);288 await helper.wait.forParachainBlockNumber(pendingUnstake[0].block);289 expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, feeFrozen: 0n, miscFrozen: 0n});289 expect (await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 0n});290 expect (await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);290 expect (await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);291 });291 });292 });292 });454 await helper.wait.forParachainBlockNumber(unstake2.block);454 await helper.wait.forParachainBlockNumber(unstake2.block);455455456 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([]);456 expect(await helper.balance.getLocked(staker.address)).to.deep.eq([]);457 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, miscFrozen: 0n, feeFrozen: 0n});457 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n, frozen: 0n});458 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(999n);458 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.eq(999n);459 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(0n);459 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.eq(0n);460 expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.eq(0n);460 expect(await helper.staking.getPendingUnstake({Substrate: staker.address})).to.eq(0n);822 expect(totalStakedPerBlock[1].amount).to.equal(income2);822 expect(totalStakedPerBlock[1].amount).to.equal(income2);823823824 const stakerBalance = await helper.balance.getSubstrateFull(staker.address);824 const stakerBalance = await helper.balance.getSubstrateFull(staker.address);825 expect(stakerBalance).to.contain({miscFrozen: income1 + income2, feeFrozen: income1 + income2, reserved: 0n});825 expect(stakerBalance).to.contain({frozen: income1 + income2, reserved: 0n});826 expect(stakerBalance.free / nominal).to.eq(999n);826 expect(stakerBalance.free / nominal).to.eq(999n);827 });827 });828828841841842 const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address);842 const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address);843843844 expect(stakerFullBalance).to.contain({reserved: 0n, feeFrozen: frozenBalanceShouldBe, miscFrozen: frozenBalanceShouldBe});844 expect(stakerFullBalance).to.contain({reserved: 0n, frozen: frozenBalanceShouldBe});845 });845 });846846847 itSub('should not be credited for pending-unstaked tokens', async ({helper}) => {847 itSub('should not be credited for pending-unstaked tokens', async ({helper}) => {923 {method: 'unstakeAll' as const},923 {method: 'unstakeAll' as const},924 ].map(testCase => {924 ].map(testCase => {925 itSub(testCase.method, async ({helper}) => {925 itSub(testCase.method, async ({helper}) => {926 const unstakeParams = testCase.method === 'unstakePartial'926 const unstakeParams: [] | [bigint] = testCase.method === 'unstakePartial'927 ? [100n * nominal - 1n]927 ? [100n * nominal - 1n]928 : [];928 : [];929 const [staker] = await getAccounts(1);929 const [staker] = await getAccounts(1);tests/src/util/index.tsdiffbeforeafterboth135 TestUtils = 'testutils',135 TestUtils = 'testutils',136}136}137137138export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) {138export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: readonly string[]) {139 const missingPallets = helper.fetchMissingPalletNames(requiredPallets);139 const missingPallets = helper.fetchMissingPalletNames(requiredPallets);140140141 if (missingPallets.length > 0) {141 if (missingPallets.length > 0) {145 }145 }146}146}147147148export function itSub(name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) {148export function itSub(name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: readonly string[] } = {}) {149 (opts.only ? it.only :149 (opts.only ? it.only :150 opts.skip ? it.skip : it)(name, async function () {150 opts.skip ? it.skip : it)(name, async function () {151 await usingPlaygrounds(async (helper, privateKey) => {151 await usingPlaygrounds(async (helper, privateKey) => {157 });157 });158 });158 });159}159}160export function itSubIfWithPallet(name: string, required: string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: string[] } = {}) {160export function itSubIfWithPallet(name: string, required: readonly string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any, opts: { only?: boolean, skip?: boolean, requiredPallets?: readonly string[] } = {}) {161 return itSub(name, cb, {requiredPallets: required, ...opts});161 return itSub(name, cb, {requiredPallets: required, ...opts});162}162}163itSub.only = (name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSub(name, cb, {only: true});163itSub.only = (name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSub(name, cb, {only: true});164itSub.skip = (name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSub(name, cb, {skip: true});164itSub.skip = (name: string, cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSub(name, cb, {skip: true});165165166itSubIfWithPallet.only = (name: string, required: string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSubIfWithPallet(name, required, cb, {only: true});166itSubIfWithPallet.only = (name: string, required: readonly string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSubIfWithPallet(name, required, cb, {only: true});167itSubIfWithPallet.skip = (name: string, required: string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSubIfWithPallet(name, required, cb, {skip: true});167itSubIfWithPallet.skip = (name: string, required: readonly string[], cb: (apis: { helper: DevUniqueHelper, privateKey: (seed: string) => Promise<IKeyringPair> }) => any) => itSubIfWithPallet(name, required, cb, {skip: true});168itSub.ifWithPallets = itSubIfWithPallet;168itSub.ifWithPallets = itSubIfWithPallet;169169170export type SchedKind = 'anon' | 'named';170export type SchedKind = 'anon' | 'named';tests/src/util/playgrounds/types.tsdiffbeforeafterboth61 decorated?: (...args: any[]) => any;61 decorated?: (...args: any[]) => any;62}62}636364export interface ICrossAccountId {64export type ICrossAccountId = {65 Substrate?: TSubstrateAccount;65 Substrate: TSubstrateAccount;66} | {66 Ethereum?: TEthereumAccount;67 Ethereum: TEthereumAccount;67}68}686969export interface ICrossAccountIdLower {70export type ICrossAccountIdLower = {70 substrate?: TSubstrateAccount;71 substrate: TSubstrateAccount;72} | {71 ethereum?: TEthereumAccount;73 ethereum: TEthereumAccount;72}74};737574export interface IEthCrossAccountId {76export interface IEthCrossAccountId {75 0: TEthereumAccount;77 0: TEthereumAccount;163export interface ISubstrateBalance {165export interface ISubstrateBalance {164 free: bigint,166 free: bigint,165 reserved: bigint,167 reserved: bigint,166 miscFrozen: bigint,168 frozen: bigint,167 feeFrozen: bigint168}169}169170170export interface IStakingInfo {171export interface IStakingInfo {tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth469 };469 };470470471 async calculcateFee(payer: ICrossAccountId, promise: () => Promise<any>): Promise<bigint> {471 async calculcateFee(payer: ICrossAccountId, promise: () => Promise<any>): Promise<bigint> {472 const address = payer.Substrate ? payer.Substrate : this.helper.address.ethToSubstrate(payer.Ethereum!);472 const address = 'Substrate' in payer ? payer.Substrate : this.helper.address.ethToSubstrate(payer.Ethereum);473 let balance = await this.helper.balance.getSubstrate(address);473 let balance = await this.helper.balance.getSubstrate(address);474474475 await promise();475 await promise();991991992 //todo:collator documentation992 //todo:collator documentation993 async getIndex(): Promise<number> {993 async getIndex(): Promise<number> {994 return (await this.helper.callRpc('api.query.session.currentIndex')).toNumber();994 return (await this.helper.callRpc('api.query.session.currentIndex', [])).toNumber();995 }995 }996996997 newSessions(sessionCount = 1, blockTimeout = 24000): Promise<void> {997 newSessions(sessionCount = 1, blockTimeout = 24000): Promise<void> {tests/src/util/playgrounds/unique.tsdiffbeforeafterboth778import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';8import {ApiPromise, WsProvider, Keyring} from '@polkadot/api';9import {SignerOptions} from '@polkadot/api/types/submittable';9import {SignerOptions} from '@polkadot/api/types/submittable';10import '../../interfaces/augment-api-tx';11import {AugmentedSubmittables} from '@polkadot/api-base/types/submittable';12import {RpcInterface} from '@polkadot/rpc-core/types';13import {QueryableStorage} from '@polkadot/api-base/types/storage';14import {DecoratedRpc} from '@polkadot/api-base/types/rpc';10import {ApiInterfaceEvents} from '@polkadot/api/types';15import {ApiInterfaceEvents} from '@polkadot/api/types';11import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';16import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm, base58Encode, blake2AsU8a} from '@polkadot/util-crypto';12import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';47import type {Vec} from '@polkadot/types-codec';52import type {Vec} from '@polkadot/types-codec';48import {FrameSystemEventRecord} from '@polkadot/types/lookup';53import {FrameSystemEventRecord} from '@polkadot/types/lookup';495450export class CrossAccountId implements ICrossAccountId {55export class CrossAccountId {51 Substrate?: TSubstrateAccount;56 Substrate!: TSubstrateAccount;52 Ethereum?: TEthereumAccount;57 Ethereum!: TEthereumAccount;535854 constructor(account: ICrossAccountId) {59 constructor(account: ICrossAccountId) {55 if (account.Substrate) this.Substrate = account.Substrate;60 if ('Substrate' in account) this.Substrate = account.Substrate;56 if (account.Ethereum) this.Ethereum = account.Ethereum;61 else this.Ethereum = account.Ethereum;57 }62 }586359 static fromKeyring(account: IKeyringPair, domain: 'Substrate' | 'Ethereum' = 'Substrate') {64 static fromKeyring(account: IKeyringPair, domain: 'Substrate' | 'Ethereum' = 'Substrate') {64 }69 }657066 static fromLowerCaseKeys(address: ICrossAccountIdLower): CrossAccountId {71 static fromLowerCaseKeys(address: ICrossAccountIdLower): CrossAccountId {67 return new CrossAccountId({Substrate: address.substrate, Ethereum: address.ethereum});72 if ('substrate' in address) return new CrossAccountId({Substrate: address.substrate});73 else return new CrossAccountId({Ethereum: address.ethereum});68 }74 }697570 static normalizeSubstrateAddress(address: TSubstrateAccount, ss58Format = 42): TSubstrateAccount {76 static normalizeSubstrateAddress(address: TSubstrateAccount, ss58Format = 42): TSubstrateAccount {263 if(typeof address === 'string') return address;269 if (typeof address === 'string') return address;264 const obj = {} as any;270 const obj = {} as any;265 Object.keys(address).forEach(k => {271 Object.keys(address).forEach(k => {266 obj[k.toLocaleLowerCase()] = address[k as 'Substrate' | 'Ethereum'];272 obj[k.toLocaleLowerCase()] = (address as any)[k];267 });273 });268 if(obj.substrate) return CrossAccountId.withNormalizedSubstrate(obj.substrate);274 if (obj.substrate) return CrossAccountId.withNormalizedSubstrate(obj.substrate);269 if(obj.ethereum) return CrossAccountId.fromLowerCaseKeys(obj).toLowerCase();275 if (obj.ethereum) return CrossAccountId.fromLowerCaseKeys(obj).toLowerCase();360 return parsedEvents;366 return parsedEvents;361 }367 }362}368}369const InvalidTypeSymbol = Symbol('Invalid type');370// eslint-disable-next-line @typescript-eslint/no-unused-vars371export type Invalid<ErrorMessage> =372 | ((373 invalidType: typeof InvalidTypeSymbol,374 ..._: typeof InvalidTypeSymbol[]375 ) => typeof InvalidTypeSymbol)376 | null377 | undefined;378// Has slightly better error messages than Get379type Get2<T, P extends string, E> =380 P extends `${infer Key}.${infer Key2}` ? Key extends keyof T ? Key2 extends keyof T[Key] ? T[Key][Key2] : E : E : E;381type ForceFunction<T> = T extends (...args: any) => any ? T : (...args: any) => Invalid<'not a function'>;382type ReturnTypeWithArgs<T extends (...args: any[]) => any, ARGS_T> =383 Extract<384 T extends { (...args: infer A1): infer R1; (...args: infer A2): infer R2; (...args: infer A3): infer R3; (...args: infer A4): infer R4; } ? [A1, R1] | [A2, R2] | [A3, R3] | [A4, R4] :385 T extends { (...args: infer A1): infer R1; (...args: infer A2): infer R2; (...args: infer A3): infer R3; } ? [A1, R1] | [A2, R2] | [A3, R3] :386 T extends { (...args: infer A1): infer R1; (...args: infer A2): infer R2; } ? [A1, R1] | [A2, R2] :387 T extends { (...args: infer A1): infer R1; } ? [A1, R1] :388 never,389 [ARGS_T, any]390 >[1]363391364export class ChainHelperBase {392export class ChainHelperBase {365 helperBase: any;393 helperBase: any;646 return this.constructApiCall(apiCall, params).method.toHex();674 return this.constructApiCall(apiCall, params).method.toHex();647 }675 }648676649 async executeExtrinsic(sender: TSigner, extrinsic: string, params: any[], expectSuccess=true, options: Partial<SignerOptions>|null = null/*, failureMessage='expected success'*/) {677 async executeExtrinsic<678 E extends string,679 V extends (680...args: any) => any = ForceFunction<681 Get2<682 AugmentedSubmittables<'promise'>,683 E, (...args: any) => Invalid<'not found'>684 >685 >686 >(687 sender: TSigner,688 extrinsic: `api.tx.${E}`,689 params: Parameters<V>,690 expectSuccess = true,691 options: Partial<SignerOptions> | null = null,/*, failureMessage='expected success'*/692 ): Promise<ITransactionResult> {650 if(this.api === null) throw Error('API not initialized');693 if (this.api === null) throw Error('API not initialized');651 if(!extrinsic.startsWith('api.tx.')) throw Error(`${extrinsic} is not transaction`);694 if (!extrinsic.startsWith('api.tx.')) throw Error(`${extrinsic} is not transaction`);652695696 if (result.moduleError) throw Error(`${errorMessage}`);739 if (result.moduleError) throw Error(`${errorMessage}`);697 else if (result.result.dispatchError) throw Error(JSON.stringify(result.result.dispatchError));740 else if (result.result.dispatchError) throw Error(JSON.stringify(result.result.dispatchError));698 }741 }699 return result;742 return result as any;700 }743 }701744702 async callRpc(rpc: string, params?: any[]) {745 async callRpc746 // <747 // K extends 'rpc' | 'query',748 // E extends string,749 // V extends (...args: any) => any = ForceFunction<750 // Get2<751 // K extends 'rpc' ? DecoratedRpc<'promise', RpcInterface> : QueryableStorage<'promise'>,752 // E, (...args: any) => Invalid<'not found'>753 // >754 // >,755 // P = Parameters<V>,756 // >757 (rpc: string, params?: any[]): Promise<any> {758703 if(typeof params === 'undefined') params = [];759 if (typeof params === 'undefined') params = [] as any;704 if(this.api === null) throw Error('API not initialized');760 if (this.api === null) throw Error('API not initialized');705 if(!rpc.startsWith('api.rpc.') && !rpc.startsWith('api.query.')) throw Error(`${rpc} is not RPC call`);761 if (!rpc.startsWith('api.rpc.') && !rpc.startsWith('api.query.')) throw Error(`${rpc} is not RPC call`);706762711 type: this.chainLogType.RPC,767 type: this.chainLogType.RPC,712 call: rpc,768 call: rpc,713 params,769 params,714 } as IUniqueHelperLog;770 } as any as IUniqueHelperLog;715771716 try {772 try {717 result = await this.constructApiCall(rpc, params);773 result = await this.constructApiCall(rpc, params as any);718 }774 }719 catch(e) {775 catch (e) {720 error = e;776 error = e;743 return this.api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase()).sort();799 return this.api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase()).sort();744 }800 }745801746 fetchMissingPalletNames(requiredPallets: string[]): string[] {802 fetchMissingPalletNames(requiredPallets: readonly string[]): string[] {747 const palletNames = this.fetchAllPalletNames();803 const palletNames = this.fetchAllPalletNames();748 return requiredPallets.filter(p => !palletNames.includes(p));804 return requiredPallets.filter(p => !palletNames.includes(p));749 }805 }1731 const creationResult = await this.helper.executeExtrinsic(1787 const creationResult = await this.helper.executeExtrinsic(1732 signer,1788 signer,1733 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1789 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1734 nft: {1790 NFT: {1735 properties: data.properties,1791 properties: data.properties,1736 },1792 },1737 }],1793 }],1918 const creationResult = await this.helper.executeExtrinsic(1974 const creationResult = await this.helper.executeExtrinsic(1919 signer,1975 signer,1920 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1976 'api.tx.unique.createItem', [data.collectionId, (typeof data.owner === 'string') ? {Substrate: data.owner} : data.owner, {1921 refungible: {1977 ReFungible: {1922 pieces: data.pieces,1978 pieces: data.pieces,1923 properties: data.properties,1979 properties: data.properties,1924 },1980 },2093 const creationResult = await this.helper.executeExtrinsic(2149 const creationResult = await this.helper.executeExtrinsic(2094 signer,2150 signer,2095 'api.tx.unique.createItem', [collectionId, (typeof owner === 'string') ? {Substrate: owner} : owner, {2151 'api.tx.unique.createItem', [collectionId, (typeof owner === 'string') ? {Substrate: owner} : owner, {2096 fungible: {2152 Fungible: {2097 value: amount,2153 value: amount,2098 },2154 },2099 }],2155 }],2334 return isSuccess;2390 return isSuccess;2335 }2391 }233623922337 /**2393 /**2338 * Get full substrate balance including free, miscFrozen, feeFrozen, and reserved2394 * Get full substrate balance including free, frozen, and reserved2339 * @param address substrate address2395 * @param address substrate address2340 * @returns2396 * @returns2341 */2397 */2342 async getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {2398 async getSubstrateFull(address: TSubstrateAccount): Promise<ISubstrateBalance> {2343 const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data;2399 const accountInfo = (await this.helper.callRpc('api.query.system.account', [address])).data;2344 return {free: accountInfo.free.toBigInt(), miscFrozen: accountInfo.miscFrozen.toBigInt(), feeFrozen: accountInfo.feeFrozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};2400 return {free: accountInfo.free.toBigInt(), frozen: accountInfo.frozen.toBigInt(), reserved: accountInfo.reserved.toBigInt()};2345 }2401 }234624022347 async getLocked(address: TSubstrateAccount): Promise<[{id: string, amount: bigint, reason: string}]> {2403 async getLocked(address: TSubstrateAccount): Promise<[{ id: string, amount: bigint, reason: string }]> {2710 * @returns {number}2766 * @returns {number}2711 */2767 */2712 async getStakesNumber(address: ICrossAccountId): Promise<number> {2768 async getStakesNumber(address: ICrossAccountId): Promise<number> {2713 if (address.Ethereum) throw Error('only substrate address');2769 if ('Ethereum' in address) throw Error('only substrate address');2714 return (await this.helper.callRpc('api.query.appPromotion.stakesPerAccount', [address.Substrate])).toNumber();2770 return (await this.helper.callRpc('api.query.appPromotion.stakesPerAccount', [address.Substrate])).toNumber();2715 }2771 }27162772337134273372 return super.executeExtrinsic(3428 return super.executeExtrinsic(3373 sender,3429 sender,3374 extrinsic,3430 extrinsic as any,3375 schedArgs,3431 schedArgs,3376 expectSuccess,3432 expectSuccess,3377 );3433 );3410 const error = (result.result.events[1].event.data as any).sudoResult.asErr.asModule;3466 const error = (result.result.events[1].event.data as any).sudoResult.asErr.asModule;3411 const metaError = super.getApi()?.registry.findMetaError(error);3467 const metaError = super.getApi()?.registry.findMetaError(error);3412 throw new Error(`${metaError.section}.${metaError.name}`);3468 throw new Error(`${metaError.section}.${metaError.name}`);3413 } else {3469 } else if (data.asErr.isToken) {3414 throw new Error(data.asErr.toHuman());3470 throw new Error(`Token: ${data.asErr.asToken}`);3415 }3471 }3416 }3472 }3417 return result;3473 return result;3418 }3474 }tests/src/vesting.test.tsdiffbeforeafterboth47 // check senders balance after vesting:47 // check senders balance after vesting:48 let balanceSender = await helper.balance.getSubstrateFull(sender.address);48 let balanceSender = await helper.balance.getSubstrateFull(sender.address);49 expect(balanceSender.free / nominal).to.eq(699n);49 expect(balanceSender.free / nominal).to.eq(699n);50 expect(balanceSender.feeFrozen).to.eq(0n);50 expect(balanceSender.frozen).to.eq(0n);51 expect(balanceSender.miscFrozen).to.eq(0n);52 expect(balanceSender.reserved).to.eq(0n);51 expect(balanceSender.reserved).to.eq(0n);535254 // check recepient balance after vesting:53 // check recepient balance after vesting:55 let balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);54 let balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);56 expect(balanceRecepient.free).to.eq(301n * nominal);55 expect(balanceRecepient.free).to.eq(301n * nominal);57 expect(balanceRecepient.feeFrozen).to.eq(300n * nominal);56 expect(balanceRecepient.frozen).to.eq(300n * nominal);58 expect(balanceRecepient.miscFrozen).to.eq(300n * nominal);59 expect(balanceRecepient.reserved).to.eq(0n);57 expect(balanceRecepient.reserved).to.eq(0n);605861 // Schedules list correct:59 // Schedules list correct:70 // check recepient balance after claim (50 tokens claimed, 250 left):68 // check recepient balance after claim (50 tokens claimed, 250 left):71 balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);69 balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);72 expect(balanceRecepient.free / nominal).to.eq(300n);70 expect(balanceRecepient.free / nominal).to.eq(300n);73 expect(balanceRecepient.feeFrozen).to.eq(250n * nominal);71 expect(balanceRecepient.frozen).to.eq(250n * nominal);74 expect(balanceRecepient.miscFrozen).to.eq(250n * nominal);75 expect(balanceRecepient.reserved).to.eq(0n);72 expect(balanceRecepient.reserved).to.eq(0n);767377 // Wait first schedule ends and first part od second schedule:74 // Wait first schedule ends and first part od second schedule:81 // check recepient balance after second claim (150 tokens claimed, 100 left):78 // check recepient balance after second claim (150 tokens claimed, 100 left):82 balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);79 balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);83 expect(balanceRecepient.free / nominal).to.eq(300n);80 expect(balanceRecepient.free / nominal).to.eq(300n);84 expect(balanceRecepient.feeFrozen).to.eq(100n * nominal);81 expect(balanceRecepient.frozen).to.eq(100n * nominal);85 expect(balanceRecepient.miscFrozen).to.eq(100n * nominal);86 expect(balanceRecepient.reserved).to.eq(0n);82 expect(balanceRecepient.reserved).to.eq(0n);878388 // Schedules list contain 1 vesting:84 // Schedules list contain 1 vesting:97 // check recepient balance after second claim (100 tokens claimed, 0 left):93 // check recepient balance after second claim (100 tokens claimed, 0 left):98 balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);94 balanceRecepient = await helper.balance.getSubstrateFull(recepient.address);99 expect(balanceRecepient.free / nominal).to.eq(300n);95 expect(balanceRecepient.free / nominal).to.eq(300n);100 expect(balanceRecepient.feeFrozen).to.eq(0n);96 expect(balanceRecepient.frozen).to.eq(0n);101 expect(balanceRecepient.miscFrozen).to.eq(0n);102 expect(balanceRecepient.reserved).to.eq(0n);97 expect(balanceRecepient.reserved).to.eq(0n);10398104 // check sender balance does not changed:99 // check sender balance does not changed:105 balanceSender = await helper.balance.getSubstrateFull(sender.address);100 balanceSender = await helper.balance.getSubstrateFull(sender.address);106 expect(balanceSender.free / nominal).to.eq(699n);101 expect(balanceSender.free / nominal).to.eq(699n);107 expect(balanceSender.feeFrozen).to.eq(0n);102 expect(balanceSender.frozen).to.eq(0n);108 expect(balanceSender.miscFrozen).to.eq(0n);109 expect(balanceSender.reserved).to.eq(0n);103 expect(balanceSender.reserved).to.eq(0n);110 });104 });111105112 itSub('cannot send more tokens than have', async ({helper}) => {106 itSub.only('cannot send more tokens than have', async ({helper}) => {113 const [sender, receiver] = await helper.arrange.createAccounts([1000n, 1n], donor);107 const [sender, receiver] = await helper.arrange.createAccounts([1000n, 1n], donor);114 const schedule = {start: 0n, period: 1n, periodCount: 1n, perPeriod: 100n * nominal};108 const schedule = {start: 0n, period: 1n, periodCount: 1n, perPeriod: 100n * nominal};115 const manyPeriodsSchedule = {start: 0n, period: 1n, periodCount: 100n, perPeriod: 10n * nominal};109 const manyPeriodsSchedule = {start: 0n, period: 1n, periodCount: 100n, perPeriod: 10n * nominal};116 const oneBigSumSchedule = {start: 0n, period: 1n, periodCount: 1n, perPeriod: 5000n * nominal};110 const oneBigSumSchedule = {start: 0n, period: 1n, periodCount: 1n, perPeriod: 5000n * nominal};117111118 // Sender cannot send vestedTransfer to self or other112 // Sender cannot send vestedTransfer to self or other119 await expect(helper.balance.vestedTransfer(sender, sender.address, manyPeriodsSchedule)).to.be.rejectedWith(/InsufficientBalance/);113 await expect(helper.balance.vestedTransfer(sender, sender.address, manyPeriodsSchedule)).to.be.rejectedWith(/^vesting.InsufficientBalanceToLock$/);120 await expect(helper.balance.vestedTransfer(sender, receiver.address, manyPeriodsSchedule)).to.be.rejectedWith(/InsufficientBalance/);114 await expect(helper.balance.vestedTransfer(sender, receiver.address, manyPeriodsSchedule)).to.be.rejectedWith(/^Token: FundsUnavailable$/);121 await expect(helper.balance.vestedTransfer(sender, sender.address, oneBigSumSchedule)).to.be.rejectedWith(/InsufficientBalance/);115 await expect(helper.balance.vestedTransfer(sender, sender.address, oneBigSumSchedule)).to.be.rejectedWith(/^vesting.InsufficientBalanceToLock$/);122 await expect(helper.balance.vestedTransfer(sender, receiver.address, oneBigSumSchedule)).to.be.rejectedWith(/InsufficientBalance/);116 await expect(helper.balance.vestedTransfer(sender, receiver.address, oneBigSumSchedule)).to.be.rejectedWith(/^Token: FundsUnavailable$/);123117124 const balanceSender = await helper.balance.getSubstrateFull(sender.address);118 const balanceSender = await helper.balance.getSubstrateFull(sender.address);125 const balanceReceiver = await helper.balance.getSubstrateFull(receiver.address);119 const balanceReceiver = await helper.balance.getSubstrateFull(receiver.address);126120127 // Sender's balance has not changed121 // Sender's balance has not changed128 expect(balanceSender.free / nominal).to.eq(999n);122 expect(balanceSender.free / nominal).to.eq(999n);129 expect(balanceSender.feeFrozen).to.eq(0n);123 expect(balanceSender.frozen).to.eq(0n);130 expect(balanceSender.miscFrozen).to.eq(0n);131 expect(balanceSender.reserved).to.eq(0n);124 expect(balanceSender.reserved).to.eq(0n);132125133 // Receiver's balance has not changed126 // Receiver's balance has not changed134 expect(balanceReceiver.free).to.be.eq(1n * nominal);127 expect(balanceReceiver.free).to.be.eq(1n * nominal);135 expect(balanceReceiver.feeFrozen).to.be.eq(0n);128 expect(balanceReceiver.frozen).to.be.eq(0n);136 expect(balanceReceiver.miscFrozen).to.be.eq(0n);137 expect(balanceReceiver.reserved).to.be.eq(0n);129 expect(balanceReceiver.reserved).to.be.eq(0n);138130139 // Receiver cannot send vestedTransfer back because of freeze131 // Receiver cannot send vestedTransfer back because of freeze140 await expect(helper.balance.vestedTransfer(receiver, sender.address, schedule)).to.be.rejectedWith(/InsufficientBalance/);132 await expect(helper.balance.vestedTransfer(receiver, sender.address, schedule)).to.be.rejectedWith(/^Token: FundsUnavailable$/);141 });133 });142134143 itSub('cannot send vestedTransfer with incorrect parameters', async ({helper}) => {135 itSub('cannot send vestedTransfer with incorrect parameters', async ({helper}) => {153 const balanceSender = await helper.balance.getSubstrateFull(sender.address);145 const balanceSender = await helper.balance.getSubstrateFull(sender.address);154 // Sender's balance has not changed146 // Sender's balance has not changed155 expect(balanceSender.free / nominal).to.eq(999n);147 expect(balanceSender.free / nominal).to.eq(999n);156 expect(balanceSender.feeFrozen).to.eq(0n);148 expect(balanceSender.frozen).to.eq(0n);157 expect(balanceSender.miscFrozen).to.eq(0n);158 expect(balanceSender.reserved).to.eq(0n);149 expect(balanceSender.reserved).to.eq(0n);159 });150 });160});151});