difftreelog
fix tests cleanup
in: master
10 files changed
tests/src/eth/collectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/eth/collectionLimits.test.ts
+++ b/tests/src/eth/collectionLimits.test.ts
@@ -97,7 +97,7 @@
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('Limits', 'absolutely anything', 'ISNI', testCase.case, 18)).send();
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.case, owner);
// Cannot set non-existing limit
await expect(collectionEvm.methods
tests/src/eth/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createCollection.test.ts
+++ b/tests/src/eth/createCollection.test.ts
@@ -23,12 +23,13 @@
const DECIMALS = 18;
const CREATE_COLLECTION_DATA_DEFAULTS_ARRAY = [
- [],
- [],
- [],
- [false, false, []],
- [],
- [0],
+ [], // properties
+ [], // tokenPropertyPermissions
+ [], // adminList
+ [false, false, []], // nestingSettings
+ [], // limits
+ emptyAddress, // pendingSponsor
+ [0], // flags
];
type ElementOf<A> = A extends readonly (infer T)[] ? T : never;
@@ -64,7 +65,7 @@
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
@@ -76,7 +77,7 @@
.to.be.true;
// check collectionOwner:
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
const collectionOwner = await collectionEvm.methods.collectionOwner().call();
expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
@@ -84,7 +85,7 @@
itEth('destroyCollection', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress, collectionId} = await helper.eth.createCollection(owner, new CreateCollectionData('Exister', 'absolutely anything', 'WIWT', 'ft', DECIMALS)).send();
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
const result = await collectionHelper.methods
.destroyCollection(collectionAddress)
@@ -110,7 +111,7 @@
itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
{
const MAX_NAME_LENGTH = 64;
const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);
@@ -119,7 +120,6 @@
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
collectionName,
description,
tokenPrefix,
@@ -136,7 +136,6 @@
const tokenPrefix = 'A';
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
collectionName,
description,
tokenPrefix,
@@ -153,7 +152,6 @@
const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
collectionName,
description,
tokenPrefix,
@@ -167,11 +165,10 @@
itEth('(!negative test!) cannot create collection if value !== 2', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
const expects = [0n, 1n, 30n].map(async value => {
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
'Peasantry',
'absolutely anything',
'TWIW',
@@ -238,7 +235,7 @@
const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;
const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers.methods
.isCollectionExist(expectedCollectionAddress)
@@ -246,7 +243,6 @@
await collectionHelpers.methods
.createCollection([
- emptyAddress,
'A',
'A',
'A',
@@ -331,7 +327,7 @@
const ss58Format = helper.chain.getChainProperties().ss58Format;
const {collectionId, collectionAddress} = await helper.eth.createCollection(owner, new CreateCollectionData('Sponsor', 'absolutely anything', 'ENVY', 'rft')).send();
- const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
await collection.methods.setCollectionSponsorCross(sponsorCross).send();
@@ -340,7 +336,7 @@
await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
data = (await helper.rft.getData(collectionId))!;
@@ -350,7 +346,7 @@
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
@@ -362,7 +358,7 @@
.to.be.true;
// check collectionOwner:
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
const collectionOwner = await collectionEvm.methods.collectionOwner().call();
expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
@@ -370,7 +366,7 @@
itEth('destroyCollection', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress, collectionId} = await helper.eth.createCollection(owner, new CreateCollectionData('Limits', 'absolutely anything', 'OLF', 'rft')).send();
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
await expect(collectionHelper.methods
.destroyCollection(collectionAddress)
@@ -384,7 +380,7 @@
itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
{
const MAX_NAME_LENGTH = 64;
const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);
@@ -393,7 +389,6 @@
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
collectionName,
description,
tokenPrefix,
@@ -410,7 +405,6 @@
const tokenPrefix = 'A';
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
collectionName,
description,
tokenPrefix,
@@ -427,7 +421,6 @@
const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
collectionName,
description,
tokenPrefix,
@@ -441,10 +434,9 @@
itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
await expect(collectionHelper.methods
.createCollection([
- emptyAddress,
'Peasantry',
'absolutely anything',
'TWIW',
@@ -473,7 +465,7 @@
pendingSponsor: sponsorCross,
},
).send();
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
expect(await collectionEvm.methods.hasCollectionPendingSponsor().call({from: owner})).to.be.true;
@@ -657,7 +649,7 @@
'',
);
const collectionSub = helper.nft.getCollectionObject(collectionId);
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
// Set and confirm sponsor:
await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsorEth});
@@ -695,7 +687,7 @@
'',
);
const receiver = await helper.eth.createAccountWithBalance(donor);
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
@@ -764,7 +756,7 @@
adminList: [adminCrossSub, adminCrossEth],
},
).send();
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner, true);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner, true);
// 1. Expect api.rpc.unique.adminlist returns admins:
const adminListRpc = await helper.collection.getAdmins(collectionId);
@@ -801,7 +793,7 @@
},
'uri',
);
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true);
// admin (sub and eth) can mint token:
await collectionEvm.methods.mint(owner).send({from: adminEth});
@@ -852,7 +844,7 @@
},
).send();
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
{
const adminList = await helper.collection.getAdmins(collectionId);
@@ -1062,7 +1054,7 @@
},
).send();
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, caller);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, testCase.mode, caller);
await collectionEvm.methods.deleteCollectionProperties(['testKey1', 'testKey2']).send({from: caller});
@@ -1162,7 +1154,7 @@
],
},
).send();
- const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
+ const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, owner);
expect(await helper[testCase.mode].getPropertyPermissions(collectionId)).to.be.deep.equal([{
key: 'testKey',
@@ -1287,7 +1279,7 @@
},
).send();
- const collection = await helper.ethNativeContract.collection(collectionAddress, testCase.mode, caller);
+ const collection = helper.ethNativeContract.collection(collectionAddress, testCase.mode, caller);
const tokenId = (await collection.methods.mintCross(receiver, [{key: 'testKey', value: Buffer.from('testValue')}, {key: 'testKey_1', value: Buffer.from('testValue_1')}]).send()).events.Transfer.returnValues.tokenId;
expect(await collection.methods.properties(tokenId, ['testKey', 'testKey_1']).call()).to.has.length(2);
@@ -1311,7 +1303,7 @@
},
).send();
- const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
// Create a token to be nested to
const mintingTargetNFTTokenIdResult = await contract.methods.mint(owner).send({from: owner});
@@ -1342,7 +1334,7 @@
new CreateCollectionData('A', 'B', 'C', 'nft'),
).send();
- const unnestedContract = await helper.ethNativeContract.collection(unnestedCollectionAddress, 'nft', owner);
+ const unnestedContract = helper.ethNativeContract.collection(unnestedCollectionAddress, 'nft', owner);
expect(await unnestedContract.methods.collectionNesting().call({from: owner})).to.be.like([false, false, []]);
const {collectionAddress} = await helper.eth.createCollection(
@@ -1357,7 +1349,7 @@
},
).send();
- const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
expect(await contract.methods.collectionNesting().call({from: owner})).to.be.like([true, false, [unnestedCollectionAddress.toString()]]);
await contract.methods.setCollectionNesting([false, false, []]).send({from: owner});
expect(await contract.methods.collectionNesting().call({from: owner})).to.be.like([false, false, []]);
@@ -1378,7 +1370,7 @@
},
).send();
- const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
// Create a token to nest into
const mintingTargetTokenIdResult = await contract.methods.mint(owner).send({from: owner});
@@ -1419,17 +1411,15 @@
}
});
- itEth('NFT: foreign flag number is ignored', async ({helper}) => {
+ itEth('NFT: can\'t set foreign flag number', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
{
- const {collectionId} = await helper.eth.createCollection(owner, {...createCollectionData, flags: 128}).send();
- expect((await helper.nft.getData(collectionId))?.raw.flags).to.be.deep.equal({foreign: false, erc721metadata: false});
+ await expect(helper.eth.createCollection(owner, {...createCollectionData, flags: 128}).call({from: owner})).to.be.rejectedWith(/internal flags were used/);
}
{
- const {collectionId} = await helper.eth.createCollection(owner, {...createCollectionData, flags: 192}).send();
- expect((await helper.nft.getData(collectionId))?.raw.flags).to.be.deep.equal({foreign: false, erc721metadata: true});
+ await expect(helper.eth.createCollection(owner, {...createCollectionData, flags: 192}).call({from: owner})).to.be.rejectedWith(/internal flags were used/);
}
});
@@ -1446,13 +1436,11 @@
const owner = await helper.eth.createAccountWithBalance(donor);
{
- const {collectionId} = await helper.eth.createCollection(owner, {...createCollectionData, flags: [CollectionFlag.Foreign]}).send();
- expect((await helper.nft.getData(collectionId))?.raw.flags).to.be.deep.equal({foreign: false, erc721metadata: false});
+ await expect(helper.eth.createCollection(owner, {...createCollectionData, flags: [CollectionFlag.Foreign]}).call({from: owner})).to.be.rejectedWith(/internal flags were used/);
}
{
- const {collectionId} = await helper.eth.createCollection(owner, {...createCollectionData, flags: [CollectionFlag.Erc721metadata | CollectionFlag.Foreign]}).send();
- expect((await helper.nft.getData(collectionId))?.raw.flags).to.be.deep.equal({foreign: false, erc721metadata: true});
+ await expect(helper.eth.createCollection(owner, {...createCollectionData, flags: [CollectionFlag.Erc721metadata | CollectionFlag.Foreign]}).call({from: owner})).to.be.rejectedWith(/internal flags were used/);
}
});
});
tests/src/eth/createFTCollection.seqtest.tsdiffbeforeafterboth--- a/tests/src/eth/createFTCollection.seqtest.ts
+++ b/tests/src/eth/createFTCollection.seqtest.ts
@@ -59,7 +59,7 @@
const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;
const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers.methods
.isCollectionExist(expectedCollectionAddress)
tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createFTCollection.test.ts
+++ b/tests/src/eth/createFTCollection.test.ts
@@ -50,7 +50,7 @@
await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
data = (await helper.rft.getData(collectionId))!;
@@ -64,7 +64,7 @@
const description = 'absolutely anything';
const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, description, 'ENVY');
- const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
await collection.methods.setCollectionSponsorCross(sponsorCross).send();
@@ -73,7 +73,7 @@
await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
data = (await helper.rft.getData(collectionId))!;
@@ -84,7 +84,7 @@
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
@@ -96,7 +96,7 @@
.to.be.true;
// check collectionOwner:
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
const collectionOwner = await collectionEvm.methods.collectionOwner().call();
expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
@@ -104,7 +104,7 @@
itEth('destroyCollection', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress, collectionId} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT');
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
const result = await collectionHelper.methods
.destroyCollection(collectionAddress)
@@ -143,7 +143,7 @@
itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
{
const MAX_NAME_LENGTH = 64;
const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);
@@ -176,7 +176,7 @@
itEth('(!negative test!) cannot create collection if value !== 2', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
const expects = [0n, 1n, 30n].map(async value => {
await expect(collectionHelper.methods
.createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW')
@@ -190,7 +190,7 @@
const owner = await helper.eth.createAccountWithBalance(donor);
const peasant = helper.eth.createAccount();
const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Transgressed', DECIMALS, 'absolutely anything', 'YVNE');
- const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', peasant, true);
+ const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', peasant, true);
const EXPECTED_ERROR = 'NoPermission';
{
const sponsor = await helper.eth.createAccountWithBalance(donor);
@@ -198,7 +198,7 @@
.setCollectionSponsor(sponsor)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor, true);
await expect(sponsorCollection.methods
.confirmCollectionSponsorship()
.call()).to.be.rejectedWith('ConfirmSponsorshipFail');
@@ -214,7 +214,7 @@
const owner = await helper.eth.createAccountWithBalance(donor);
const peasant = helper.eth.createAccount();
const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Transgressed', DECIMALS, 'absolutely anything', 'YVNE');
- const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', peasant);
+ const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', peasant);
const EXPECTED_ERROR = 'NoPermission';
{
const sponsor = await helper.eth.createAccountWithBalance(donor);
@@ -223,7 +223,7 @@
.setCollectionSponsorCross(sponsorCross)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'ft', sponsor);
await expect(sponsorCollection.methods
.confirmCollectionSponsorship()
.call()).to.be.rejectedWith('ConfirmSponsorshipFail');
tests/src/eth/createNFTCollection.seqtest.tsdiffbeforeafterboth--- a/tests/src/eth/createNFTCollection.seqtest.ts
+++ b/tests/src/eth/createNFTCollection.seqtest.ts
@@ -72,7 +72,7 @@
const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;
const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers.methods
.isCollectionExist(expectedCollectionAddress)
tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createNFTCollection.test.ts
+++ b/tests/src/eth/createNFTCollection.test.ts
@@ -39,7 +39,7 @@
const baseUri = 'BaseURI';
const {collectionId, collectionAddress, events} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri);
- const contract = await helper.ethNativeContract.collection(collectionAddress, 'nft');
+ const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
expect(events).to.be.deep.equal([
{
@@ -82,7 +82,7 @@
const ss58Format = helper.chain.getChainProperties().ss58Format;
const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');
- const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true);
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true);
await collection.methods.setCollectionSponsor(sponsor).send();
let data = (await helper.nft.getData(collectionId))!;
@@ -90,7 +90,7 @@
await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
data = (await helper.nft.getData(collectionId))!;
@@ -104,7 +104,7 @@
const description = 'absolutely anything';
const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', description, 'ROC');
- const collection = await helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
await collection.methods.setCollectionSponsorCross(sponsorCross).send();
@@ -125,7 +125,7 @@
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
@@ -137,7 +137,7 @@
.to.be.true;
// check collectionOwner:
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
const collectionOwner = await collectionEvm.methods.collectionOwner().call();
expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
@@ -156,7 +156,7 @@
itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
{
const MAX_NAME_LENGTH = 64;
const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);
@@ -190,7 +190,7 @@
itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
await expect(collectionHelper.methods
.createNFTCollection('Peasantry', 'absolutely anything', 'CVE')
.call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');
@@ -209,7 +209,7 @@
.setCollectionSponsor(sponsor)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);
await expect(sponsorCollection.methods
.confirmCollectionSponsorship()
.call()).to.be.rejectedWith('ConfirmSponsorshipFail');
@@ -225,7 +225,7 @@
const owner = await helper.eth.createAccountWithBalance(donor);
const malfeasant = helper.eth.createAccount();
const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR');
- const malfeasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);
+ const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);
const EXPECTED_ERROR = 'NoPermission';
{
const sponsor = await helper.eth.createAccountWithBalance(donor);
@@ -234,7 +234,7 @@
.setCollectionSponsorCross(sponsorCross)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);
await expect(sponsorCollection.methods
.confirmCollectionSponsorship()
.call()).to.be.rejectedWith('ConfirmSponsorshipFail');
@@ -249,7 +249,7 @@
itEth('destroyCollection', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
const result = await collectionHelper.methods
tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createRFTCollection.test.ts
+++ b/tests/src/eth/createRFTCollection.test.ts
@@ -95,7 +95,7 @@
const ss58Format = helper.chain.getChainProperties().ss58Format;
const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');
- const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);
await collection.methods.setCollectionSponsor(sponsor).send();
let data = (await helper.rft.getData(collectionId))!;
@@ -103,7 +103,7 @@
await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
data = (await helper.rft.getData(collectionId))!;
@@ -116,7 +116,7 @@
const ss58Format = helper.chain.getChainProperties().ss58Format;
const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');
- const collection = await helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
+ const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
await collection.methods.setCollectionSponsorCross(sponsorCross).send();
@@ -125,7 +125,7 @@
await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
data = (await helper.rft.getData(collectionId))!;
@@ -135,7 +135,7 @@
itEth('Collection address exist', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';
- const collectionHelpers = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);
expect(await collectionHelpers
.methods.isCollectionExist(collectionAddressForNonexistentCollection).call())
@@ -147,7 +147,7 @@
.to.be.true;
// check collectionOwner:
- const collectionEvm = await helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
+ const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
const collectionOwner = await collectionEvm.methods.collectionOwner().call();
expect(helper.address.restoreCrossAccountFromBigInt(BigInt(collectionOwner.sub))).to.eq(helper.address.ethToSubstrate(owner, true));
});
@@ -167,7 +167,7 @@
itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
{
const MAX_NAME_LENGTH = 64;
const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);
@@ -200,7 +200,7 @@
itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
await expect(collectionHelper.methods
.createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')
.call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');
@@ -211,7 +211,7 @@
const owner = await helper.eth.createAccountWithBalance(donor);
const peasant = helper.eth.createAccount();
const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');
- const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true);
+ const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true);
const EXPECTED_ERROR = 'NoPermission';
{
const sponsor = await helper.eth.createAccountWithBalance(donor);
@@ -219,7 +219,7 @@
.setCollectionSponsor(sponsor)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);
await expect(sponsorCollection.methods
.confirmCollectionSponsorship()
.call()).to.be.rejectedWith('ConfirmSponsorshipFail');
@@ -235,7 +235,7 @@
const owner = await helper.eth.createAccountWithBalance(donor);
const peasant = helper.eth.createAccount();
const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');
- const peasantCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);
+ const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);
const EXPECTED_ERROR = 'NoPermission';
{
const sponsor = await helper.eth.createAccountWithBalance(donor);
@@ -244,7 +244,7 @@
.setCollectionSponsorCross(sponsorCross)
.call()).to.be.rejectedWith(EXPECTED_ERROR);
- const sponsorCollection = await helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
+ const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);
await expect(sponsorCollection.methods
.confirmCollectionSponsorship()
.call()).to.be.rejectedWith('ConfirmSponsorshipFail');
@@ -259,7 +259,7 @@
itEth('destroyCollection', async ({helper}) => {
const owner = await helper.eth.createAccountWithBalance(donor);
const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
- const collectionHelper = await helper.ethNativeContract.collectionHelpers(owner);
+ const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
await expect(collectionHelper.methods
.destroyCollection(collectionAddress)
tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/eth/util/playgrounds/unique.dev.ts
+++ b/tests/src/eth/util/playgrounds/unique.dev.ts
@@ -207,7 +207,7 @@
}
private async createTransaction() {
- const collectionHelper = await this.helper.ethNativeContract.collectionHelpers(this.signer);
+ const collectionHelper = this.helper.ethNativeContract.collectionHelpers(this.signer);
let collectionMode;
switch (this.data.collectionMode) {
case 'nft': collectionMode = CollectionMode.Nonfungible; break;
tests/src/util/index.tsdiffbeforeafterboth--- a/tests/src/util/index.ts
+++ b/tests/src/util/index.ts
@@ -15,6 +15,7 @@
import {dirname} from 'path';
import {fileURLToPath} from 'url';
+chai.config.truncateThreshold = 0;
chai.use(chaiAsPromised);
chai.use(chaiSubset);
export const expect = chai.expect;
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034import {stringToU8a} from '@polkadot/util';5import {blake2AsHex, encodeAddress, mnemonicGenerate} from '@polkadot/util-crypto';6import {UniqueHelper, MoonbeamHelper, ChainHelperBase, AcalaHelper, RelayHelper, WestmintHelper, AstarHelper} from './unique';7import {ApiPromise, Keyring, WsProvider} from '@polkadot/api';8import * as defs from '../../interfaces/definitions';9import {IKeyringPair} from '@polkadot/types/types';10import {EventRecord} from '@polkadot/types/interfaces';11import {ICrossAccountId, IPovInfo, ITransactionResult, TSigner} from './types';12import {FrameSystemEventRecord, XcmV2TraitsError, PalletSchedulerEvent} from '@polkadot/types/lookup';13import {VoidFn} from '@polkadot/api/types';14import {Pallets} from '..';15import {spawnSync} from 'child_process';1617export class SilentLogger {18 log(_msg: any, _level: any): void { }19 level = {20 ERROR: 'ERROR' as const,21 WARNING: 'WARNING' as const,22 INFO: 'INFO' as const,23 };24}2526export class SilentConsole {27 // TODO: Remove, this is temporary: Filter unneeded API output28 // (Jaco promised it will be removed in the next version)29 consoleErr: any;30 consoleLog: any;31 consoleWarn: any;3233 constructor() {34 this.consoleErr = console.error;35 this.consoleLog = console.log;36 this.consoleWarn = console.warn;37 }3839 enable() {40 const outFn = (printer: any) => (...args: any[]) => {41 for(const arg of args) {42 if(typeof arg !== 'string')43 continue;44 if(arg.includes('1000:: Normal connection closure') || arg.includes('Not decorating unknown runtime apis:') || arg.includes('RPC methods not decorated:') || arg === 'Normal connection closure')45 return;46 }47 printer(...args);48 };4950 console.error = outFn(this.consoleErr.bind(console));51 console.log = outFn(this.consoleLog.bind(console));52 console.warn = outFn(this.consoleWarn.bind(console));53 }5455 disable() {56 console.error = this.consoleErr;57 console.log = this.consoleLog;58 console.warn = this.consoleWarn;59 }60}6162export interface IEventHelper {63 section(): string;6465 method(): string;6667 wrapEvent(data: any[]): any;68}6970// eslint-disable-next-line @typescript-eslint/naming-convention71function EventHelper(section: string, method: string, wrapEvent: (data: any[]) => any) {72 const helperClass = class implements IEventHelper {73 wrapEvent: (data: any[]) => any;74 _section: string;75 _method: string;7677 constructor() {78 this.wrapEvent = wrapEvent;79 this._section = section;80 this._method = method;81 }8283 section(): string {84 return this._section;85 }8687 method(): string {88 return this._method;89 }9091 filter(txres: ITransactionResult) {92 return txres.result.events.filter(e => e.event.section === section && e.event.method === method)93 .map(e => this.wrapEvent(e.event.data));94 }9596 find(txres: ITransactionResult) {97 const e = txres.result.events.find(e => e.event.section === section && e.event.method === method);98 return e ? this.wrapEvent(e.event.data) : null;99 }100101 expect(txres: ITransactionResult) {102 const e = this.find(txres);103 if(e) {104 return e;105 } else {106 throw Error(`Expected event ${section}.${method}`);107 }108 }109 };110111 return helperClass;112}113114function eventJsonData<T = any>(data: any[], index: number) {115 return data[index].toJSON() as T;116}117118function eventHumanData(data: any[], index: number) {119 return data[index].toHuman();120}121122function eventData<T = any>(data: any[], index: number) {123 return data[index] as T;124}125126// eslint-disable-next-line @typescript-eslint/naming-convention127function EventSection(section: string) {128 return class Section {129 static section = section;130131 static Method(name: string, wrapEvent: (data: any[]) => any = () => {}) {132 const helperClass = EventHelper(Section.section, name, wrapEvent);133 return new helperClass();134 }135 };136}137138function schedulerSection(schedulerInstance: string) {139 return class extends EventSection(schedulerInstance) {140 static Dispatched = this.Method('Dispatched', data => ({141 task: eventJsonData(data, 0),142 id: eventHumanData(data, 1),143 result: data[2],144 }));145146 static PriorityChanged = this.Method('PriorityChanged', data => ({147 task: eventJsonData(data, 0),148 priority: eventJsonData(data, 1),149 }));150 };151}152153export class Event {154 static Democracy = class extends EventSection('democracy') {155 static Proposed = this.Method('Proposed', data => ({156 proposalIndex: eventJsonData<number>(data, 0),157 }));158159 static ExternalTabled = this.Method('ExternalTabled');160161 static Started = this.Method('Started', data => ({162 referendumIndex: eventJsonData<number>(data, 0),163 threshold: eventHumanData(data, 1),164 }));165166 static Voted = this.Method('Voted', data => ({167 voter: eventJsonData(data, 0),168 referendumIndex: eventJsonData<number>(data, 1),169 vote: eventJsonData(data, 2),170 }));171172 static Passed = this.Method('Passed', data => ({173 referendumIndex: eventJsonData<number>(data, 0),174 }));175 };176177 static Council = class extends EventSection('council') {178 static Proposed = this.Method('Proposed', data => ({179 account: eventHumanData(data, 0),180 proposalIndex: eventJsonData<number>(data, 1),181 proposalHash: eventHumanData(data, 2),182 threshold: eventJsonData<number>(data, 3),183 }));184 static Closed = this.Method('Closed', data => ({185 proposalHash: eventHumanData(data, 0),186 yes: eventJsonData<number>(data, 1),187 no: eventJsonData<number>(data, 2),188 }));189 };190191 static TechnicalCommittee = class extends EventSection('technicalCommittee') {192 static Proposed = this.Method('Proposed', data => ({193 account: eventHumanData(data, 0),194 proposalIndex: eventJsonData<number>(data, 1),195 proposalHash: eventHumanData(data, 2),196 threshold: eventJsonData<number>(data, 3),197 }));198 static Closed = this.Method('Closed', data => ({199 proposalHash: eventHumanData(data, 0),200 yes: eventJsonData<number>(data, 1),201 no: eventJsonData<number>(data, 2),202 }));203 };204205 static FellowshipReferenda = class extends EventSection('fellowshipReferenda') {206 static Submitted = this.Method('Submitted', data => ({207 referendumIndex: eventJsonData<number>(data, 0),208 trackId: eventJsonData<number>(data, 1),209 proposal: eventJsonData(data, 2),210 }));211 };212213 static UniqueScheduler = schedulerSection('uniqueScheduler');214 static Scheduler = schedulerSection('scheduler');215216 static XcmpQueue = class extends EventSection('xcmpQueue') {217 static XcmpMessageSent = this.Method('XcmpMessageSent', data => ({218 messageHash: eventJsonData(data, 0),219 }));220221 static Fail = this.Method('Fail', data => ({222 messageHash: eventJsonData(data, 0),223 outcome: eventData<XcmV2TraitsError>(data, 1),224 }));225 };226}227228export class DevUniqueHelper extends UniqueHelper {229 /**230 * Arrange methods for tests231 */232 arrange: ArrangeGroup;233 wait: WaitGroup;234 admin: AdminGroup;235 session: SessionGroup;236 testUtils: TestUtilGroup;237238 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {239 options.helperBase = options.helperBase ?? DevUniqueHelper;240241 super(logger, options);242 this.arrange = new ArrangeGroup(this);243 this.wait = new WaitGroup(this);244 this.admin = new AdminGroup(this);245 this.testUtils = new TestUtilGroup(this);246 this.session = new SessionGroup(this);247 }248249 async connect(wsEndpoint: string, _listeners?: any): Promise<void> {250 const wsProvider = new WsProvider(wsEndpoint);251 this.api = new ApiPromise({252 provider: wsProvider,253 signedExtensions: {254 ContractHelpers: {255 extrinsic: {},256 payload: {},257 },258 CheckMaintenance: {259 extrinsic: {},260 payload: {},261 },262 DisableIdentityCalls: {263 extrinsic: {},264 payload: {},265 },266 FakeTransactionFinalizer: {267 extrinsic: {},268 payload: {},269 },270 },271 rpc: {272 unique: defs.unique.rpc,273 appPromotion: defs.appPromotion.rpc,274 povinfo: defs.povinfo.rpc,275 eth: {276 feeHistory: {277 description: 'Dummy',278 params: [],279 type: 'u8',280 },281 maxPriorityFeePerGas: {282 description: 'Dummy',283 params: [],284 type: 'u8',285 },286 },287 },288 });289 await this.api.isReadyOrError;290 this.network = await UniqueHelper.detectNetwork(this.api);291 this.wsEndpoint = wsEndpoint;292 }293}294295export class DevRelayHelper extends RelayHelper {296 wait: WaitGroup;297298 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {299 options.helperBase = options.helperBase ?? DevRelayHelper;300301 super(logger, options);302 this.wait = new WaitGroup(this);303 }304}305306export class DevWestmintHelper extends WestmintHelper {307 wait: WaitGroup;308309 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {310 options.helperBase = options.helperBase ?? DevWestmintHelper;311312 super(logger, options);313 this.wait = new WaitGroup(this);314 }315}316317export class DevStatemineHelper extends DevWestmintHelper {}318319export class DevStatemintHelper extends DevWestmintHelper {}320321export class DevMoonbeamHelper extends MoonbeamHelper {322 account: MoonbeamAccountGroup;323 wait: WaitGroup;324 fastDemocracy: MoonbeamFastDemocracyGroup;325326 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {327 options.helperBase = options.helperBase ?? DevMoonbeamHelper;328 options.notePreimagePallet = options.notePreimagePallet ?? 'preimage';329330 super(logger, options);331 this.account = new MoonbeamAccountGroup(this);332 this.wait = new WaitGroup(this);333 this.fastDemocracy = new MoonbeamFastDemocracyGroup(this);334 }335}336337export class DevMoonriverHelper extends DevMoonbeamHelper {338 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {339 options.notePreimagePallet = options.notePreimagePallet ?? 'preimage';340 super(logger, options);341 }342}343344export class DevAstarHelper extends AstarHelper {345 wait: WaitGroup;346347 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {348 options.helperBase = options.helperBase ?? DevAstarHelper;349350 super(logger, options);351 this.wait = new WaitGroup(this);352 }353}354355export class DevShidenHelper extends AstarHelper {356 wait: WaitGroup;357358 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {359 options.helperBase = options.helperBase ?? DevShidenHelper;360361 super(logger, options);362 this.wait = new WaitGroup(this);363 }364}365366export class DevAcalaHelper extends AcalaHelper {367 wait: WaitGroup;368369 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {370 options.helperBase = options.helperBase ?? DevAcalaHelper;371372 super(logger, options);373 this.wait = new WaitGroup(this);374 }375}376377export class DevKaruraHelper extends DevAcalaHelper {}378379export class ArrangeGroup {380 helper: DevUniqueHelper;381382 scheduledIdSlider = 0;383384 constructor(helper: DevUniqueHelper) {385 this.helper = helper;386 }387388 /**389 * Generates accounts with the specified UNQ token balance390 * @param balances balances for generated accounts. Each balance will be multiplied by the token nominal.391 * @param donor donor account for balances392 * @returns array of newly created accounts393 * @example const [acc1, acc2, acc3] = await createAccounts([0n, 10n, 20n], donor);394 */395 createAccounts = async (balances: bigint[], donor: IKeyringPair): Promise<IKeyringPair[]> => {396 let nonce = await this.helper.chain.getNonce(donor.address);397 const wait = new WaitGroup(this.helper);398 const ss58Format = this.helper.chain.getChainProperties().ss58Format;399 const tokenNominal = this.helper.balance.getOneTokenNominal();400 const transactions = [];401 const accounts: IKeyringPair[] = [];402 for(const balance of balances) {403 const recipient = this.helper.util.fromSeed(mnemonicGenerate(), ss58Format);404 accounts.push(recipient);405 if(balance !== 0n) {406 const tx = this.helper.constructApiCall('api.tx.balances.transfer', [{Id: recipient.address}, balance * tokenNominal]);407 transactions.push(this.helper.signTransaction(donor, tx, {nonce, era: 0}, 'account generation'));408 nonce++;409 }410 }411412 await Promise.all(transactions).catch(_e => {});413414 //#region TODO remove this region, when nonce problem will be solved415 const checkBalances = async () => {416 let isSuccess = true;417 for(let i = 0; i < balances.length; i++) {418 const balance = await this.helper.balance.getSubstrate(accounts[i].address);419 if(balance !== balances[i] * tokenNominal) {420 isSuccess = false;421 break;422 }423 }424 return isSuccess;425 };426427 let accountsCreated = false;428 const maxBlocksChecked = await this.helper.arrange.isDevNode() ? 50 : 5;429 // checkBalances retry up to 5-50 blocks430 for(let index = 0; index < maxBlocksChecked; index++) {431 accountsCreated = await checkBalances();432 if(accountsCreated) break;433 await wait.newBlocks(1);434 }435436 if(!accountsCreated) throw Error('Accounts generation failed');437 //#endregion438439 return accounts;440 };441442 // TODO combine this method and createAccounts into one443 createCrowd = async (accountsToCreate: number, withBalance: bigint, donor: IKeyringPair): Promise<IKeyringPair[]> => {444 const createAsManyAsCan = async () => {445 let transactions: any = [];446 const accounts: IKeyringPair[] = [];447 let nonce = await this.helper.chain.getNonce(donor.address);448 const tokenNominal = this.helper.balance.getOneTokenNominal();449 const ss58Format = this.helper.chain.getChainProperties().ss58Format;450 for(let i = 0; i < accountsToCreate; i++) {451 if(i === 500) { // if there are too many accounts to create452 await Promise.allSettled(transactions); // wait while first 500 (should be 100 for devnode) tx will be settled453 transactions = []; //454 nonce = await this.helper.chain.getNonce(donor.address); // update nonce455 }456 const recipient = this.helper.util.fromSeed(mnemonicGenerate(), ss58Format);457 accounts.push(recipient);458 if(withBalance !== 0n) {459 const tx = this.helper.constructApiCall('api.tx.balances.transfer', [{Id: recipient.address}, withBalance * tokenNominal]);460 transactions.push(this.helper.signTransaction(donor, tx, {nonce}, 'account generation'));461 nonce++;462 }463 }464465 const fullfilledAccounts = [];466 await Promise.allSettled(transactions);467 for(const account of accounts) {468 const accountBalance = await this.helper.balance.getSubstrate(account.address);469 if(accountBalance === withBalance * tokenNominal) {470 fullfilledAccounts.push(account);471 }472 }473 return fullfilledAccounts;474 };475476477 const crowd: IKeyringPair[] = [];478 // do up to 5 retries479 for(let index = 0; index < 5 && accountsToCreate !== 0; index++) {480 const asManyAsCan = await createAsManyAsCan();481 crowd.push(...asManyAsCan);482 accountsToCreate -= asManyAsCan.length;483 }484485 if(accountsToCreate !== 0) throw Error(`Crowd generation failed: ${accountsToCreate} accounts left`);486487 return crowd;488 };489490 /**491 * Generates one account with zero balance492 * @returns the newly generated account493 * @example const account = await helper.arrange.createEmptyAccount();494 */495 createEmptyAccount = (): IKeyringPair => {496 const ss58Format = this.helper.chain.getChainProperties().ss58Format;497 return this.helper.util.fromSeed(mnemonicGenerate(), ss58Format);498 };499500 isDevNode = async () => {501 let blockNumber = (await this.helper.callRpc('api.query.system.number')).toJSON();502 if(blockNumber == 0) {503 await this.helper.wait.newBlocks(1);504 blockNumber = (await this.helper.callRpc('api.query.system.number')).toJSON();505 }506 const block2 = await this.helper.callRpc('api.rpc.chain.getBlock', [await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockNumber])]);507 const block1 = await this.helper.callRpc('api.rpc.chain.getBlock', [await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockNumber - 1])]);508 const findCreationDate = (block: any) => {509 const humanBlock = block.toHuman();510 let date;511 humanBlock.block.extrinsics.forEach((ext: any) => {512 if(ext.method.section === 'timestamp') {513 date = Number(ext.method.args.now.replaceAll(',', ''));514 }515 });516 return date;517 };518 const block1date = await findCreationDate(block1);519 const block2date = await findCreationDate(block2);520 if(block2date! - block1date! < 9000) return true;521 };522523 async calculcateFee(payer: ICrossAccountId, promise: () => Promise<any>): Promise<bigint> {524 const address = 'Substrate' in payer ? payer.Substrate : this.helper.address.ethToSubstrate(payer.Ethereum);525 let balance = await this.helper.balance.getSubstrate(address);526527 await promise();528529 balance -= await this.helper.balance.getSubstrate(address);530531 return balance;532 }533534 async calculatePoVInfo(txs: any[]): Promise<IPovInfo> {535 const rawPovInfo = await this.helper.callRpc('api.rpc.povinfo.estimateExtrinsicPoV', [txs]);536537 const kvJson: {[key: string]: string} = {};538539 for(const kv of rawPovInfo.keyValues) {540 kvJson[kv.key.toHex()] = kv.value.toHex();541 }542543 const kvStr = JSON.stringify(kvJson);544545 const chainql = spawnSync(546 'chainql',547 [548 `--tla-code=data=${kvStr}`,549 '-e', `function(data) cql.dump(cql.chain("${this.helper.getEndpoint()}").latest._meta, data, {omit_empty:true})`,550 ],551 );552553 if(!chainql.stdout) {554 throw Error('unable to get an output from the `chainql`');555 }556557 return {558 proofSize: rawPovInfo.proofSize.toNumber(),559 compactProofSize: rawPovInfo.compactProofSize.toNumber(),560 compressedProofSize: rawPovInfo.compressedProofSize.toNumber(),561 results: rawPovInfo.results,562 kv: JSON.parse(chainql.stdout.toString()),563 };564 }565566 calculatePalletAddress(palletId: any) {567 const address = stringToU8a(('modl' + palletId).padEnd(32, '\0'));568 return encodeAddress(address, this.helper.chain.getChainProperties().ss58Format);569 }570571 makeScheduledIds(num: number): string[] {572 function makeId(slider: number) {573 const scheduledIdSize = 64;574 const hexId = slider.toString(16);575 const prefixSize = scheduledIdSize - hexId.length;576577 const scheduledId = '0x' + '0'.repeat(prefixSize) + hexId;578579 return scheduledId;580 }581582 const ids = [];583 for(let i = 0; i < num; i++) {584 ids.push(makeId(this.scheduledIdSlider));585 this.scheduledIdSlider += 1;586 }587588 return ids;589 }590591 makeScheduledId(): string {592 return (this.makeScheduledIds(1))[0];593 }594595 async captureEvents(eventSection: string, eventMethod: string): Promise<EventCapture> {596 const capture = new EventCapture(this.helper, eventSection, eventMethod);597 await capture.startCapture();598599 return capture;600 }601602 makeXcmProgramWithdrawDeposit(beneficiary: Uint8Array, id: any, amount: bigint) {603 return {604 V2: [605 {606 WithdrawAsset: [607 {608 id,609 fun: {610 Fungible: amount,611 },612 },613 ],614 },615 {616 BuyExecution: {617 fees: {618 id,619 fun: {620 Fungible: amount,621 },622 },623 weightLimit: 'Unlimited',624 },625 },626 {627 DepositAsset: {628 assets: {629 Wild: 'All',630 },631 maxAssets: 1,632 beneficiary: {633 parents: 0,634 interior: {635 X1: {636 AccountId32: {637 network: 'Any',638 id: beneficiary,639 },640 },641 },642 },643 },644 },645 ],646 };647 }648649 makeXcmProgramReserveAssetDeposited(beneficiary: Uint8Array, id: any, amount: bigint) {650 return {651 V2: [652 {653 ReserveAssetDeposited: [654 {655 id,656 fun: {657 Fungible: amount,658 },659 },660 ],661 },662 {663 BuyExecution: {664 fees: {665 id,666 fun: {667 Fungible: amount,668 },669 },670 weightLimit: 'Unlimited',671 },672 },673 {674 DepositAsset: {675 assets: {676 Wild: 'All',677 },678 maxAssets: 1,679 beneficiary: {680 parents: 0,681 interior: {682 X1: {683 AccountId32: {684 network: 'Any',685 id: beneficiary,686 },687 },688 },689 },690 },691 },692 ],693 };694 }695}696697class MoonbeamAccountGroup {698 helper: MoonbeamHelper;699700 keyring: Keyring;701 _alithAccount: IKeyringPair;702 _baltatharAccount: IKeyringPair;703 _dorothyAccount: IKeyringPair;704705 constructor(helper: MoonbeamHelper) {706 this.helper = helper;707708 this.keyring = new Keyring({type: 'ethereum'});709 const alithPrivateKey = '0x5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133';710 const baltatharPrivateKey = '0x8075991ce870b93a8870eca0c0f91913d12f47948ca0fd25b49c6fa7cdbeee8b';711 const dorothyPrivateKey = '0x39539ab1876910bbf3a223d84a29e28f1cb4e2e456503e7e91ed39b2e7223d68';712713 this._alithAccount = this.keyring.addFromUri(alithPrivateKey, undefined, 'ethereum');714 this._baltatharAccount = this.keyring.addFromUri(baltatharPrivateKey, undefined, 'ethereum');715 this._dorothyAccount = this.keyring.addFromUri(dorothyPrivateKey, undefined, 'ethereum');716 }717718 alithAccount() {719 return this._alithAccount;720 }721722 baltatharAccount() {723 return this._baltatharAccount;724 }725726 dorothyAccount() {727 return this._dorothyAccount;728 }729730 create() {731 return this.keyring.addFromUri(mnemonicGenerate());732 }733}734735class MoonbeamFastDemocracyGroup {736 helper: DevMoonbeamHelper;737738 constructor(helper: DevMoonbeamHelper) {739 this.helper = helper;740 }741742 async executeProposal(proposalDesciption: string, encodedProposal: string) {743 const proposalHash = blake2AsHex(encodedProposal);744745 const alithAccount = this.helper.account.alithAccount();746 const baltatharAccount = this.helper.account.baltatharAccount();747 const dorothyAccount = this.helper.account.dorothyAccount();748749 const councilVotingThreshold = 2;750 const technicalCommitteeThreshold = 2;751 const fastTrackVotingPeriod = 3;752 const fastTrackDelayPeriod = 0;753754 console.log(`[democracy] executing '${proposalDesciption}' proposal`);755756 // >>> Propose external motion through council >>>757 console.log('\t* Propose external motion through council.......');758 const externalMotion = this.helper.democracy.externalProposeMajority({Inline: encodedProposal});759 const encodedMotion = externalMotion?.method.toHex() || '';760 const motionHash = blake2AsHex(encodedMotion);761 console.log('\t* Motion hash is %s', motionHash);762763 await this.helper.collective.council.propose(764 baltatharAccount,765 councilVotingThreshold,766 externalMotion,767 externalMotion.encodedLength,768 );769770 const councilProposalIdx = await this.helper.collective.council.proposalCount() - 1;771 await this.helper.collective.council.vote(dorothyAccount, motionHash, councilProposalIdx, true);772 await this.helper.collective.council.vote(baltatharAccount, motionHash, councilProposalIdx, true);773774 await this.helper.collective.council.close(775 dorothyAccount,776 motionHash,777 councilProposalIdx,778 {779 refTime: 1_000_000_000,780 proofSize: 1_000_000,781 },782 externalMotion.encodedLength,783 );784 console.log('\t* Propose external motion through council.......DONE');785 // <<< Propose external motion through council <<<786787 // >>> Fast track proposal through technical committee >>>788 console.log('\t* Fast track proposal through technical committee.......');789 const fastTrack = this.helper.democracy.fastTrack(proposalHash, fastTrackVotingPeriod, fastTrackDelayPeriod);790 const encodedFastTrack = fastTrack?.method.toHex() || '';791 const fastTrackHash = blake2AsHex(encodedFastTrack);792 console.log('\t* FastTrack hash is %s', fastTrackHash);793794 await this.helper.collective.techCommittee.propose(alithAccount, technicalCommitteeThreshold, fastTrack, fastTrack.encodedLength);795796 const techProposalIdx = await this.helper.collective.techCommittee.proposalCount() - 1;797 await this.helper.collective.techCommittee.vote(baltatharAccount, fastTrackHash, techProposalIdx, true);798 await this.helper.collective.techCommittee.vote(alithAccount, fastTrackHash, techProposalIdx, true);799800 await this.helper.collective.techCommittee.close(801 baltatharAccount,802 fastTrackHash,803 techProposalIdx,804 {805 refTime: 1_000_000_000,806 proofSize: 1_000_000,807 },808 fastTrack.encodedLength,809 );810 console.log('\t* Fast track proposal through technical committee.......DONE');811 // <<< Fast track proposal through technical committee <<<812813 const democracyStarted = await this.helper.wait.expectEvent(3, Event.Democracy.Started);814 const referendumIndex = democracyStarted.referendumIndex;815816 // >>> Referendum voting >>>817 console.log(`\t* Referendum #${referendumIndex} voting.......`);818 await this.helper.democracy.referendumVote(dorothyAccount, referendumIndex, {819 balance: 10_000_000_000_000_000_000n,820 vote: {aye: true, conviction: 1},821 });822 console.log(`\t* Referendum #${referendumIndex} voting.......DONE`);823 // <<< Referendum voting <<<824825 // Wait the proposal to pass826 await this.helper.wait.expectEvent(3, Event.Democracy.Passed, event => event.referendumIndex == referendumIndex);827828 await this.helper.wait.newBlocks(1);829830 console.log(`[democracy] executing '${proposalDesciption}' proposal.......DONE`);831 }832}833834class WaitGroup {835 helper: ChainHelperBase;836837 constructor(helper: ChainHelperBase) {838 this.helper = helper;839 }840841 sleep(milliseconds: number) {842 return new Promise((resolve) => setTimeout(resolve, milliseconds));843 }844845 private async waitWithTimeout(promise: Promise<any>, timeout: number) {846 let isBlock = false;847 promise.then(() => isBlock = true).catch(() => isBlock = true);848 let totalTime = 0;849 const step = 100;850 while(!isBlock) {851 await this.sleep(step);852 totalTime += step;853 if(totalTime >= timeout) throw Error('Blocks production failed');854 }855 return promise;856 }857858 /**859 * Launch some async operation, or throw an error after some time. Note that it will still continue executing after the timeout.860 * @param promise async operation to race against the timeout861 * @param timeoutMS time after which to time out862 * @param timeoutError error message to throw863 * @returns promise of the same type the operation had864 */865 withTimeout<T>(866 promise: Promise<T>,867 timeoutMS = 30000,868 timeoutError = 'The operation has timed out!',869 ): Promise<T> {870 const timeout = new Promise<never>((_, reject) => {871 setTimeout(() => {872 reject(new Error(timeoutError));873 }, timeoutMS);874 });875876 return Promise.race<T>([promise, timeout]).catch(e => {throw new Error(e);});877 }878879 /**880 * Wait for specified number of blocks881 * @param blocksCount number of blocks to wait882 * @returns883 */884 async newBlocks(blocksCount = 1, timeout?: number): Promise<void> {885 timeout = timeout ?? blocksCount * 60_000;886 // eslint-disable-next-line no-async-promise-executor887 const promise = new Promise<void>(async (resolve) => {888 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads(() => {889 if(blocksCount > 0) {890 blocksCount--;891 } else {892 unsubscribe();893 resolve();894 }895 });896 });897 await this.waitWithTimeout(promise, timeout);898 return promise;899 }900901 /**902 * Wait for the specified number of sessions to pass.903 * Only applicable if the Session pallet is turned on.904 * @param sessionCount number of sessions to wait905 * @param blockTimeout time in ms until panicking that the chain has stopped producing blocks906 * @returns907 */908 async newSessions(sessionCount = 1, blockTimeout = 60000): Promise<void> {909 console.log(`Waiting for ${sessionCount} new session${sessionCount>1's'''}.`910 + ' This might take a while -- check SessionPeriod in pallet_session::Config for session time.');911912 const expectedSessionIndex = await (this.helper as DevUniqueHelper).session.getIndex() + sessionCount;913 let currentSessionIndex = -1;914915 while(currentSessionIndex < expectedSessionIndex) {916 // eslint-disable-next-line no-async-promise-executor917 currentSessionIndex = await this.withTimeout(new Promise(async (resolve) => {918 await this.newBlocks(1);919 const res = await (this.helper as DevUniqueHelper).session.getIndex();920 resolve(res);921 }), blockTimeout, 'The chain has stopped producing blocks!');922 }923 }924925 async forParachainBlockNumber(blockNumber: bigint | number, timeout?: number) {926 timeout = timeout ?? 30 * 60 * 1000;927 // eslint-disable-next-line no-async-promise-executor928 const promise = new Promise<void>(async (resolve) => {929 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads((data: any) => {930 if(data.number.toNumber() >= blockNumber) {931 unsubscribe();932 resolve();933 }934 });935 });936 await this.waitWithTimeout(promise, timeout);937 return promise;938 }939940 async forRelayBlockNumber(blockNumber: bigint | number, timeout?: number) {941 timeout = timeout ?? 30 * 60 * 1000;942 // eslint-disable-next-line no-async-promise-executor943 const promise = new Promise<void>(async (resolve) => {944 const unsubscribe = await this.helper.getApi().query.parachainSystem.validationData((data: any) => {945 if(data.value.relayParentNumber.toNumber() >= blockNumber) {946 // @ts-ignore947 unsubscribe();948 resolve();949 }950 });951 });952 await this.waitWithTimeout(promise, timeout);953 return promise;954 }955956 noScheduledTasks() {957 const api = this.helper.getApi();958959 // eslint-disable-next-line no-async-promise-executor960 const promise = new Promise<void>(async resolve => {961 const unsubscribe = await api.rpc.chain.subscribeNewHeads(async () => {962 const areThereScheduledTasks = await api.query.scheduler.lookup.entries();963964 if(areThereScheduledTasks.length == 0) {965 unsubscribe();966 resolve();967 }968 });969 });970971 return promise;972 }973974 parachainBlockMultiplesOf(val: bigint) {975 // eslint-disable-next-line no-async-promise-executor976 const promise = new Promise<void>(async resolve => {977 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads((data: any) => {978 if(data.number.toBigInt() % val == 0n) {979 console.log(`from waiter: ${data.number.toBigInt()}`);980 unsubscribe();981 resolve();982 }983 });984 });985 return promise;986 }987988 event<T extends IEventHelper>(989 maxBlocksToWait: number,990 eventHelper: T,991 filter: (_: any) => boolean = () => true,992 ): any {993 // eslint-disable-next-line no-async-promise-executor994 const promise = new Promise<T | null>(async (resolve) => {995 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads(async header => {996 const blockNumber = header.number.toHuman();997 const blockHash = header.hash;998 const eventIdStr = `${eventHelper.section()}.${eventHelper.method()}`;999 const waitLimitStr = `wait blocks remaining: ${maxBlocksToWait}`;10001001 this.helper.logger.log(`[Block #${blockNumber}] Waiting for event \`${eventIdStr}\` (${waitLimitStr})`);10021003 const apiAt = await this.helper.getApi().at(blockHash);1004 const eventRecords = (await apiAt.query.system.events()) as any;10051006 const neededEvent = eventRecords.toArray()1007 .filter((r: FrameSystemEventRecord) => r.event.section == eventHelper.section() && r.event.method == eventHelper.method())1008 .map((r: FrameSystemEventRecord) => eventHelper.wrapEvent(r.event.data))1009 .find(filter);10101011 if(neededEvent) {1012 unsubscribe();1013 resolve(neededEvent);1014 } else if(maxBlocksToWait > 0) {1015 maxBlocksToWait--;1016 } else {1017 this.helper.logger.log(`Eligible event \`${eventIdStr}\` is NOT found`);1018 unsubscribe();1019 resolve(null);1020 }1021 });1022 });1023 return promise;1024 }10251026 async expectEvent<T extends IEventHelper>(1027 maxBlocksToWait: number,1028 eventHelper: T,1029 filter: (e: any) => boolean = () => true,1030 ) {1031 const e = await this.event(maxBlocksToWait, eventHelper, filter);1032 if(e == null) {1033 throw Error(`The event '${eventHelper.section()}.${eventHelper.method()}' is expected`);1034 } else {1035 return e;1036 }1037 }1038}10391040class SessionGroup {1041 helper: ChainHelperBase;10421043 constructor(helper: ChainHelperBase) {1044 this.helper = helper;1045 }10461047 //todo:collator documentation1048 async getIndex(): Promise<number> {1049 return (await this.helper.callRpc('api.query.session.currentIndex', [])).toNumber();1050 }10511052 newSessions(sessionCount = 1, blockTimeout = 24000): Promise<void> {1053 return (this.helper as DevUniqueHelper).wait.newSessions(sessionCount, blockTimeout);1054 }10551056 setOwnKeys(signer: TSigner, key: string) {1057 return this.helper.executeExtrinsic(1058 signer,1059 'api.tx.session.setKeys',1060 [key, '0x0'],1061 true,1062 );1063 }10641065 setOwnKeysFromAddress(signer: TSigner) {1066 return this.setOwnKeys(signer, '0x' + Buffer.from(signer.addressRaw).toString('hex'));1067 }1068}10691070class TestUtilGroup {1071 helper: DevUniqueHelper;10721073 constructor(helper: DevUniqueHelper) {1074 this.helper = helper;1075 }10761077 async enable() {1078 if(this.helper.fetchMissingPalletNames([Pallets.TestUtils]).length != 0) {1079 return;1080 }10811082 const signer = this.helper.util.fromSeed('//Alice');1083 await this.helper.getSudo<DevUniqueHelper>().executeExtrinsic(signer, 'api.tx.testUtils.enable', [], true);1084 }10851086 async setTestValue(signer: TSigner, testVal: number) {1087 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.setTestValue', [testVal], true);1088 }10891090 async incTestValue(signer: TSigner) {1091 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.incTestValue', [], true);1092 }10931094 async setTestValueAndRollback(signer: TSigner, testVal: number) {1095 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.setTestValueAndRollback', [testVal], true);1096 }10971098 async testValue(blockIdx?: number) {1099 const api = blockIdx1100 ? await this.helper.getApi().at(await this.helper.callRpc('api.rpc.chain.getBlockHash', [blockIdx]))1101 : this.helper.getApi();11021103 return (await api.query.testUtils.testValue()).toJSON();1104 }11051106 async justTakeFee(signer: TSigner) {1107 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.justTakeFee', [], true);1108 }11091110 async selfCancelingInc(signer: TSigner, scheduledId: string, maxTestVal: number) {1111 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.selfCancelingInc', [scheduledId, maxTestVal], true);1112 }1113}11141115class EventCapture {1116 helper: DevUniqueHelper;1117 eventSection: string;1118 eventMethod: string;1119 events: EventRecord[] = [];1120 unsubscribe: VoidFn | null = null;11211122 constructor(1123 helper: DevUniqueHelper,1124 eventSection: string,1125 eventMethod: string,1126 ) {1127 this.helper = helper;1128 this.eventSection = eventSection;1129 this.eventMethod = eventMethod;1130 }11311132 async startCapture() {1133 this.stopCapture();1134 this.unsubscribe = (await this.helper.getApi().query.system.events((eventRecords: FrameSystemEventRecord[]) => {1135 const newEvents = eventRecords.filter(r => r.event.section == this.eventSection && r.event.method == this.eventMethod);11361137 this.events.push(...newEvents);1138 })) as any;1139 }11401141 stopCapture() {1142 if(this.unsubscribe !== null) {1143 this.unsubscribe();1144 }1145 }11461147 extractCapturedEvents() {1148 return this.events;1149 }1150}11511152class AdminGroup {1153 helper: UniqueHelper;11541155 constructor(helper: UniqueHelper) {1156 this.helper = helper;1157 }11581159 async payoutStakers(signer: IKeyringPair, stakersToPayout: number): Promise<{staker: string, stake: bigint, payout: bigint}[]> {1160 const payoutResult = await this.helper.executeExtrinsic(signer, 'api.tx.appPromotion.payoutStakers', [stakersToPayout], true);1161 return payoutResult.result.events.filter(e => e.event.method === 'StakingRecalculation').map(e => ({1162 staker: e.event.data[0].toString(),1163 stake: e.event.data[1].toBigInt(),1164 payout: e.event.data[2].toBigInt(),1165 }));1166 }1167}