From 5ba8d8146cedbcf27a65d264b48dc53bc1534a57 Mon Sep 17 00:00:00 2001 From: Gleb Urvanov Date: Thu, 23 Jul 2020 14:47:24 +0200 Subject: [PATCH 1/6] iznik test folder created --- .../src/iznik/dto/fillOpeningParameters.ts | 85 + .../src/iznik/dto/workingGroupOpening.ts | 255 +++ .../src/iznik/tap-parallel-not-ok | 0 .../src/iznik/tests/electingCouncilTest.ts | 38 + .../src/iznik/tests/impl/closeApi.ts | 8 + .../src/iznik/tests/impl/electingCouncil.ts | 100 ++ .../iznik/tests/impl/membershipCreation.ts | 86 + .../src/iznik/tests/membershipCreationTest.ts | 29 + ...entWorkingGroupMintCapacityProposalTest.ts | 41 + .../electionParametersProposalTest.ts | 40 + .../impl/electionParametersProposal.ts | 124 ++ .../tests/proposals/impl/proposalsModule.ts | 315 ++++ .../tests/proposals/impl/setLeadProposal.ts | 46 + .../tests/proposals/impl/spendingProposal.ts | 64 + .../tests/proposals/impl/textProposal.ts | 46 + .../tests/proposals/impl/updateRuntime.ts | 52 + .../proposals/impl/validatorCountProposal.ts | 55 + .../impl/workingGroupMintCapacityProposal.ts | 59 + .../iznik/tests/proposals/manageLeaderRole.ts | 213 +++ .../tests/proposals/setLeadProposalTest.ts | 40 + .../tests/proposals/spendingProposalTest.ts | 42 + .../iznik/tests/proposals/textProposalTest.ts | 40 + .../tests/proposals/updateRuntimeTest.ts | 41 + .../proposals/validatorCountProposalTest.ts | 41 + .../workingGroupMintCapacityProposalTest.ts | 63 + .../tests/workingGroup/atLeastValueBugTest.ts | 130 ++ .../workingGroup/impl/workingGroupModule.ts | 599 +++++++ .../workingGroup/manageWorkerAsLeadTest.ts | 207 +++ .../workingGroup/manageWorkerAsWorkerTest.ts | 159 ++ .../workerApplicationHappyCaseTest.ts | 160 ++ .../workerApplicationRejectionCaseTest.ts | 160 ++ .../iznik/tests/workingGroup/workerPayout.ts | 152 ++ .../src/iznik/utils/apiWrapper.ts | 1547 +++++++++++++++++ tests/network-tests/src/iznik/utils/config.ts | 5 + tests/network-tests/src/iznik/utils/sender.ts | 66 + .../src/iznik/utils/setTestTimeout.ts | 7 + tests/network-tests/src/iznik/utils/utils.ts | 53 + 37 files changed, 5168 insertions(+) create mode 100644 tests/network-tests/src/iznik/dto/fillOpeningParameters.ts create mode 100644 tests/network-tests/src/iznik/dto/workingGroupOpening.ts create mode 100644 tests/network-tests/src/iznik/tap-parallel-not-ok create mode 100644 tests/network-tests/src/iznik/tests/electingCouncilTest.ts create mode 100644 tests/network-tests/src/iznik/tests/impl/closeApi.ts create mode 100644 tests/network-tests/src/iznik/tests/impl/electingCouncil.ts create mode 100644 tests/network-tests/src/iznik/tests/impl/membershipCreation.ts create mode 100644 tests/network-tests/src/iznik/tests/membershipCreationTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts create mode 100644 tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts create mode 100644 tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts create mode 100644 tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts create mode 100644 tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts create mode 100644 tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts create mode 100644 tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts create mode 100644 tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts create mode 100644 tests/network-tests/src/iznik/tests/workingGroup/workerPayout.ts create mode 100644 tests/network-tests/src/iznik/utils/apiWrapper.ts create mode 100644 tests/network-tests/src/iznik/utils/config.ts create mode 100644 tests/network-tests/src/iznik/utils/sender.ts create mode 100644 tests/network-tests/src/iznik/utils/setTestTimeout.ts create mode 100644 tests/network-tests/src/iznik/utils/utils.ts diff --git a/tests/network-tests/src/iznik/dto/fillOpeningParameters.ts b/tests/network-tests/src/iznik/dto/fillOpeningParameters.ts new file mode 100644 index 0000000000..e3fb7bf50f --- /dev/null +++ b/tests/network-tests/src/iznik/dto/fillOpeningParameters.ts @@ -0,0 +1,85 @@ +import BN from 'bn.js' + +export class FillOpeningParameters { + private amountPerPayout!: BN + private nextPaymentAtBlock!: BN + private payoutInterval!: BN + private openingId!: BN + private successfulApplicationId!: BN + private workingGroup!: string + + public getAmountPerPayout(): BN { + return this.amountPerPayout + } + + public getNextPaymentAtBlock(): BN { + return this.nextPaymentAtBlock + } + + public getPayoutInterval(): BN { + return this.payoutInterval + } + + public getOpeningId(): BN { + return this.openingId + } + + public getSuccessfulApplicationId(): BN { + return this.successfulApplicationId + } + + public getWorkingGroup(): string { + return this.workingGroup + } + + public setAmountPerPayout(value: BN): FillOpeningParameters { + this.amountPerPayout = value + return this + } + + public setNextPaymentAtBlock(value: BN): FillOpeningParameters { + this.nextPaymentAtBlock = value + return this + } + + public setPayoutInterval(value: BN): FillOpeningParameters { + this.payoutInterval = value + return this + } + + public setOpeningId(value: BN): FillOpeningParameters { + this.openingId = value + return this + } + + public setSuccessfulApplicationId(value: BN): FillOpeningParameters { + this.successfulApplicationId = value + return this + } + + public setWorkingGroup(value: string): FillOpeningParameters { + this.workingGroup = value + return this + } + + constructor() { + return + } + + public getRewardPolicy() { + return { + amount_per_payout: this.amountPerPayout, + next_payment_at_block: this.nextPaymentAtBlock, + payout_interval: this.payoutInterval, + } + } + + public getFillOpeningParameters() { + return { + opening_id: this.openingId, + successful_application_id: this.successfulApplicationId, + reward_policy: this.getRewardPolicy(), + working_group: this.workingGroup, + } + } +} diff --git a/tests/network-tests/src/iznik/dto/workingGroupOpening.ts b/tests/network-tests/src/iznik/dto/workingGroupOpening.ts new file mode 100644 index 0000000000..b0474e62d4 --- /dev/null +++ b/tests/network-tests/src/iznik/dto/workingGroupOpening.ts @@ -0,0 +1,255 @@ +import BN from 'bn.js' + +export class WorkingGroupOpening { + private activateAtBlock: BN | undefined + private maxActiveApplicants!: BN + private maxReviewPeriodLength!: BN + private applicationStakingPolicyAmount!: BN + private applicationCrowdedOutUnstakingPeriodLength!: BN + private applicationExpiredUnstakingPeriodLength!: BN + private roleStakingPolicyAmount!: BN + private roleCrowdedOutUnstakingPeriodLength!: BN + private roleExpiredUnstakingPeriodLength!: BN + private slashableMaxCount!: BN + private slashableMaxPercentPtsPerTime!: BN + private successfulApplicantApplicationStakeUnstakingPeriod!: BN + private failedApplicantApplicationStakeUnstakingPeriod!: BN + private failedApplicantRoleStakeUnstakingPeriod!: BN + private terminateApplicationStakeUnstakingPeriod!: BN + private terminateRoleStakeUnstakingPeriod!: BN + private exitRoleApplicationStakeUnstakingPeriod!: BN + private exitRoleStakeUnstakingPeriod!: BN + private text!: string + private openingType!: string + + public getActivateAtBlock(): BN | undefined { + return this.activateAtBlock + } + + public getMaxActiveApplicants(): BN { + return this.maxActiveApplicants + } + + public getMaxReviewPeriodLength(): BN { + return this.maxReviewPeriodLength + } + + public getApplicationStakingPolicyAmount(): BN { + return this.applicationStakingPolicyAmount + } + + public getApplicationCrowdedOutUnstakingPeriodLength(): BN { + return this.applicationCrowdedOutUnstakingPeriodLength + } + + public getApplicationExpiredUnstakingPeriodLength(): BN { + return this.applicationExpiredUnstakingPeriodLength + } + + public getRoleStakingPolicyAmount(): BN { + return this.roleStakingPolicyAmount + } + + public getRoleCrowdedOutUnstakingPeriodLength(): BN { + return this.roleCrowdedOutUnstakingPeriodLength + } + + public getRoleExpiredUnstakingPeriodLength(): BN { + return this.roleExpiredUnstakingPeriodLength + } + + public getSlashableMaxCount(): BN { + return this.slashableMaxCount + } + + public getSlashableMaxPercentPtsPerTime(): BN { + return this.slashableMaxPercentPtsPerTime + } + + public getSuccessfulApplicantApplicationStakeUnstakingPeriod(): BN { + return this.successfulApplicantApplicationStakeUnstakingPeriod + } + + public getFailedApplicantApplicationStakeUnstakingPeriod(): BN { + return this.failedApplicantApplicationStakeUnstakingPeriod + } + + public getFailedApplicantRoleStakeUnstakingPeriod(): BN { + return this.failedApplicantRoleStakeUnstakingPeriod + } + + public getTerminateApplicationStakeUnstakingPeriod(): BN { + return this.terminateApplicationStakeUnstakingPeriod + } + + public getTerminateRoleStakeUnstakingPeriod(): BN { + return this.terminateRoleStakeUnstakingPeriod + } + + public getExitRoleApplicationStakeUnstakingPeriod(): BN { + return this.exitRoleApplicationStakeUnstakingPeriod + } + + public getExitRoleStakeUnstakingPeriod(): BN { + return this.exitRoleStakeUnstakingPeriod + } + + public getText(): string { + return this.text + } + + public getOpeningType(): string { + return this.openingType + } + + public setActivateAtBlock(value: BN | undefined): WorkingGroupOpening { + this.activateAtBlock = value + return this + } + + public setMaxActiveApplicants(value: BN): WorkingGroupOpening { + this.maxActiveApplicants = value + return this + } + + public setMaxReviewPeriodLength(value: BN): WorkingGroupOpening { + this.maxReviewPeriodLength = value + return this + } + + public setApplicationStakingPolicyAmount(value: BN): WorkingGroupOpening { + this.applicationStakingPolicyAmount = value + return this + } + + public setApplicationCrowdedOutUnstakingPeriodLength(value: BN): WorkingGroupOpening { + this.applicationCrowdedOutUnstakingPeriodLength = value + return this + } + + public setApplicationExpiredUnstakingPeriodLength(value: BN): WorkingGroupOpening { + this.applicationExpiredUnstakingPeriodLength = value + return this + } + + public setRoleStakingPolicyAmount(value: BN): WorkingGroupOpening { + this.roleStakingPolicyAmount = value + return this + } + + public setRoleCrowdedOutUnstakingPeriodLength(value: BN): WorkingGroupOpening { + this.roleCrowdedOutUnstakingPeriodLength = value + return this + } + + public setRoleExpiredUnstakingPeriodLength(value: BN): WorkingGroupOpening { + this.roleExpiredUnstakingPeriodLength = value + return this + } + + public setSlashableMaxCount(value: BN): WorkingGroupOpening { + this.slashableMaxCount = value + return this + } + + public setSlashableMaxPercentPtsPerTime(value: BN): WorkingGroupOpening { + this.slashableMaxPercentPtsPerTime = value + return this + } + + public setSuccessfulApplicantApplicationStakeUnstakingPeriod(value: BN): WorkingGroupOpening { + this.successfulApplicantApplicationStakeUnstakingPeriod = value + return this + } + + public setFailedApplicantApplicationStakeUnstakingPeriod(value: BN): WorkingGroupOpening { + this.failedApplicantApplicationStakeUnstakingPeriod = value + return this + } + + public setFailedApplicantRoleStakeUnstakingPeriod(value: BN): WorkingGroupOpening { + this.failedApplicantRoleStakeUnstakingPeriod = value + return this + } + + public setTerminateApplicationStakeUnstakingPeriod(value: BN): WorkingGroupOpening { + this.terminateApplicationStakeUnstakingPeriod = value + return this + } + + public setTerminateRoleStakeUnstakingPeriod(value: BN): WorkingGroupOpening { + this.terminateRoleStakeUnstakingPeriod = value + return this + } + + public setExitRoleApplicationStakeUnstakingPeriod(value: BN): WorkingGroupOpening { + this.exitRoleApplicationStakeUnstakingPeriod = value + return this + } + + public setExitRoleStakeUnstakingPeriod(value: BN): WorkingGroupOpening { + this.exitRoleStakeUnstakingPeriod = value + return this + } + + public setText(value: string): WorkingGroupOpening { + this.text = value + return this + } + + public setOpeningType(value: string): WorkingGroupOpening { + this.openingType = value + return this + } + + constructor() { + return + } + + public getActivateAt() { + return this.activateAtBlock === undefined ? 'CurrentBlock' : { ExactBlock: this.activateAtBlock } + } + + public getCommitment() { + return { + 'application_rationing_policy': { 'max_active_applicants': this.maxActiveApplicants }, + 'max_review_period_length': this.maxReviewPeriodLength, + 'application_staking_policy': { + 'amount': this.applicationStakingPolicyAmount, + 'amount_mode': 'AtLeast', + 'crowded_out_unstaking_period_length': this.applicationCrowdedOutUnstakingPeriodLength, + 'review_period_expired_unstaking_period_length': this.applicationExpiredUnstakingPeriodLength, + }, + 'role_staking_policy': { + 'amount': this.roleStakingPolicyAmount, + 'amount_mode': 'AtLeast', + 'crowded_out_unstaking_period_length': this.roleCrowdedOutUnstakingPeriodLength, + 'review_period_expired_unstaking_period_length': this.roleExpiredUnstakingPeriodLength, + }, + 'role_slashing_terms': { + 'Slashable': { + 'max_count': this.slashableMaxCount, + 'max_percent_pts_per_time': this.slashableMaxPercentPtsPerTime, + }, + }, + 'fill_opening_successful_applicant_application_stake_unstaking_period': this + .successfulApplicantApplicationStakeUnstakingPeriod, + 'fill_opening_failed_applicant_application_stake_unstaking_period': this + .failedApplicantApplicationStakeUnstakingPeriod, + 'fill_opening_failed_applicant_role_stake_unstaking_period': this.failedApplicantRoleStakeUnstakingPeriod, + 'terminate_application_stake_unstaking_period': this.terminateApplicationStakeUnstakingPeriod, + 'terminate_role_stake_unstaking_period': this.terminateRoleStakeUnstakingPeriod, + 'exit_role_application_stake_unstaking_period': this.exitRoleApplicationStakeUnstakingPeriod, + 'exit_role_stake_unstaking_period': this.exitRoleStakeUnstakingPeriod, + } + } + + public getAddOpeningParameters(workingGroup: string) { + return { + activate_at: this.getActivateAt(), + commitment: this.getCommitment(), + human_readable_text: this.getText(), + working_group: workingGroup, + } + } +} diff --git a/tests/network-tests/src/iznik/tap-parallel-not-ok b/tests/network-tests/src/iznik/tap-parallel-not-ok new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/network-tests/src/iznik/tests/electingCouncilTest.ts b/tests/network-tests/src/iznik/tests/electingCouncilTest.ts new file mode 100644 index 0000000000..f9b75453ec --- /dev/null +++ b/tests/network-tests/src/iznik/tests/electingCouncilTest.ts @@ -0,0 +1,38 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from './impl/membershipCreation' +import { councilTest } from './impl/electingCouncil' +import { initConfig } from '../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import { setTestTimeout } from '../utils/setTestTimeout' +import BN from 'bn.js' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { ApiWrapper } from '../utils/apiWrapper' +import { closeApi } from './impl/closeApi' + +tap.mocha.describe('Electing council scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const durationInBlocks = 25 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/impl/closeApi.ts b/tests/network-tests/src/iznik/tests/impl/closeApi.ts new file mode 100644 index 0000000000..6d16dd237f --- /dev/null +++ b/tests/network-tests/src/iznik/tests/impl/closeApi.ts @@ -0,0 +1,8 @@ +import { ApiWrapper } from '../../utils/apiWrapper' +import tap from 'tap' + +export function closeApi(apiWrapper: ApiWrapper) { + tap.teardown(() => { + apiWrapper.close() + }) +} diff --git a/tests/network-tests/src/iznik/tests/impl/electingCouncil.ts b/tests/network-tests/src/iznik/tests/impl/electingCouncil.ts new file mode 100644 index 0000000000..05c5f72c48 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/impl/electingCouncil.ts @@ -0,0 +1,100 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../utils/apiWrapper' +import { Keyring } from '@polkadot/api' +import BN from 'bn.js' +import { Seat } from '@nicaea/types/council' +import { assert } from 'chai' +import { v4 as uuid } from 'uuid' +import { Utils } from '../../utils/utils' +import tap from 'tap' + +export function councilTest( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + k: number, + sudoUri: string, + greaterStake: BN, + lesserStake: BN +) { + let sudo: KeyringPair + + tap.test('Electing a council test', async () => { + // Setup goes here because M keypairs are generated after before() function + sudo = keyring.addFromUri(sudoUri) + let now = await apiWrapper.getBestBlock() + const applyForCouncilFee: BN = apiWrapper.estimateApplyForCouncilFee(greaterStake) + const voteForCouncilFee: BN = apiWrapper.estimateVoteForCouncilFee(sudo.address, sudo.address, greaterStake) + const salt: string[] = [] + m1KeyPairs.forEach(() => { + salt.push(''.concat(uuid().replace(/-/g, ''))) + }) + const revealVoteFee: BN = apiWrapper.estimateRevealVoteFee(sudo.address, salt[0]) + + // Topping the balances + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, applyForCouncilFee.add(greaterStake)) + await apiWrapper.transferBalanceToAccounts(sudo, m1KeyPairs, voteForCouncilFee.add(revealVoteFee).add(greaterStake)) + + // First K members stake more + await apiWrapper.sudoStartAnnouncingPerion(sudo, now.addn(100)) + await apiWrapper.batchApplyForCouncilElection(m2KeyPairs.slice(0, k), greaterStake) + m2KeyPairs.slice(0, k).forEach((keyPair) => + apiWrapper.getCouncilElectionStake(keyPair.address).then((stake) => { + assert( + stake.eq(greaterStake), + `${keyPair.address} not applied correctrly for council election with stake ${stake} versus expected ${greaterStake}` + ) + }) + ) + + // Last members stake less + await apiWrapper.batchApplyForCouncilElection(m2KeyPairs.slice(k), lesserStake) + m2KeyPairs.slice(k).forEach((keyPair) => + apiWrapper.getCouncilElectionStake(keyPair.address).then((stake) => { + assert( + stake.eq(lesserStake), + `${keyPair.address} not applied correctrly for council election with stake ${stake} versus expected ${lesserStake}` + ) + }) + ) + + // Voting + await apiWrapper.sudoStartVotingPerion(sudo, now.addn(100)) + await apiWrapper.batchVoteForCouncilMember( + m1KeyPairs.slice(0, k), + m2KeyPairs.slice(0, k), + salt.slice(0, k), + lesserStake + ) + await apiWrapper.batchVoteForCouncilMember(m1KeyPairs.slice(k), m2KeyPairs.slice(k), salt.slice(k), greaterStake) + + // Revealing + await apiWrapper.sudoStartRevealingPerion(sudo, now.addn(100)) + await apiWrapper.batchRevealVote(m1KeyPairs.slice(0, k), m2KeyPairs.slice(0, k), salt.slice(0, k)) + await apiWrapper.batchRevealVote(m1KeyPairs.slice(k), m2KeyPairs.slice(k), salt.slice(k)) + now = await apiWrapper.getBestBlock() + + // Resolving election + // 3 is to ensure the revealing block is in future + await apiWrapper.sudoStartRevealingPerion(sudo, now.addn(3)) + await Utils.wait(apiWrapper.getBlockDuration().muln(2.5).toNumber()) + const seats: Seat[] = await apiWrapper.getCouncil() + + // Preparing collections to increase assertion readability + const m2addresses: string[] = m2KeyPairs.map((keyPair) => keyPair.address) + const m1addresses: string[] = m1KeyPairs.map((keyPair) => keyPair.address) + const members: string[] = seats.map((seat) => seat.member.toString()) + const bakers: string[] = seats.map((seat) => seat.backers.map((baker) => baker.member.toString())).flat() + + // Assertions + m2addresses.forEach((address) => assert(members.includes(address), `Account ${address} is not in the council`)) + m1addresses.forEach((address) => assert(bakers.includes(address), `Account ${address} is not in the voters`)) + seats.forEach((seat) => + assert( + Utils.getTotalStake(seat).eq(greaterStake.add(lesserStake)), + `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}` + ) + ) + }) +} diff --git a/tests/network-tests/src/iznik/tests/impl/membershipCreation.ts b/tests/network-tests/src/iznik/tests/impl/membershipCreation.ts new file mode 100644 index 0000000000..78a23cbfb0 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/impl/membershipCreation.ts @@ -0,0 +1,86 @@ +import { Keyring } from '@polkadot/keyring' +import { assert } from 'chai' +import { KeyringPair } from '@polkadot/keyring/types' +import BN from 'bn.js' +import { ApiWrapper } from '../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import tap from 'tap' + +export function membershipTest( + apiWrapper: ApiWrapper, + nKeyPairs: KeyringPair[], + keyring: Keyring, + n: number, + paidTerms: number, + sudoUri: string +) { + let sudo: KeyringPair + let aKeyPair: KeyringPair + let membershipFee: BN + let membershipTransactionFee: BN + + tap.test('Membership creation test setup', async () => { + sudo = keyring.addFromUri(sudoUri) + for (let i = 0; i < n; i++) { + nKeyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8))) + } + aKeyPair = keyring.addFromUri(uuid().substring(0, 8)) + membershipFee = await apiWrapper.getMembershipFee(paidTerms) + membershipTransactionFee = apiWrapper.estimateBuyMembershipFee( + sudo, + paidTerms, + 'member_name_which_is_longer_than_expected' + ) + await apiWrapper.transferBalanceToAccounts(sudo, nKeyPairs, membershipTransactionFee.add(new BN(membershipFee))) + await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee) + }) + + tap.test('Buy membeship is accepted with sufficient funds', async () => { + await Promise.all( + nKeyPairs.map(async (keyPair, index) => { + await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`) + }) + ) + nKeyPairs.forEach((keyPair, index) => + apiWrapper + .getMemberIds(keyPair.address) + .then((membership) => assert(membership.length > 0, `Account ${keyPair.address} is not a member`)) + ) + }) + + tap.test('Account A can not buy the membership with insufficient funds', async () => { + await apiWrapper + .getBalance(aKeyPair.address) + .then((balance) => + assert( + balance.toBn() < membershipFee.add(membershipTransactionFee), + 'Account A already have sufficient balance to purchase membership' + ) + ) + await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`, true) + apiWrapper + .getMemberIds(aKeyPair.address) + .then((membership) => assert(membership.length === 0, 'Account A is a member')) + }) + + tap.test('Account A was able to buy the membership with sufficient funds', async () => { + await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipFee.add(membershipTransactionFee)) + apiWrapper + .getBalance(aKeyPair.address) + .then((balance) => + assert(balance.toBn() >= membershipFee, 'The account balance is insufficient to purchase membership') + ) + await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`) + apiWrapper + .getMemberIds(aKeyPair.address) + .then((membership) => assert(membership.length > 0, 'Account A is a not member')) + }) +} + +export function createKeyPairs(keyring: Keyring, n: number): KeyringPair[] { + const nKeyPairs: KeyringPair[] = [] + for (let i = 0; i < n; i++) { + nKeyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8))) + } + return nKeyPairs +} diff --git a/tests/network-tests/src/iznik/tests/membershipCreationTest.ts b/tests/network-tests/src/iznik/tests/membershipCreationTest.ts new file mode 100644 index 0000000000..ab0ca84d77 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/membershipCreationTest.ts @@ -0,0 +1,29 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from './impl/membershipCreation' +import { Keyring, WsProvider } from '@polkadot/api' +import { initConfig } from '../utils/config' +import { setTestTimeout } from '../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { ApiWrapper } from '../utils/apiWrapper' +import { closeApi } from './impl/closeApi' + +tap.mocha.describe('Membership creation scenario', async () => { + initConfig() + registerJoystreamTypes() + + const nKeyPairs: KeyringPair[] = [] + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const durationInBlocks = 7 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts new file mode 100644 index 0000000000..c16377fe35 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts @@ -0,0 +1,41 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { workingGroupMintCapacityProposalTest } from './impl/workingGroupMintCapacityProposal' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper } from '../../utils/apiWrapper' + +tap.mocha.describe('Validator count proposal scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const mintingCapacityIncrement: BN = new BN(+process.env.MINTING_CAPACITY_INCREMENT!) + const durationInBlocks = 29 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + workingGroupMintCapacityProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri, mintingCapacityIncrement) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts new file mode 100644 index 0000000000..96e18c5b36 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts @@ -0,0 +1,40 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { electionParametersProposalTest } from './impl/electionParametersProposal' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper } from '../../utils/apiWrapper' + +tap.mocha.describe('Election parameters proposal scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const durationInBlocks = 29 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + electionParametersProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts new file mode 100644 index 0000000000..56695acdf7 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts @@ -0,0 +1,124 @@ +import { Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import { assert } from 'chai' +import tap from 'tap' + +export function electionParametersProposalTest( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + sudoUri: string +) { + let sudo: KeyringPair + + tap.test('Election parameters proposal test', async () => { + // Setup + sudo = keyring.addFromUri(sudoUri) + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) + const announcingPeriod: BN = await apiWrapper.getAnnouncingPeriod() + const votingPeriod: BN = await apiWrapper.getVotingPeriod() + const revealingPeriod: BN = await apiWrapper.getRevealingPeriod() + const councilSize: BN = await apiWrapper.getCouncilSize() + const candidacyLimit: BN = await apiWrapper.getCandidacyLimit() + const newTermDuration: BN = await apiWrapper.getNewTermDuration() + const minCouncilStake: BN = await apiWrapper.getMinCouncilStake() + const minVotingStake: BN = await apiWrapper.getMinVotingStake() + + // Proposal stake calculation + const proposalStake: BN = new BN(200000) + const proposalFee: BN = apiWrapper.estimateProposeElectionParametersFee( + description, + description, + proposalStake, + announcingPeriod, + votingPeriod, + revealingPeriod, + councilSize, + candidacyLimit, + newTermDuration, + minCouncilStake, + minVotingStake + ) + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposedAnnouncingPeriod: BN = announcingPeriod.subn(1) + const proposedVotingPeriod: BN = votingPeriod.addn(1) + const proposedRevealingPeriod: BN = revealingPeriod.addn(1) + const proposedCouncilSize: BN = councilSize.addn(1) + const proposedCandidacyLimit: BN = candidacyLimit.addn(1) + const proposedNewTermDuration: BN = newTermDuration.addn(1) + const proposedMinCouncilStake: BN = minCouncilStake.addn(1) + const proposedMinVotingStake: BN = minVotingStake.addn(1) + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeElectionParameters( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + proposedAnnouncingPeriod, + proposedVotingPeriod, + proposedRevealingPeriod, + proposedCouncilSize, + proposedCandidacyLimit, + proposedNewTermDuration, + proposedMinCouncilStake, + proposedMinVotingStake + ) + const proposalNumber = await proposalPromise + + // Approving the proposal + const proposalExecutionPromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await proposalExecutionPromise + + // Assertions + const newAnnouncingPeriod: BN = await apiWrapper.getAnnouncingPeriod() + const newVotingPeriod: BN = await apiWrapper.getVotingPeriod() + const newRevealingPeriod: BN = await apiWrapper.getRevealingPeriod() + const newCouncilSize: BN = await apiWrapper.getCouncilSize() + const newCandidacyLimit: BN = await apiWrapper.getCandidacyLimit() + const newNewTermDuration: BN = await apiWrapper.getNewTermDuration() + const newMinCouncilStake: BN = await apiWrapper.getMinCouncilStake() + const newMinVotingStake: BN = await apiWrapper.getMinVotingStake() + assert( + proposedAnnouncingPeriod.eq(newAnnouncingPeriod), + `Announcing period has unexpected value ${newAnnouncingPeriod}, expected ${proposedAnnouncingPeriod}` + ) + assert( + proposedVotingPeriod.eq(newVotingPeriod), + `Voting period has unexpected value ${newVotingPeriod}, expected ${proposedVotingPeriod}` + ) + assert( + proposedRevealingPeriod.eq(newRevealingPeriod), + `Revealing has unexpected value ${newRevealingPeriod}, expected ${proposedRevealingPeriod}` + ) + assert( + proposedCouncilSize.eq(newCouncilSize), + `Council size has unexpected value ${newCouncilSize}, expected ${proposedCouncilSize}` + ) + assert( + proposedCandidacyLimit.eq(newCandidacyLimit), + `Candidacy limit has unexpected value ${newCandidacyLimit}, expected ${proposedCandidacyLimit}` + ) + assert( + proposedNewTermDuration.eq(newNewTermDuration), + `New term duration has unexpected value ${newNewTermDuration}, expected ${proposedNewTermDuration}` + ) + assert( + proposedMinCouncilStake.eq(newMinCouncilStake), + `Min council stake has unexpected value ${newMinCouncilStake}, expected ${proposedMinCouncilStake}` + ) + assert( + proposedMinVotingStake.eq(newMinVotingStake), + `Min voting stake has unexpected value ${newMinVotingStake}, expected ${proposedMinVotingStake}` + ) + }) +} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts b/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts new file mode 100644 index 0000000000..82b390961b --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts @@ -0,0 +1,315 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper, WorkingGroups } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import { WorkingGroupOpening } from '../../../dto/workingGroupOpening' +import { FillOpeningParameters } from '../../../dto/fillOpeningParameters' + +export async function createWorkingGroupLeaderOpening( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + workingGroup: string +): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing working group lead opening proposal ' + uuid().substring(0, 8) + + // Proposal stake calculation + const proposalStake: BN = new BN(100000) + const proposalFee: BN = apiWrapper.estimateProposeCreateWorkingGroupLeaderOpeningFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Opening construction + const opening = new WorkingGroupOpening() + .setMaxActiveApplicants(new BN(m1KeyPairs.length)) + .setMaxReviewPeriodLength(new BN(32)) + .setApplicationStakingPolicyAmount(new BN(applicationStake)) + .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) + .setApplicationExpiredUnstakingPeriodLength(new BN(1)) + .setRoleStakingPolicyAmount(new BN(roleStake)) + .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) + .setRoleExpiredUnstakingPeriodLength(new BN(1)) + .setSlashableMaxCount(new BN(1)) + .setSlashableMaxPercentPtsPerTime(new BN(100)) + .setSuccessfulApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantRoleStakeUnstakingPeriod(new BN(1)) + .setTerminateApplicationStakeUnstakingPeriod(new BN(1)) + .setTerminateRoleStakeUnstakingPeriod(new BN(1)) + .setExitRoleApplicationStakeUnstakingPeriod(new BN(1)) + .setExitRoleStakeUnstakingPeriod(new BN(1)) + .setText(uuid().substring(0, 8)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeCreateWorkingGroupLeaderOpening( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + opening, + workingGroup + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function beginWorkingGroupLeaderApplicationReview( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + openingId: BN, + workingGroup: string +): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8) + + // Proposal stake calculation + const proposalStake: BN = new BN(25000) + const proposalFee: BN = apiWrapper.estimateProposeBeginWorkingGroupLeaderApplicationReviewFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeBeginWorkingGroupLeaderApplicationReview( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + openingId, + workingGroup + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function fillLeaderOpeningProposal( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + applicantRoleAccountAddress: string, + sudo: KeyringPair, + firstRewardInterval: BN, + rewardInterval: BN, + payoutAmount: BN, + openingId: BN, + workingGroup: WorkingGroups +): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing fill opening proposal ' + uuid().substring(0, 8) + const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = apiWrapper.estimateProposeFillLeaderOpeningFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const applicationId: BN = ( + await apiWrapper.getActiveApplicationsIdsByRoleAccount(applicantRoleAccountAddress, workingGroup) + )[0] + const now = await apiWrapper.getBestBlock() + const fillOpeningParameters: FillOpeningParameters = new FillOpeningParameters() + .setAmountPerPayout(payoutAmount) + .setNextPaymentAtBlock(now.add(firstRewardInterval)) + .setPayoutInterval(rewardInterval) + .setOpeningId(openingId) + .setSuccessfulApplicationId(applicationId) + .setWorkingGroup(workingGroupString) + + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeFillLeaderOpening( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + fillOpeningParameters + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function terminateLeaderRoleProposal( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + leaderRoleAccountAddress: string, + sudo: KeyringPair, + slash: boolean, + workingGroup: WorkingGroups +) { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8) + const rationale: string = 'Testing leader termination ' + uuid().substring(0, 8) + const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(leaderRoleAccountAddress, workingGroup) + + // Proposal stake calculation + const proposalStake: BN = new BN(100000) + const proposalFee: BN = apiWrapper.estimateProposeTerminateLeaderRoleFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeTerminateLeaderRole( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + rationale, + slash, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function setLeaderRewardProposal( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + payoutAmount: BN, + workingGroup: WorkingGroups +): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing set leader reward proposal ' + uuid().substring(0, 8) + const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) + const workerId: BN = (await apiWrapper.getLeadWorkerId(workingGroup))! + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = apiWrapper.estimateProposeLeaderRewardFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeLeaderReward( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + payoutAmount, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function decreaseLeaderStakeProposal( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + stakeDecrement: BN, + workingGroup: WorkingGroups +): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing decrease leader stake proposal ' + uuid().substring(0, 8) + const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) + const workerId: BN = (await apiWrapper.getLeadWorkerId(workingGroup))! + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = apiWrapper.estimateProposeDecreaseLeaderStakeFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeDecreaseLeaderStake( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + stakeDecrement, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function slashLeaderProposal( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + slashAmount: BN, + workingGroup: WorkingGroups +): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing slash leader stake proposal ' + uuid().substring(0, 8) + const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) + const workerId: BN = (await apiWrapper.getLeadWorkerId(workingGroup))! + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = apiWrapper.estimateProposeSlashLeaderStakeFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeSlashLeaderStake( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + slashAmount, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function workingGroupMintCapacityProposal( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + mintCapacity: BN, + workingGroup: WorkingGroups +): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing working group mint capacity proposal ' + uuid().substring(0, 8) + const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = apiWrapper.estimateProposeWorkingGroupMintCapacityFee() + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeWorkingGroupMintCapacity( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + mintCapacity, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + return proposalNumber +} + +export async function voteForProposal( + apiWrapper: ApiWrapper, + m2KeyPairs: KeyringPair[], + sudo: KeyringPair, + proposalNumber: BN +): Promise { + const proposalVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, proposalVoteFee) + + // Approving the proposal + const proposalExecutionPromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await proposalExecutionPromise +} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts new file mode 100644 index 0000000000..075759f62b --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts @@ -0,0 +1,46 @@ +import { Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import { assert } from 'chai' +import tap from 'tap' + +export function setLeadProposalTest( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + sudoUri: string +) { + let sudo: KeyringPair + + tap.test('Lead proposal test', async () => { + // Setup + sudo = keyring.addFromUri(sudoUri) + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = apiWrapper.estimateProposeLeadFee(description, description, proposalStake, sudo.address) + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeLead(m1KeyPairs[0], proposalTitle, description, proposalStake, m1KeyPairs[1]) + const proposalNumber = await proposalPromise + + // Approving the proposal + const proposalExecutionPromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await proposalExecutionPromise + const newLead: string = await apiWrapper.getCurrentLeadAddress() + assert( + newLead === m1KeyPairs[1].address, + `New lead has unexpected value ${newLead}, expected ${m1KeyPairs[1].address}` + ) + }) +} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts new file mode 100644 index 0000000000..72780b457f --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts @@ -0,0 +1,64 @@ +import { Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import { assert } from 'chai' +import tap from 'tap' + +export function spendingProposalTest( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + sudoUri: string, + spendingBalance: BN, + mintCapacity: BN +) { + let sudo: KeyringPair + + tap.test('Spending proposal test', async () => { + // Setup + sudo = keyring.addFromUri(sudoUri) + const description = 'spending proposal which is used for API network testing with some mock data' + const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + + // Topping the balances + const proposalStake: BN = new BN(25000) + const runtimeProposalFee: BN = apiWrapper.estimateProposeSpendingFee( + description, + description, + proposalStake, + spendingBalance, + sudo.address + ) + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) + await apiWrapper.sudoSetCouncilMintCapacity(sudo, mintCapacity) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeSpending( + m1KeyPairs[0], + 'testing spending' + uuid().substring(0, 8), + 'spending to test proposal functionality' + uuid().substring(0, 8), + proposalStake, + spendingBalance, + sudo.address + ) + const proposalNumber = await proposalPromise + + // Approving spending proposal + const balanceBeforeMinting: BN = await apiWrapper.getBalance(sudo.address) + const spendingPromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await spendingPromise + const balanceAfterMinting: BN = await apiWrapper.getBalance(sudo.address) + assert( + balanceAfterMinting.sub(balanceBeforeMinting).eq(spendingBalance), + `member ${ + m1KeyPairs[0].address + } has unexpected balance ${balanceAfterMinting}, expected ${balanceBeforeMinting.add(spendingBalance)}` + ) + }) +} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts new file mode 100644 index 0000000000..2a76107088 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts @@ -0,0 +1,46 @@ +import { Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import tap from 'tap' + +export function textProposalTest( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + sudoUri: string +) { + let sudo: KeyringPair + + tap.test('Text proposal test', async () => { + // Setup + sudo = keyring.addFromUri(sudoUri) + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing text proposal ' + uuid().substring(0, 8) + const proposalText: string = 'Text of the testing proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) + + // Proposal stake calculation + const proposalStake: BN = new BN(25000) + const runtimeProposalFee: BN = apiWrapper.estimateProposeTextFee( + proposalStake, + description, + description, + proposalText + ) + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeText(m1KeyPairs[0], proposalStake, proposalTitle, description, proposalText) + const proposalNumber = await proposalPromise + + // Approving text proposal + const textProposalPromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await textProposalPromise + }) +} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts b/tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts new file mode 100644 index 0000000000..64cab936c5 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts @@ -0,0 +1,52 @@ +import { Keyring } from '@polkadot/api' +import { Bytes } from '@polkadot/types' +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import tap from 'tap' + +export function updateRuntimeTest( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + sudoUri: string +) { + let sudo: KeyringPair + + tap.test('\n\tUpgrading the runtime test', async () => { + // Setup + sudo = keyring.addFromUri(sudoUri) + const runtime: Bytes = await apiWrapper.getRuntime() + const description = 'runtime upgrade proposal which is used for API network testing' + const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + + // Topping the balances + const proposalStake: BN = new BN(1000000) + const runtimeProposalFee: BN = apiWrapper.estimateProposeRuntimeUpgradeFee( + proposalStake, + description, + description, + runtime + ) + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) + + // Proposal creation + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeRuntime( + m1KeyPairs[0], + proposalStake, + 'testing runtime' + uuid().substring(0, 8), + 'runtime to test proposal functionality' + uuid().substring(0, 8), + runtime + ) + const proposalNumber = await proposalPromise + + // Approving runtime update proposal + const runtimePromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await runtimePromise + }) +} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts new file mode 100644 index 0000000000..f0465e7e19 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts @@ -0,0 +1,55 @@ +import { Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import { assert } from 'chai' +import tap from 'tap' + +export function validatorCountProposal( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + sudoUri: string, + validatorCountIncrement: BN +) { + let sudo: KeyringPair + + tap.test('Validator count proposal test', async () => { + // Setup + sudo = keyring.addFromUri(sudoUri) + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) + + // Proposal stake calculation + const proposalStake: BN = new BN(100000) + const proposalFee: BN = apiWrapper.estimateProposeValidatorCountFee(description, description, proposalStake) + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) + const validatorCount: BN = await apiWrapper.getValidatorCount() + + // Proposal creation + const proposedValidatorCount: BN = validatorCount.add(validatorCountIncrement) + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeValidatorCount( + m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + proposedValidatorCount + ) + const proposalNumber = await proposalPromise + + // Approving the proposal + const proposalExecutionPromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await proposalExecutionPromise + const newValidatorCount: BN = await apiWrapper.getValidatorCount() + assert( + proposedValidatorCount.eq(newValidatorCount), + `Validator count has unexpeccted value ${newValidatorCount}, expected ${proposedValidatorCount}` + ) + }) +} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts new file mode 100644 index 0000000000..6b7f086144 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts @@ -0,0 +1,59 @@ +import { Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { ApiWrapper } from '../../../utils/apiWrapper' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import { assert } from 'chai' +import tap from 'tap' + +export function workingGroupMintCapacityProposalTest( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + keyring: Keyring, + sudoUri: string, + mintingCapacityIncrement: BN +) { + let sudo: KeyringPair + + tap.test('Mint capacity proposal test', async () => { + // Setup + sudo = keyring.addFromUri(sudoUri) + const description = 'Mint capacity proposal which is used for API network testing' + const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() + const initialMintingCapacity: BN = await apiWrapper.getContentWorkingGroupMintCapacity() + + // Topping the balances + const proposalStake: BN = new BN(50000) + const runtimeProposalFee: BN = apiWrapper.estimateProposeContentWorkingGroupMintCapacityFee( + description, + description, + proposalStake, + initialMintingCapacity.add(mintingCapacityIncrement) + ) + await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) + + // Proposal creation + const proposedMintingCapacity: BN = initialMintingCapacity.add(mintingCapacityIncrement) + const proposalPromise = apiWrapper.expectProposalCreated() + await apiWrapper.proposeContentWorkingGroupMintCapacity( + m1KeyPairs[0], + 'testing mint capacity' + uuid().substring(0, 8), + 'mint capacity to test proposal functionality' + uuid().substring(0, 8), + proposalStake, + proposedMintingCapacity + ) + const proposalNumber = await proposalPromise + + // Approving mint capacity proposal + const mintCapacityPromise = apiWrapper.expectProposalFinalized() + await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) + await mintCapacityPromise + const newMintingCapacity: BN = await apiWrapper.getContentWorkingGroupMintCapacity() + assert( + proposedMintingCapacity.eq(newMintingCapacity), + `Content working group has unexpected minting capacity ${newMintingCapacity}, expected ${proposedMintingCapacity}` + ) + }) +} diff --git a/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts new file mode 100644 index 0000000000..d1b08c632f --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts @@ -0,0 +1,213 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { + createWorkingGroupLeaderOpening, + voteForProposal, + beginWorkingGroupLeaderApplicationReview, + fillLeaderOpeningProposal, + terminateLeaderRoleProposal, + setLeaderRewardProposal, + decreaseLeaderStakeProposal, + slashLeaderProposal, +} from './impl/proposalsModule' +import { + applyForOpening, + expectLeadOpeningAdded, + expectLeaderSet, + expectBeganApplicationReview, + expectLeaderRoleTerminated, + expectLeaderRewardAmountUpdated, + expectLeaderStakeDecreased, + expectLeaderSlashed, +} from '../workingGroup/impl/workingGroupModule' + +tap.mocha.describe('Set lead proposal scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + const leadKeyPair: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) + const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const rewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) + const alteredPayoutAmount: BN = new BN(process.env.ALTERED_PAYOUT_AMOUNT!) + const stakeDecrement: BN = new BN(process.env.STAKE_DECREMENT!) + const slashAmount: BN = new BN(process.env.SLASH_AMOUNT!) + const durationInBlocks = 70 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + + let createOpeningProposalId: BN + let openingId: BN + tap.test( + 'Propose create leader opening', + async () => + (createOpeningProposalId = await createWorkingGroupLeaderOpening( + apiWrapper, + m1KeyPairs, + sudo, + applicationStake, + roleStake, + 'Storage' + )) + ) + tap.test('Approve add opening proposal', async () => { + voteForProposal(apiWrapper, m2KeyPairs, sudo, createOpeningProposalId) + openingId = await expectLeadOpeningAdded(apiWrapper) + }) + + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + new BN(openingId), + WorkingGroups.StorageWorkingGroup, + false + ) + ) + let beginReviewProposalId: BN + tap.test( + 'Propose begin leader application review', + async () => + (beginReviewProposalId = await beginWorkingGroupLeaderApplicationReview( + apiWrapper, + m1KeyPairs, + sudo, + new BN(openingId), + 'Storage' + )) + ) + tap.test('Approve begin review proposal', async () => { + voteForProposal(apiWrapper, m2KeyPairs, sudo, beginReviewProposalId) + expectBeganApplicationReview(apiWrapper) + }) + + let fillLeaderOpeningProposalId: BN + tap.test( + 'Propose fill leader opening', + async () => + (fillLeaderOpeningProposalId = await fillLeaderOpeningProposal( + apiWrapper, + m1KeyPairs, + leadKeyPair[0].address, + sudo, + firstRewardInterval, + rewardInterval, + payoutAmount, + new BN(openingId), + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test('Approve fill leader opening', async () => { + voteForProposal(apiWrapper, m2KeyPairs, sudo, fillLeaderOpeningProposalId) + await expectLeaderSet(apiWrapper, leadKeyPair[0].address, WorkingGroups.StorageWorkingGroup) + }) + + let rewardProposalId: BN + tap.test( + 'Propose leader reward', + async () => + (rewardProposalId = await setLeaderRewardProposal( + apiWrapper, + m1KeyPairs, + sudo, + alteredPayoutAmount, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test('Approve new leader reward', async () => { + voteForProposal(apiWrapper, m2KeyPairs, sudo, rewardProposalId) + await expectLeaderRewardAmountUpdated(apiWrapper, alteredPayoutAmount, WorkingGroups.StorageWorkingGroup) + }) + + let decreaseStakeProposalId: BN + let newStake: BN + tap.test( + 'Propose decrease stake', + async () => + (decreaseStakeProposalId = await decreaseLeaderStakeProposal( + apiWrapper, + m1KeyPairs, + sudo, + stakeDecrement, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test('Approve decreased leader stake', async () => { + newStake = applicationStake.sub(stakeDecrement) + voteForProposal(apiWrapper, m2KeyPairs, sudo, decreaseStakeProposalId) + await expectLeaderStakeDecreased(apiWrapper, newStake, WorkingGroups.StorageWorkingGroup) + }) + + let slashProposalId: BN + tap.test( + 'Propose leader slash', + async () => + (slashProposalId = await slashLeaderProposal( + apiWrapper, + m1KeyPairs, + sudo, + slashAmount, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test('Approve leader slash', async () => { + newStake = newStake.sub(slashAmount) + voteForProposal(apiWrapper, m2KeyPairs, sudo, slashProposalId) + await expectLeaderSlashed(apiWrapper, newStake, WorkingGroups.StorageWorkingGroup) + }) + + let terminateLeaderRoleProposalId: BN + tap.test( + 'Propose terminate leader role', + async () => + (terminateLeaderRoleProposalId = await terminateLeaderRoleProposal( + apiWrapper, + m1KeyPairs, + leadKeyPair[0].address, + sudo, + false, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test('Approve leader role termination', async () => { + voteForProposal(apiWrapper, m2KeyPairs, sudo, terminateLeaderRoleProposalId) + await expectLeaderRoleTerminated(apiWrapper, WorkingGroups.StorageWorkingGroup) + }) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts new file mode 100644 index 0000000000..e7a93d468b --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts @@ -0,0 +1,40 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { setLeadProposalTest } from './impl/setLeadProposal' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper } from '../../utils/apiWrapper' + +tap.mocha.describe('Set lead proposal scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const durationInBlocks = 29 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + setLeadProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts new file mode 100644 index 0000000000..e5dc4eef81 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts @@ -0,0 +1,42 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { spendingProposalTest } from './impl/spendingProposal' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper } from '../../utils/apiWrapper' + +tap.mocha.describe('Spending proposal scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const spendingBalance: BN = new BN(+process.env.SPENDING_BALANCE!) + const mintCapacity: BN = new BN(+process.env.COUNCIL_MINTING_CAPACITY!) + const durationInBlocks = 29 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + spendingProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri, spendingBalance, mintCapacity) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts new file mode 100644 index 0000000000..be7a44c066 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts @@ -0,0 +1,40 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { textProposalTest } from './impl/textProposal' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper } from '../../utils/apiWrapper' + +tap.mocha.describe('Text proposal scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const durationInBlocks = 28 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + textProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts b/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts new file mode 100644 index 0000000000..00f8a094f7 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts @@ -0,0 +1,41 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { updateRuntimeTest } from './impl/updateRuntime' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper } from '../../utils/apiWrapper' + +tap.mocha.describe('Update runtime scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const durationInBlocks = 54 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + updateRuntimeTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) + membershipTest(apiWrapper, new Array(), keyring, N, paidTerms, sudoUri) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts new file mode 100644 index 0000000000..b306b08a51 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts @@ -0,0 +1,41 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { validatorCountProposal } from './impl/validatorCountProposal' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper } from '../../utils/apiWrapper' + +tap.mocha.describe('Validator count proposal scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const validatorCountIncrement: BN = new BN(+process.env.VALIDATOR_COUNT_INCREMENT!) + const durationInBlocks = 29 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + validatorCountProposal(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri, validatorCountIncrement) + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts new file mode 100644 index 0000000000..61da31ccf4 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts @@ -0,0 +1,63 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { membershipTest } from '../impl/membershipCreation' +import { councilTest } from '../impl/electingCouncil' +import { initConfig } from '../../utils/config' +import { Keyring, WsProvider } from '@polkadot/api' +import BN from 'bn.js' +import { setTestTimeout } from '../../utils/setTestTimeout' +import tap from 'tap' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { voteForProposal, workingGroupMintCapacityProposal } from './impl/proposalsModule' +import { expectMintCapacityChanged } from '../workingGroup/impl/workingGroupModule' + +tap.mocha.describe('Set storage working group mint capacity scenario', async () => { + initConfig() + registerJoystreamTypes() + + const m1KeyPairs: KeyringPair[] = [] + const m2KeyPairs: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) + const mintCapacityIncrement: BN = new BN(process.env.MINT_CAPACITY_INCREMENT!) + const durationInBlocks = 30 + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + + let mintCapacityProposalId: BN + const newMintCapacity: BN = (await apiWrapper.getWorkingGroupMintCapacity(WorkingGroups.StorageWorkingGroup)).add( + mintCapacityIncrement + ) + tap.test( + 'Propose mint capacity', + async () => + (mintCapacityProposalId = await workingGroupMintCapacityProposal( + apiWrapper, + m1KeyPairs, + sudo, + newMintCapacity, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test('Approve mint capacity', async () => { + voteForProposal(apiWrapper, m2KeyPairs, sudo, mintCapacityProposalId) + await expectMintCapacityChanged(apiWrapper, newMintCapacity) + }) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts new file mode 100644 index 0000000000..7fc6e502fc --- /dev/null +++ b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts @@ -0,0 +1,130 @@ +import { initConfig } from '../../utils/config' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { WsProvider, Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { setTestTimeout } from '../../utils/setTestTimeout' +import { membershipTest } from '../impl/membershipCreation' +import { + addWorkerOpening, + applyForOpening, + addLeaderOpening, + beginLeaderApplicationReview, + fillLeaderOpening, + leaveRole, +} from './impl/workingGroupModule' +import BN from 'bn.js' +import tap from 'tap' + +tap.mocha.describe('Worker application happy case scenario', async () => { + initConfig() + registerJoystreamTypes() + + const nKeyPairs: KeyringPair[] = [] + const leadKeyPair: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.WORKING_GROUP_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) + const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const rewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) + const unstakingPeriod: BN = new BN(process.env.STORAGE_WORKING_GROUP_UNSTAKING_PERIOD!) + const durationInBlocks = 48 + const openingActivationDelay: BN = new BN(0) + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + let leadOpenignId: BN + tap.test( + 'Add lead opening', + async () => + (leadOpenignId = await addLeaderOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + leadOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin lead application review', async () => + beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill lead opening', async () => + fillLeaderOpening( + apiWrapper, + leadKeyPair, + sudo, + leadOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + let workerOpenignId: BN + tap.test( + 'Add worker opening with 0 stake, expect failure', + async () => + (workerOpenignId = await addWorkerOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + new BN(0), + new BN(0), + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup, + true + )) + ) + tap.test( + 'Add worker opening with 0 unstaking period, expect failure', + async () => + (workerOpenignId = await addWorkerOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + new BN(0), + WorkingGroups.StorageWorkingGroup, + true + )) + ) + + tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts b/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts new file mode 100644 index 0000000000..ae38c63cbd --- /dev/null +++ b/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts @@ -0,0 +1,599 @@ +import BN from 'bn.js' +import { assert } from 'chai' +import { ApiWrapper, WorkingGroups } from '../../../utils/apiWrapper' +import { KeyringPair } from '@polkadot/keyring/types' +import { Balance } from '@polkadot/types/interfaces' +import { Keyring } from '@polkadot/api' +import { v4 as uuid } from 'uuid' +import { RewardRelationship } from '@nicaea/types/recurring-rewards' +import { Worker, ApplicationIdToWorkerIdMap, Application } from '@nicaea/types/working-group' +import { Utils } from '../../../utils/utils' +import { Opening as HiringOpening } from '@nicaea/types/hiring' +import { WorkingGroupOpening } from '../../../dto/workingGroupOpening' + +export async function addWorkerOpening( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + activationDelay: BN, + unstakingPeriod: BN, + module: WorkingGroups, + expectFailure: boolean +): Promise { + // Worker opening construction + const activateAtBlock: BN | undefined = activationDelay.eqn(0) + ? undefined + : (await apiWrapper.getBestBlock()).add(activationDelay) + const opening = new WorkingGroupOpening() + .setActivateAtBlock(activateAtBlock) + .setMaxActiveApplicants(new BN(membersKeyPairs.length)) + .setMaxReviewPeriodLength(new BN(32)) + .setApplicationStakingPolicyAmount(new BN(applicationStake)) + .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) + .setApplicationExpiredUnstakingPeriodLength(new BN(1)) + .setRoleStakingPolicyAmount(new BN(roleStake)) + .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) + .setRoleExpiredUnstakingPeriodLength(new BN(1)) + .setSlashableMaxCount(new BN(1)) + .setSlashableMaxPercentPtsPerTime(new BN(100)) + .setSuccessfulApplicantApplicationStakeUnstakingPeriod(unstakingPeriod) + .setFailedApplicantApplicationStakeUnstakingPeriod(unstakingPeriod) + .setFailedApplicantRoleStakeUnstakingPeriod(unstakingPeriod) + .setTerminateApplicationStakeUnstakingPeriod(unstakingPeriod) + .setTerminateRoleStakeUnstakingPeriod(unstakingPeriod) + .setExitRoleApplicationStakeUnstakingPeriod(unstakingPeriod) + .setExitRoleStakeUnstakingPeriod(unstakingPeriod) + .setText(uuid().substring(0, 8)) + .setOpeningType('Worker') + + // Fee estimation and transfer + const addOpeningFee: BN = apiWrapper.estimateAddOpeningFee(opening, module) + await apiWrapper.transferBalance(sudo, lead.address, addOpeningFee) + + // Worker opening creation + const addOpeningPromise: Promise = apiWrapper.expectOpeningAdded() + await apiWrapper.addOpening(lead, opening, module, expectFailure) + if (!expectFailure) { + const openingId: BN = await addOpeningPromise + return openingId + } + return new BN(-1) +} + +export async function addLeaderOpening( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + activationDelay: BN, + module: WorkingGroups +): Promise { + // Leader opening creation + const activateAtBlock: BN | undefined = activationDelay.eqn(0) + ? undefined + : (await apiWrapper.getBestBlock()).add(activationDelay) + const opening = new WorkingGroupOpening() + .setActivateAtBlock(activateAtBlock) + .setMaxActiveApplicants(new BN(membersKeyPairs.length)) + .setMaxReviewPeriodLength(new BN(32)) + .setApplicationStakingPolicyAmount(new BN(applicationStake)) + .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) + .setApplicationExpiredUnstakingPeriodLength(new BN(1)) + .setRoleStakingPolicyAmount(new BN(roleStake)) + .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) + .setRoleExpiredUnstakingPeriodLength(new BN(1)) + .setSlashableMaxCount(new BN(1)) + .setSlashableMaxPercentPtsPerTime(new BN(100)) + .setSuccessfulApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantRoleStakeUnstakingPeriod(new BN(1)) + .setTerminateApplicationStakeUnstakingPeriod(new BN(1)) + .setTerminateRoleStakeUnstakingPeriod(new BN(1)) + .setExitRoleApplicationStakeUnstakingPeriod(new BN(1)) + .setExitRoleStakeUnstakingPeriod(new BN(1)) + .setText(uuid().substring(0, 8)) + .setOpeningType('leader') + + const addOpeningPromise: Promise = apiWrapper.expectOpeningAdded() + await apiWrapper.sudoAddOpening(sudo, opening, module) + const openingId: BN = await addOpeningPromise + + return openingId +} + +export async function acceptApplications( + apiWrapper: ApiWrapper, + lead: KeyringPair, + sudo: KeyringPair, + openingId: BN, + module: WorkingGroups +) { + // Fee estimation and transfer + const acceptApplicationsFee = apiWrapper.estimateAcceptApplicationsFee(module) + await apiWrapper.transferBalance(sudo, lead.address, acceptApplicationsFee) + + // Begin accepting applications + await apiWrapper.acceptApplications(lead, openingId, module) + + const opening: HiringOpening = await apiWrapper.getHiringOpening(openingId) + assert(opening.is_active, `Opening ${openingId} is not active`) +} + +export async function applyForOpening( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + openingId: BN, + module: WorkingGroups, + expectFailure: boolean +): Promise { + // Fee estimation and transfer + const applyOnOpeningFee: BN = apiWrapper.estimateApplyOnOpeningFee(sudo, module).add(applicationStake).add(roleStake) + await apiWrapper.transferBalanceToAccounts(sudo, membersKeyPairs, applyOnOpeningFee) + + // Applying for created worker opening + await apiWrapper.batchApplyOnOpening( + membersKeyPairs, + openingId, + roleStake, + applicationStake, + uuid().substring(0, 8), + module, + expectFailure + ) +} + +export async function withdrawApplicaiton( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + module: WorkingGroups +) { + // Fee estimation and transfer + const withdrawApplicaitonFee: BN = apiWrapper.estimateWithdrawApplicationFee(module) + await apiWrapper.transferBalanceToAccounts(sudo, membersKeyPairs, withdrawApplicaitonFee) + + // Application withdrawal + await apiWrapper.batchWithdrawApplication(membersKeyPairs, module) + + // Assertions + membersKeyPairs.forEach(async (keyPair) => { + const activeApplications: BN[] = await apiWrapper.getActiveApplicationsIdsByRoleAccount(keyPair.address, module) + assert(activeApplications.length === 0, `Unexpected active application found for ${keyPair.address}`) + }) +} + +export async function beginApplicationReview( + apiWrapper: ApiWrapper, + lead: KeyringPair, + sudo: KeyringPair, + openingId: BN, + module: WorkingGroups +) { + // Fee estimation and transfer + const beginReviewFee: BN = apiWrapper.estimateBeginApplicantReviewFee(module) + await apiWrapper.transferBalance(sudo, lead.address, beginReviewFee) + + // Begin application review + const beginApplicantReviewPromise: Promise = apiWrapper.expectApplicationReviewBegan() + await apiWrapper.beginApplicantReview(lead, openingId, module) + await beginApplicantReviewPromise +} + +export async function beginLeaderApplicationReview( + apiWrapper: ApiWrapper, + sudo: KeyringPair, + openingId: BN, + module: WorkingGroups +) { + // Begin application review + await apiWrapper.sudoBeginApplicantReview(sudo, openingId, module) +} + +export async function fillOpening( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + openingId: BN, + firstPayoutInterval: BN, + payoutInterval: BN, + amountPerPayout: BN, + module: WorkingGroups +) { + // Fee estimation and transfer + const beginReviewFee: BN = apiWrapper.estimateBeginApplicantReviewFee(module) + await apiWrapper.transferBalance(sudo, lead.address, beginReviewFee) + const applicationIds: BN[] = ( + await Promise.all( + membersKeyPairs.map(async (keypair) => apiWrapper.getActiveApplicationsIdsByRoleAccount(keypair.address, module)) + ) + ).flat() + + // Fill worker opening + const now: BN = await apiWrapper.getBestBlock() + const fillOpeningPromise: Promise = apiWrapper.expectOpeningFilled() + await apiWrapper.fillOpening( + lead, + openingId, + applicationIds, + amountPerPayout, + now.add(firstPayoutInterval), + payoutInterval, + module + ) + const applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap = await fillOpeningPromise + + // Assertions + applicationIdToWorkerIdMap.forEach(async (workerId, applicationId) => { + const worker: Worker = await apiWrapper.getWorkerById(workerId, module) + const application: Application = await apiWrapper.getApplicationById(applicationId, module) + assert( + worker.role_account_id.toString() === application.role_account_id.toString(), + `Role account ids does not match, worker account: ${worker.role_account_id}, application account ${application.role_account_id}` + ) + }) + const openingWorkersAccounts: string[] = (await apiWrapper.getWorkers(module)).map((worker) => + worker.role_account_id.toString() + ) + membersKeyPairs.forEach((keyPair) => + assert(openingWorkersAccounts.includes(keyPair.address), `Account ${keyPair.address} is not worker`) + ) +} + +export async function fillLeaderOpening( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + openingId: BN, + firstPayoutInterval: BN, + payoutInterval: BN, + amountPerPayout: BN, + module: WorkingGroups +) { + const applicationIds: BN[] = ( + await Promise.all( + membersKeyPairs.map(async (keypair) => apiWrapper.getActiveApplicationsIdsByRoleAccount(keypair.address, module)) + ) + ).flat() + + // Fill leader opening + const now: BN = await apiWrapper.getBestBlock() + const fillOpeningPromise: Promise = apiWrapper.expectOpeningFilled() + await apiWrapper.sudoFillOpening( + sudo, + openingId, + applicationIds, + amountPerPayout, + now.add(firstPayoutInterval), + payoutInterval, + module + ) + + // Assertions + const applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap = await fillOpeningPromise + applicationIdToWorkerIdMap.forEach(async (workerId, applicationId) => { + const worker: Worker = await apiWrapper.getWorkerById(workerId, module) + const application: Application = await apiWrapper.getApplicationById(applicationId, module) + assert( + worker.role_account_id.toString() === application.role_account_id.toString(), + `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}` + ) + }) + const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! + const openingLeaderAccount: string = (await apiWrapper.getWorkerById(leadWorkerId, module)).role_account_id.toString() + assert( + openingLeaderAccount === membersKeyPairs[0].address, + `Unexpected leader account ${openingLeaderAccount}, expected ${membersKeyPairs[0].address}` + ) +} + +export async function increaseStake( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + module: WorkingGroups +) { + // Fee estimation and transfer + const increaseStakeFee: BN = apiWrapper.estimateIncreaseStakeFee(module) + const stakeIncrement: BN = new BN(1) + await apiWrapper.transferBalance(sudo, membersKeyPairs[0].address, increaseStakeFee.add(stakeIncrement)) + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + + // Increase worker stake + const increasedWorkerStake: BN = (await apiWrapper.getWorkerStakeAmount(workerId, module)).add(stakeIncrement) + await apiWrapper.increaseStake(membersKeyPairs[0], workerId, stakeIncrement, module) + const newWorkerStake: BN = await apiWrapper.getWorkerStakeAmount(workerId, module) + assert( + increasedWorkerStake.eq(newWorkerStake), + `Unexpected worker stake ${newWorkerStake}, expected ${increasedWorkerStake}` + ) +} + +export async function updateRewardAccount( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + keyring: Keyring, + sudo: KeyringPair, + module: WorkingGroups +) { + // Fee estimation and transfer + const updateRewardAccountFee: BN = apiWrapper.estimateUpdateRewardAccountFee(sudo.address, module) + await apiWrapper.transferBalance(sudo, membersKeyPairs[0].address, updateRewardAccountFee) + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + + // Update reward account + const createdAccount: KeyringPair = keyring.addFromUri(uuid().substring(0, 8)) + await apiWrapper.updateRewardAccount(membersKeyPairs[0], workerId, createdAccount.address, module) + const newRewardAccount: string = await apiWrapper.getWorkerRewardAccount(workerId, module) + assert( + newRewardAccount === createdAccount.address, + `Unexpected role account ${newRewardAccount}, expected ${createdAccount.address}` + ) +} + +export async function updateRoleAccount( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + keyring: Keyring, + sudo: KeyringPair, + module: WorkingGroups +) { + // Fee estimation and transfer + const updateRoleAccountFee: BN = apiWrapper.estimateUpdateRoleAccountFee(sudo.address, module) + await apiWrapper.transferBalance(sudo, membersKeyPairs[0].address, updateRoleAccountFee) + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + + // Update role account + const createdAccount: KeyringPair = keyring.addFromUri(uuid().substring(0, 8)) + await apiWrapper.updateRoleAccount(membersKeyPairs[0], workerId, createdAccount.address, module) + const newRoleAccount: string = (await apiWrapper.getWorkerById(workerId, module)).role_account_id.toString() + assert( + newRoleAccount === createdAccount.address, + `Unexpected role account ${newRoleAccount}, expected ${createdAccount.address}` + ) + + membersKeyPairs[0] = createdAccount +} + +export async function terminateApplications( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups +) { + // Fee estimation and transfer + const terminateApplicationFee = apiWrapper.estimateTerminateApplicationFee(module) + await apiWrapper.transferBalance(sudo, lead.address, terminateApplicationFee.muln(membersKeyPairs.length)) + + // Terminate worker applications + await apiWrapper.batchTerminateApplication(lead, membersKeyPairs, module) + membersKeyPairs.forEach(async (keyPair) => { + const activeApplications = await apiWrapper.getActiveApplicationsIdsByRoleAccount(keyPair.address, module) + assert(activeApplications.length === 0, `Account ${keyPair.address} has unexpected active applications`) + }) +} + +export async function decreaseStake( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups, + expectFailure: boolean +) { + // Fee estimation and transfer + const decreaseStakeFee = apiWrapper.estimateDecreaseStakeFee(module) + await apiWrapper.transferBalance(sudo, lead.address, decreaseStakeFee) + const workerStakeDecrement = new BN(1) + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + + // Worker stake decrement + const decreasedWorkerStake: BN = (await apiWrapper.getWorkerStakeAmount(workerId, module)).sub(workerStakeDecrement) + await apiWrapper.decreaseStake(lead, workerId, workerStakeDecrement, module, expectFailure) + const newWorkerStake: BN = await apiWrapper.getWorkerStakeAmount(workerId, module) + + // Assertions + if (!expectFailure) { + assert( + decreasedWorkerStake.eq(newWorkerStake), + `Unexpected worker stake ${newWorkerStake}, expected ${decreasedWorkerStake}` + ) + } +} + +export async function slash( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups, + expectFailure: boolean +) { + // Fee estimation and transfer + const slashStakeFee = apiWrapper.estimateSlashStakeFee(module) + await apiWrapper.transferBalance(sudo, lead.address, slashStakeFee) + const slashAmount = new BN(1) + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + + // Slash worker + const slashedStake: BN = (await apiWrapper.getWorkerStakeAmount(workerId, module)).sub(slashAmount) + await apiWrapper.slashStake(lead, workerId, slashAmount, module, expectFailure) + const newStake: BN = await apiWrapper.getWorkerStakeAmount(workerId, module) + + // Assertions + assert(slashedStake.eq(newStake), `Unexpected worker stake ${newStake}, expected ${slashedStake}`) +} + +export async function terminateRole( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups, + expectFailure: boolean +) { + // Fee estimation and transfer + const terminateRoleFee = apiWrapper.estimateTerminateRoleFee(module) + await apiWrapper.transferBalance(sudo, lead.address, terminateRoleFee) + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + + // Slash worker + await apiWrapper.terminateRole(lead, workerId, uuid().substring(0, 8), module, expectFailure) + + // Assertions + apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + const newWorkerId = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + assert(newWorkerId === undefined, `Worker with account ${membersKeyPairs[0].address} is not terminated`) +} + +export async function leaveRole( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + module: WorkingGroups +) { + // Fee estimation and transfer + const leaveRoleFee = apiWrapper.estimateLeaveRoleFee(module) + await apiWrapper.transferBalanceToAccounts(sudo, membersKeyPairs, leaveRoleFee) + + await apiWrapper.batchLeaveRole(membersKeyPairs, uuid().substring(0, 8), false, module) + + // Assertions + membersKeyPairs.forEach(async (keyPair) => { + apiWrapper.getWorkerIdByRoleAccount(keyPair.address, module) + const newWorkerId = await apiWrapper.getWorkerIdByRoleAccount(keyPair.address, module) + assert(newWorkerId === undefined, `Worker with account ${keyPair.address} is not terminated`) + }) +} + +export async function awaitPayout(apiWrapper: ApiWrapper, membersKeyPairs: KeyringPair[], module: WorkingGroups) { + const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) + const worker: Worker = await apiWrapper.getWorkerById(workerId, module) + const reward: RewardRelationship = await apiWrapper.getRewardRelationship(worker.reward_relationship.unwrap()) + const now: BN = await apiWrapper.getBestBlock() + const nextPaymentBlock: BN = new BN(reward.getField('next_payment_at_block').toString()) + const payoutInterval: BN = new BN(reward.getField('payout_interval').toString()) + const amountPerPayout: BN = new BN(reward.getField('amount_per_payout').toString()) + + assert(now.lt(nextPaymentBlock), `Payout already happened in block ${nextPaymentBlock} now ${now}`) + const balance = await apiWrapper.getBalance(membersKeyPairs[0].address) + + const firstPayoutWaitingPeriod = nextPaymentBlock.sub(now).addn(1) + await Utils.wait(apiWrapper.getBlockDuration().mul(firstPayoutWaitingPeriod).toNumber()) + + const balanceAfterFirstPayout = await apiWrapper.getBalance(membersKeyPairs[0].address) + const expectedBalanceFirst = balance.add(amountPerPayout) + assert( + balanceAfterFirstPayout.eq(expectedBalanceFirst), + `Unexpected balance, expected ${expectedBalanceFirst} got ${balanceAfterFirstPayout}` + ) + + const secondPayoutWaitingPeriod = payoutInterval.addn(1) + await Utils.wait(apiWrapper.getBlockDuration().mul(secondPayoutWaitingPeriod).toNumber()) + + const balanceAfterSecondPayout = await apiWrapper.getBalance(membersKeyPairs[0].address) + const expectedBalanceSecond = expectedBalanceFirst.add(amountPerPayout) + assert( + balanceAfterSecondPayout.eq(expectedBalanceSecond), + `Unexpected balance, expected ${expectedBalanceSecond} got ${balanceAfterSecondPayout}` + ) +} + +export async function setMintCapacity(apiWrapper: ApiWrapper, sudo: KeyringPair, capacity: BN, module: WorkingGroups) { + await apiWrapper.sudoSetWorkingGroupMintCapacity(sudo, capacity, module) +} + +export async function expectLeadOpeningAdded(apiWrapper: ApiWrapper): Promise { + return apiWrapper.expectOpeningAdded() +} + +export async function expectLeaderSet( + apiWrapper: ApiWrapper, + leaderAddress: string, + module: WorkingGroups +): Promise { + const leadWorkerId: BN = await apiWrapper.expectLeaderSet() + const worker: Worker = await apiWrapper.getWorkerById(leadWorkerId, module) + const leaderApplicationId = (await apiWrapper.getApplicationsIdsByRoleAccount(leaderAddress, module))[0] + const application: Application = await apiWrapper.getApplicationById(leaderApplicationId, module) + assert( + worker.role_account_id.eq(application.role_account_id), + `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}` + ) + return leadWorkerId +} + +export async function expectBeganApplicationReview(apiWrapper: ApiWrapper): Promise { + return apiWrapper.expectApplicationReviewBegan() +} + +export async function expectLeaderRoleTerminated(apiWrapper: ApiWrapper, module: WorkingGroups): Promise { + await apiWrapper.expectLeaderTerminated() + const leadWorkerId: BN | undefined = await apiWrapper.getLeadWorkerId(module) + assert(leadWorkerId === undefined, `Unexpected lead worker id: ${leadWorkerId}, expected none`) + return +} + +export async function expectLeaderRewardAmountUpdated( + apiWrapper: ApiWrapper, + expectedReward: BN, + module: WorkingGroups +): Promise { + await apiWrapper.expectWorkerRewardAmountUpdated() + const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! + const receivedReward: BN = (await apiWrapper.getRewardRelationship(leadWorkerId)).getField( + 'amount_per_payout' + ) + assert( + receivedReward.eq(expectedReward), + `Unexpected reward amount for worker with id ${leadWorkerId}: ${receivedReward}, expected ${expectedReward}` + ) + return +} + +export async function expectLeaderStakeDecreased( + apiWrapper: ApiWrapper, + expectedStake: BN, + module: WorkingGroups +): Promise { + await apiWrapper.expectWorkerStakeDecreased() + const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! + const receivedStake: BN = await apiWrapper.getWorkerStakeAmount(leadWorkerId, module) + assert( + receivedStake.eq(expectedStake), + `Unexpected stake amount for worker with id ${leadWorkerId}: ${receivedStake}, expected ${expectedStake}` + ) + return +} + +export async function expectLeaderSlashed( + apiWrapper: ApiWrapper, + expectedStake: BN, + module: WorkingGroups +): Promise { + await apiWrapper.expectWorkerStakeSlashed() + const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! + const receivedStake: BN = await apiWrapper.getWorkerStakeAmount(leadWorkerId, module) + assert( + receivedStake.eq(expectedStake), + `Unexpected stake amount for worker with id after slash ${leadWorkerId}: ${receivedStake}, expected ${expectedStake}` + ) + return +} + +export async function expectMintCapacityChanged(apiWrapper: ApiWrapper, expectedMintCapacity: BN): Promise { + const receivedMintCapacity = await apiWrapper.expectMintCapacityChanged() + assert( + receivedMintCapacity.eq(expectedMintCapacity), + `Unexpected mint capacity: ${receivedMintCapacity}, expected ${expectedMintCapacity}` + ) + return +} diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts new file mode 100644 index 0000000000..b337ae330b --- /dev/null +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts @@ -0,0 +1,207 @@ +import { initConfig } from '../../utils/config' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { WsProvider, Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { setTestTimeout } from '../../utils/setTestTimeout' +import { membershipTest } from '../impl/membershipCreation' +import { + addWorkerOpening, + applyForOpening, + beginApplicationReview, + fillOpening, + decreaseStake, + slash, + terminateRole, + addLeaderOpening, + beginLeaderApplicationReview, + fillLeaderOpening, + leaveRole, +} from './impl/workingGroupModule' +import BN from 'bn.js' +import tap = require('tap') + +tap.mocha.describe('Manage worker as worker scenario', async () => { + initConfig() + registerJoystreamTypes() + + const nKeyPairs: KeyringPair[] = [] + const leadKeyPair: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.WORKING_GROUP_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) + const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const rewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) + const unstakingPeriod: BN = new BN(process.env.STORAGE_WORKING_GROUP_UNSTAKING_PERIOD!) + const durationInBlocks = 60 + const openingActivationDelay: BN = new BN(0) + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + let leadOpenignId: BN + tap.test( + 'Add lead opening', + async () => + (leadOpenignId = await addLeaderOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + leadOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin lead application review', async () => + beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill lead opening', async () => + fillLeaderOpening( + apiWrapper, + leadKeyPair, + sudo, + leadOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + let openignId: BN + tap.test( + 'Add worker opening', + async () => + (openignId = await addWorkerOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup, + false + )) + ) + tap.test( + 'Apply for worker opening', + async () => + await applyForOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin application review', async () => + beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, openignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill worker opening', async () => + fillOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + openignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + tap.test('Decrease worker stake, expect failure', async () => + decreaseStake(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, true) + ) + + tap.test( + 'Add lead opening', + async () => + (leadOpenignId = await addLeaderOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + leadOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin lead application review', async () => + beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill lead opening', async () => + fillLeaderOpening( + apiWrapper, + leadKeyPair, + sudo, + leadOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + tap.test('Decrease worker stake', async () => + decreaseStake(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, false) + ) + tap.test('Slash worker', async () => + slash(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, false) + ) + tap.test('Terminate worker role', async () => + terminateRole(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, false) + ) + + tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts new file mode 100644 index 0000000000..6bb0609b60 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts @@ -0,0 +1,159 @@ +import { initConfig } from '../../utils/config' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { WsProvider, Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { setTestTimeout } from '../../utils/setTestTimeout' +import { membershipTest } from '../impl/membershipCreation' +import { + addWorkerOpening, + applyForOpening, + beginApplicationReview, + fillOpening, + increaseStake, + updateRewardAccount, + updateRoleAccount, + addLeaderOpening, + beginLeaderApplicationReview, + fillLeaderOpening, + leaveRole, +} from './impl/workingGroupModule' +import BN from 'bn.js' +import tap = require('tap') + +tap.mocha.describe('Manage worker as worker scenario', async () => { + initConfig() + registerJoystreamTypes() + + const nKeyPairs: KeyringPair[] = [] + const leadKeyPair: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.WORKING_GROUP_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) + const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const rewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) + const unstakingPeriod: BN = new BN(process.env.STORAGE_WORKING_GROUP_UNSTAKING_PERIOD!) + const durationInBlocks = 38 + const openingActivationDelay: BN = new BN(0) + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + let leadOpenignId: BN + tap.test( + 'Add lead opening', + async () => + (leadOpenignId = await addLeaderOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + leadOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin lead application review', async () => + beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill lead opening', async () => + fillLeaderOpening( + apiWrapper, + leadKeyPair, + sudo, + leadOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + let openignId: BN + tap.test( + 'Add worker opening', + async () => + (openignId = await addWorkerOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup, + false + )) + ) + tap.test( + 'Apply for worker opening', + async () => + await applyForOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin application review', async () => + beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, openignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill worker opening', async () => + fillOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + openignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + tap.test('Increase worker stake', async () => + increaseStake(apiWrapper, nKeyPairs, sudo, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Update reward account', async () => + updateRewardAccount(apiWrapper, nKeyPairs, keyring, sudo, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Update role account', async () => + updateRoleAccount(apiWrapper, nKeyPairs, keyring, sudo, WorkingGroups.StorageWorkingGroup) + ) + + tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts new file mode 100644 index 0000000000..26d5322458 --- /dev/null +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts @@ -0,0 +1,160 @@ +import { initConfig } from '../../utils/config' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { WsProvider, Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { setTestTimeout } from '../../utils/setTestTimeout' +import { membershipTest } from '../impl/membershipCreation' +import { + addWorkerOpening, + applyForOpening, + beginApplicationReview, + fillOpening, + withdrawApplicaiton, + addLeaderOpening, + beginLeaderApplicationReview, + fillLeaderOpening, + leaveRole, +} from './impl/workingGroupModule' +import BN from 'bn.js' +import tap from 'tap' + +tap.mocha.describe('Worker application happy case scenario', async () => { + initConfig() + registerJoystreamTypes() + + const nKeyPairs: KeyringPair[] = [] + const leadKeyPair: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.WORKING_GROUP_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) + const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const rewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) + const unstakingPeriod: BN = new BN(process.env.STORAGE_WORKING_GROUP_UNSTAKING_PERIOD!) + const durationInBlocks = 48 + const openingActivationDelay: BN = new BN(0) + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + let leadOpenignId: BN + tap.test( + 'Add lead opening', + async () => + (leadOpenignId = await addLeaderOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + leadOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin lead application review', async () => + beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill lead opening', async () => + fillLeaderOpening( + apiWrapper, + leadKeyPair, + sudo, + leadOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + let workerOpenignId: BN + tap.test( + 'Add worker opening', + async () => + (workerOpenignId = await addWorkerOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup, + false + )) + ) + tap.test('Apply for worker opening', async () => + applyForOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + workerOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Withdraw worker application', async () => + withdrawApplicaiton(apiWrapper, nKeyPairs, sudo, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Apply for worker opening', async () => + applyForOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + workerOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin application review', async () => + beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, workerOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill worker opening', async () => + fillOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + workerOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts new file mode 100644 index 0000000000..ce021bf4bf --- /dev/null +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts @@ -0,0 +1,160 @@ +import { initConfig } from '../../utils/config' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { WsProvider, Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { setTestTimeout } from '../../utils/setTestTimeout' +import { membershipTest, createKeyPairs } from '../impl/membershipCreation' +import { + addWorkerOpening, + applyForOpening, + acceptApplications, + terminateApplications, + addLeaderOpening, + beginLeaderApplicationReview, + fillLeaderOpening, + leaveRole, +} from './impl/workingGroupModule' +import BN from 'bn.js' +import tap from 'tap' + +tap.mocha.describe('Worker application happy case scenario', async () => { + initConfig() + registerJoystreamTypes() + + const nKeyPairs: KeyringPair[] = [] + const leadKeyPair: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.WORKING_GROUP_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) + const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const rewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) + const unstakingPeriod: BN = new BN(process.env.STORAGE_WORKING_GROUP_UNSTAKING_PERIOD!) + const durationInBlocks = 38 + const openingActivationDelay: BN = new BN(100) + const leadOpeningActivationDelay: BN = new BN(0) + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const nonMemberKeyPairs = createKeyPairs(keyring, N) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + let leadOpenignId: BN + tap.test( + 'Add lead opening', + async () => + (leadOpenignId = await addLeaderOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + leadOpeningActivationDelay, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + leadOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin lead application review', async () => + beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill lead opening', async () => + fillLeaderOpening( + apiWrapper, + leadKeyPair, + sudo, + leadOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + let openignId: BN + tap.test( + 'Add worker opening', + async () => + (openignId = await addWorkerOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup, + false + )) + ) + tap.test('Apply for worker opening, expect failure', async () => + applyForOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openignId, + WorkingGroups.StorageWorkingGroup, + true + ) + ) + tap.test('Begin accepting worker applications', async () => + acceptApplications(apiWrapper, leadKeyPair[0], sudo, openignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Apply for worker opening as non-member, expect failure', async () => + applyForOpening( + apiWrapper, + nonMemberKeyPairs, + sudo, + applicationStake, + roleStake, + openignId, + WorkingGroups.StorageWorkingGroup, + true + ) + ) + tap.test('Apply for worker opening as member', async () => + applyForOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Terminate worker applicaitons', async () => + terminateApplications(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup) + ) + + tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerPayout.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerPayout.ts new file mode 100644 index 0000000000..ebd06f8fdb --- /dev/null +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerPayout.ts @@ -0,0 +1,152 @@ +import { initConfig } from '../../utils/config' +import { registerJoystreamTypes } from '@nicaea/types' +import { closeApi } from '../impl/closeApi' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { WsProvider, Keyring } from '@polkadot/api' +import { KeyringPair } from '@polkadot/keyring/types' +import { setTestTimeout } from '../../utils/setTestTimeout' +import { membershipTest } from '../impl/membershipCreation' +import { + addWorkerOpening, + applyForOpening, + beginApplicationReview, + fillOpening, + addLeaderOpening, + beginLeaderApplicationReview, + fillLeaderOpening, + leaveRole, + awaitPayout, + setMintCapacity, +} from './impl/workingGroupModule' +import BN from 'bn.js' +import tap from 'tap' + +tap.mocha.describe('Worker application happy case scenario', async () => { + initConfig() + registerJoystreamTypes() + + const nKeyPairs: KeyringPair[] = [] + const leadKeyPair: KeyringPair[] = [] + + const keyring = new Keyring({ type: 'sr25519' }) + const N: number = +process.env.WORKING_GROUP_N! + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! + const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) + const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const firstRewardInterval: BN = new BN(process.env.SHORT_FIRST_REWARD_INTERVAL!) + const rewardInterval: BN = new BN(process.env.SHORT_REWARD_INTERVAL!) + const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) + const unstakingPeriod: BN = new BN(process.env.STORAGE_WORKING_GROUP_UNSTAKING_PERIOD!) + const mintCapacity: BN = new BN(process.env.STORAGE_WORKING_GROUP_MINTING_CAPACITY!) + const durationInBlocks = 48 + const openingActivationDelay: BN = new BN(0) + + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + + setTestTimeout(apiWrapper, durationInBlocks) + membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + let leadOpenignId: BN + tap.test( + 'Add lead opening', + async () => + (leadOpenignId = await addLeaderOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup + )) + ) + tap.test( + 'Apply for lead opening', + async () => + await applyForOpening( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + leadOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin lead application review', async () => + beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill lead opening', async () => + fillLeaderOpening( + apiWrapper, + leadKeyPair, + sudo, + leadOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + let workerOpenignId: BN + tap.test( + 'Add worker opening', + async () => + (workerOpenignId = await addWorkerOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup, + false + )) + ) + tap.test('Apply for worker opening', async () => + applyForOpening( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + workerOpenignId, + WorkingGroups.StorageWorkingGroup, + false + ) + ) + tap.test('Begin application review', async () => + beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, workerOpenignId, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Set mint capacity', async () => + setMintCapacity(apiWrapper, sudo, mintCapacity, WorkingGroups.StorageWorkingGroup) + ) + tap.test('Fill worker opening', async () => + fillOpening( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + workerOpenignId, + firstRewardInterval, + rewardInterval, + payoutAmount, + WorkingGroups.StorageWorkingGroup + ) + ) + + tap.test('Await worker payout', async () => awaitPayout(apiWrapper, nKeyPairs, WorkingGroups.StorageWorkingGroup)) + + tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + + closeApi(apiWrapper) +}) diff --git a/tests/network-tests/src/iznik/utils/apiWrapper.ts b/tests/network-tests/src/iznik/utils/apiWrapper.ts new file mode 100644 index 0000000000..e64b421a85 --- /dev/null +++ b/tests/network-tests/src/iznik/utils/apiWrapper.ts @@ -0,0 +1,1547 @@ +import { ApiPromise, WsProvider } from '@polkadot/api' +import { Option, Vec, Bytes, u32 } from '@polkadot/types' +import { Codec } from '@polkadot/types/types' +import { KeyringPair } from '@polkadot/keyring/types' +import { UserInfo, PaidMembershipTerms, MemberId } from '@nicaea/types/members' +import { Mint, MintId } from '@nicaea/types/mint' +import { Lead, LeadId } from '@nicaea/types/content-working-group' +import { Application, WorkerId, Worker, ApplicationIdToWorkerIdMap, Opening } from '@nicaea/types/working-group' +import { RoleParameters } from '@nicaea/types/roles' +import { Seat } from '@nicaea/types/council' +import { Balance, EventRecord, AccountId, BlockNumber, BalanceOf } from '@polkadot/types/interfaces' +import BN from 'bn.js' +import { SubmittableExtrinsic } from '@polkadot/api/types' +import { Sender } from './sender' +import { Utils } from './utils' +import { Stake, StakedState } from '@nicaea/types/stake' +import { RewardRelationship } from '@nicaea/types/recurring-rewards' +import { Opening as HiringOpening, Application as HiringApplication, ApplicationId } from '@nicaea/types/hiring' +import { WorkingGroupOpening } from '../dto/workingGroupOpening' +import { FillOpeningParameters } from '../dto/fillOpeningParameters' + +export enum WorkingGroups { + StorageWorkingGroup = 'storageWorkingGroup', +} + +export class ApiWrapper { + private readonly api: ApiPromise + private readonly sender: Sender + + public static async create(provider: WsProvider): Promise { + const api = await ApiPromise.create({ provider }) + return new ApiWrapper(api) + } + + constructor(api: ApiPromise) { + this.api = api + this.sender = new Sender(api) + } + + public close() { + this.api.disconnect() + } + + public getWorkingGroupString(workingGroup: WorkingGroups): string { + switch (workingGroup) { + case WorkingGroups.StorageWorkingGroup: + return 'Storage' + default: + throw new Error(`Invalid working group string representation: ${workingGroup}`) + } + } + + public async buyMembership( + account: KeyringPair, + paidTermsId: number, + name: string, + expectFailure = false + ): Promise { + return this.sender.signAndSend( + this.api.tx.members.buyMembership(paidTermsId, new UserInfo({ 'handle': name, 'avatar_uri': '', 'about': '' })), + account, + expectFailure + ) + } + + public getMemberIds(address: string): Promise { + return this.api.query.members.memberIdsByControllerAccountId>(address) + } + + public getBalance(address: string): Promise { + return this.api.query.balances.freeBalance(address) + } + + public async transferBalance(from: KeyringPair, to: string, amount: BN): Promise { + return this.sender.signAndSend(this.api.tx.balances.transfer(to, amount), from) + } + + public getPaidMembershipTerms(paidTermsId: number): Promise> { + return this.api.query.members.paidMembershipTermsById>(paidTermsId) + } + + public getMembershipFee(paidTermsId: number): Promise { + return this.getPaidMembershipTerms(paidTermsId).then((terms) => terms.unwrap().fee.toBn()) + } + + public async transferBalanceToAccounts(from: KeyringPair, to: KeyringPair[], amount: BN): Promise { + return Promise.all( + to.map(async (keyPair) => { + await this.transferBalance(from, keyPair.address, amount) + }) + ) + } + + private getBaseTxFee(): BN { + return this.api.createType('BalanceOf', this.api.consts.transactionPayment.transactionBaseFee).toBn() + } + + private estimateTxFee(tx: SubmittableExtrinsic<'promise'>): BN { + const baseFee: BN = this.getBaseTxFee() + const byteFee: BN = this.api.createType('BalanceOf', this.api.consts.transactionPayment.transactionByteFee).toBn() + return Utils.calcTxLength(tx).mul(byteFee).add(baseFee) + } + + public estimateBuyMembershipFee(account: KeyringPair, paidTermsId: number, name: string): BN { + return this.estimateTxFee( + this.api.tx.members.buyMembership(paidTermsId, new UserInfo({ 'handle': name, 'avatar_uri': '', 'about': '' })) + ) + } + + public estimateApplyForCouncilFee(amount: BN): BN { + return this.estimateTxFee(this.api.tx.councilElection.apply(amount)) + } + + public estimateVoteForCouncilFee(nominee: string, salt: string, stake: BN): BN { + const hashedVote: string = Utils.hashVote(nominee, salt) + return this.estimateTxFee(this.api.tx.councilElection.vote(hashedVote, stake)) + } + + public estimateRevealVoteFee(nominee: string, salt: string): BN { + const hashedVote: string = Utils.hashVote(nominee, salt) + return this.estimateTxFee(this.api.tx.councilElection.reveal(hashedVote, nominee, salt)) + } + + public estimateProposeRuntimeUpgradeFee(stake: BN, name: string, description: string, runtime: Bytes | string): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createRuntimeUpgradeProposal(stake, name, description, stake, runtime) + ) + } + + public estimateProposeTextFee(stake: BN, name: string, description: string, text: string): BN { + return this.estimateTxFee(this.api.tx.proposalsCodex.createTextProposal(stake, name, description, stake, text)) + } + + public estimateProposeSpendingFee( + title: string, + description: string, + stake: BN, + balance: BN, + destination: string + ): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSpendingProposal(stake, title, description, stake, balance, destination) + ) + } + + public estimateProposeContentWorkingGroupMintCapacityFee( + title: string, + description: string, + stake: BN, + balance: BN + ): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSetContentWorkingGroupMintCapacityProposal( + stake, + title, + description, + stake, + balance + ) + ) + } + + public estimateProposeValidatorCountFee(title: string, description: string, stake: BN): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSetValidatorCountProposal(stake, title, description, stake, stake) + ) + } + + public estimateProposeLeadFee(title: string, description: string, stake: BN, address: string): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSetLeadProposal(stake, title, description, stake, { stake, address }) + ) + } + + public estimateProposeEvictStorageProviderFee(title: string, description: string, stake: BN, address: string): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createEvictStorageProviderProposal(stake, title, description, stake, address) + ) + } + + public estimateProposeStorageRoleParametersFee( + title: string, + description: string, + stake: BN, + minStake: BN, + minActors: BN, + maxActors: BN, + reward: BN, + rewardPeriod: BN, + bondingPeriod: BN, + unbondingPeriod: BN, + minServicePeriod: BN, + startupGracePeriod: BN, + entryRequestFee: BN + ): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSetStorageRoleParametersProposal(stake, title, description, stake, [ + minStake, + minActors, + maxActors, + reward, + rewardPeriod, + bondingPeriod, + unbondingPeriod, + minServicePeriod, + startupGracePeriod, + entryRequestFee, + ]) + ) + } + + public estimateProposeElectionParametersFee( + title: string, + description: string, + stake: BN, + announcingPeriod: BN, + votingPeriod: BN, + revealingPeriod: BN, + councilSize: BN, + candidacyLimit: BN, + newTermDuration: BN, + minCouncilStake: BN, + minVotingStake: BN + ): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSetElectionParametersProposal(stake, title, description, stake, [ + announcingPeriod, + votingPeriod, + revealingPeriod, + councilSize, + candidacyLimit, + newTermDuration, + minCouncilStake, + minVotingStake, + ]) + ) + } + + public estimateVoteForProposalFee(): BN { + return this.estimateTxFee(this.api.tx.proposalsEngine.vote(0, 0, 'Approve')) + } + + public estimateAddOpeningFee(opening: WorkingGroupOpening, module: WorkingGroups): BN { + return this.estimateTxFee( + this.api.tx[module].addOpening( + opening.getActivateAt(), + opening.getCommitment(), + opening.getText(), + opening.getOpeningType() + ) + ) + } + + public estimateAcceptApplicationsFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].acceptApplications(0)) + } + + public estimateApplyOnOpeningFee(account: KeyringPair, module: WorkingGroups): BN { + return this.estimateTxFee( + this.api.tx[module].applyOnOpening( + 0, + 0, + account.address, + 0, + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test' + ) + ) + } + + public estimateBeginApplicantReviewFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].beginApplicantReview(0)) + } + + public estimateFillOpeningFee(module: WorkingGroups): BN { + return this.estimateTxFee( + this.api.tx[module].fillOpening(0, [0], { + 'amount_per_payout': 0, + 'next_payment_at_block': 0, + 'payout_interval': 0, + }) + ) + } + + public estimateIncreaseStakeFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].increaseStake(0, 0)) + } + + public estimateDecreaseStakeFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].decreaseStake(0, 0)) + } + + public estimateUpdateRoleAccountFee(address: string, module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].updateRoleAccount(0, address)) + } + + public estimateUpdateRewardAccountFee(address: string, module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].updateRewardAccount(0, address)) + } + + public estimateLeaveRoleFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].leaveRole(0, 'Long justification text')) + } + + public estimateWithdrawApplicationFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].withdrawApplication(0)) + } + + public estimateTerminateApplicationFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].terminateApplication(0)) + } + + public estimateSlashStakeFee(module: WorkingGroups): BN { + return this.estimateTxFee(this.api.tx[module].slashStake(0, 0)) + } + + public estimateTerminateRoleFee(module: WorkingGroups): BN { + return this.estimateTxFee( + this.api.tx[module].terminateRole( + 0, + 'Long justification text explaining why the worker role will be terminated', + false + ) + ) + } + + public estimateProposeCreateWorkingGroupLeaderOpeningFee(): BN { + const opening: WorkingGroupOpening = new WorkingGroupOpening() + .setActivateAtBlock(undefined) + .setMaxActiveApplicants(new BN(32)) + .setMaxReviewPeriodLength(new BN(32)) + .setApplicationStakingPolicyAmount(new BN(1)) + .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) + .setApplicationExpiredUnstakingPeriodLength(new BN(1)) + .setRoleStakingPolicyAmount(new BN(1)) + .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) + .setRoleExpiredUnstakingPeriodLength(new BN(1)) + .setSlashableMaxCount(new BN(0)) + .setSlashableMaxPercentPtsPerTime(new BN(0)) + .setSuccessfulApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantRoleStakeUnstakingPeriod(new BN(1)) + .setTerminateApplicationStakeUnstakingPeriod(new BN(1)) + .setTerminateRoleStakeUnstakingPeriod(new BN(1)) + .setExitRoleApplicationStakeUnstakingPeriod(new BN(1)) + .setExitRoleStakeUnstakingPeriod(new BN(1)) + + return this.estimateTxFee( + this.api.tx.proposalsCodex.createAddWorkingGroupLeaderOpeningProposal( + 0, + 'some long title for the purpose of testing', + 'some long description for the purpose of testing', + 0, + { + 'activate_at': opening.getActivateAt(), + 'commitment': opening.getCommitment(), + 'human_readable_text': 'Opening readable text', + 'working_group': 'Storage', + } + ) + ) + } + + public estimateProposeBeginWorkingGroupLeaderApplicationReviewFee(): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createBeginReviewWorkingGroupLeaderApplicationsProposal( + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 0, + 0, + 'Storage' + ) + ) + } + + public estimateProposeFillLeaderOpeningFee(): BN { + const fillOpeningParameters: FillOpeningParameters = new FillOpeningParameters() + .setAmountPerPayout(new BN(1)) + .setNextPaymentAtBlock(new BN(99999)) + .setPayoutInterval(new BN(99999)) + .setOpeningId(new BN(0)) + .setSuccessfulApplicationId(new BN(0)) + .setWorkingGroup('Storage') + + return this.estimateTxFee( + this.api.tx.proposalsCodex.createFillWorkingGroupLeaderOpeningProposal( + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 0, + fillOpeningParameters.getFillOpeningParameters() + ) + ) + } + + public estimateProposeTerminateLeaderRoleFee(): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createTerminateWorkingGroupLeaderRoleProposal( + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 0, + { + 'worker_id': 0, + 'rationale': 'Exceptionaly long and extraordinary descriptive rationale', + 'slash': true, + 'working_group': 'Storage', + } + ) + ) + } + + public estimateProposeLeaderRewardFee(): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSetWorkingGroupLeaderRewardProposal( + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 0, + 0, + 0, + 'Storage' + ) + ) + } + + public estimateProposeDecreaseLeaderStakeFee(): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createDecreaseWorkingGroupLeaderStakeProposal( + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 0, + 0, + 0, + 'Storage' + ) + ) + } + + public estimateProposeSlashLeaderStakeFee(): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSlashWorkingGroupLeaderStakeProposal( + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 0, + 0, + 0, + 'Storage' + ) + ) + } + + public estimateProposeWorkingGroupMintCapacityFee(): BN { + return this.estimateTxFee( + this.api.tx.proposalsCodex.createSetWorkingGroupMintCapacityProposal( + 0, + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 'Some testing text used for estimation purposes which is longer than text expected during the test', + 0, + 0, + 'Storage' + ) + ) + } + + private applyForCouncilElection(account: KeyringPair, amount: BN): Promise { + return this.sender.signAndSend(this.api.tx.councilElection.apply(amount), account, false) + } + + public batchApplyForCouncilElection(accounts: KeyringPair[], amount: BN): Promise { + return Promise.all( + accounts.map(async (keyPair) => { + await this.applyForCouncilElection(keyPair, amount) + }) + ) + } + + public async getCouncilElectionStake(address: string): Promise { + // TODO alter then `applicantStake` type will be introduced + return this.api.query.councilElection.applicantStakes(address).then((stake) => { + const parsed = JSON.parse(stake.toString()) + return new BN(parsed.new) + }) + } + + private voteForCouncilMember(account: KeyringPair, nominee: string, salt: string, stake: BN): Promise { + const hashedVote: string = Utils.hashVote(nominee, salt) + return this.sender.signAndSend(this.api.tx.councilElection.vote(hashedVote, stake), account, false) + } + + public batchVoteForCouncilMember( + accounts: KeyringPair[], + nominees: KeyringPair[], + salt: string[], + stake: BN + ): Promise { + return Promise.all( + accounts.map(async (keyPair, index) => { + await this.voteForCouncilMember(keyPair, nominees[index].address, salt[index], stake) + }) + ) + } + + private revealVote(account: KeyringPair, commitment: string, nominee: string, salt: string): Promise { + return this.sender.signAndSend(this.api.tx.councilElection.reveal(commitment, nominee, salt), account, false) + } + + public batchRevealVote(accounts: KeyringPair[], nominees: KeyringPair[], salt: string[]): Promise { + return Promise.all( + accounts.map(async (keyPair, index) => { + const commitment = Utils.hashVote(nominees[index].address, salt[index]) + await this.revealVote(keyPair, commitment, nominees[index].address, salt[index]) + }) + ) + } + + // TODO consider using configurable genesis instead + public sudoStartAnnouncingPerion(sudo: KeyringPair, endsAtBlock: BN): Promise { + return this.sender.signAndSend( + this.api.tx.sudo.sudo(this.api.tx.councilElection.setStageAnnouncing(endsAtBlock)), + sudo, + false + ) + } + + public sudoStartVotingPerion(sudo: KeyringPair, endsAtBlock: BN): Promise { + return this.sender.signAndSend( + this.api.tx.sudo.sudo(this.api.tx.councilElection.setStageVoting(endsAtBlock)), + sudo, + false + ) + } + + public sudoStartRevealingPerion(sudo: KeyringPair, endsAtBlock: BN): Promise { + return this.sender.signAndSend( + this.api.tx.sudo.sudo(this.api.tx.councilElection.setStageRevealing(endsAtBlock)), + sudo, + false + ) + } + + public sudoSetCouncilMintCapacity(sudo: KeyringPair, capacity: BN): Promise { + return this.sender.signAndSend( + this.api.tx.sudo.sudo(this.api.tx.council.setCouncilMintCapacity(capacity)), + sudo, + false + ) + } + + public sudoSetWorkingGroupMintCapacity(sudo: KeyringPair, capacity: BN, module: WorkingGroups): Promise { + return this.sender.signAndSend(this.api.tx.sudo.sudo(this.api.tx[module].setMintCapacity(capacity)), sudo, false) + } + + public getBestBlock(): Promise { + return this.api.derive.chain.bestNumber() + } + + public getCouncil(): Promise { + return this.api.query.council.activeCouncil>().then((seats) => { + return (seats as unknown) as Seat[] + }) + } + + public getRuntime(): Promise { + return this.api.query.substrate.code() + } + + public async proposeRuntime( + account: KeyringPair, + stake: BN, + name: string, + description: string, + runtime: Bytes | string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createRuntimeUpgradeProposal(memberId, name, description, stake, runtime), + account, + false + ) + } + + public async proposeText( + account: KeyringPair, + stake: BN, + name: string, + description: string, + text: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createTextProposal(memberId, name, description, stake, text), + account, + false + ) + } + + public async proposeSpending( + account: KeyringPair, + title: string, + description: string, + stake: BN, + balance: BN, + destination: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSpendingProposal(memberId, title, description, stake, balance, destination), + account, + false + ) + } + + public async proposeContentWorkingGroupMintCapacity( + account: KeyringPair, + title: string, + description: string, + stake: BN, + balance: BN + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSetContentWorkingGroupMintCapacityProposal( + memberId, + title, + description, + stake, + balance + ), + account, + false + ) + } + + public async proposeValidatorCount( + account: KeyringPair, + title: string, + description: string, + stake: BN, + validatorCount: BN + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSetValidatorCountProposal(memberId, title, description, stake, validatorCount), + account, + false + ) + } + + public async proposeLead( + account: KeyringPair, + title: string, + description: string, + stake: BN, + leadAccount: KeyringPair + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + const leadMemberId: BN = (await this.getMemberIds(leadAccount.address))[0].toBn() + const addressString: string = leadAccount.address + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSetLeadProposal(memberId, title, description, stake, [ + leadMemberId, + addressString, + ]), + account, + false + ) + } + + public async proposeEvictStorageProvider( + account: KeyringPair, + title: string, + description: string, + stake: BN, + storageProvider: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createEvictStorageProviderProposal( + memberId, + title, + description, + stake, + storageProvider + ), + account, + false + ) + } + + public async proposeStorageRoleParameters( + account: KeyringPair, + title: string, + description: string, + stake: BN, + minStake: BN, + minActors: BN, + maxActors: BN, + reward: BN, + rewardPeriod: BN, + bondingPeriod: BN, + unbondingPeriod: BN, + minServicePeriod: BN, + startupGracePeriod: BN, + entryRequestFee: BN + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSetStorageRoleParametersProposal(memberId, title, description, stake, [ + minStake, + minActors, + maxActors, + reward, + rewardPeriod, + bondingPeriod, + unbondingPeriod, + minServicePeriod, + startupGracePeriod, + entryRequestFee, + ]), + account, + false + ) + } + + public async proposeElectionParameters( + account: KeyringPair, + title: string, + description: string, + stake: BN, + announcingPeriod: BN, + votingPeriod: BN, + revealingPeriod: BN, + councilSize: BN, + candidacyLimit: BN, + newTermDuration: BN, + minCouncilStake: BN, + minVotingStake: BN + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSetElectionParametersProposal(memberId, title, description, stake, [ + announcingPeriod, + votingPeriod, + revealingPeriod, + councilSize, + candidacyLimit, + newTermDuration, + minCouncilStake, + minVotingStake, + ]), + account, + false + ) + } + + public async proposeBeginWorkingGroupLeaderApplicationReview( + account: KeyringPair, + title: string, + description: string, + stake: BN, + openingId: BN, + workingGroup: string + ) { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createBeginReviewWorkingGroupLeaderApplicationsProposal( + memberId, + title, + description, + stake, + openingId, + workingGroup + ), + account, + false + ) + } + + public approveProposal(account: KeyringPair, memberId: BN, proposal: BN): Promise { + return this.sender.signAndSend(this.api.tx.proposalsEngine.vote(memberId, proposal, 'Approve'), account, false) + } + + public batchApproveProposal(council: KeyringPair[], proposal: BN): Promise { + return Promise.all( + council.map(async (keyPair) => { + const memberId: BN = (await this.getMemberIds(keyPair.address))[0].toBn() + await this.approveProposal(keyPair, memberId, proposal) + }) + ) + } + + public getBlockDuration(): BN { + return this.api.createType('Moment', this.api.consts.babe.expectedBlockTime).toBn() + } + + public expectProposalCreated(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'ProposalCreated') { + unsubscribe() + resolve(new BN(record.event.data[1].toString())) + } + }) + }) + }) + } + + public expectRuntimeUpgraded(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method.toString() === 'RuntimeUpdated') { + unsubscribe() + resolve() + } + }) + }) + }) + } + + public expectProposalFinalized(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if ( + record.event.method && + record.event.method.toString() === 'ProposalStatusUpdated' && + record.event.data[1].toString().includes('Executed') + ) { + unsubscribe() + resolve() + } + }) + }) + }) + } + + public expectOpeningFilled(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'OpeningFilled') { + unsubscribe() + resolve((record.event.data[1] as unknown) as ApplicationIdToWorkerIdMap) + } + }) + }) + }) + } + + public expectOpeningAdded(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'OpeningAdded') { + unsubscribe() + resolve((record.event.data as unknown) as BN) + } + }) + }) + }) + } + + public expectLeaderSet(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'LeaderSet') { + unsubscribe() + resolve((record.event.data as unknown) as BN) + } + }) + }) + }) + } + + public expectLeaderTerminated(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'TerminatedLeader') { + unsubscribe() + resolve() + } + }) + }) + }) + } + + public expectWorkerRewardAmountUpdated(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'WorkerRewardAmountUpdated') { + unsubscribe() + resolve() + } + }) + }) + }) + } + + public expectWorkerStakeDecreased(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'StakeDecreased') { + unsubscribe() + resolve() + } + }) + }) + }) + } + + public expectWorkerStakeSlashed(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'StakeSlashed') { + unsubscribe() + resolve() + } + }) + }) + }) + } + + public expectApplicationReviewBegan(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'BeganApplicationReview') { + unsubscribe() + resolve((record.event.data as unknown) as BN) + } + }) + }) + }) + } + + public expectMintCapacityChanged(): Promise { + return new Promise(async (resolve) => { + const unsubscribe = await this.api.query.system.events>((events) => { + events.forEach((record) => { + if (record.event.method && record.event.method.toString() === 'MintCapacityChanged') { + unsubscribe() + resolve((record.event.data[1] as unknown) as BN) + } + }) + }) + }) + } + + public getTotalIssuance(): Promise { + return this.api.query.balances.totalIssuance() + } + + public async getRequiredProposalStake(numerator: number, denominator: number): Promise { + const issuance: number = await (await this.getTotalIssuance()).toNumber() + const stake = (issuance * numerator) / denominator + return new BN(stake.toFixed(0)) + } + + public getProposalCount(): Promise { + return this.api.query.proposalsEngine.proposalCount() + } + + public async getContentWorkingGroupMintCapacity(): Promise { + const mintId: MintId = await this.api.query.contentWorkingGroup.mint() + const mintCodec = await this.api.query.minting.mints(mintId) + const mint: Mint = (mintCodec[0] as unknown) as Mint + return mint.getField('capacity') + } + + public async getWorkingGroupMintCapacity(module: WorkingGroups): Promise { + const mintId: MintId = await this.api.query[module].mint() + const mintCodec = await this.api.query.minting.mints(mintId) + const mint: Mint = (mintCodec[0] as unknown) as Mint + return mint.getField('capacity') + } + + public getValidatorCount(): Promise { + return this.api.query.staking.validatorCount() + } + + public async getCurrentLeadAddress(): Promise { + const leadId: Option = await this.api.query.contentWorkingGroup.currentLeadId>() + const leadCodec = await this.api.query.contentWorkingGroup.leadById(leadId.unwrap()) + const lead = (leadCodec[0] as unknown) as Lead + return lead.role_account.toString() + } + + public async createStorageProvider(account: KeyringPair): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0].toBn() + await this.sender.signAndSend(this.api.tx.actors.roleEntryRequest('StorageProvider', memberId), account, false) + await this.sender.signAndSend(this.api.tx.actors.stake('StorageProvider', account.address), account, false) + return + } + + public async isStorageProvider(address: string): Promise { + const storageProviders: Vec = await this.api.query.actors.accountIdsByRole>( + 'StorageProvider' + ) + const accountWorkers: BN = await this.getWorkerIdByRoleAccount(address, WorkingGroups.StorageWorkingGroup) + return accountWorkers !== undefined + } + + public async addOpening( + leader: KeyringPair, + opening: WorkingGroupOpening, + module: WorkingGroups, + expectFailure: boolean + ): Promise { + return this.sender.signAndSend(this.createAddOpeningTransaction(opening, module), leader, expectFailure) + } + + public async sudoAddOpening(sudo: KeyringPair, opening: WorkingGroupOpening, module: WorkingGroups): Promise { + return this.sender.signAndSend( + this.api.tx.sudo.sudo(this.createAddOpeningTransaction(opening, module)), + sudo, + false + ) + } + + public async proposeCreateWorkingGroupLeaderOpening( + account: KeyringPair, + title: string, + description: string, + proposalStake: BN, + opening: WorkingGroupOpening, + workingGroup: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createAddWorkingGroupLeaderOpeningProposal( + memberId, + title, + description, + proposalStake, + opening.getAddOpeningParameters(workingGroup) + ), + account, + false + ) + } + + public async proposeFillLeaderOpening( + account: KeyringPair, + title: string, + description: string, + proposalStake: BN, + fillOpeningParameters: FillOpeningParameters + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createFillWorkingGroupLeaderOpeningProposal( + memberId, + title, + description, + proposalStake, + fillOpeningParameters.getFillOpeningParameters() + ), + account, + false + ) + } + + public async proposeTerminateLeaderRole( + account: KeyringPair, + title: string, + description: string, + proposalStake: BN, + leadWorkerId: BN, + rationale: string, + slash: boolean, + workingGroup: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createTerminateWorkingGroupLeaderRoleProposal( + memberId, + title, + description, + proposalStake, + { + 'worker_id': leadWorkerId, + rationale, + slash, + 'working_group': workingGroup, + } + ), + account, + false + ) + } + + public async proposeLeaderReward( + account: KeyringPair, + title: string, + description: string, + proposalStake: BN, + workerId: BN, + rewardAmount: BN, + workingGroup: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSetWorkingGroupLeaderRewardProposal( + memberId, + title, + description, + proposalStake, + workerId, + rewardAmount, + workingGroup + ), + account, + false + ) + } + + public async proposeDecreaseLeaderStake( + account: KeyringPair, + title: string, + description: string, + proposalStake: BN, + workerId: BN, + rewardAmount: BN, + workingGroup: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createDecreaseWorkingGroupLeaderStakeProposal( + memberId, + title, + description, + proposalStake, + workerId, + rewardAmount, + workingGroup + ), + account, + false + ) + } + + public async proposeSlashLeaderStake( + account: KeyringPair, + title: string, + description: string, + proposalStake: BN, + workerId: BN, + rewardAmount: BN, + workingGroup: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSlashWorkingGroupLeaderStakeProposal( + memberId, + title, + description, + proposalStake, + workerId, + rewardAmount, + workingGroup + ), + account, + false + ) + } + + public async proposeWorkingGroupMintCapacity( + account: KeyringPair, + title: string, + description: string, + proposalStake: BN, + mintCapacity: BN, + workingGroup: string + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx.proposalsCodex.createSetWorkingGroupMintCapacityProposal( + memberId, + title, + description, + proposalStake, + mintCapacity, + workingGroup + ), + account, + false + ) + } + + private createAddOpeningTransaction( + opening: WorkingGroupOpening, + module: WorkingGroups + ): SubmittableExtrinsic<'promise'> { + return this.api.tx[module].addOpening( + opening.getActivateAt(), + opening.getCommitment(), + opening.getText(), + opening.getOpeningType() + ) + } + + public async acceptApplications(leader: KeyringPair, openingId: BN, module: WorkingGroups): Promise { + return this.sender.signAndSend(this.api.tx[module].acceptApplications(openingId), leader, false) + } + + public async beginApplicantReview(leader: KeyringPair, openingId: BN, module: WorkingGroups): Promise { + return this.sender.signAndSend(this.api.tx[module].beginApplicantReview(openingId), leader, false) + } + + public async sudoBeginApplicantReview(sudo: KeyringPair, openingId: BN, module: WorkingGroups): Promise { + return this.sender.signAndSend( + this.api.tx.sudo.sudo(this.api.tx[module].beginApplicantReview(openingId)), + sudo, + false + ) + } + + public async applyOnOpening( + account: KeyringPair, + roleAccountAddress: string, + openingId: BN, + roleStake: BN, + applicantStake: BN, + text: string, + expectFailure: boolean, + module: WorkingGroups + ): Promise { + const memberId: BN = (await this.getMemberIds(account.address))[0] + return this.sender.signAndSend( + this.api.tx[module].applyOnOpening(memberId, openingId, roleAccountAddress, roleStake, applicantStake, text), + account, + expectFailure + ) + } + + public async batchApplyOnOpening( + accounts: KeyringPair[], + openingId: BN, + roleStake: BN, + applicantStake: BN, + text: string, + module: WorkingGroups, + expectFailure: boolean + ): Promise { + return Promise.all( + accounts.map(async (keyPair) => { + await this.applyOnOpening( + keyPair, + keyPair.address, + openingId, + roleStake, + applicantStake, + text, + expectFailure, + module + ) + }) + ) + } + + public async fillOpening( + leader: KeyringPair, + openingId: BN, + applicationId: BN[], + amountPerPayout: BN, + nextPaymentBlock: BN, + payoutInterval: BN, + module: WorkingGroups + ): Promise { + return this.sender.signAndSend( + this.api.tx[module].fillOpening(openingId, applicationId, { + 'amount_per_payout': amountPerPayout, + 'next_payment_at_block': nextPaymentBlock, + 'payout_interval': payoutInterval, + }), + leader, + false + ) + } + + public async sudoFillOpening( + sudo: KeyringPair, + openingId: BN, + applicationId: BN[], + amountPerPayout: BN, + nextPaymentBlock: BN, + payoutInterval: BN, + module: WorkingGroups + ): Promise { + return this.sender.signAndSend( + this.api.tx.sudo.sudo( + this.api.tx[module].fillOpening(openingId, applicationId, { + 'amount_per_payout': amountPerPayout, + 'next_payment_at_block': nextPaymentBlock, + 'payout_interval': payoutInterval, + }) + ), + sudo, + false + ) + } + + public async increaseStake(worker: KeyringPair, workerId: BN, stake: BN, module: WorkingGroups): Promise { + return this.sender.signAndSend(this.api.tx[module].increaseStake(workerId, stake), worker, false) + } + + public async decreaseStake( + leader: KeyringPair, + workerId: BN, + stake: BN, + module: WorkingGroups, + expectFailure: boolean + ): Promise { + return this.sender.signAndSend(this.api.tx[module].decreaseStake(workerId, stake), leader, expectFailure) + } + + public async slashStake( + leader: KeyringPair, + workerId: BN, + stake: BN, + module: WorkingGroups, + expectFailure: boolean + ): Promise { + return this.sender.signAndSend(this.api.tx[module].slashStake(workerId, stake), leader, expectFailure) + } + + public async updateRoleAccount( + worker: KeyringPair, + workerId: BN, + newRoleAccount: string, + module: WorkingGroups + ): Promise { + return this.sender.signAndSend(this.api.tx[module].updateRoleAccount(workerId, newRoleAccount), worker, false) + } + + public async updateRewardAccount( + worker: KeyringPair, + workerId: BN, + newRewardAccount: string, + module: WorkingGroups + ): Promise { + return this.sender.signAndSend(this.api.tx[module].updateRewardAccount(workerId, newRewardAccount), worker, false) + } + + public async withdrawApplication(account: KeyringPair, workerId: BN, module: WorkingGroups): Promise { + return this.sender.signAndSend(this.api.tx[module].withdrawApplication(workerId), account, false) + } + + public async batchWithdrawApplication(accounts: KeyringPair[], module: WorkingGroups): Promise { + return Promise.all( + accounts.map(async (keyPair) => { + const applicationIds: BN[] = await this.getApplicationsIdsByRoleAccount(keyPair.address, module) + await this.withdrawApplication(keyPair, applicationIds[0], module) + }) + ) + } + + public async terminateApplication(leader: KeyringPair, applicationId: BN, module: WorkingGroups): Promise { + return this.sender.signAndSend(this.api.tx[module].terminateApplication(applicationId), leader, false) + } + + public async batchTerminateApplication( + leader: KeyringPair, + roleAccounts: KeyringPair[], + module: WorkingGroups + ): Promise { + return Promise.all( + roleAccounts.map(async (keyPair) => { + const applicationIds: BN[] = await this.getActiveApplicationsIdsByRoleAccount(keyPair.address, module) + await this.terminateApplication(leader, applicationIds[0], module) + }) + ) + } + + public async terminateRole( + leader: KeyringPair, + applicationId: BN, + text: string, + module: WorkingGroups, + expectFailure: boolean + ): Promise { + return this.sender.signAndSend(this.api.tx[module].terminateRole(applicationId, text, false), leader, expectFailure) + } + + public async leaveRole( + account: KeyringPair, + text: string, + expectFailure: boolean, + module: WorkingGroups + ): Promise { + const workerId: BN = await this.getWorkerIdByRoleAccount(account.address, module) + return this.sender.signAndSend(this.api.tx[module].leaveRole(workerId, text), account, expectFailure) + } + + public async batchLeaveRole( + roleAccounts: KeyringPair[], + text: string, + expectFailure: boolean, + module: WorkingGroups + ): Promise { + return Promise.all( + roleAccounts.map(async (keyPair) => { + await this.leaveRole(keyPair, text, expectFailure, module) + }) + ) + } + + public async getStorageRoleParameters(): Promise { + return (await this.api.query.actors.parameters>('StorageProvider')).unwrap() + } + + public async getAnnouncingPeriod(): Promise { + return this.api.query.councilElection.announcingPeriod() + } + + public async getVotingPeriod(): Promise { + return this.api.query.councilElection.votingPeriod() + } + + public async getRevealingPeriod(): Promise { + return this.api.query.councilElection.revealingPeriod() + } + + public async getCouncilSize(): Promise { + return this.api.query.councilElection.councilSize() + } + + public async getCandidacyLimit(): Promise { + return this.api.query.councilElection.candidacyLimit() + } + + public async getNewTermDuration(): Promise { + return this.api.query.councilElection.newTermDuration() + } + + public async getMinCouncilStake(): Promise { + return this.api.query.councilElection.minCouncilStake() + } + + public async getMinVotingStake(): Promise { + return this.api.query.councilElection.minVotingStake() + } + + public async getNextOpeningId(module: WorkingGroups): Promise { + return this.api.query[module].nextOpeningId() + } + + public async getNextApplicationId(module: WorkingGroups): Promise { + return this.api.query[module].nextApplicationId() + } + + public async getOpening(id: BN, module: WorkingGroups): Promise { + return ((await this.api.query[module].openingById(id))[0] as unknown) as Opening + } + + public async getHiringOpening(id: BN): Promise { + return ((await this.api.query.hiring.openingById(id))[0] as unknown) as HiringOpening + } + + public async getWorkers(module: WorkingGroups): Promise { + return ((await this.api.query[module].workerById())[1] as unknown) as Worker[] + } + + public async getWorkerById(id: BN, module: WorkingGroups): Promise { + return ((await this.api.query[module].workerById(id))[0] as unknown) as Worker + } + + public async getWorkerIdByRoleAccount(address: string, module: WorkingGroups): Promise { + const workersAndIds = await this.api.query[module].workerById() + const workers: Worker[] = (workersAndIds[1] as unknown) as Worker[] + const ids: WorkerId[] = (workersAndIds[0] as unknown) as WorkerId[] + const index: number = workers.findIndex((worker) => worker.role_account_id.toString() === address) + return ids[index] + } + + public async getApplicationsIdsByRoleAccount(address: string, module: WorkingGroups): Promise { + const applicationsAndIds = await this.api.query[module].applicationById() + const applications: Application[] = (applicationsAndIds[1] as unknown) as Application[] + const ids: ApplicationId[] = (applicationsAndIds[0] as unknown) as ApplicationId[] + return applications + .map((application, index) => (application.role_account_id.toString() === address ? ids[index] : undefined)) + .filter((id) => id !== undefined) as BN[] + } + + public async getHiringApplicationById(id: BN): Promise { + return ((await this.api.query.hiring.applicationById(id))[0] as unknown) as HiringApplication + } + + public async getApplicationById(id: BN, module: WorkingGroups): Promise { + return ((await this.api.query[module].applicationById(id))[0] as unknown) as Application + } + + public async getActiveApplicationsIdsByRoleAccount(address: string, module: WorkingGroups): Promise { + const applicationsAndIds = await this.api.query[module].applicationById() + const applications: Application[] = (applicationsAndIds[1] as unknown) as Application[] + const ids: ApplicationId[] = (applicationsAndIds[0] as unknown) as ApplicationId[] + return ( + await Promise.all( + applications.map(async (application, index) => { + if ( + application.role_account_id.toString() === address && + (await this.getHiringApplicationById(application.application_id)).stage.type === 'Active' + ) { + return ids[index] + } else { + return undefined + } + }) + ) + ).filter((index) => index !== undefined) as BN[] + } + + public async getStake(id: BN): Promise { + return ((await this.api.query.stake.stakes(id))[0] as unknown) as Stake + } + + public async getWorkerStakeAmount(workerId: BN, module: WorkingGroups): Promise { + const stakeId: BN = (await this.getWorkerById(workerId, module)).role_stake_profile.unwrap().stake_id + return (((await this.getStake(stakeId)).staking_status.value as unknown) as StakedState).staked_amount + } + + public async getRewardRelationship(id: BN): Promise { + return (( + await this.api.query.recurringRewards.rewardRelationships(id) + )[0] as unknown) as RewardRelationship + } + + public async getWorkerRewardAccount(workerId: BN, module: WorkingGroups): Promise { + const rewardRelationshipId: BN = (await this.getWorkerById(workerId, module)).reward_relationship.unwrap() + return (await this.getRewardRelationship(rewardRelationshipId)).getField('account').toString() + } + + public async getLeadWorkerId(module: WorkingGroups): Promise { + return (await this.api.query[module].currentLead>()).unwrapOr(undefined) + } +} diff --git a/tests/network-tests/src/iznik/utils/config.ts b/tests/network-tests/src/iznik/utils/config.ts new file mode 100644 index 0000000000..0c431297e1 --- /dev/null +++ b/tests/network-tests/src/iznik/utils/config.ts @@ -0,0 +1,5 @@ +import { config } from 'dotenv' + +export function initConfig() { + config() +} diff --git a/tests/network-tests/src/iznik/utils/sender.ts b/tests/network-tests/src/iznik/utils/sender.ts new file mode 100644 index 0000000000..2fba9b887c --- /dev/null +++ b/tests/network-tests/src/iznik/utils/sender.ts @@ -0,0 +1,66 @@ +import BN from 'bn.js' +import { ApiPromise } from '@polkadot/api' +import { Index } from '@polkadot/types/interfaces' +import { SubmittableExtrinsic } from '@polkadot/api/types' +import { KeyringPair } from '@polkadot/keyring/types' + +export class Sender { + private readonly api: ApiPromise + private static nonceMap: Map = new Map() + + constructor(api: ApiPromise) { + this.api = api + } + + private async getNonce(address: string): Promise { + let oncahinNonce: BN = new BN(0) + if (!Sender.nonceMap.get(address)) { + oncahinNonce = await this.api.query.system.accountNonce(address) + } + let nonce: BN | undefined = Sender.nonceMap.get(address) + if (!nonce) { + nonce = oncahinNonce + } + const nextNonce: BN = nonce.addn(1) + Sender.nonceMap.set(address, nextNonce) + return nonce + } + + private clearNonce(address: string): void { + Sender.nonceMap.delete(address) + } + + public async signAndSend( + tx: SubmittableExtrinsic<'promise'>, + account: KeyringPair, + expectFailure = false + ): Promise { + return new Promise(async (resolve, reject) => { + const nonce: BN = await this.getNonce(account.address) + const signedTx = tx.sign(account, { nonce }) + await signedTx + .send(async (result) => { + if (result.status.isFinalized === true && result.events !== undefined) { + result.events.forEach((event) => { + if (event.event.method === 'ExtrinsicFailed') { + if (expectFailure) { + resolve() + } else { + reject(new Error('Extrinsic failed unexpectedly')) + } + } + }) + resolve() + } + if (result.status.isFuture) { + console.log('nonce ' + nonce + ' for account ' + account.address + ' is in future') + this.clearNonce(account.address) + reject(new Error('Extrinsic nonce is in future')) + } + }) + .catch((error) => { + reject(error) + }) + }) + } +} diff --git a/tests/network-tests/src/iznik/utils/setTestTimeout.ts b/tests/network-tests/src/iznik/utils/setTestTimeout.ts new file mode 100644 index 0000000000..66328bd88a --- /dev/null +++ b/tests/network-tests/src/iznik/utils/setTestTimeout.ts @@ -0,0 +1,7 @@ +import tap from 'tap' +import { ApiWrapper } from './apiWrapper' + +export function setTestTimeout(apiWrapper: ApiWrapper, durationInBlocks: number) { + const durationInMillis = apiWrapper.getBlockDuration().muln(durationInBlocks).toNumber() + tap.setTimeout(durationInMillis) +} diff --git a/tests/network-tests/src/iznik/utils/utils.ts b/tests/network-tests/src/iznik/utils/utils.ts new file mode 100644 index 0000000000..12ea2f0efd --- /dev/null +++ b/tests/network-tests/src/iznik/utils/utils.ts @@ -0,0 +1,53 @@ +import { IExtrinsic } from '@polkadot/types/types' +import { compactToU8a, stringToU8a } from '@polkadot/util' +import { blake2AsHex } from '@polkadot/util-crypto' +import BN from 'bn.js' +import fs from 'fs' +import { decodeAddress } from '@polkadot/keyring' +import { Seat } from '@nicaea/types/council' + +export class Utils { + private static LENGTH_ADDRESS = 32 + 1 // publicKey + prefix + private static LENGTH_ERA = 2 // assuming mortals + private static LENGTH_SIGNATURE = 64 // assuming ed25519 or sr25519 + private static LENGTH_VERSION = 1 // 0x80 & version + + public static calcTxLength = (extrinsic?: IExtrinsic | null, nonce?: BN): BN => { + return new BN( + Utils.LENGTH_VERSION + + Utils.LENGTH_ADDRESS + + Utils.LENGTH_SIGNATURE + + Utils.LENGTH_ERA + + compactToU8a(nonce || 0).length + + (extrinsic ? extrinsic.encodedLength : 0) + ) + } + + /** hash(accountId + salt) */ + public static hashVote(accountId: string, salt: string): string { + const accountU8a = decodeAddress(accountId) + const saltU8a = stringToU8a(salt) + const voteU8a = new Uint8Array(accountU8a.length + saltU8a.length) + voteU8a.set(accountU8a) + voteU8a.set(saltU8a, accountU8a.length) + + const hash = blake2AsHex(voteU8a, 256) + return hash + } + + public static wait(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)) + } + + public static getTotalStake(seat: Seat): BN { + return new BN(+seat.stake.toString() + seat.backers.reduce((a, baker) => a + +baker.stake.toString(), 0)) + } + + public static readRuntimeFromFile(path: string): string { + return '0x' + fs.readFileSync(path).toString('hex') + } + + public static camelToSnakeCase(key: string): string { + return key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`) + } +} From f0807e9d6e8e076c5172461b0f2da96d88f8668b Mon Sep 17 00:00:00 2001 From: Gleb Urvanov Date: Thu, 23 Jul 2020 16:45:11 +0200 Subject: [PATCH 2/6] started refactoring membership tests --- .../src/iznik/tests/impl/membershipModule.ts | 93 +++++++++++++++++++ .../src/iznik/tests/membershipCreationTest.ts | 2 + 2 files changed, 95 insertions(+) create mode 100644 tests/network-tests/src/iznik/tests/impl/membershipModule.ts diff --git a/tests/network-tests/src/iznik/tests/impl/membershipModule.ts b/tests/network-tests/src/iznik/tests/impl/membershipModule.ts new file mode 100644 index 0000000000..d7a930ecbd --- /dev/null +++ b/tests/network-tests/src/iznik/tests/impl/membershipModule.ts @@ -0,0 +1,93 @@ +import { ApiWrapper } from '../../utils/apiWrapper' +import { KeyringPair } from '@polkadot/keyring/types' +import { Keyring } from '@polkadot/api' +import { v4 as uuid } from 'uuid' +import BN from 'bn.js' +import { assert } from 'chai' + +export class BuyMembershipHappyCaseFixture { + private keyPairs: KeyringPair[] = [] + + public getKeyPairs(): KeyringPair[] { + return this.keyPairs + } + + public async runner( + apiWrapper: ApiWrapper, + sudo: KeyringPair, + keyPairs: KeyringPair[], + keyring: Keyring, + n: number, + paidTerms: number + ): Promise { + // Account creation + for (let i = 0; i < n; i++) { + keyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8))) + } + + // Fee estimation and transfer + const membershipFee: BN = await apiWrapper.getMembershipFee(paidTerms) + const membershipTransactionFee: BN = apiWrapper.estimateBuyMembershipFee( + sudo, + paidTerms, + 'member_name_which_is_longer_than_expected' + ) + await apiWrapper.transferBalanceToAccounts(sudo, keyPairs, membershipTransactionFee.add(new BN(membershipFee))) + + // Buying membership + await Promise.all( + keyPairs.map(async (keyPair, index) => { + await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`) + }) + ) + + // Assertions + keyPairs.forEach((keyPair, index) => + apiWrapper + .getMemberIds(keyPair.address) + .then((membership) => assert(membership.length > 0, `Account ${keyPair.address} is not a member`)) + ) + + this.keyPairs = keyPairs + } +} + +export class BuyMembershipWithInsufficienFunds { + public async runner( + apiWrapper: ApiWrapper, + sudo: KeyringPair, + aKeyPair: KeyringPair, + keyring: Keyring, + paidTerms: number + ) { + // Account creation + aKeyPair = keyring.addFromUri(uuid().substring(0, 8)) + + // Fee estimation and transfer + const membershipFee: BN = await apiWrapper.getMembershipFee(paidTerms) + const membershipTransactionFee: BN = apiWrapper.estimateBuyMembershipFee( + sudo, + paidTerms, + 'member_name_which_is_longer_than_expected' + ) + await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee) + + // Balance assertion + await apiWrapper + .getBalance(aKeyPair.address) + .then((balance) => + assert( + balance.toBn() < membershipFee.add(membershipTransactionFee), + 'Account A already have sufficient balance to purchase membership' + ) + ) + + // Buying memebership + await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`, true) + + // Assertions + apiWrapper + .getMemberIds(aKeyPair.address) + .then((membership) => assert(membership.length === 0, 'Account A is a member')) + } +} diff --git a/tests/network-tests/src/iznik/tests/membershipCreationTest.ts b/tests/network-tests/src/iznik/tests/membershipCreationTest.ts index ab0ca84d77..d0d0c0c549 100644 --- a/tests/network-tests/src/iznik/tests/membershipCreationTest.ts +++ b/tests/network-tests/src/iznik/tests/membershipCreationTest.ts @@ -13,6 +13,7 @@ tap.mocha.describe('Membership creation scenario', async () => { registerJoystreamTypes() const nKeyPairs: KeyringPair[] = [] + let aKeyPair: KeyringPair const keyring = new Keyring({ type: 'sr25519' }) const N: number = +process.env.MEMBERSHIP_CREATION_N! const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! @@ -22,6 +23,7 @@ tap.mocha.describe('Membership creation scenario', async () => { const provider = new WsProvider(nodeUrl) const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) setTestTimeout(apiWrapper, durationInBlocks) membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) From 3f3b0ead30d99955e8787bfd37a30b0663ff2593 Mon Sep 17 00:00:00 2001 From: Gleb Urvanov Date: Fri, 24 Jul 2020 15:48:16 +0200 Subject: [PATCH 3/6] refactored membership and council fixtures --- .prettierrc.js | 2 +- tests/network-tests/package.json | 2 +- .../src/iznik/tests/electingCouncilTest.ts | 53 +++++-- .../iznik/tests/impl/councilElectionModule.ts | 137 ++++++++++++++++++ .../src/iznik/tests/impl/membershipModule.ts | 107 +++++++------- .../src/iznik/tests/membershipCreationTest.ts | 43 ++++-- .../iznik/tests/proposals/manageLeaderRole.ts | 29 +++- .../tests/workingGroup/atLeastValueBugTest.ts | 39 +++-- .../workingGroup/manageWorkerAsLeadTest.ts | 39 +++-- .../workingGroup/manageWorkerAsWorkerTest.ts | 39 +++-- .../workerApplicationHappyCaseTest.ts | 39 +++-- .../workerApplicationRejectionCaseTest.ts | 41 ++++-- .../{workerPayout.ts => workerPayoutTest.ts} | 39 +++-- .../network-tests/src/iznik/utils/fixture.ts | 3 + tests/network-tests/src/iznik/utils/utils.ts | 12 +- 15 files changed, 472 insertions(+), 152 deletions(-) create mode 100644 tests/network-tests/src/iznik/tests/impl/councilElectionModule.ts rename tests/network-tests/src/iznik/tests/workingGroup/{workerPayout.ts => workerPayoutTest.ts} (85%) create mode 100644 tests/network-tests/src/iznik/utils/fixture.ts diff --git a/.prettierrc.js b/.prettierrc.js index f2c1c07c33..03b543c4bd 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,3 +1,3 @@ module.exports = { - ...require('@joystream/prettier-config'), + ...require('./devops/prettier-config'), } diff --git a/tests/network-tests/package.json b/tests/network-tests/package.json index b5b77b23ef..acac02ad75 100644 --- a/tests/network-tests/package.json +++ b/tests/network-tests/package.json @@ -7,7 +7,7 @@ "test": "tap --files src/nicaea/tests/proposals/*Test.ts --files src/nicaea/tests/workingGroup/*Test.ts -T", "test-migration-constantinople": "tap --files src/rome/tests/romeRuntimeUpgradeTest.ts --files src/constantinople/tests/electingCouncilTest.ts -T", "test-migration-nicaea": "tap --files src/constantinople/tests/proposals/updateRuntimeTest.ts --files src/nicaea/tests/electingCouncilTest.ts -T", - "debug": "tap --files src/nicaea/tests/workingGroup/*Test.ts -T", + "debug": "tap --files src/iznik/tests/workingGroup/*Test.ts -T", "lint": "eslint . --quiet --ext .ts", "checks": "yarn lint && tsc --noEmit --pretty && prettier ./ --check", "format": "prettier ./ --write " diff --git a/tests/network-tests/src/iznik/tests/electingCouncilTest.ts b/tests/network-tests/src/iznik/tests/electingCouncilTest.ts index f9b75453ec..279895ad05 100644 --- a/tests/network-tests/src/iznik/tests/electingCouncilTest.ts +++ b/tests/network-tests/src/iznik/tests/electingCouncilTest.ts @@ -1,6 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from './impl/membershipCreation' -import { councilTest } from './impl/electingCouncil' import { initConfig } from '../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import { setTestTimeout } from '../utils/setTestTimeout' @@ -9,30 +7,59 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { ApiWrapper } from '../utils/apiWrapper' import { closeApi } from './impl/closeApi' +import { BuyMembershipHappyCaseFixture } from './impl/membershipModule' +import { ElectCouncilFixture } from './impl/councilElectionModule' +import { Utils } from '../utils/utils' tap.mocha.describe('Electing council scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) - const durationInBlocks = 25 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const durationInBlocks = 25 setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/impl/councilElectionModule.ts b/tests/network-tests/src/iznik/tests/impl/councilElectionModule.ts new file mode 100644 index 0000000000..09ceeeed4f --- /dev/null +++ b/tests/network-tests/src/iznik/tests/impl/councilElectionModule.ts @@ -0,0 +1,137 @@ +import { ApiWrapper } from '../../utils/apiWrapper' +import { KeyringPair } from '@polkadot/keyring/types' +import BN from 'bn.js' +import { assert } from 'chai' +import { Seat } from '@nicaea/types/council' +import { v4 as uuid } from 'uuid' +import { Utils } from '../../utils/utils' +import { Fixture } from '../../utils/fixture' + +export class ElectCouncilFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private k: number + private sudo: KeyringPair + private greaterStake: BN + private lesserStake: BN + + public constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + k: number, + sudo: KeyringPair, + greaterStake: BN, + lesserStake: BN + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.k = k + this.sudo = sudo + this.greaterStake = greaterStake + this.lesserStake = lesserStake + } + + public async runner(expectFailure: boolean): Promise { + let now = await this.apiWrapper.getBestBlock() + const applyForCouncilFee: BN = this.apiWrapper.estimateApplyForCouncilFee(this.greaterStake) + const voteForCouncilFee: BN = this.apiWrapper.estimateVoteForCouncilFee( + this.sudo.address, + this.sudo.address, + this.greaterStake + ) + const salt: string[] = [] + this.m1KeyPairs.forEach(() => { + salt.push(''.concat(uuid().replace(/-/g, ''))) + }) + const revealVoteFee: BN = this.apiWrapper.estimateRevealVoteFee(this.sudo.address, salt[0]) + + // Topping the balances + await this.apiWrapper.transferBalanceToAccounts( + this.sudo, + this.m2KeyPairs, + applyForCouncilFee.add(this.greaterStake) + ) + await this.apiWrapper.transferBalanceToAccounts( + this.sudo, + this.m1KeyPairs, + voteForCouncilFee.add(revealVoteFee).add(this.greaterStake) + ) + + // First K members stake more + await this.apiWrapper.sudoStartAnnouncingPerion(this.sudo, now.addn(100)) + await this.apiWrapper.batchApplyForCouncilElection(this.m2KeyPairs.slice(0, this.k), this.greaterStake) + this.m2KeyPairs.slice(0, this.k).forEach((keyPair) => + this.apiWrapper.getCouncilElectionStake(keyPair.address).then((stake) => { + assert( + stake.eq(this.greaterStake), + `${keyPair.address} not applied correctrly for council election with stake ${stake} versus expected ${this.greaterStake}` + ) + }) + ) + + // Last members stake less + await this.apiWrapper.batchApplyForCouncilElection(this.m2KeyPairs.slice(this.k), this.lesserStake) + this.m2KeyPairs.slice(this.k).forEach((keyPair) => + this.apiWrapper.getCouncilElectionStake(keyPair.address).then((stake) => { + assert( + stake.eq(this.lesserStake), + `${keyPair.address} not applied correctrly for council election with stake ${stake} versus expected ${this.lesserStake}` + ) + }) + ) + + // Voting + await this.apiWrapper.sudoStartVotingPerion(this.sudo, now.addn(100)) + await this.apiWrapper.batchVoteForCouncilMember( + this.m1KeyPairs.slice(0, this.k), + this.m2KeyPairs.slice(0, this.k), + salt.slice(0, this.k), + this.lesserStake + ) + await this.apiWrapper.batchVoteForCouncilMember( + this.m1KeyPairs.slice(this.k), + this.m2KeyPairs.slice(this.k), + salt.slice(this.k), + this.greaterStake + ) + + // Revealing + await this.apiWrapper.sudoStartRevealingPerion(this.sudo, now.addn(100)) + await this.apiWrapper.batchRevealVote( + this.m1KeyPairs.slice(0, this.k), + this.m2KeyPairs.slice(0, this.k), + salt.slice(0, this.k) + ) + await this.apiWrapper.batchRevealVote( + this.m1KeyPairs.slice(this.k), + this.m2KeyPairs.slice(this.k), + salt.slice(this.k) + ) + now = await this.apiWrapper.getBestBlock() + + // Resolving election + // 3 is to ensure the revealing block is in future + await this.apiWrapper.sudoStartRevealingPerion(this.sudo, now.addn(3)) + await Utils.wait(this.apiWrapper.getBlockDuration().muln(2.5).toNumber()) + const seats: Seat[] = await this.apiWrapper.getCouncil() + + // Preparing collections to increase assertion readability + const m2addresses: string[] = this.m2KeyPairs.map((keyPair) => keyPair.address) + const m1addresses: string[] = this.m1KeyPairs.map((keyPair) => keyPair.address) + const members: string[] = seats.map((seat) => seat.member.toString()) + const bakers: string[] = seats.map((seat) => seat.backers.map((baker) => baker.member.toString())).flat() + + // Assertions + m2addresses.forEach((address) => assert(members.includes(address), `Account ${address} is not in the council`)) + m1addresses.forEach((address) => assert(bakers.includes(address), `Account ${address} is not in the voters`)) + seats.forEach((seat) => + assert( + Utils.getTotalStake(seat).eq(this.greaterStake.add(this.lesserStake)), + `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}` + ) + ) + } +} diff --git a/tests/network-tests/src/iznik/tests/impl/membershipModule.ts b/tests/network-tests/src/iznik/tests/impl/membershipModule.ts index d7a930ecbd..7e141fd3a7 100644 --- a/tests/network-tests/src/iznik/tests/impl/membershipModule.ts +++ b/tests/network-tests/src/iznik/tests/impl/membershipModule.ts @@ -1,80 +1,82 @@ import { ApiWrapper } from '../../utils/apiWrapper' import { KeyringPair } from '@polkadot/keyring/types' -import { Keyring } from '@polkadot/api' -import { v4 as uuid } from 'uuid' import BN from 'bn.js' import { assert } from 'chai' +import { Fixture } from '../../utils/fixture' -export class BuyMembershipHappyCaseFixture { - private keyPairs: KeyringPair[] = [] +export class BuyMembershipHappyCaseFixture implements Fixture { + private apiWrapper: ApiWrapper + private sudo: KeyringPair + private keyPairs: KeyringPair[] + private paidTerms: number - public getKeyPairs(): KeyringPair[] { - return this.keyPairs + public constructor(apiWrapper: ApiWrapper, sudo: KeyringPair, keyPairs: KeyringPair[], paidTerms: number) { + this.apiWrapper = apiWrapper + this.sudo = sudo + this.keyPairs = keyPairs + this.paidTerms = paidTerms } - public async runner( - apiWrapper: ApiWrapper, - sudo: KeyringPair, - keyPairs: KeyringPair[], - keyring: Keyring, - n: number, - paidTerms: number - ): Promise { - // Account creation - for (let i = 0; i < n; i++) { - keyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8))) - } - + public async runner(expectFailure: boolean): Promise { // Fee estimation and transfer - const membershipFee: BN = await apiWrapper.getMembershipFee(paidTerms) - const membershipTransactionFee: BN = apiWrapper.estimateBuyMembershipFee( - sudo, - paidTerms, + const membershipFee: BN = await this.apiWrapper.getMembershipFee(this.paidTerms) + const membershipTransactionFee: BN = this.apiWrapper.estimateBuyMembershipFee( + this.sudo, + this.paidTerms, 'member_name_which_is_longer_than_expected' ) - await apiWrapper.transferBalanceToAccounts(sudo, keyPairs, membershipTransactionFee.add(new BN(membershipFee))) + await this.apiWrapper.transferBalanceToAccounts( + this.sudo, + this.keyPairs, + membershipTransactionFee.add(new BN(membershipFee)) + ) // Buying membership await Promise.all( - keyPairs.map(async (keyPair, index) => { - await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`) + this.keyPairs.map(async (keyPair, index) => { + await this.apiWrapper.buyMembership( + keyPair, + this.paidTerms, + `new_member_${index}${keyPair.address.substring(0, 8)}` + ) }) ) // Assertions - keyPairs.forEach((keyPair, index) => - apiWrapper + this.keyPairs.forEach((keyPair) => + this.apiWrapper .getMemberIds(keyPair.address) .then((membership) => assert(membership.length > 0, `Account ${keyPair.address} is not a member`)) ) - - this.keyPairs = keyPairs } } -export class BuyMembershipWithInsufficienFunds { - public async runner( - apiWrapper: ApiWrapper, - sudo: KeyringPair, - aKeyPair: KeyringPair, - keyring: Keyring, - paidTerms: number - ) { - // Account creation - aKeyPair = keyring.addFromUri(uuid().substring(0, 8)) +export class BuyMembershipWithInsufficienFundsFixture implements Fixture { + private apiWrapper: ApiWrapper + private sudo: KeyringPair + private aKeyPair: KeyringPair + private paidTerms: number + + public constructor(apiWrapper: ApiWrapper, sudo: KeyringPair, aKeyPair: KeyringPair, paidTerms: number) { + this.apiWrapper = apiWrapper + this.sudo = sudo + this.aKeyPair = aKeyPair + this.paidTerms = paidTerms + } + public async runner(expectFailure: boolean) { // Fee estimation and transfer - const membershipFee: BN = await apiWrapper.getMembershipFee(paidTerms) - const membershipTransactionFee: BN = apiWrapper.estimateBuyMembershipFee( - sudo, - paidTerms, + const membershipFee: BN = await this.apiWrapper.getMembershipFee(this.paidTerms) + const membershipTransactionFee: BN = this.apiWrapper.estimateBuyMembershipFee( + this.sudo, + this.paidTerms, 'member_name_which_is_longer_than_expected' ) - await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee) + await this.apiWrapper.transferBalance(this.sudo, this.aKeyPair.address, membershipTransactionFee) // Balance assertion - await apiWrapper - .getBalance(aKeyPair.address) + await this.apiWrapper + .getBalance(this.aKeyPair.address) .then((balance) => assert( balance.toBn() < membershipFee.add(membershipTransactionFee), @@ -83,11 +85,16 @@ export class BuyMembershipWithInsufficienFunds { ) // Buying memebership - await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`, true) + await this.apiWrapper.buyMembership( + this.aKeyPair, + this.paidTerms, + `late_member_${this.aKeyPair.address.substring(0, 8)}`, + true + ) // Assertions - apiWrapper - .getMemberIds(aKeyPair.address) + this.apiWrapper + .getMemberIds(this.aKeyPair.address) .then((membership) => assert(membership.length === 0, 'Account A is a member')) } } diff --git a/tests/network-tests/src/iznik/tests/membershipCreationTest.ts b/tests/network-tests/src/iznik/tests/membershipCreationTest.ts index d0d0c0c549..71516b2233 100644 --- a/tests/network-tests/src/iznik/tests/membershipCreationTest.ts +++ b/tests/network-tests/src/iznik/tests/membershipCreationTest.ts @@ -1,5 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from './impl/membershipCreation' import { Keyring, WsProvider } from '@polkadot/api' import { initConfig } from '../utils/config' import { setTestTimeout } from '../utils/setTestTimeout' @@ -7,25 +6,51 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { ApiWrapper } from '../utils/apiWrapper' import { closeApi } from './impl/closeApi' +import { BuyMembershipHappyCaseFixture, BuyMembershipWithInsufficienFundsFixture } from './impl/membershipModule' +import { Utils } from '../utils/utils' tap.mocha.describe('Membership creation scenario', async () => { initConfig() registerJoystreamTypes() - const nKeyPairs: KeyringPair[] = [] - let aKeyPair: KeyringPair - const keyring = new Keyring({ type: 'sr25519' }) - const N: number = +process.env.MEMBERSHIP_CREATION_N! - const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! const nodeUrl: string = process.env.NODE_URL! const sudoUri: string = process.env.SUDO_ACCOUNT_URI! - const durationInBlocks = 7 - + const keyring = new Keyring({ type: 'sr25519' }) const provider = new WsProvider(nodeUrl) const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + let aKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + + const durationInBlocks = 7 + setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + nKeyPairs, + paidTerms + ) + tap.test('Buy membeship is accepted with sufficient funds', async () => happyCaseFixture.runner(false)) + + const insufficientFundsFixture: BuyMembershipWithInsufficienFundsFixture = new BuyMembershipWithInsufficienFundsFixture( + apiWrapper, + sudo, + aKeyPair[0], + paidTerms + ) + tap.test('Account A can not buy the membership with insufficient funds', async () => + insufficientFundsFixture.runner(false) + ) + + const buyMembershipAfterAccountTopUp = new BuyMembershipHappyCaseFixture(apiWrapper, sudo, aKeyPair, paidTerms) + tap.test('Account A was able to buy the membership with sufficient funds', async () => + buyMembershipAfterAccountTopUp.runner(false) + ) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts index d1b08c632f..25ea7ce4c0 100644 --- a/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts +++ b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts @@ -29,6 +29,8 @@ import { expectLeaderStakeDecreased, expectLeaderSlashed, } from '../workingGroup/impl/workingGroupModule' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' tap.mocha.describe('Set lead proposal scenario', async () => { initConfig() @@ -61,10 +63,29 @@ tap.mocha.describe('Set lead proposal scenario', async () => { const sudo: KeyringPair = keyring.addFromUri(sudoUri) setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture() + tap.test('Buy membeship is accepted with sufficient funds', async () => + happyCaseFixture.runner(apiWrapper, sudo, m1KeyPairs, keyring, N, paidTerms) + ) + + tap.test('Buy membeship is accepted with sufficient funds', async () => + happyCaseFixture.runner(apiWrapper, sudo, m2KeyPairs, keyring, N, paidTerms) + ) + + tap.test('Buy membeship is accepted with sufficient funds', async () => + happyCaseFixture.runner(apiWrapper, sudo, leadKeyPair, keyring, 1, paidTerms) + ) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture() + tap.test('Elect council', async () => + electCouncilFixture.runner(apiWrapper, m1KeyPairs, m2KeyPairs, K, sudo, greaterStake, lesserStake) + ) + + // membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) + // membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) + // membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + // councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) let createOpeningProposalId: BN let openingId: BN diff --git a/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts index 7fc6e502fc..4f75bf527c 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts @@ -5,7 +5,6 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { membershipTest } from '../impl/membershipCreation' import { addWorkerOpening, applyForOpening, @@ -16,19 +15,25 @@ import { } from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() registerJoystreamTypes() - const nKeyPairs: KeyringPair[] = [] - const leadKeyPair: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.WORKING_GROUP_N! + const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) @@ -38,13 +43,23 @@ tap.mocha.describe('Worker application happy case scenario', async () => { const durationInBlocks = 48 const openingActivationDelay: BN = new BN(0) - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + nKeyPairs, + paidTerms + ) + tap.test('Creating a set of members', async () => happyCaseFixture.runner(false)) + + const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + leadKeyPair, + paidTerms + ) + tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) let leadOpenignId: BN tap.test( diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts index b337ae330b..1f8217da85 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts @@ -5,7 +5,6 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { membershipTest } from '../impl/membershipCreation' import { addWorkerOpening, applyForOpening, @@ -21,19 +20,25 @@ import { } from './impl/workingGroupModule' import BN from 'bn.js' import tap = require('tap') +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Manage worker as worker scenario', async () => { initConfig() registerJoystreamTypes() - const nKeyPairs: KeyringPair[] = [] - const leadKeyPair: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.WORKING_GROUP_N! + const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) @@ -43,13 +48,23 @@ tap.mocha.describe('Manage worker as worker scenario', async () => { const durationInBlocks = 60 const openingActivationDelay: BN = new BN(0) - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + nKeyPairs, + paidTerms + ) + tap.test('Creating a set of members', async () => happyCaseFixture.runner(false)) + + const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + leadKeyPair, + paidTerms + ) + tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) let leadOpenignId: BN tap.test( diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts index 6bb0609b60..632f22f902 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts @@ -5,7 +5,6 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { membershipTest } from '../impl/membershipCreation' import { addWorkerOpening, applyForOpening, @@ -21,19 +20,25 @@ import { } from './impl/workingGroupModule' import BN from 'bn.js' import tap = require('tap') +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Manage worker as worker scenario', async () => { initConfig() registerJoystreamTypes() - const nKeyPairs: KeyringPair[] = [] - const leadKeyPair: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.WORKING_GROUP_N! + const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) @@ -43,13 +48,23 @@ tap.mocha.describe('Manage worker as worker scenario', async () => { const durationInBlocks = 38 const openingActivationDelay: BN = new BN(0) - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + nKeyPairs, + paidTerms + ) + tap.test('Creating a set of members', async () => happyCaseFixture.runner(false)) + + const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + leadKeyPair, + paidTerms + ) + tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) let leadOpenignId: BN tap.test( diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts index 26d5322458..59ac353880 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts @@ -5,7 +5,6 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { membershipTest } from '../impl/membershipCreation' import { addWorkerOpening, applyForOpening, @@ -19,19 +18,25 @@ import { } from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() registerJoystreamTypes() - const nKeyPairs: KeyringPair[] = [] - const leadKeyPair: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.WORKING_GROUP_N! + const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) @@ -41,13 +46,23 @@ tap.mocha.describe('Worker application happy case scenario', async () => { const durationInBlocks = 48 const openingActivationDelay: BN = new BN(0) - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + nKeyPairs, + paidTerms + ) + tap.test('Creating a set of members', async () => happyCaseFixture.runner(false)) + + const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + leadKeyPair, + paidTerms + ) + tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) let leadOpenignId: BN tap.test( diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts index ce021bf4bf..fe67895355 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts @@ -5,7 +5,6 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { membershipTest, createKeyPairs } from '../impl/membershipCreation' import { addWorkerOpening, applyForOpening, @@ -18,19 +17,26 @@ import { } from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() registerJoystreamTypes() - const nKeyPairs: KeyringPair[] = [] - const leadKeyPair: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.WORKING_GROUP_N! + const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const nonMemberKeyPairs = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) const firstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) @@ -41,14 +47,23 @@ tap.mocha.describe('Worker application happy case scenario', async () => { const openingActivationDelay: BN = new BN(100) const leadOpeningActivationDelay: BN = new BN(0) - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - const nonMemberKeyPairs = createKeyPairs(keyring, N) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + nKeyPairs, + paidTerms + ) + tap.test('Creating a set of members', async () => happyCaseFixture.runner(false)) + + const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + leadKeyPair, + paidTerms + ) + tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) let leadOpenignId: BN tap.test( diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerPayout.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts similarity index 85% rename from tests/network-tests/src/iznik/tests/workingGroup/workerPayout.ts rename to tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts index ebd06f8fdb..01764a2e6f 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerPayout.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts @@ -5,7 +5,6 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { membershipTest } from '../impl/membershipCreation' import { addWorkerOpening, applyForOpening, @@ -20,19 +19,25 @@ import { } from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() registerJoystreamTypes() - const nKeyPairs: KeyringPair[] = [] - const leadKeyPair: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.WORKING_GROUP_N! + const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) const firstRewardInterval: BN = new BN(process.env.SHORT_FIRST_REWARD_INTERVAL!) @@ -43,13 +48,23 @@ tap.mocha.describe('Worker application happy case scenario', async () => { const durationInBlocks = 48 const openingActivationDelay: BN = new BN(0) - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, nKeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) + + const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + nKeyPairs, + paidTerms + ) + tap.test('Creating a set of members', async () => happyCaseFixture.runner(false)) + + const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + leadKeyPair, + paidTerms + ) + tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) let leadOpenignId: BN tap.test( diff --git a/tests/network-tests/src/iznik/utils/fixture.ts b/tests/network-tests/src/iznik/utils/fixture.ts new file mode 100644 index 0000000000..06d94a98ff --- /dev/null +++ b/tests/network-tests/src/iznik/utils/fixture.ts @@ -0,0 +1,3 @@ +export interface Fixture { + runner(expectFailure: boolean): Promise +} diff --git a/tests/network-tests/src/iznik/utils/utils.ts b/tests/network-tests/src/iznik/utils/utils.ts index 12ea2f0efd..6db1768733 100644 --- a/tests/network-tests/src/iznik/utils/utils.ts +++ b/tests/network-tests/src/iznik/utils/utils.ts @@ -3,8 +3,10 @@ import { compactToU8a, stringToU8a } from '@polkadot/util' import { blake2AsHex } from '@polkadot/util-crypto' import BN from 'bn.js' import fs from 'fs' -import { decodeAddress } from '@polkadot/keyring' +import Keyring, { decodeAddress } from '@polkadot/keyring' import { Seat } from '@nicaea/types/council' +import { KeyringPair } from '@polkadot/keyring/types' +import { v4 as uuid } from 'uuid' export class Utils { private static LENGTH_ADDRESS = 32 + 1 // publicKey + prefix @@ -50,4 +52,12 @@ export class Utils { public static camelToSnakeCase(key: string): string { return key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`) } + + public static createKeyPairs(keyring: Keyring, n: number): KeyringPair[] { + const nKeyPairs: KeyringPair[] = [] + for (let i = 0; i < n; i++) { + nKeyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8))) + } + return nKeyPairs + } } From 809d0d6eb3bc6015f249d36f2ca3e82b9d7f3aa9 Mon Sep 17 00:00:00 2001 From: Gleb Urvanov Date: Mon, 27 Jul 2020 16:57:44 +0200 Subject: [PATCH 4/6] working group module refactored --- .../workingGroup/impl/workingGroupModule.ts | 1555 +++++++++++------ .../src/iznik/utils/apiWrapper.ts | 86 +- 2 files changed, 1033 insertions(+), 608 deletions(-) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts b/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts index ae38c63cbd..1929731740 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts @@ -2,7 +2,7 @@ import BN from 'bn.js' import { assert } from 'chai' import { ApiWrapper, WorkingGroups } from '../../../utils/apiWrapper' import { KeyringPair } from '@polkadot/keyring/types' -import { Balance } from '@polkadot/types/interfaces' +import { Balance, Event } from '@polkadot/types/interfaces' import { Keyring } from '@polkadot/api' import { v4 as uuid } from 'uuid' import { RewardRelationship } from '@nicaea/types/recurring-rewards' @@ -10,590 +10,1093 @@ import { Worker, ApplicationIdToWorkerIdMap, Application } from '@nicaea/types/w import { Utils } from '../../../utils/utils' import { Opening as HiringOpening } from '@nicaea/types/hiring' import { WorkingGroupOpening } from '../../../dto/workingGroupOpening' +import { Fixture } from '../../../utils/fixture' -export async function addWorkerOpening( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - lead: KeyringPair, - sudo: KeyringPair, - applicationStake: BN, - roleStake: BN, - activationDelay: BN, - unstakingPeriod: BN, - module: WorkingGroups, - expectFailure: boolean -): Promise { - // Worker opening construction - const activateAtBlock: BN | undefined = activationDelay.eqn(0) - ? undefined - : (await apiWrapper.getBestBlock()).add(activationDelay) - const opening = new WorkingGroupOpening() - .setActivateAtBlock(activateAtBlock) - .setMaxActiveApplicants(new BN(membersKeyPairs.length)) - .setMaxReviewPeriodLength(new BN(32)) - .setApplicationStakingPolicyAmount(new BN(applicationStake)) - .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) - .setApplicationExpiredUnstakingPeriodLength(new BN(1)) - .setRoleStakingPolicyAmount(new BN(roleStake)) - .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) - .setRoleExpiredUnstakingPeriodLength(new BN(1)) - .setSlashableMaxCount(new BN(1)) - .setSlashableMaxPercentPtsPerTime(new BN(100)) - .setSuccessfulApplicantApplicationStakeUnstakingPeriod(unstakingPeriod) - .setFailedApplicantApplicationStakeUnstakingPeriod(unstakingPeriod) - .setFailedApplicantRoleStakeUnstakingPeriod(unstakingPeriod) - .setTerminateApplicationStakeUnstakingPeriod(unstakingPeriod) - .setTerminateRoleStakeUnstakingPeriod(unstakingPeriod) - .setExitRoleApplicationStakeUnstakingPeriod(unstakingPeriod) - .setExitRoleStakeUnstakingPeriod(unstakingPeriod) - .setText(uuid().substring(0, 8)) - .setOpeningType('Worker') - - // Fee estimation and transfer - const addOpeningFee: BN = apiWrapper.estimateAddOpeningFee(opening, module) - await apiWrapper.transferBalance(sudo, lead.address, addOpeningFee) - - // Worker opening creation - const addOpeningPromise: Promise = apiWrapper.expectOpeningAdded() - await apiWrapper.addOpening(lead, opening, module, expectFailure) - if (!expectFailure) { +export class AddWorkerOpeningFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private lead: KeyringPair + private sudo: KeyringPair + private applicationStake: BN + private roleStake: BN + private activationDelay: BN + private unstakingPeriod: BN + private module: WorkingGroups + + private result: BN | undefined + + public getResult(): BN | undefined { + return this.result + } + + public constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + activationDelay: BN, + unstakingPeriod: BN, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.lead = lead + this.sudo = sudo + this.applicationStake = applicationStake + this.roleStake = roleStake + this.activationDelay = activationDelay + this.unstakingPeriod = unstakingPeriod + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Worker opening construction + const activateAtBlock: BN | undefined = this.activationDelay.eqn(0) + ? undefined + : (await this.apiWrapper.getBestBlock()).add(this.activationDelay) + const opening = new WorkingGroupOpening() + .setActivateAtBlock(activateAtBlock) + .setMaxActiveApplicants(new BN(this.membersKeyPairs.length)) + .setMaxReviewPeriodLength(new BN(32)) + .setApplicationStakingPolicyAmount(new BN(this.applicationStake)) + .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) + .setApplicationExpiredUnstakingPeriodLength(new BN(1)) + .setRoleStakingPolicyAmount(new BN(this.roleStake)) + .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) + .setRoleExpiredUnstakingPeriodLength(new BN(1)) + .setSlashableMaxCount(new BN(1)) + .setSlashableMaxPercentPtsPerTime(new BN(100)) + .setSuccessfulApplicantApplicationStakeUnstakingPeriod(this.unstakingPeriod) + .setFailedApplicantApplicationStakeUnstakingPeriod(this.unstakingPeriod) + .setFailedApplicantRoleStakeUnstakingPeriod(this.unstakingPeriod) + .setTerminateApplicationStakeUnstakingPeriod(this.unstakingPeriod) + .setTerminateRoleStakeUnstakingPeriod(this.unstakingPeriod) + .setExitRoleApplicationStakeUnstakingPeriod(this.unstakingPeriod) + .setExitRoleStakeUnstakingPeriod(this.unstakingPeriod) + .setText(uuid().substring(0, 8)) + .setOpeningType('Worker') + + // Fee estimation and transfer + const addOpeningFee: BN = this.apiWrapper.estimateAddOpeningFee(opening, this.module) + await this.apiWrapper.transferBalance(this.sudo, this.lead.address, addOpeningFee) + + // Worker opening creation + const addOpeningPromise: Promise = this.apiWrapper.expectOpeningAdded() + await this.apiWrapper.addOpening(this.lead, opening, this.module, expectFailure) + if (!expectFailure) { + const openingId: BN = await addOpeningPromise + this.result = openingId + } + } +} + +export class AddLeaderOpeningFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private sudo: KeyringPair + private applicationStake: BN + private roleStake: BN + private activationDelay: BN + private module: WorkingGroups + + private result: BN | undefined + + public getResult(): BN | undefined { + return this.result + } + + public constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + activationDelay: BN, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.sudo = sudo + this.applicationStake = applicationStake + this.roleStake = roleStake + this.activationDelay = activationDelay + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Leader opening creation + const activateAtBlock: BN | undefined = this.activationDelay.eqn(0) + ? undefined + : (await this.apiWrapper.getBestBlock()).add(this.activationDelay) + const opening = new WorkingGroupOpening() + .setActivateAtBlock(activateAtBlock) + .setMaxActiveApplicants(new BN(this.membersKeyPairs.length)) + .setMaxReviewPeriodLength(new BN(32)) + .setApplicationStakingPolicyAmount(new BN(this.applicationStake)) + .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) + .setApplicationExpiredUnstakingPeriodLength(new BN(1)) + .setRoleStakingPolicyAmount(new BN(this.roleStake)) + .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) + .setRoleExpiredUnstakingPeriodLength(new BN(1)) + .setSlashableMaxCount(new BN(1)) + .setSlashableMaxPercentPtsPerTime(new BN(100)) + .setSuccessfulApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantRoleStakeUnstakingPeriod(new BN(1)) + .setTerminateApplicationStakeUnstakingPeriod(new BN(1)) + .setTerminateRoleStakeUnstakingPeriod(new BN(1)) + .setExitRoleApplicationStakeUnstakingPeriod(new BN(1)) + .setExitRoleStakeUnstakingPeriod(new BN(1)) + .setText(uuid().substring(0, 8)) + .setOpeningType('leader') + + const addOpeningPromise: Promise = this.apiWrapper.expectOpeningAdded() + await this.apiWrapper.sudoAddOpening(this.sudo, opening, this.module) const openingId: BN = await addOpeningPromise - return openingId + + this.result = openingId } - return new BN(-1) } -export async function addLeaderOpening( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - sudo: KeyringPair, - applicationStake: BN, - roleStake: BN, - activationDelay: BN, - module: WorkingGroups -): Promise { - // Leader opening creation - const activateAtBlock: BN | undefined = activationDelay.eqn(0) - ? undefined - : (await apiWrapper.getBestBlock()).add(activationDelay) - const opening = new WorkingGroupOpening() - .setActivateAtBlock(activateAtBlock) - .setMaxActiveApplicants(new BN(membersKeyPairs.length)) - .setMaxReviewPeriodLength(new BN(32)) - .setApplicationStakingPolicyAmount(new BN(applicationStake)) - .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) - .setApplicationExpiredUnstakingPeriodLength(new BN(1)) - .setRoleStakingPolicyAmount(new BN(roleStake)) - .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) - .setRoleExpiredUnstakingPeriodLength(new BN(1)) - .setSlashableMaxCount(new BN(1)) - .setSlashableMaxPercentPtsPerTime(new BN(100)) - .setSuccessfulApplicantApplicationStakeUnstakingPeriod(new BN(1)) - .setFailedApplicantApplicationStakeUnstakingPeriod(new BN(1)) - .setFailedApplicantRoleStakeUnstakingPeriod(new BN(1)) - .setTerminateApplicationStakeUnstakingPeriod(new BN(1)) - .setTerminateRoleStakeUnstakingPeriod(new BN(1)) - .setExitRoleApplicationStakeUnstakingPeriod(new BN(1)) - .setExitRoleStakeUnstakingPeriod(new BN(1)) - .setText(uuid().substring(0, 8)) - .setOpeningType('leader') - - const addOpeningPromise: Promise = apiWrapper.expectOpeningAdded() - await apiWrapper.sudoAddOpening(sudo, opening, module) - const openingId: BN = await addOpeningPromise - - return openingId +export class AcceptApplicationsFixture implements Fixture { + private apiWrapper: ApiWrapper + private lead: KeyringPair + private sudo: KeyringPair + private openingId: BN + private module: WorkingGroups + + public constructor( + apiWrapper: ApiWrapper, + lead: KeyringPair, + sudo: KeyringPair, + openingId: BN, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.lead = lead + this.sudo = sudo + this.openingId = openingId + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const acceptApplicationsFee = this.apiWrapper.estimateAcceptApplicationsFee(this.module) + await this.apiWrapper.transferBalance(this.sudo, this.lead.address, acceptApplicationsFee) + + // Begin accepting applications + await this.apiWrapper.acceptApplications(this.lead, this.openingId, this.module) + + const opening: HiringOpening = await this.apiWrapper.getHiringOpening(this.openingId) + assert(opening.is_active, `Opening ${this.openingId} is not active`) + } } -export async function acceptApplications( - apiWrapper: ApiWrapper, - lead: KeyringPair, - sudo: KeyringPair, - openingId: BN, - module: WorkingGroups -) { - // Fee estimation and transfer - const acceptApplicationsFee = apiWrapper.estimateAcceptApplicationsFee(module) - await apiWrapper.transferBalance(sudo, lead.address, acceptApplicationsFee) - - // Begin accepting applications - await apiWrapper.acceptApplications(lead, openingId, module) - - const opening: HiringOpening = await apiWrapper.getHiringOpening(openingId) - assert(opening.is_active, `Opening ${openingId} is not active`) +export class ApplyForOpeningFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private sudo: KeyringPair + private applicationStake: BN + private roleStake: BN + private openingId: BN + private module: WorkingGroups + private expectFailure: boolean + + public constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + openingId: BN, + module: WorkingGroups, + expectFailure: boolean + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.sudo = sudo + this.applicationStake = applicationStake + this.roleStake = roleStake + this.openingId = openingId + this.module = module + this.expectFailure = expectFailure + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const applyOnOpeningFee: BN = this.apiWrapper + .estimateApplyOnOpeningFee(this.sudo, this.module) + .add(this.applicationStake) + .add(this.roleStake) + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.membersKeyPairs, applyOnOpeningFee) + + // Applying for created worker opening + await this.apiWrapper.batchApplyOnOpening( + this.membersKeyPairs, + this.openingId, + this.roleStake, + this.applicationStake, + uuid().substring(0, 8), + this.module, + this.expectFailure + ) + } } -export async function applyForOpening( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - sudo: KeyringPair, - applicationStake: BN, - roleStake: BN, - openingId: BN, - module: WorkingGroups, - expectFailure: boolean -): Promise { - // Fee estimation and transfer - const applyOnOpeningFee: BN = apiWrapper.estimateApplyOnOpeningFee(sudo, module).add(applicationStake).add(roleStake) - await apiWrapper.transferBalanceToAccounts(sudo, membersKeyPairs, applyOnOpeningFee) - - // Applying for created worker opening - await apiWrapper.batchApplyOnOpening( - membersKeyPairs, - openingId, - roleStake, - applicationStake, - uuid().substring(0, 8), - module, - expectFailure - ) +export class WithdrawApplicationFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private sudo: KeyringPair + private module: WorkingGroups + + constructor(apiWrapper: ApiWrapper, membersKeyPairs: KeyringPair[], sudo: KeyringPair, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const withdrawApplicaitonFee: BN = this.apiWrapper.estimateWithdrawApplicationFee(this.module) + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.membersKeyPairs, withdrawApplicaitonFee) + + // Application withdrawal + await this.apiWrapper.batchWithdrawApplication(this.membersKeyPairs, this.module) + + // Assertions + this.membersKeyPairs.forEach(async (keyPair) => { + const activeApplications: BN[] = await this.apiWrapper.getActiveApplicationsIdsByRoleAccount( + keyPair.address, + this.module + ) + assert(activeApplications.length === 0, `Unexpected active application found for ${keyPair.address}`) + }) + } } -export async function withdrawApplicaiton( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - sudo: KeyringPair, - module: WorkingGroups -) { - // Fee estimation and transfer - const withdrawApplicaitonFee: BN = apiWrapper.estimateWithdrawApplicationFee(module) - await apiWrapper.transferBalanceToAccounts(sudo, membersKeyPairs, withdrawApplicaitonFee) - - // Application withdrawal - await apiWrapper.batchWithdrawApplication(membersKeyPairs, module) - - // Assertions - membersKeyPairs.forEach(async (keyPair) => { - const activeApplications: BN[] = await apiWrapper.getActiveApplicationsIdsByRoleAccount(keyPair.address, module) - assert(activeApplications.length === 0, `Unexpected active application found for ${keyPair.address}`) - }) +export class BeginApplicationReviewFixture implements Fixture { + private apiWrapper: ApiWrapper + private lead: KeyringPair + private sudo: KeyringPair + private openingId: BN + private module: WorkingGroups + + constructor(apiWrapper: ApiWrapper, lead: KeyringPair, sudo: KeyringPair, openingId: BN, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.lead = lead + this.sudo = sudo + this.openingId = openingId + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const beginReviewFee: BN = this.apiWrapper.estimateBeginApplicantReviewFee(this.module) + await this.apiWrapper.transferBalance(this.sudo, this.lead.address, beginReviewFee) + + // Begin application review + const beginApplicantReviewPromise: Promise = this.apiWrapper.expectApplicationReviewBegan() + await this.apiWrapper.beginApplicantReview(this.lead, this.openingId, this.module) + await beginApplicantReviewPromise + } } -export async function beginApplicationReview( - apiWrapper: ApiWrapper, - lead: KeyringPair, - sudo: KeyringPair, - openingId: BN, - module: WorkingGroups -) { - // Fee estimation and transfer - const beginReviewFee: BN = apiWrapper.estimateBeginApplicantReviewFee(module) - await apiWrapper.transferBalance(sudo, lead.address, beginReviewFee) - - // Begin application review - const beginApplicantReviewPromise: Promise = apiWrapper.expectApplicationReviewBegan() - await apiWrapper.beginApplicantReview(lead, openingId, module) - await beginApplicantReviewPromise +export class BeginLeaderApplicationReviewFixture implements Fixture { + private apiWrapper: ApiWrapper + private sudo: KeyringPair + private openingId: BN + private module: WorkingGroups + + constructor(apiWrapper: ApiWrapper, sudo: KeyringPair, openingId: BN, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.sudo = sudo + this.openingId = openingId + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Begin application review + await this.apiWrapper.sudoBeginApplicantReview(this.sudo, this.openingId, this.module) + } } -export async function beginLeaderApplicationReview( - apiWrapper: ApiWrapper, - sudo: KeyringPair, - openingId: BN, - module: WorkingGroups -) { - // Begin application review - await apiWrapper.sudoBeginApplicantReview(sudo, openingId, module) +export class FillOpeningFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private lead: KeyringPair + private sudo: KeyringPair + private openingId: BN + private firstPayoutInterval: BN + private payoutInterval: BN + private amountPerPayout: BN + private module: WorkingGroups + + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + openingId: BN, + firstPayoutInterval: BN, + payoutInterval: BN, + amountPerPayout: BN, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.lead = lead + this.sudo = sudo + this.openingId = openingId + this.firstPayoutInterval = firstPayoutInterval + this.payoutInterval = payoutInterval + this.amountPerPayout = amountPerPayout + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const beginReviewFee: BN = this.apiWrapper.estimateBeginApplicantReviewFee(this.module) + await this.apiWrapper.transferBalance(this.sudo, this.lead.address, beginReviewFee) + const applicationIds: BN[] = ( + await Promise.all( + this.membersKeyPairs.map(async (keypair) => + this.apiWrapper.getActiveApplicationsIdsByRoleAccount(keypair.address, this.module) + ) + ) + ).flat() + + // Fill worker opening + const now: BN = await this.apiWrapper.getBestBlock() + const fillOpeningPromise: Promise = this.apiWrapper.expectOpeningFilled() + await this.apiWrapper.fillOpening( + this.lead, + this.openingId, + applicationIds, + this.amountPerPayout, + now.add(this.firstPayoutInterval), + this.payoutInterval, + this.module + ) + const applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap = await fillOpeningPromise + + // Assertions + applicationIdToWorkerIdMap.forEach(async (workerId, applicationId) => { + const worker: Worker = await this.apiWrapper.getWorkerById(workerId, this.module) + const application: Application = await this.apiWrapper.getApplicationById(applicationId, this.module) + assert( + worker.role_account_id.toString() === application.role_account_id.toString(), + `Role account ids does not match, worker account: ${worker.role_account_id}, application account ${application.role_account_id}` + ) + }) + const openingWorkersAccounts: string[] = (await this.apiWrapper.getWorkers(this.module)).map((worker) => + worker.role_account_id.toString() + ) + this.membersKeyPairs.forEach((keyPair) => + assert(openingWorkersAccounts.includes(keyPair.address), `Account ${keyPair.address} is not worker`) + ) + } } -export async function fillOpening( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - lead: KeyringPair, - sudo: KeyringPair, - openingId: BN, - firstPayoutInterval: BN, - payoutInterval: BN, - amountPerPayout: BN, - module: WorkingGroups -) { - // Fee estimation and transfer - const beginReviewFee: BN = apiWrapper.estimateBeginApplicantReviewFee(module) - await apiWrapper.transferBalance(sudo, lead.address, beginReviewFee) - const applicationIds: BN[] = ( - await Promise.all( - membersKeyPairs.map(async (keypair) => apiWrapper.getActiveApplicationsIdsByRoleAccount(keypair.address, module)) +export class FillLeaderOpeningFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private sudo: KeyringPair + private openingId: BN + private firstPayoutInterval: BN + private payoutInterval: BN + private amountPerPayout: BN + private module: WorkingGroups + + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + sudo: KeyringPair, + openingId: BN, + firstPayoutInterval: BN, + payoutInterval: BN, + amountPerPayout: BN, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.sudo = sudo + this.openingId = openingId + this.firstPayoutInterval = firstPayoutInterval + this.payoutInterval = payoutInterval + this.amountPerPayout = amountPerPayout + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + const applicationIds: BN[] = ( + await Promise.all( + this.membersKeyPairs.map(async (keypair) => + this.apiWrapper.getActiveApplicationsIdsByRoleAccount(keypair.address, this.module) + ) + ) + ).flat() + + // Fill leader opening + const now: BN = await this.apiWrapper.getBestBlock() + const fillOpeningPromise: Promise = this.apiWrapper.expectOpeningFilled() + await this.apiWrapper.sudoFillOpening( + this.sudo, + this.openingId, + applicationIds, + this.amountPerPayout, + now.add(this.firstPayoutInterval), + this.payoutInterval, + this.module ) - ).flat() - - // Fill worker opening - const now: BN = await apiWrapper.getBestBlock() - const fillOpeningPromise: Promise = apiWrapper.expectOpeningFilled() - await apiWrapper.fillOpening( - lead, - openingId, - applicationIds, - amountPerPayout, - now.add(firstPayoutInterval), - payoutInterval, - module - ) - const applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap = await fillOpeningPromise - - // Assertions - applicationIdToWorkerIdMap.forEach(async (workerId, applicationId) => { - const worker: Worker = await apiWrapper.getWorkerById(workerId, module) - const application: Application = await apiWrapper.getApplicationById(applicationId, module) + + // Assertions + const applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap = await fillOpeningPromise + applicationIdToWorkerIdMap.forEach(async (workerId, applicationId) => { + const worker: Worker = await this.apiWrapper.getWorkerById(workerId, this.module) + const application: Application = await this.apiWrapper.getApplicationById(applicationId, this.module) + assert( + worker.role_account_id.toString() === application.role_account_id.toString(), + `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}` + ) + }) + const leadWorkerId: BN = (await this.apiWrapper.getLeadWorkerId(this.module))! + const openingLeaderAccount: string = ( + await this.apiWrapper.getWorkerById(leadWorkerId, this.module) + ).role_account_id.toString() assert( - worker.role_account_id.toString() === application.role_account_id.toString(), - `Role account ids does not match, worker account: ${worker.role_account_id}, application account ${application.role_account_id}` + openingLeaderAccount === this.membersKeyPairs[0].address, + `Unexpected leader account ${openingLeaderAccount}, expected ${this.membersKeyPairs[0].address}` ) - }) - const openingWorkersAccounts: string[] = (await apiWrapper.getWorkers(module)).map((worker) => - worker.role_account_id.toString() - ) - membersKeyPairs.forEach((keyPair) => - assert(openingWorkersAccounts.includes(keyPair.address), `Account ${keyPair.address} is not worker`) - ) + } } -export async function fillLeaderOpening( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - sudo: KeyringPair, - openingId: BN, - firstPayoutInterval: BN, - payoutInterval: BN, - amountPerPayout: BN, - module: WorkingGroups -) { - const applicationIds: BN[] = ( - await Promise.all( - membersKeyPairs.map(async (keypair) => apiWrapper.getActiveApplicationsIdsByRoleAccount(keypair.address, module)) +export class IncreaseStakeFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private sudo: KeyringPair + private module: WorkingGroups + + constructor(apiWrapper: ApiWrapper, membersKeyPairs: KeyringPair[], sudo: KeyringPair, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const increaseStakeFee: BN = this.apiWrapper.estimateIncreaseStakeFee(this.module) + const stakeIncrement: BN = new BN(1) + await this.apiWrapper.transferBalance( + this.sudo, + this.membersKeyPairs[0].address, + increaseStakeFee.add(stakeIncrement) ) - ).flat() - - // Fill leader opening - const now: BN = await apiWrapper.getBestBlock() - const fillOpeningPromise: Promise = apiWrapper.expectOpeningFilled() - await apiWrapper.sudoFillOpening( - sudo, - openingId, - applicationIds, - amountPerPayout, - now.add(firstPayoutInterval), - payoutInterval, - module - ) - - // Assertions - const applicationIdToWorkerIdMap: ApplicationIdToWorkerIdMap = await fillOpeningPromise - applicationIdToWorkerIdMap.forEach(async (workerId, applicationId) => { - const worker: Worker = await apiWrapper.getWorkerById(workerId, module) - const application: Application = await apiWrapper.getApplicationById(applicationId, module) + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + + // Increase worker stake + const increasedWorkerStake: BN = (await this.apiWrapper.getWorkerStakeAmount(workerId, this.module)).add( + stakeIncrement + ) + await this.apiWrapper.increaseStake(this.membersKeyPairs[0], workerId, stakeIncrement, this.module) + const newWorkerStake: BN = await this.apiWrapper.getWorkerStakeAmount(workerId, this.module) assert( - worker.role_account_id.toString() === application.role_account_id.toString(), - `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}` + increasedWorkerStake.eq(newWorkerStake), + `Unexpected worker stake ${newWorkerStake}, expected ${increasedWorkerStake}` ) - }) - const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! - const openingLeaderAccount: string = (await apiWrapper.getWorkerById(leadWorkerId, module)).role_account_id.toString() - assert( - openingLeaderAccount === membersKeyPairs[0].address, - `Unexpected leader account ${openingLeaderAccount}, expected ${membersKeyPairs[0].address}` - ) + } } -export async function increaseStake( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - sudo: KeyringPair, - module: WorkingGroups -) { - // Fee estimation and transfer - const increaseStakeFee: BN = apiWrapper.estimateIncreaseStakeFee(module) - const stakeIncrement: BN = new BN(1) - await apiWrapper.transferBalance(sudo, membersKeyPairs[0].address, increaseStakeFee.add(stakeIncrement)) - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - - // Increase worker stake - const increasedWorkerStake: BN = (await apiWrapper.getWorkerStakeAmount(workerId, module)).add(stakeIncrement) - await apiWrapper.increaseStake(membersKeyPairs[0], workerId, stakeIncrement, module) - const newWorkerStake: BN = await apiWrapper.getWorkerStakeAmount(workerId, module) - assert( - increasedWorkerStake.eq(newWorkerStake), - `Unexpected worker stake ${newWorkerStake}, expected ${increasedWorkerStake}` - ) -} +export class UpdateRewardAccountFixture implements Fixture { + public apiWrapper: ApiWrapper + public membersKeyPairs: KeyringPair[] + public keyring: Keyring + public sudo: KeyringPair + public module: WorkingGroups -export async function updateRewardAccount( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - keyring: Keyring, - sudo: KeyringPair, - module: WorkingGroups -) { - // Fee estimation and transfer - const updateRewardAccountFee: BN = apiWrapper.estimateUpdateRewardAccountFee(sudo.address, module) - await apiWrapper.transferBalance(sudo, membersKeyPairs[0].address, updateRewardAccountFee) - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - - // Update reward account - const createdAccount: KeyringPair = keyring.addFromUri(uuid().substring(0, 8)) - await apiWrapper.updateRewardAccount(membersKeyPairs[0], workerId, createdAccount.address, module) - const newRewardAccount: string = await apiWrapper.getWorkerRewardAccount(workerId, module) - assert( - newRewardAccount === createdAccount.address, - `Unexpected role account ${newRewardAccount}, expected ${createdAccount.address}` - ) -} + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + keyring: Keyring, + sudo: KeyringPair, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.keyring = keyring + this.sudo = sudo + this.module = module + } -export async function updateRoleAccount( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - keyring: Keyring, - sudo: KeyringPair, - module: WorkingGroups -) { - // Fee estimation and transfer - const updateRoleAccountFee: BN = apiWrapper.estimateUpdateRoleAccountFee(sudo.address, module) - await apiWrapper.transferBalance(sudo, membersKeyPairs[0].address, updateRoleAccountFee) - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - - // Update role account - const createdAccount: KeyringPair = keyring.addFromUri(uuid().substring(0, 8)) - await apiWrapper.updateRoleAccount(membersKeyPairs[0], workerId, createdAccount.address, module) - const newRoleAccount: string = (await apiWrapper.getWorkerById(workerId, module)).role_account_id.toString() - assert( - newRoleAccount === createdAccount.address, - `Unexpected role account ${newRoleAccount}, expected ${createdAccount.address}` - ) - - membersKeyPairs[0] = createdAccount -} + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const updateRewardAccountFee: BN = this.apiWrapper.estimateUpdateRewardAccountFee(this.sudo.address, this.module) + await this.apiWrapper.transferBalance(this.sudo, this.membersKeyPairs[0].address, updateRewardAccountFee) + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) -export async function terminateApplications( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - lead: KeyringPair, - sudo: KeyringPair, - module: WorkingGroups -) { - // Fee estimation and transfer - const terminateApplicationFee = apiWrapper.estimateTerminateApplicationFee(module) - await apiWrapper.transferBalance(sudo, lead.address, terminateApplicationFee.muln(membersKeyPairs.length)) - - // Terminate worker applications - await apiWrapper.batchTerminateApplication(lead, membersKeyPairs, module) - membersKeyPairs.forEach(async (keyPair) => { - const activeApplications = await apiWrapper.getActiveApplicationsIdsByRoleAccount(keyPair.address, module) - assert(activeApplications.length === 0, `Account ${keyPair.address} has unexpected active applications`) - }) + // Update reward account + const createdAccount: KeyringPair = this.keyring.addFromUri(uuid().substring(0, 8)) + await this.apiWrapper.updateRewardAccount(this.membersKeyPairs[0], workerId, createdAccount.address, this.module) + const newRewardAccount: string = await this.apiWrapper.getWorkerRewardAccount(workerId, this.module) + assert( + newRewardAccount === createdAccount.address, + `Unexpected role account ${newRewardAccount}, expected ${createdAccount.address}` + ) + } } -export async function decreaseStake( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - lead: KeyringPair, - sudo: KeyringPair, - module: WorkingGroups, - expectFailure: boolean -) { - // Fee estimation and transfer - const decreaseStakeFee = apiWrapper.estimateDecreaseStakeFee(module) - await apiWrapper.transferBalance(sudo, lead.address, decreaseStakeFee) - const workerStakeDecrement = new BN(1) - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - - // Worker stake decrement - const decreasedWorkerStake: BN = (await apiWrapper.getWorkerStakeAmount(workerId, module)).sub(workerStakeDecrement) - await apiWrapper.decreaseStake(lead, workerId, workerStakeDecrement, module, expectFailure) - const newWorkerStake: BN = await apiWrapper.getWorkerStakeAmount(workerId, module) - - // Assertions - if (!expectFailure) { +export class UpdateRoleAccountFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private keyring: Keyring + private sudo: KeyringPair + private module: WorkingGroups + + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + keyring: Keyring, + sudo: KeyringPair, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.keyring = keyring + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const updateRoleAccountFee: BN = this.apiWrapper.estimateUpdateRoleAccountFee(this.sudo.address, this.module) + await this.apiWrapper.transferBalance(this.sudo, this.membersKeyPairs[0].address, updateRoleAccountFee) + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + + // Update role account + const createdAccount: KeyringPair = this.keyring.addFromUri(uuid().substring(0, 8)) + await this.apiWrapper.updateRoleAccount(this.membersKeyPairs[0], workerId, createdAccount.address, this.module) + const newRoleAccount: string = ( + await this.apiWrapper.getWorkerById(workerId, this.module) + ).role_account_id.toString() assert( - decreasedWorkerStake.eq(newWorkerStake), - `Unexpected worker stake ${newWorkerStake}, expected ${decreasedWorkerStake}` + newRoleAccount === createdAccount.address, + `Unexpected role account ${newRoleAccount}, expected ${createdAccount.address}` ) + + this.membersKeyPairs[0] = createdAccount } } -export async function slash( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - lead: KeyringPair, - sudo: KeyringPair, - module: WorkingGroups, - expectFailure: boolean -) { - // Fee estimation and transfer - const slashStakeFee = apiWrapper.estimateSlashStakeFee(module) - await apiWrapper.transferBalance(sudo, lead.address, slashStakeFee) - const slashAmount = new BN(1) - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - - // Slash worker - const slashedStake: BN = (await apiWrapper.getWorkerStakeAmount(workerId, module)).sub(slashAmount) - await apiWrapper.slashStake(lead, workerId, slashAmount, module, expectFailure) - const newStake: BN = await apiWrapper.getWorkerStakeAmount(workerId, module) - - // Assertions - assert(slashedStake.eq(newStake), `Unexpected worker stake ${newStake}, expected ${slashedStake}`) +export class TerminateApplicationsFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private lead: KeyringPair + private sudo: KeyringPair + private module: WorkingGroups + + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.lead = lead + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const terminateApplicationFee = this.apiWrapper.estimateTerminateApplicationFee(this.module) + await this.apiWrapper.transferBalance( + this.sudo, + this.lead.address, + terminateApplicationFee.muln(this.membersKeyPairs.length) + ) + + // Terminate worker applications + await this.apiWrapper.batchTerminateApplication(this.lead, this.membersKeyPairs, this.module) + this.membersKeyPairs.forEach(async (keyPair) => { + const activeApplications = await this.apiWrapper.getActiveApplicationsIdsByRoleAccount( + keyPair.address, + this.module + ) + assert(activeApplications.length === 0, `Account ${keyPair.address} has unexpected active applications`) + }) + } } -export async function terminateRole( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - lead: KeyringPair, - sudo: KeyringPair, - module: WorkingGroups, - expectFailure: boolean -) { - // Fee estimation and transfer - const terminateRoleFee = apiWrapper.estimateTerminateRoleFee(module) - await apiWrapper.transferBalance(sudo, lead.address, terminateRoleFee) - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - - // Slash worker - await apiWrapper.terminateRole(lead, workerId, uuid().substring(0, 8), module, expectFailure) - - // Assertions - apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - const newWorkerId = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - assert(newWorkerId === undefined, `Worker with account ${membersKeyPairs[0].address} is not terminated`) +export class DecreaseStakeFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private lead: KeyringPair + private sudo: KeyringPair + private module: WorkingGroups + + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups, + expectFailure: boolean + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.lead = lead + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const decreaseStakeFee = this.apiWrapper.estimateDecreaseStakeFee(this.module) + await this.apiWrapper.transferBalance(this.sudo, this.lead.address, decreaseStakeFee) + const workerStakeDecrement = new BN(1) + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + + // Worker stake decrement + const decreasedWorkerStake: BN = (await this.apiWrapper.getWorkerStakeAmount(workerId, this.module)).sub( + workerStakeDecrement + ) + await this.apiWrapper.decreaseStake(this.lead, workerId, workerStakeDecrement, this.module, expectFailure) + const newWorkerStake: BN = await this.apiWrapper.getWorkerStakeAmount(workerId, this.module) + + // Assertions + if (!expectFailure) { + assert( + decreasedWorkerStake.eq(newWorkerStake), + `Unexpected worker stake ${newWorkerStake}, expected ${decreasedWorkerStake}` + ) + } + } } -export async function leaveRole( - apiWrapper: ApiWrapper, - membersKeyPairs: KeyringPair[], - sudo: KeyringPair, - module: WorkingGroups -) { - // Fee estimation and transfer - const leaveRoleFee = apiWrapper.estimateLeaveRoleFee(module) - await apiWrapper.transferBalanceToAccounts(sudo, membersKeyPairs, leaveRoleFee) - - await apiWrapper.batchLeaveRole(membersKeyPairs, uuid().substring(0, 8), false, module) - - // Assertions - membersKeyPairs.forEach(async (keyPair) => { - apiWrapper.getWorkerIdByRoleAccount(keyPair.address, module) - const newWorkerId = await apiWrapper.getWorkerIdByRoleAccount(keyPair.address, module) - assert(newWorkerId === undefined, `Worker with account ${keyPair.address} is not terminated`) - }) +export class SlashFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private lead: KeyringPair + private sudo: KeyringPair + private module: WorkingGroups + + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.lead = lead + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const slashStakeFee = this.apiWrapper.estimateSlashStakeFee(this.module) + await this.apiWrapper.transferBalance(this.sudo, this.lead.address, slashStakeFee) + const slashAmount = new BN(1) + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + + // Slash worker + const slashedStake: BN = (await this.apiWrapper.getWorkerStakeAmount(workerId, this.module)).sub(slashAmount) + await this.apiWrapper.slashStake(this.lead, workerId, slashAmount, this.module, expectFailure) + const newStake: BN = await this.apiWrapper.getWorkerStakeAmount(workerId, this.module) + + // Assertions + assert(slashedStake.eq(newStake), `Unexpected worker stake ${newStake}, expected ${slashedStake}`) + } } -export async function awaitPayout(apiWrapper: ApiWrapper, membersKeyPairs: KeyringPair[], module: WorkingGroups) { - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(membersKeyPairs[0].address, module) - const worker: Worker = await apiWrapper.getWorkerById(workerId, module) - const reward: RewardRelationship = await apiWrapper.getRewardRelationship(worker.reward_relationship.unwrap()) - const now: BN = await apiWrapper.getBestBlock() - const nextPaymentBlock: BN = new BN(reward.getField('next_payment_at_block').toString()) - const payoutInterval: BN = new BN(reward.getField('payout_interval').toString()) - const amountPerPayout: BN = new BN(reward.getField('amount_per_payout').toString()) - - assert(now.lt(nextPaymentBlock), `Payout already happened in block ${nextPaymentBlock} now ${now}`) - const balance = await apiWrapper.getBalance(membersKeyPairs[0].address) - - const firstPayoutWaitingPeriod = nextPaymentBlock.sub(now).addn(1) - await Utils.wait(apiWrapper.getBlockDuration().mul(firstPayoutWaitingPeriod).toNumber()) - - const balanceAfterFirstPayout = await apiWrapper.getBalance(membersKeyPairs[0].address) - const expectedBalanceFirst = balance.add(amountPerPayout) - assert( - balanceAfterFirstPayout.eq(expectedBalanceFirst), - `Unexpected balance, expected ${expectedBalanceFirst} got ${balanceAfterFirstPayout}` - ) - - const secondPayoutWaitingPeriod = payoutInterval.addn(1) - await Utils.wait(apiWrapper.getBlockDuration().mul(secondPayoutWaitingPeriod).toNumber()) - - const balanceAfterSecondPayout = await apiWrapper.getBalance(membersKeyPairs[0].address) - const expectedBalanceSecond = expectedBalanceFirst.add(amountPerPayout) - assert( - balanceAfterSecondPayout.eq(expectedBalanceSecond), - `Unexpected balance, expected ${expectedBalanceSecond} got ${balanceAfterSecondPayout}` - ) +export class TerminateRoleFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private lead: KeyringPair + private sudo: KeyringPair + private module: WorkingGroups + + constructor( + apiWrapper: ApiWrapper, + membersKeyPairs: KeyringPair[], + lead: KeyringPair, + sudo: KeyringPair, + module: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.lead = lead + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const terminateRoleFee = this.apiWrapper.estimateTerminateRoleFee(this.module) + await this.apiWrapper.transferBalance(this.sudo, this.lead.address, terminateRoleFee) + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + + // Slash worker + await this.apiWrapper.terminateRole(this.lead, workerId, uuid().substring(0, 8), this.module, expectFailure) + + // Assertions + this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + const newWorkerId = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + assert(newWorkerId === undefined, `Worker with account ${this.membersKeyPairs[0].address} is not terminated`) + } } -export async function setMintCapacity(apiWrapper: ApiWrapper, sudo: KeyringPair, capacity: BN, module: WorkingGroups) { - await apiWrapper.sudoSetWorkingGroupMintCapacity(sudo, capacity, module) +export class LeaveRoleFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private sudo: KeyringPair + private module: WorkingGroups + + constructor(apiWrapper: ApiWrapper, membersKeyPairs: KeyringPair[], sudo: KeyringPair, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.sudo = sudo + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + // Fee estimation and transfer + const leaveRoleFee = this.apiWrapper.estimateLeaveRoleFee(this.module) + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.membersKeyPairs, leaveRoleFee) + + await this.apiWrapper.batchLeaveRole(this.membersKeyPairs, uuid().substring(0, 8), false, this.module) + + // Assertions + this.membersKeyPairs.forEach(async (keyPair) => { + this.apiWrapper.getWorkerIdByRoleAccount(keyPair.address, this.module) + const newWorkerId = await this.apiWrapper.getWorkerIdByRoleAccount(keyPair.address, this.module) + assert(newWorkerId === undefined, `Worker with account ${keyPair.address} is not terminated`) + }) + } } -export async function expectLeadOpeningAdded(apiWrapper: ApiWrapper): Promise { - return apiWrapper.expectOpeningAdded() +export class AwaitPayoutFixture implements Fixture { + private apiWrapper: ApiWrapper + private membersKeyPairs: KeyringPair[] + private module: WorkingGroups + + constructor(apiWrapper: ApiWrapper, membersKeyPairs: KeyringPair[], module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.membersKeyPairs = membersKeyPairs + this.module = module + } + + public async runner(expectFailure: boolean): Promise { + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount(this.membersKeyPairs[0].address, this.module) + const worker: Worker = await this.apiWrapper.getWorkerById(workerId, this.module) + const reward: RewardRelationship = await this.apiWrapper.getRewardRelationship(worker.reward_relationship.unwrap()) + const now: BN = await this.apiWrapper.getBestBlock() + const nextPaymentBlock: BN = new BN(reward.getField('next_payment_at_block').toString()) + const payoutInterval: BN = new BN(reward.getField('payout_interval').toString()) + const amountPerPayout: BN = new BN(reward.getField('amount_per_payout').toString()) + + assert(now.lt(nextPaymentBlock), `Payout already happened in block ${nextPaymentBlock} now ${now}`) + const balance = await this.apiWrapper.getBalance(this.membersKeyPairs[0].address) + + const firstPayoutWaitingPeriod = nextPaymentBlock.sub(now).addn(1) + await Utils.wait(this.apiWrapper.getBlockDuration().mul(firstPayoutWaitingPeriod).toNumber()) + + const balanceAfterFirstPayout = await this.apiWrapper.getBalance(this.membersKeyPairs[0].address) + const expectedBalanceFirst = balance.add(amountPerPayout) + assert( + balanceAfterFirstPayout.eq(expectedBalanceFirst), + `Unexpected balance, expected ${expectedBalanceFirst} got ${balanceAfterFirstPayout}` + ) + + const secondPayoutWaitingPeriod = payoutInterval.addn(1) + await Utils.wait(this.apiWrapper.getBlockDuration().mul(secondPayoutWaitingPeriod).toNumber()) + + const balanceAfterSecondPayout = await this.apiWrapper.getBalance(this.membersKeyPairs[0].address) + const expectedBalanceSecond = expectedBalanceFirst.add(amountPerPayout) + assert( + balanceAfterSecondPayout.eq(expectedBalanceSecond), + `Unexpected balance, expected ${expectedBalanceSecond} got ${balanceAfterSecondPayout}` + ) + } } -export async function expectLeaderSet( - apiWrapper: ApiWrapper, - leaderAddress: string, - module: WorkingGroups -): Promise { - const leadWorkerId: BN = await apiWrapper.expectLeaderSet() - const worker: Worker = await apiWrapper.getWorkerById(leadWorkerId, module) - const leaderApplicationId = (await apiWrapper.getApplicationsIdsByRoleAccount(leaderAddress, module))[0] - const application: Application = await apiWrapper.getApplicationById(leaderApplicationId, module) - assert( - worker.role_account_id.eq(application.role_account_id), - `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}` - ) - return leadWorkerId +// export class SetMintCapacityFixture implements Fixture { +// private apiWrapper: ApiWrapper +// private sudo: KeyringPair +// private capacity: BN +// private module: WorkingGroups +// +// constructor(apiWrapper: ApiWrapper, sudo: KeyringPair, capacity:, module: WorkingGroups) { +// this.apiWrapper = apiWrapper; +// this.sudo = sudo; +// this.capacity = capacity; +// this.module = module; +// } +// +// public async runner(expectFailure: boolean): Promise { +// await this.apiWrapper.sudoSetWorkingGroupMintCapacity(this.sudo, this.capacity, this.module) +// } +// +// } + +export class ExpectLeadOpeningAddedFixture implements Fixture { + private apiWrapper: ApiWrapper + + // Opening id + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper) { + this.apiWrapper = apiWrapper + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('OpeningAdded') + this.events.push(event) + this.result = (event.data as unknown) as BN + } } -export async function expectBeganApplicationReview(apiWrapper: ApiWrapper): Promise { - return apiWrapper.expectApplicationReviewBegan() +export class ExpectLeaderSetFixture implements Fixture { + private apiWrapper: ApiWrapper + private leaderAddress: string + private module: WorkingGroups + + // Lead worker id + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper, leaderAddress: string, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.leaderAddress = leaderAddress + this.module = module + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('LeaderSet') + this.events.push(event) + const leadWorkerId: BN = (event.data as unknown) as BN + const worker: Worker = await this.apiWrapper.getWorkerById(leadWorkerId, this.module) + const leaderApplicationId = ( + await this.apiWrapper.getApplicationsIdsByRoleAccount(this.leaderAddress, this.module) + )[0] + const application: Application = await this.apiWrapper.getApplicationById(leaderApplicationId, this.module) + assert( + worker.role_account_id.eq(application.role_account_id), + `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}` + ) + this.result = leadWorkerId + } } -export async function expectLeaderRoleTerminated(apiWrapper: ApiWrapper, module: WorkingGroups): Promise { - await apiWrapper.expectLeaderTerminated() - const leadWorkerId: BN | undefined = await apiWrapper.getLeadWorkerId(module) - assert(leadWorkerId === undefined, `Unexpected lead worker id: ${leadWorkerId}, expected none`) - return +export class ExpectBeganApplicationReview implements Fixture { + private apiWrapper: ApiWrapper + + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper) { + this.apiWrapper = apiWrapper + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('BeganApplicationReview') + this.events.push(event) + this.result = (event.data as unknown) as BN + } } -export async function expectLeaderRewardAmountUpdated( - apiWrapper: ApiWrapper, - expectedReward: BN, - module: WorkingGroups -): Promise { - await apiWrapper.expectWorkerRewardAmountUpdated() - const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! - const receivedReward: BN = (await apiWrapper.getRewardRelationship(leadWorkerId)).getField( - 'amount_per_payout' - ) - assert( - receivedReward.eq(expectedReward), - `Unexpected reward amount for worker with id ${leadWorkerId}: ${receivedReward}, expected ${expectedReward}` - ) - return +export class ExpectLeaderRoleTerminatedFixture implements Fixture { + private apiWrapper: ApiWrapper + private module: WorkingGroups + + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.module = module + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('TerminatedLeader') + this.events.push(event) + const leadWorkerId: BN | undefined = await this.apiWrapper.getLeadWorkerId(this.module) + assert(leadWorkerId === undefined, `Unexpected lead worker id: ${leadWorkerId}, expected none`) + } +} + +export class ExpectLeaderRewardAmountUpdatedFixture implements Fixture { + private apiWrapper: ApiWrapper + private expectedReward: BN + private module: WorkingGroups + + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper, expectedReward: BN, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.expectedReward = expectedReward + this.module = module + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('WorkerRewardAmountUpdated') + this.events.push(event) + const leadWorkerId: BN = (await this.apiWrapper.getLeadWorkerId(this.module))! + const receivedReward: BN = (await this.apiWrapper.getRewardRelationship(leadWorkerId)).getField( + 'amount_per_payout' + ) + assert( + receivedReward.eq(this.expectedReward), + `Unexpected reward amount for worker with id ${leadWorkerId}: ${receivedReward}, expected ${this.expectedReward}` + ) + } } -export async function expectLeaderStakeDecreased( - apiWrapper: ApiWrapper, - expectedStake: BN, - module: WorkingGroups -): Promise { - await apiWrapper.expectWorkerStakeDecreased() - const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! - const receivedStake: BN = await apiWrapper.getWorkerStakeAmount(leadWorkerId, module) - assert( - receivedStake.eq(expectedStake), - `Unexpected stake amount for worker with id ${leadWorkerId}: ${receivedStake}, expected ${expectedStake}` - ) - return +export class ExpectLeaderStakeDecreasedFixture implements Fixture { + private apiWrapper: ApiWrapper + private expectedStake: BN + private module: WorkingGroups + + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper, expectedStake: BN, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.expectedStake = expectedStake + this.module = module + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('StakeDecreased') + this.events.push(event) + const leadWorkerId: BN = (await this.apiWrapper.getLeadWorkerId(this.module))! + const receivedStake: BN = await this.apiWrapper.getWorkerStakeAmount(leadWorkerId, this.module) + assert( + receivedStake.eq(this.expectedStake), + `Unexpected stake amount for worker with id ${leadWorkerId}: ${receivedStake}, expected ${this.expectedStake}` + ) + } } -export async function expectLeaderSlashed( - apiWrapper: ApiWrapper, - expectedStake: BN, - module: WorkingGroups -): Promise { - await apiWrapper.expectWorkerStakeSlashed() - const leadWorkerId: BN = (await apiWrapper.getLeadWorkerId(module))! - const receivedStake: BN = await apiWrapper.getWorkerStakeAmount(leadWorkerId, module) - assert( - receivedStake.eq(expectedStake), - `Unexpected stake amount for worker with id after slash ${leadWorkerId}: ${receivedStake}, expected ${expectedStake}` - ) - return +export class ExpectLeaderSlashedFixture implements Fixture { + private apiWrapper: ApiWrapper + private expectedStake: BN + private module: WorkingGroups + + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper, expectedStake: BN, module: WorkingGroups) { + this.apiWrapper = apiWrapper + this.expectedStake = expectedStake + this.module = module + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('StakeSlashed') + this.events.push(event) + const leadWorkerId: BN = (await this.apiWrapper.getLeadWorkerId(this.module))! + const receivedStake: BN = await this.apiWrapper.getWorkerStakeAmount(leadWorkerId, this.module) + assert( + receivedStake.eq(this.expectedStake), + `Unexpected stake amount for worker with id after slash ${leadWorkerId}: ${receivedStake}, expected ${this.expectedStake}` + ) + } } -export async function expectMintCapacityChanged(apiWrapper: ApiWrapper, expectedMintCapacity: BN): Promise { - const receivedMintCapacity = await apiWrapper.expectMintCapacityChanged() - assert( - receivedMintCapacity.eq(expectedMintCapacity), - `Unexpected mint capacity: ${receivedMintCapacity}, expected ${expectedMintCapacity}` - ) - return +export class ExpectMintCapacityChanged implements Fixture { + private apiWrapper: ApiWrapper + private expectedMintCapacity: BN + + private result: BN | undefined + private events: Event[] = [] + + constructor(apiWrapper: ApiWrapper, expectedMintCapacity: BN) { + this.apiWrapper = apiWrapper + this.expectedMintCapacity = expectedMintCapacity + } + + public getResult(): BN | undefined { + return this.result + } + + public getEvents(): Event[] { + return this.events + } + + public async runner(expectFailure: boolean): Promise { + const event: Event = await this.apiWrapper.expectEvent('MintCapacityChanged') + this.events.push(event) + const receivedMintCapacity = (event.data[1] as unknown) as BN + assert( + receivedMintCapacity.eq(this.expectedMintCapacity), + `Unexpected mint capacity: ${receivedMintCapacity}, expected ${this.expectedMintCapacity}` + ) + this.result = receivedMintCapacity + } } diff --git a/tests/network-tests/src/iznik/utils/apiWrapper.ts b/tests/network-tests/src/iznik/utils/apiWrapper.ts index e64b421a85..52682fb567 100644 --- a/tests/network-tests/src/iznik/utils/apiWrapper.ts +++ b/tests/network-tests/src/iznik/utils/apiWrapper.ts @@ -8,7 +8,7 @@ import { Lead, LeadId } from '@nicaea/types/content-working-group' import { Application, WorkerId, Worker, ApplicationIdToWorkerIdMap, Opening } from '@nicaea/types/working-group' import { RoleParameters } from '@nicaea/types/roles' import { Seat } from '@nicaea/types/council' -import { Balance, EventRecord, AccountId, BlockNumber, BalanceOf } from '@polkadot/types/interfaces' +import { Balance, Event, EventRecord, AccountId, BlockNumber, BalanceOf } from '@polkadot/types/interfaces' import BN from 'bn.js' import { SubmittableExtrinsic } from '@polkadot/api/types' import { Sender } from './sender' @@ -853,78 +853,13 @@ export class ApiWrapper { }) } - public expectOpeningAdded(): Promise { + public expectEvent(eventName: string): Promise { return new Promise(async (resolve) => { const unsubscribe = await this.api.query.system.events>((events) => { events.forEach((record) => { - if (record.event.method && record.event.method.toString() === 'OpeningAdded') { + if (record.event.method && record.event.method.toString() === eventName) { unsubscribe() - resolve((record.event.data as unknown) as BN) - } - }) - }) - }) - } - - public expectLeaderSet(): Promise { - return new Promise(async (resolve) => { - const unsubscribe = await this.api.query.system.events>((events) => { - events.forEach((record) => { - if (record.event.method && record.event.method.toString() === 'LeaderSet') { - unsubscribe() - resolve((record.event.data as unknown) as BN) - } - }) - }) - }) - } - - public expectLeaderTerminated(): Promise { - return new Promise(async (resolve) => { - const unsubscribe = await this.api.query.system.events>((events) => { - events.forEach((record) => { - if (record.event.method && record.event.method.toString() === 'TerminatedLeader') { - unsubscribe() - resolve() - } - }) - }) - }) - } - - public expectWorkerRewardAmountUpdated(): Promise { - return new Promise(async (resolve) => { - const unsubscribe = await this.api.query.system.events>((events) => { - events.forEach((record) => { - if (record.event.method && record.event.method.toString() === 'WorkerRewardAmountUpdated') { - unsubscribe() - resolve() - } - }) - }) - }) - } - - public expectWorkerStakeDecreased(): Promise { - return new Promise(async (resolve) => { - const unsubscribe = await this.api.query.system.events>((events) => { - events.forEach((record) => { - if (record.event.method && record.event.method.toString() === 'StakeDecreased') { - unsubscribe() - resolve() - } - }) - }) - }) - } - - public expectWorkerStakeSlashed(): Promise { - return new Promise(async (resolve) => { - const unsubscribe = await this.api.query.system.events>((events) => { - events.forEach((record) => { - if (record.event.method && record.event.method.toString() === 'StakeSlashed') { - unsubscribe() - resolve() + resolve(record.event) } }) }) @@ -944,19 +879,6 @@ export class ApiWrapper { }) } - public expectMintCapacityChanged(): Promise { - return new Promise(async (resolve) => { - const unsubscribe = await this.api.query.system.events>((events) => { - events.forEach((record) => { - if (record.event.method && record.event.method.toString() === 'MintCapacityChanged') { - unsubscribe() - resolve((record.event.data[1] as unknown) as BN) - } - }) - }) - }) - } - public getTotalIssuance(): Promise { return this.api.query.balances.totalIssuance() } From 57d098665db21a4a7742116019d60124b936e83a Mon Sep 17 00:00:00 2001 From: Gleb Urvanov Date: Tue, 28 Jul 2020 17:38:17 +0200 Subject: [PATCH 5/6] proposals and working group fixtures refactored --- tests/network-tests/package.json | 2 +- .../src/iznik/tests/impl/electingCouncil.ts | 100 -- .../iznik/tests/impl/membershipCreation.ts | 86 -- ...entWorkingGroupMintCapacityProposalTest.ts | 68 +- .../electionParametersProposalTest.ts | 65 +- .../impl/electionParametersProposal.ts | 124 -- .../tests/proposals/impl/proposalsModule.ts | 1232 +++++++++++++---- .../tests/proposals/impl/setLeadProposal.ts | 46 - .../tests/proposals/impl/spendingProposal.ts | 64 - .../tests/proposals/impl/textProposal.ts | 46 - .../tests/proposals/impl/updateRuntime.ts | 52 - .../proposals/impl/validatorCountProposal.ts | 55 - .../impl/workingGroupMintCapacityProposal.ts | 59 - .../iznik/tests/proposals/manageLeaderRole.ts | 388 +++--- .../tests/proposals/setLeadProposalTest.ts | 65 +- .../tests/proposals/spendingProposalTest.ts | 66 +- .../iznik/tests/proposals/textProposalTest.ts | 59 +- .../tests/proposals/updateRuntimeTest.ts | 68 +- .../proposals/validatorCountProposalTest.ts | 65 +- .../workingGroupMintCapacityProposalTest.ts | 91 +- .../tests/workingGroup/atLeastValueBugTest.ts | 152 +- .../workingGroup/impl/workingGroupModule.ts | 23 +- .../workingGroup/manageWorkerAsLeadTest.ts | 306 ++-- .../workingGroup/manageWorkerAsWorkerTest.ts | 214 +-- .../workerApplicationHappyCaseTest.ts | 196 +-- .../workerApplicationRejectionCaseTest.ts | 198 +-- .../tests/workingGroup/workerPayoutTest.ts | 180 +-- 27 files changed, 2310 insertions(+), 1760 deletions(-) delete mode 100644 tests/network-tests/src/iznik/tests/impl/electingCouncil.ts delete mode 100644 tests/network-tests/src/iznik/tests/impl/membershipCreation.ts delete mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts delete mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts delete mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts delete mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts delete mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts delete mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts delete mode 100644 tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts diff --git a/tests/network-tests/package.json b/tests/network-tests/package.json index acac02ad75..a1a1dd418a 100644 --- a/tests/network-tests/package.json +++ b/tests/network-tests/package.json @@ -7,7 +7,7 @@ "test": "tap --files src/nicaea/tests/proposals/*Test.ts --files src/nicaea/tests/workingGroup/*Test.ts -T", "test-migration-constantinople": "tap --files src/rome/tests/romeRuntimeUpgradeTest.ts --files src/constantinople/tests/electingCouncilTest.ts -T", "test-migration-nicaea": "tap --files src/constantinople/tests/proposals/updateRuntimeTest.ts --files src/nicaea/tests/electingCouncilTest.ts -T", - "debug": "tap --files src/iznik/tests/workingGroup/*Test.ts -T", + "debug": "tap --files src/iznik/tests/proposals/manageLeaderRole.ts -T", "lint": "eslint . --quiet --ext .ts", "checks": "yarn lint && tsc --noEmit --pretty && prettier ./ --check", "format": "prettier ./ --write " diff --git a/tests/network-tests/src/iznik/tests/impl/electingCouncil.ts b/tests/network-tests/src/iznik/tests/impl/electingCouncil.ts deleted file mode 100644 index 05c5f72c48..0000000000 --- a/tests/network-tests/src/iznik/tests/impl/electingCouncil.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../utils/apiWrapper' -import { Keyring } from '@polkadot/api' -import BN from 'bn.js' -import { Seat } from '@nicaea/types/council' -import { assert } from 'chai' -import { v4 as uuid } from 'uuid' -import { Utils } from '../../utils/utils' -import tap from 'tap' - -export function councilTest( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - k: number, - sudoUri: string, - greaterStake: BN, - lesserStake: BN -) { - let sudo: KeyringPair - - tap.test('Electing a council test', async () => { - // Setup goes here because M keypairs are generated after before() function - sudo = keyring.addFromUri(sudoUri) - let now = await apiWrapper.getBestBlock() - const applyForCouncilFee: BN = apiWrapper.estimateApplyForCouncilFee(greaterStake) - const voteForCouncilFee: BN = apiWrapper.estimateVoteForCouncilFee(sudo.address, sudo.address, greaterStake) - const salt: string[] = [] - m1KeyPairs.forEach(() => { - salt.push(''.concat(uuid().replace(/-/g, ''))) - }) - const revealVoteFee: BN = apiWrapper.estimateRevealVoteFee(sudo.address, salt[0]) - - // Topping the balances - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, applyForCouncilFee.add(greaterStake)) - await apiWrapper.transferBalanceToAccounts(sudo, m1KeyPairs, voteForCouncilFee.add(revealVoteFee).add(greaterStake)) - - // First K members stake more - await apiWrapper.sudoStartAnnouncingPerion(sudo, now.addn(100)) - await apiWrapper.batchApplyForCouncilElection(m2KeyPairs.slice(0, k), greaterStake) - m2KeyPairs.slice(0, k).forEach((keyPair) => - apiWrapper.getCouncilElectionStake(keyPair.address).then((stake) => { - assert( - stake.eq(greaterStake), - `${keyPair.address} not applied correctrly for council election with stake ${stake} versus expected ${greaterStake}` - ) - }) - ) - - // Last members stake less - await apiWrapper.batchApplyForCouncilElection(m2KeyPairs.slice(k), lesserStake) - m2KeyPairs.slice(k).forEach((keyPair) => - apiWrapper.getCouncilElectionStake(keyPair.address).then((stake) => { - assert( - stake.eq(lesserStake), - `${keyPair.address} not applied correctrly for council election with stake ${stake} versus expected ${lesserStake}` - ) - }) - ) - - // Voting - await apiWrapper.sudoStartVotingPerion(sudo, now.addn(100)) - await apiWrapper.batchVoteForCouncilMember( - m1KeyPairs.slice(0, k), - m2KeyPairs.slice(0, k), - salt.slice(0, k), - lesserStake - ) - await apiWrapper.batchVoteForCouncilMember(m1KeyPairs.slice(k), m2KeyPairs.slice(k), salt.slice(k), greaterStake) - - // Revealing - await apiWrapper.sudoStartRevealingPerion(sudo, now.addn(100)) - await apiWrapper.batchRevealVote(m1KeyPairs.slice(0, k), m2KeyPairs.slice(0, k), salt.slice(0, k)) - await apiWrapper.batchRevealVote(m1KeyPairs.slice(k), m2KeyPairs.slice(k), salt.slice(k)) - now = await apiWrapper.getBestBlock() - - // Resolving election - // 3 is to ensure the revealing block is in future - await apiWrapper.sudoStartRevealingPerion(sudo, now.addn(3)) - await Utils.wait(apiWrapper.getBlockDuration().muln(2.5).toNumber()) - const seats: Seat[] = await apiWrapper.getCouncil() - - // Preparing collections to increase assertion readability - const m2addresses: string[] = m2KeyPairs.map((keyPair) => keyPair.address) - const m1addresses: string[] = m1KeyPairs.map((keyPair) => keyPair.address) - const members: string[] = seats.map((seat) => seat.member.toString()) - const bakers: string[] = seats.map((seat) => seat.backers.map((baker) => baker.member.toString())).flat() - - // Assertions - m2addresses.forEach((address) => assert(members.includes(address), `Account ${address} is not in the council`)) - m1addresses.forEach((address) => assert(bakers.includes(address), `Account ${address} is not in the voters`)) - seats.forEach((seat) => - assert( - Utils.getTotalStake(seat).eq(greaterStake.add(lesserStake)), - `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}` - ) - ) - }) -} diff --git a/tests/network-tests/src/iznik/tests/impl/membershipCreation.ts b/tests/network-tests/src/iznik/tests/impl/membershipCreation.ts deleted file mode 100644 index 78a23cbfb0..0000000000 --- a/tests/network-tests/src/iznik/tests/impl/membershipCreation.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Keyring } from '@polkadot/keyring' -import { assert } from 'chai' -import { KeyringPair } from '@polkadot/keyring/types' -import BN from 'bn.js' -import { ApiWrapper } from '../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import tap from 'tap' - -export function membershipTest( - apiWrapper: ApiWrapper, - nKeyPairs: KeyringPair[], - keyring: Keyring, - n: number, - paidTerms: number, - sudoUri: string -) { - let sudo: KeyringPair - let aKeyPair: KeyringPair - let membershipFee: BN - let membershipTransactionFee: BN - - tap.test('Membership creation test setup', async () => { - sudo = keyring.addFromUri(sudoUri) - for (let i = 0; i < n; i++) { - nKeyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8))) - } - aKeyPair = keyring.addFromUri(uuid().substring(0, 8)) - membershipFee = await apiWrapper.getMembershipFee(paidTerms) - membershipTransactionFee = apiWrapper.estimateBuyMembershipFee( - sudo, - paidTerms, - 'member_name_which_is_longer_than_expected' - ) - await apiWrapper.transferBalanceToAccounts(sudo, nKeyPairs, membershipTransactionFee.add(new BN(membershipFee))) - await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee) - }) - - tap.test('Buy membeship is accepted with sufficient funds', async () => { - await Promise.all( - nKeyPairs.map(async (keyPair, index) => { - await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`) - }) - ) - nKeyPairs.forEach((keyPair, index) => - apiWrapper - .getMemberIds(keyPair.address) - .then((membership) => assert(membership.length > 0, `Account ${keyPair.address} is not a member`)) - ) - }) - - tap.test('Account A can not buy the membership with insufficient funds', async () => { - await apiWrapper - .getBalance(aKeyPair.address) - .then((balance) => - assert( - balance.toBn() < membershipFee.add(membershipTransactionFee), - 'Account A already have sufficient balance to purchase membership' - ) - ) - await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`, true) - apiWrapper - .getMemberIds(aKeyPair.address) - .then((membership) => assert(membership.length === 0, 'Account A is a member')) - }) - - tap.test('Account A was able to buy the membership with sufficient funds', async () => { - await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipFee.add(membershipTransactionFee)) - apiWrapper - .getBalance(aKeyPair.address) - .then((balance) => - assert(balance.toBn() >= membershipFee, 'The account balance is insufficient to purchase membership') - ) - await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`) - apiWrapper - .getMemberIds(aKeyPair.address) - .then((membership) => assert(membership.length > 0, 'Account A is a not member')) - }) -} - -export function createKeyPairs(keyring: Keyring, n: number): KeyringPair[] { - const nKeyPairs: KeyringPair[] = [] - for (let i = 0; i < n; i++) { - nKeyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8))) - } - return nKeyPairs -} diff --git a/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts index c16377fe35..2b1dfca516 100644 --- a/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts @@ -1,7 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' -import { workingGroupMintCapacityProposalTest } from './impl/workingGroupMintCapacityProposal' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -10,32 +7,73 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' +import { ContentWorkingGroupMintCapacityProposalFixture } from './impl/proposalsModule' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Validator count proposal scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) const mintingCapacityIncrement: BN = new BN(+process.env.MINTING_CAPACITY_INCREMENT!) - const durationInBlocks = 29 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const durationInBlocks = 29 setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - workingGroupMintCapacityProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri, mintingCapacityIncrement) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + + const contentWorkingGroupMintCapacityProposalFixture: ContentWorkingGroupMintCapacityProposalFixture = new ContentWorkingGroupMintCapacityProposalFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + sudo, + mintingCapacityIncrement + ) + tap.test('Content working group mint capacity test', async () => + contentWorkingGroupMintCapacityProposalFixture.runner(false) + ) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts index 96e18c5b36..f63cfa1a9a 100644 --- a/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts @@ -1,7 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' -import { electionParametersProposalTest } from './impl/electionParametersProposal' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -10,31 +7,69 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { Utils } from '../../utils/utils' +import { ElectionParametersProposalFixture } from './impl/proposalsModule' tap.mocha.describe('Election parameters proposal scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) - const durationInBlocks = 29 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const durationInBlocks = 29 setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - electionParametersProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + + const electionParametersProposalFixture: ElectionParametersProposalFixture = new ElectionParametersProposalFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + sudo + ) + tap.test('Election parameters proposal test', async () => electionParametersProposalFixture.runner(false)) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts deleted file mode 100644 index 56695acdf7..0000000000 --- a/tests/network-tests/src/iznik/tests/proposals/impl/electionParametersProposal.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Keyring } from '@polkadot/api' -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import BN from 'bn.js' -import { assert } from 'chai' -import tap from 'tap' - -export function electionParametersProposalTest( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - sudoUri: string -) { - let sudo: KeyringPair - - tap.test('Election parameters proposal test', async () => { - // Setup - sudo = keyring.addFromUri(sudoUri) - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) - const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) - const announcingPeriod: BN = await apiWrapper.getAnnouncingPeriod() - const votingPeriod: BN = await apiWrapper.getVotingPeriod() - const revealingPeriod: BN = await apiWrapper.getRevealingPeriod() - const councilSize: BN = await apiWrapper.getCouncilSize() - const candidacyLimit: BN = await apiWrapper.getCandidacyLimit() - const newTermDuration: BN = await apiWrapper.getNewTermDuration() - const minCouncilStake: BN = await apiWrapper.getMinCouncilStake() - const minVotingStake: BN = await apiWrapper.getMinVotingStake() - - // Proposal stake calculation - const proposalStake: BN = new BN(200000) - const proposalFee: BN = apiWrapper.estimateProposeElectionParametersFee( - description, - description, - proposalStake, - announcingPeriod, - votingPeriod, - revealingPeriod, - councilSize, - candidacyLimit, - newTermDuration, - minCouncilStake, - minVotingStake - ) - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposedAnnouncingPeriod: BN = announcingPeriod.subn(1) - const proposedVotingPeriod: BN = votingPeriod.addn(1) - const proposedRevealingPeriod: BN = revealingPeriod.addn(1) - const proposedCouncilSize: BN = councilSize.addn(1) - const proposedCandidacyLimit: BN = candidacyLimit.addn(1) - const proposedNewTermDuration: BN = newTermDuration.addn(1) - const proposedMinCouncilStake: BN = minCouncilStake.addn(1) - const proposedMinVotingStake: BN = minVotingStake.addn(1) - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeElectionParameters( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - proposedAnnouncingPeriod, - proposedVotingPeriod, - proposedRevealingPeriod, - proposedCouncilSize, - proposedCandidacyLimit, - proposedNewTermDuration, - proposedMinCouncilStake, - proposedMinVotingStake - ) - const proposalNumber = await proposalPromise - - // Approving the proposal - const proposalExecutionPromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await proposalExecutionPromise - - // Assertions - const newAnnouncingPeriod: BN = await apiWrapper.getAnnouncingPeriod() - const newVotingPeriod: BN = await apiWrapper.getVotingPeriod() - const newRevealingPeriod: BN = await apiWrapper.getRevealingPeriod() - const newCouncilSize: BN = await apiWrapper.getCouncilSize() - const newCandidacyLimit: BN = await apiWrapper.getCandidacyLimit() - const newNewTermDuration: BN = await apiWrapper.getNewTermDuration() - const newMinCouncilStake: BN = await apiWrapper.getMinCouncilStake() - const newMinVotingStake: BN = await apiWrapper.getMinVotingStake() - assert( - proposedAnnouncingPeriod.eq(newAnnouncingPeriod), - `Announcing period has unexpected value ${newAnnouncingPeriod}, expected ${proposedAnnouncingPeriod}` - ) - assert( - proposedVotingPeriod.eq(newVotingPeriod), - `Voting period has unexpected value ${newVotingPeriod}, expected ${proposedVotingPeriod}` - ) - assert( - proposedRevealingPeriod.eq(newRevealingPeriod), - `Revealing has unexpected value ${newRevealingPeriod}, expected ${proposedRevealingPeriod}` - ) - assert( - proposedCouncilSize.eq(newCouncilSize), - `Council size has unexpected value ${newCouncilSize}, expected ${proposedCouncilSize}` - ) - assert( - proposedCandidacyLimit.eq(newCandidacyLimit), - `Candidacy limit has unexpected value ${newCandidacyLimit}, expected ${proposedCandidacyLimit}` - ) - assert( - proposedNewTermDuration.eq(newNewTermDuration), - `New term duration has unexpected value ${newNewTermDuration}, expected ${proposedNewTermDuration}` - ) - assert( - proposedMinCouncilStake.eq(newMinCouncilStake), - `Min council stake has unexpected value ${newMinCouncilStake}, expected ${proposedMinCouncilStake}` - ) - assert( - proposedMinVotingStake.eq(newMinVotingStake), - `Min voting stake has unexpected value ${newMinVotingStake}, expected ${proposedMinVotingStake}` - ) - }) -} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts b/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts index 82b390961b..c903a2b6e9 100644 --- a/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts +++ b/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts @@ -4,312 +4,962 @@ import { v4 as uuid } from 'uuid' import BN from 'bn.js' import { WorkingGroupOpening } from '../../../dto/workingGroupOpening' import { FillOpeningParameters } from '../../../dto/fillOpeningParameters' +import { Fixture } from '../../../utils/fixture' +import { Bytes } from '@polkadot/types' +import { assert } from 'chai' -export async function createWorkingGroupLeaderOpening( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - sudo: KeyringPair, - applicationStake: BN, - roleStake: BN, - workingGroup: string -): Promise { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing working group lead opening proposal ' + uuid().substring(0, 8) - - // Proposal stake calculation - const proposalStake: BN = new BN(100000) - const proposalFee: BN = apiWrapper.estimateProposeCreateWorkingGroupLeaderOpeningFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Opening construction - const opening = new WorkingGroupOpening() - .setMaxActiveApplicants(new BN(m1KeyPairs.length)) - .setMaxReviewPeriodLength(new BN(32)) - .setApplicationStakingPolicyAmount(new BN(applicationStake)) - .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) - .setApplicationExpiredUnstakingPeriodLength(new BN(1)) - .setRoleStakingPolicyAmount(new BN(roleStake)) - .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) - .setRoleExpiredUnstakingPeriodLength(new BN(1)) - .setSlashableMaxCount(new BN(1)) - .setSlashableMaxPercentPtsPerTime(new BN(100)) - .setSuccessfulApplicantApplicationStakeUnstakingPeriod(new BN(1)) - .setFailedApplicantApplicationStakeUnstakingPeriod(new BN(1)) - .setFailedApplicantRoleStakeUnstakingPeriod(new BN(1)) - .setTerminateApplicationStakeUnstakingPeriod(new BN(1)) - .setTerminateRoleStakeUnstakingPeriod(new BN(1)) - .setExitRoleApplicationStakeUnstakingPeriod(new BN(1)) - .setExitRoleStakeUnstakingPeriod(new BN(1)) - .setText(uuid().substring(0, 8)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeCreateWorkingGroupLeaderOpening( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - opening, - workingGroup - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class CreateWorkingGroupLeaderOpeningFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private sudo: KeyringPair + private applicationStake: BN + private roleStake: BN + private workingGroup: string + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + applicationStake: BN, + roleStake: BN, + workingGroup: string + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.sudo = sudo + this.applicationStake = applicationStake + this.roleStake = roleStake + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing working group lead opening proposal ' + uuid().substring(0, 8) + + // Proposal stake calculation + const proposalStake: BN = new BN(100000) + const proposalFee: BN = this.apiWrapper.estimateProposeCreateWorkingGroupLeaderOpeningFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Opening construction + const opening = new WorkingGroupOpening() + .setMaxActiveApplicants(new BN(this.m1KeyPairs.length)) + .setMaxReviewPeriodLength(new BN(32)) + .setApplicationStakingPolicyAmount(new BN(this.applicationStake)) + .setApplicationCrowdedOutUnstakingPeriodLength(new BN(1)) + .setApplicationExpiredUnstakingPeriodLength(new BN(1)) + .setRoleStakingPolicyAmount(new BN(this.roleStake)) + .setRoleCrowdedOutUnstakingPeriodLength(new BN(1)) + .setRoleExpiredUnstakingPeriodLength(new BN(1)) + .setSlashableMaxCount(new BN(1)) + .setSlashableMaxPercentPtsPerTime(new BN(100)) + .setSuccessfulApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantApplicationStakeUnstakingPeriod(new BN(1)) + .setFailedApplicantRoleStakeUnstakingPeriod(new BN(1)) + .setTerminateApplicationStakeUnstakingPeriod(new BN(1)) + .setTerminateRoleStakeUnstakingPeriod(new BN(1)) + .setExitRoleApplicationStakeUnstakingPeriod(new BN(1)) + .setExitRoleStakeUnstakingPeriod(new BN(1)) + .setText(uuid().substring(0, 8)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeCreateWorkingGroupLeaderOpening( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + opening, + this.workingGroup + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function beginWorkingGroupLeaderApplicationReview( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - sudo: KeyringPair, - openingId: BN, - workingGroup: string -): Promise { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8) - - // Proposal stake calculation - const proposalStake: BN = new BN(25000) - const proposalFee: BN = apiWrapper.estimateProposeBeginWorkingGroupLeaderApplicationReviewFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeBeginWorkingGroupLeaderApplicationReview( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - openingId, - workingGroup - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class BeginWorkingGroupLeaderApplicationReviewFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private sudo: KeyringPair + private openingId: BN + private workingGroup: string + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + openingId: BN, + workingGroup: string + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.sudo = sudo + this.openingId = openingId + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8) + + // Proposal stake calculation + const proposalStake: BN = new BN(25000) + const proposalFee: BN = this.apiWrapper.estimateProposeBeginWorkingGroupLeaderApplicationReviewFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeBeginWorkingGroupLeaderApplicationReview( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + this.openingId, + this.workingGroup + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function fillLeaderOpeningProposal( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - applicantRoleAccountAddress: string, - sudo: KeyringPair, - firstRewardInterval: BN, - rewardInterval: BN, - payoutAmount: BN, - openingId: BN, - workingGroup: WorkingGroups -): Promise { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing fill opening proposal ' + uuid().substring(0, 8) - const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) - - // Proposal stake calculation - const proposalStake: BN = new BN(50000) - const proposalFee: BN = apiWrapper.estimateProposeFillLeaderOpeningFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const applicationId: BN = ( - await apiWrapper.getActiveApplicationsIdsByRoleAccount(applicantRoleAccountAddress, workingGroup) - )[0] - const now = await apiWrapper.getBestBlock() - const fillOpeningParameters: FillOpeningParameters = new FillOpeningParameters() - .setAmountPerPayout(payoutAmount) - .setNextPaymentAtBlock(now.add(firstRewardInterval)) - .setPayoutInterval(rewardInterval) - .setOpeningId(openingId) - .setSuccessfulApplicationId(applicationId) - .setWorkingGroup(workingGroupString) - - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeFillLeaderOpening( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - fillOpeningParameters - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class FillLeaderOpeningProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private applicantRoleAccountAddress: string + private sudo: KeyringPair + private firstRewardInterval: BN + private rewardInterval: BN + private payoutAmount: BN + private openingId: BN + private workingGroup: WorkingGroups + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + applicantRoleAccountAddress: string, + sudo: KeyringPair, + firstRewardInterval: BN, + rewardInterval: BN, + payoutAmount: BN, + openingId: BN, + workingGroup: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.applicantRoleAccountAddress = applicantRoleAccountAddress + this.sudo = sudo + this.firstRewardInterval = firstRewardInterval + this.rewardInterval = rewardInterval + this.payoutAmount = payoutAmount + this.openingId = openingId + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing fill opening proposal ' + uuid().substring(0, 8) + const workingGroupString: string = this.apiWrapper.getWorkingGroupString(this.workingGroup) + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = this.apiWrapper.estimateProposeFillLeaderOpeningFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const applicationId: BN = ( + await this.apiWrapper.getActiveApplicationsIdsByRoleAccount(this.applicantRoleAccountAddress, this.workingGroup) + )[0] + const now = await this.apiWrapper.getBestBlock() + const fillOpeningParameters: FillOpeningParameters = new FillOpeningParameters() + .setAmountPerPayout(this.payoutAmount) + .setNextPaymentAtBlock(now.add(this.firstRewardInterval)) + .setPayoutInterval(this.rewardInterval) + .setOpeningId(this.openingId) + .setSuccessfulApplicationId(applicationId) + .setWorkingGroup(workingGroupString) + + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeFillLeaderOpening( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + fillOpeningParameters + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function terminateLeaderRoleProposal( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - leaderRoleAccountAddress: string, - sudo: KeyringPair, - slash: boolean, - workingGroup: WorkingGroups -) { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8) - const rationale: string = 'Testing leader termination ' + uuid().substring(0, 8) - const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) - const workerId: BN = await apiWrapper.getWorkerIdByRoleAccount(leaderRoleAccountAddress, workingGroup) - - // Proposal stake calculation - const proposalStake: BN = new BN(100000) - const proposalFee: BN = apiWrapper.estimateProposeTerminateLeaderRoleFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeTerminateLeaderRole( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - workerId, - rationale, - slash, - workingGroupString - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class TerminateLeaderRoleProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private leaderRoleAccountAddress: string + private sudo: KeyringPair + private slash: boolean + private workingGroup: WorkingGroups + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + leaderRoleAccountAddress: string, + sudo: KeyringPair, + slash: boolean, + workingGroup: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.leaderRoleAccountAddress = leaderRoleAccountAddress + this.sudo = sudo + this.slash = slash + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing begin working group lead application review proposal ' + uuid().substring(0, 8) + const rationale: string = 'Testing leader termination ' + uuid().substring(0, 8) + const workingGroupString: string = this.apiWrapper.getWorkingGroupString(this.workingGroup) + const workerId: BN = await this.apiWrapper.getWorkerIdByRoleAccount( + this.leaderRoleAccountAddress, + this.workingGroup + ) + + // Proposal stake calculation + const proposalStake: BN = new BN(100000) + const proposalFee: BN = this.apiWrapper.estimateProposeTerminateLeaderRoleFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeTerminateLeaderRole( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + rationale, + this.slash, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function setLeaderRewardProposal( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - sudo: KeyringPair, - payoutAmount: BN, - workingGroup: WorkingGroups -): Promise { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing set leader reward proposal ' + uuid().substring(0, 8) - const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) - const workerId: BN = (await apiWrapper.getLeadWorkerId(workingGroup))! - - // Proposal stake calculation - const proposalStake: BN = new BN(50000) - const proposalFee: BN = apiWrapper.estimateProposeLeaderRewardFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeLeaderReward( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - workerId, - payoutAmount, - workingGroupString - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class SetLeaderRewardProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private sudo: KeyringPair + private payoutAmount: BN + private workingGroup: WorkingGroups + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + payoutAmount: BN, + workingGroup: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.sudo = sudo + this.payoutAmount = payoutAmount + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing set leader reward proposal ' + uuid().substring(0, 8) + const workingGroupString: string = this.apiWrapper.getWorkingGroupString(this.workingGroup) + const workerId: BN = (await this.apiWrapper.getLeadWorkerId(this.workingGroup))! + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = this.apiWrapper.estimateProposeLeaderRewardFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeLeaderReward( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + this.payoutAmount, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function decreaseLeaderStakeProposal( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - sudo: KeyringPair, - stakeDecrement: BN, - workingGroup: WorkingGroups -): Promise { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing decrease leader stake proposal ' + uuid().substring(0, 8) - const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) - const workerId: BN = (await apiWrapper.getLeadWorkerId(workingGroup))! - - // Proposal stake calculation - const proposalStake: BN = new BN(50000) - const proposalFee: BN = apiWrapper.estimateProposeDecreaseLeaderStakeFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeDecreaseLeaderStake( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - workerId, - stakeDecrement, - workingGroupString - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class DecreaseLeaderStakeProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private sudo: KeyringPair + private stakeDecrement: BN + private workingGroup: WorkingGroups + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + stakeDecrement: BN, + workingGroup: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.sudo = sudo + this.stakeDecrement = stakeDecrement + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing decrease leader stake proposal ' + uuid().substring(0, 8) + const workingGroupString: string = this.apiWrapper.getWorkingGroupString(this.workingGroup) + const workerId: BN = (await this.apiWrapper.getLeadWorkerId(this.workingGroup))! + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = this.apiWrapper.estimateProposeDecreaseLeaderStakeFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeDecreaseLeaderStake( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + this.stakeDecrement, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function slashLeaderProposal( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - sudo: KeyringPair, - slashAmount: BN, - workingGroup: WorkingGroups -): Promise { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing slash leader stake proposal ' + uuid().substring(0, 8) - const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) - const workerId: BN = (await apiWrapper.getLeadWorkerId(workingGroup))! - - // Proposal stake calculation - const proposalStake: BN = new BN(50000) - const proposalFee: BN = apiWrapper.estimateProposeSlashLeaderStakeFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeSlashLeaderStake( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - workerId, - slashAmount, - workingGroupString - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class SlashLeaderProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private sudo: KeyringPair + private slashAmount: BN + private workingGroup: WorkingGroups + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + slashAmount: BN, + workingGroup: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.sudo = sudo + this.slashAmount = slashAmount + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing slash leader stake proposal ' + uuid().substring(0, 8) + const workingGroupString: string = this.apiWrapper.getWorkingGroupString(this.workingGroup) + const workerId: BN = (await this.apiWrapper.getLeadWorkerId(this.workingGroup))! + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = this.apiWrapper.estimateProposeSlashLeaderStakeFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeSlashLeaderStake( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + workerId, + this.slashAmount, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function workingGroupMintCapacityProposal( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - sudo: KeyringPair, - mintCapacity: BN, - workingGroup: WorkingGroups -): Promise { - // Setup - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing working group mint capacity proposal ' + uuid().substring(0, 8) - const workingGroupString: string = apiWrapper.getWorkingGroupString(workingGroup) - - // Proposal stake calculation - const proposalStake: BN = new BN(50000) - const proposalFee: BN = apiWrapper.estimateProposeWorkingGroupMintCapacityFee() - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeWorkingGroupMintCapacity( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - mintCapacity, - workingGroupString - ) - const proposalNumber: BN = await proposalPromise - return proposalNumber +export class WorkingGroupMintCapacityProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private sudo: KeyringPair + private mintCapacity: BN + private workingGroup: WorkingGroups + + private result: BN | undefined + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + sudo: KeyringPair, + mintCapacity: BN, + workingGroup: WorkingGroups + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.sudo = sudo + this.mintCapacity = mintCapacity + this.workingGroup = workingGroup + } + + public getResult(): BN | undefined { + return this.result + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing working group mint capacity proposal ' + uuid().substring(0, 8) + const workingGroupString: string = this.apiWrapper.getWorkingGroupString(this.workingGroup) + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = this.apiWrapper.estimateProposeWorkingGroupMintCapacityFee() + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeWorkingGroupMintCapacity( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + this.mintCapacity, + workingGroupString + ) + const proposalNumber: BN = await proposalPromise + this.result = proposalNumber + } } -export async function voteForProposal( - apiWrapper: ApiWrapper, - m2KeyPairs: KeyringPair[], - sudo: KeyringPair, - proposalNumber: BN -): Promise { - const proposalVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, proposalVoteFee) - - // Approving the proposal - const proposalExecutionPromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await proposalExecutionPromise +export class ElectionParametersProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + + constructor(apiWrapper: ApiWrapper, m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[], sudo: KeyringPair) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, runtimeVoteFee) + const announcingPeriod: BN = await this.apiWrapper.getAnnouncingPeriod() + const votingPeriod: BN = await this.apiWrapper.getVotingPeriod() + const revealingPeriod: BN = await this.apiWrapper.getRevealingPeriod() + const councilSize: BN = await this.apiWrapper.getCouncilSize() + const candidacyLimit: BN = await this.apiWrapper.getCandidacyLimit() + const newTermDuration: BN = await this.apiWrapper.getNewTermDuration() + const minCouncilStake: BN = await this.apiWrapper.getMinCouncilStake() + const minVotingStake: BN = await this.apiWrapper.getMinVotingStake() + + // Proposal stake calculation + const proposalStake: BN = new BN(200000) + const proposalFee: BN = this.apiWrapper.estimateProposeElectionParametersFee( + description, + description, + proposalStake, + announcingPeriod, + votingPeriod, + revealingPeriod, + councilSize, + candidacyLimit, + newTermDuration, + minCouncilStake, + minVotingStake + ) + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposedAnnouncingPeriod: BN = announcingPeriod.subn(1) + const proposedVotingPeriod: BN = votingPeriod.addn(1) + const proposedRevealingPeriod: BN = revealingPeriod.addn(1) + const proposedCouncilSize: BN = councilSize.addn(1) + const proposedCandidacyLimit: BN = candidacyLimit.addn(1) + const proposedNewTermDuration: BN = newTermDuration.addn(1) + const proposedMinCouncilStake: BN = minCouncilStake.addn(1) + const proposedMinVotingStake: BN = minVotingStake.addn(1) + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeElectionParameters( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + proposedAnnouncingPeriod, + proposedVotingPeriod, + proposedRevealingPeriod, + proposedCouncilSize, + proposedCandidacyLimit, + proposedNewTermDuration, + proposedMinCouncilStake, + proposedMinVotingStake + ) + const proposalNumber = await proposalPromise + + // Approving the proposal + const proposalExecutionPromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) + await proposalExecutionPromise + + // Assertions + const newAnnouncingPeriod: BN = await this.apiWrapper.getAnnouncingPeriod() + const newVotingPeriod: BN = await this.apiWrapper.getVotingPeriod() + const newRevealingPeriod: BN = await this.apiWrapper.getRevealingPeriod() + const newCouncilSize: BN = await this.apiWrapper.getCouncilSize() + const newCandidacyLimit: BN = await this.apiWrapper.getCandidacyLimit() + const newNewTermDuration: BN = await this.apiWrapper.getNewTermDuration() + const newMinCouncilStake: BN = await this.apiWrapper.getMinCouncilStake() + const newMinVotingStake: BN = await this.apiWrapper.getMinVotingStake() + assert( + proposedAnnouncingPeriod.eq(newAnnouncingPeriod), + `Announcing period has unexpected value ${newAnnouncingPeriod}, expected ${proposedAnnouncingPeriod}` + ) + assert( + proposedVotingPeriod.eq(newVotingPeriod), + `Voting period has unexpected value ${newVotingPeriod}, expected ${proposedVotingPeriod}` + ) + assert( + proposedRevealingPeriod.eq(newRevealingPeriod), + `Revealing has unexpected value ${newRevealingPeriod}, expected ${proposedRevealingPeriod}` + ) + assert( + proposedCouncilSize.eq(newCouncilSize), + `Council size has unexpected value ${newCouncilSize}, expected ${proposedCouncilSize}` + ) + assert( + proposedCandidacyLimit.eq(newCandidacyLimit), + `Candidacy limit has unexpected value ${newCandidacyLimit}, expected ${proposedCandidacyLimit}` + ) + assert( + proposedNewTermDuration.eq(newNewTermDuration), + `New term duration has unexpected value ${newNewTermDuration}, expected ${proposedNewTermDuration}` + ) + assert( + proposedMinCouncilStake.eq(newMinCouncilStake), + `Min council stake has unexpected value ${newMinCouncilStake}, expected ${proposedMinCouncilStake}` + ) + assert( + proposedMinVotingStake.eq(newMinVotingStake), + `Min voting stake has unexpected value ${newMinVotingStake}, expected ${proposedMinVotingStake}` + ) + } +} + +export class SetLeadProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + + constructor(apiWrapper: ApiWrapper, m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[], sudo: KeyringPair) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, runtimeVoteFee) + + // Proposal stake calculation + const proposalStake: BN = new BN(50000) + const proposalFee: BN = this.apiWrapper.estimateProposeLeadFee( + description, + description, + proposalStake, + this.sudo.address + ) + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeLead(this.m1KeyPairs[0], proposalTitle, description, proposalStake, this.m1KeyPairs[1]) + const proposalNumber = await proposalPromise + + // Approving the proposal + const proposalExecutionPromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) + await proposalExecutionPromise + const newLead: string = await this.apiWrapper.getCurrentLeadAddress() + assert( + newLead === this.m1KeyPairs[1].address, + `New lead has unexpected value ${newLead}, expected ${this.m1KeyPairs[1].address}` + ) + } +} + +export class SpendingProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + private spendingBalance: BN + private mintCapacity: BN + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + sudo: KeyringPair, + spendingBalance: BN, + mintCapacity: BN + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + this.spendingBalance = spendingBalance + this.mintCapacity = mintCapacity + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const description = 'spending proposal which is used for API network testing with some mock data' + const runtimeVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + + // Topping the balances + const proposalStake: BN = new BN(25000) + const runtimeProposalFee: BN = this.apiWrapper.estimateProposeSpendingFee( + description, + description, + proposalStake, + this.spendingBalance, + this.sudo.address + ) + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, runtimeVoteFee) + await this.apiWrapper.sudoSetCouncilMintCapacity(this.sudo, this.mintCapacity) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeSpending( + this.m1KeyPairs[0], + 'testing spending' + uuid().substring(0, 8), + 'spending to test proposal functionality' + uuid().substring(0, 8), + proposalStake, + this.spendingBalance, + this.sudo.address + ) + const proposalNumber = await proposalPromise + + // Approving spending proposal + const balanceBeforeMinting: BN = await this.apiWrapper.getBalance(this.sudo.address) + const spendingPromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) + await spendingPromise + const balanceAfterMinting: BN = await this.apiWrapper.getBalance(this.sudo.address) + assert( + balanceAfterMinting.sub(balanceBeforeMinting).eq(this.spendingBalance), + `member ${ + this.m1KeyPairs[0].address + } has unexpected balance ${balanceAfterMinting}, expected ${balanceBeforeMinting.add(this.spendingBalance)}` + ) + } +} + +export class TextProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + + constructor(apiWrapper: ApiWrapper, m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[], sudo: KeyringPair) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing text proposal ' + uuid().substring(0, 8) + const proposalText: string = 'Text of the testing proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, runtimeVoteFee) + + // Proposal stake calculation + const proposalStake: BN = new BN(25000) + const runtimeProposalFee: BN = this.apiWrapper.estimateProposeTextFee( + proposalStake, + description, + description, + proposalText + ) + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeText(this.m1KeyPairs[0], proposalStake, proposalTitle, description, proposalText) + const proposalNumber = await proposalPromise + + // Approving text proposal + const textProposalPromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) + await textProposalPromise + } +} + +export class ValidatorCountProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + private validatorCountIncrement: BN + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + sudo: KeyringPair, + validatorCountIncrement: BN + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + this.validatorCountIncrement = validatorCountIncrement + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) + const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) + const runtimeVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, runtimeVoteFee) + + // Proposal stake calculation + const proposalStake: BN = new BN(100000) + const proposalFee: BN = this.apiWrapper.estimateProposeValidatorCountFee(description, description, proposalStake) + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, proposalFee.add(proposalStake)) + const validatorCount: BN = await this.apiWrapper.getValidatorCount() + + // Proposal creation + const proposedValidatorCount: BN = validatorCount.add(this.validatorCountIncrement) + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeValidatorCount( + this.m1KeyPairs[0], + proposalTitle, + description, + proposalStake, + proposedValidatorCount + ) + const proposalNumber = await proposalPromise + + // Approving the proposal + const proposalExecutionPromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) + await proposalExecutionPromise + const newValidatorCount: BN = await this.apiWrapper.getValidatorCount() + assert( + proposedValidatorCount.eq(newValidatorCount), + `Validator count has unexpeccted value ${newValidatorCount}, expected ${proposedValidatorCount}` + ) + } +} + +export class ContentWorkingGroupMintCapacityProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + private mintingCapacityIncrement: BN + + constructor( + apiWrapper: ApiWrapper, + m1KeyPairs: KeyringPair[], + m2KeyPairs: KeyringPair[], + sudo: KeyringPair, + mintingCapacityIncrement: BN + ) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + this.mintingCapacityIncrement = mintingCapacityIncrement + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const description = 'Mint capacity proposal which is used for API network testing' + const runtimeVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + const initialMintingCapacity: BN = await this.apiWrapper.getContentWorkingGroupMintCapacity() + + // Topping the balances + const proposalStake: BN = new BN(50000) + const runtimeProposalFee: BN = this.apiWrapper.estimateProposeContentWorkingGroupMintCapacityFee( + description, + description, + proposalStake, + initialMintingCapacity.add(this.mintingCapacityIncrement) + ) + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, runtimeVoteFee) + + // Proposal creation + const proposedMintingCapacity: BN = initialMintingCapacity.add(this.mintingCapacityIncrement) + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeContentWorkingGroupMintCapacity( + this.m1KeyPairs[0], + 'testing mint capacity' + uuid().substring(0, 8), + 'mint capacity to test proposal functionality' + uuid().substring(0, 8), + proposalStake, + proposedMintingCapacity + ) + const proposalNumber = await proposalPromise + + // Approving mint capacity proposal + const mintCapacityPromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) + await mintCapacityPromise + const newMintingCapacity: BN = await this.apiWrapper.getContentWorkingGroupMintCapacity() + assert( + proposedMintingCapacity.eq(newMintingCapacity), + `Content working group has unexpected minting capacity ${newMintingCapacity}, expected ${proposedMintingCapacity}` + ) + } +} + +export class UpdateRuntimeFixture implements Fixture { + private apiWrapper: ApiWrapper + private m1KeyPairs: KeyringPair[] + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + + constructor(apiWrapper: ApiWrapper, m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[], sudo: KeyringPair) { + this.apiWrapper = apiWrapper + this.m1KeyPairs = m1KeyPairs + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + } + + public async runner(expectFailure: boolean): Promise { + // Setup + const runtime: Bytes = await this.apiWrapper.getRuntime() + const description = 'runtime upgrade proposal which is used for API network testing' + const runtimeVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + + // Topping the balances + const proposalStake: BN = new BN(1000000) + const runtimeProposalFee: BN = this.apiWrapper.estimateProposeRuntimeUpgradeFee( + proposalStake, + description, + description, + runtime + ) + await this.apiWrapper.transferBalance(this.sudo, this.m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, runtimeVoteFee) + + // Proposal creation + const proposalPromise = this.apiWrapper.expectProposalCreated() + await this.apiWrapper.proposeRuntime( + this.m1KeyPairs[0], + proposalStake, + 'testing runtime' + uuid().substring(0, 8), + 'runtime to test proposal functionality' + uuid().substring(0, 8), + runtime + ) + const proposalNumber = await proposalPromise + + // Approving runtime update proposal + const runtimePromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) + await runtimePromise + } +} + +export class VoteForProposalFixture implements Fixture { + private apiWrapper: ApiWrapper + private m2KeyPairs: KeyringPair[] + private sudo: KeyringPair + private proposalNumber: BN + + constructor(apiWrapper: ApiWrapper, m2KeyPairs: KeyringPair[], sudo: KeyringPair, proposalNumber: BN) { + this.apiWrapper = apiWrapper + this.m2KeyPairs = m2KeyPairs + this.sudo = sudo + this.proposalNumber = proposalNumber + } + + public async runner(expectFailure: boolean): Promise { + const proposalVoteFee: BN = this.apiWrapper.estimateVoteForProposalFee() + await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.m2KeyPairs, proposalVoteFee) + + // Approving the proposal + const proposalExecutionPromise = this.apiWrapper.expectProposalFinalized() + await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, this.proposalNumber) + await proposalExecutionPromise + } } diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts deleted file mode 100644 index 075759f62b..0000000000 --- a/tests/network-tests/src/iznik/tests/proposals/impl/setLeadProposal.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Keyring } from '@polkadot/api' -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import BN from 'bn.js' -import { assert } from 'chai' -import tap from 'tap' - -export function setLeadProposalTest( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - sudoUri: string -) { - let sudo: KeyringPair - - tap.test('Lead proposal test', async () => { - // Setup - sudo = keyring.addFromUri(sudoUri) - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) - const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) - - // Proposal stake calculation - const proposalStake: BN = new BN(50000) - const proposalFee: BN = apiWrapper.estimateProposeLeadFee(description, description, proposalStake, sudo.address) - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeLead(m1KeyPairs[0], proposalTitle, description, proposalStake, m1KeyPairs[1]) - const proposalNumber = await proposalPromise - - // Approving the proposal - const proposalExecutionPromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await proposalExecutionPromise - const newLead: string = await apiWrapper.getCurrentLeadAddress() - assert( - newLead === m1KeyPairs[1].address, - `New lead has unexpected value ${newLead}, expected ${m1KeyPairs[1].address}` - ) - }) -} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts deleted file mode 100644 index 72780b457f..0000000000 --- a/tests/network-tests/src/iznik/tests/proposals/impl/spendingProposal.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { Keyring } from '@polkadot/api' -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import BN from 'bn.js' -import { assert } from 'chai' -import tap from 'tap' - -export function spendingProposalTest( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - sudoUri: string, - spendingBalance: BN, - mintCapacity: BN -) { - let sudo: KeyringPair - - tap.test('Spending proposal test', async () => { - // Setup - sudo = keyring.addFromUri(sudoUri) - const description = 'spending proposal which is used for API network testing with some mock data' - const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - - // Topping the balances - const proposalStake: BN = new BN(25000) - const runtimeProposalFee: BN = apiWrapper.estimateProposeSpendingFee( - description, - description, - proposalStake, - spendingBalance, - sudo.address - ) - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) - await apiWrapper.sudoSetCouncilMintCapacity(sudo, mintCapacity) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeSpending( - m1KeyPairs[0], - 'testing spending' + uuid().substring(0, 8), - 'spending to test proposal functionality' + uuid().substring(0, 8), - proposalStake, - spendingBalance, - sudo.address - ) - const proposalNumber = await proposalPromise - - // Approving spending proposal - const balanceBeforeMinting: BN = await apiWrapper.getBalance(sudo.address) - const spendingPromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await spendingPromise - const balanceAfterMinting: BN = await apiWrapper.getBalance(sudo.address) - assert( - balanceAfterMinting.sub(balanceBeforeMinting).eq(spendingBalance), - `member ${ - m1KeyPairs[0].address - } has unexpected balance ${balanceAfterMinting}, expected ${balanceBeforeMinting.add(spendingBalance)}` - ) - }) -} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts deleted file mode 100644 index 2a76107088..0000000000 --- a/tests/network-tests/src/iznik/tests/proposals/impl/textProposal.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Keyring } from '@polkadot/api' -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import BN from 'bn.js' -import tap from 'tap' - -export function textProposalTest( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - sudoUri: string -) { - let sudo: KeyringPair - - tap.test('Text proposal test', async () => { - // Setup - sudo = keyring.addFromUri(sudoUri) - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing text proposal ' + uuid().substring(0, 8) - const proposalText: string = 'Text of the testing proposal ' + uuid().substring(0, 8) - const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) - - // Proposal stake calculation - const proposalStake: BN = new BN(25000) - const runtimeProposalFee: BN = apiWrapper.estimateProposeTextFee( - proposalStake, - description, - description, - proposalText - ) - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeText(m1KeyPairs[0], proposalStake, proposalTitle, description, proposalText) - const proposalNumber = await proposalPromise - - // Approving text proposal - const textProposalPromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await textProposalPromise - }) -} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts b/tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts deleted file mode 100644 index 64cab936c5..0000000000 --- a/tests/network-tests/src/iznik/tests/proposals/impl/updateRuntime.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Keyring } from '@polkadot/api' -import { Bytes } from '@polkadot/types' -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import BN from 'bn.js' -import tap from 'tap' - -export function updateRuntimeTest( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - sudoUri: string -) { - let sudo: KeyringPair - - tap.test('\n\tUpgrading the runtime test', async () => { - // Setup - sudo = keyring.addFromUri(sudoUri) - const runtime: Bytes = await apiWrapper.getRuntime() - const description = 'runtime upgrade proposal which is used for API network testing' - const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - - // Topping the balances - const proposalStake: BN = new BN(1000000) - const runtimeProposalFee: BN = apiWrapper.estimateProposeRuntimeUpgradeFee( - proposalStake, - description, - description, - runtime - ) - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) - - // Proposal creation - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeRuntime( - m1KeyPairs[0], - proposalStake, - 'testing runtime' + uuid().substring(0, 8), - 'runtime to test proposal functionality' + uuid().substring(0, 8), - runtime - ) - const proposalNumber = await proposalPromise - - // Approving runtime update proposal - const runtimePromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await runtimePromise - }) -} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts deleted file mode 100644 index f0465e7e19..0000000000 --- a/tests/network-tests/src/iznik/tests/proposals/impl/validatorCountProposal.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Keyring } from '@polkadot/api' -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import BN from 'bn.js' -import { assert } from 'chai' -import tap from 'tap' - -export function validatorCountProposal( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - sudoUri: string, - validatorCountIncrement: BN -) { - let sudo: KeyringPair - - tap.test('Validator count proposal test', async () => { - // Setup - sudo = keyring.addFromUri(sudoUri) - const proposalTitle: string = 'Testing proposal ' + uuid().substring(0, 8) - const description: string = 'Testing validator count proposal ' + uuid().substring(0, 8) - const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) - - // Proposal stake calculation - const proposalStake: BN = new BN(100000) - const proposalFee: BN = apiWrapper.estimateProposeValidatorCountFee(description, description, proposalStake) - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake)) - const validatorCount: BN = await apiWrapper.getValidatorCount() - - // Proposal creation - const proposedValidatorCount: BN = validatorCount.add(validatorCountIncrement) - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeValidatorCount( - m1KeyPairs[0], - proposalTitle, - description, - proposalStake, - proposedValidatorCount - ) - const proposalNumber = await proposalPromise - - // Approving the proposal - const proposalExecutionPromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await proposalExecutionPromise - const newValidatorCount: BN = await apiWrapper.getValidatorCount() - assert( - proposedValidatorCount.eq(newValidatorCount), - `Validator count has unexpeccted value ${newValidatorCount}, expected ${proposedValidatorCount}` - ) - }) -} diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts b/tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts deleted file mode 100644 index 6b7f086144..0000000000 --- a/tests/network-tests/src/iznik/tests/proposals/impl/workingGroupMintCapacityProposal.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Keyring } from '@polkadot/api' -import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper } from '../../../utils/apiWrapper' -import { v4 as uuid } from 'uuid' -import BN from 'bn.js' -import { assert } from 'chai' -import tap from 'tap' - -export function workingGroupMintCapacityProposalTest( - apiWrapper: ApiWrapper, - m1KeyPairs: KeyringPair[], - m2KeyPairs: KeyringPair[], - keyring: Keyring, - sudoUri: string, - mintingCapacityIncrement: BN -) { - let sudo: KeyringPair - - tap.test('Mint capacity proposal test', async () => { - // Setup - sudo = keyring.addFromUri(sudoUri) - const description = 'Mint capacity proposal which is used for API network testing' - const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee() - const initialMintingCapacity: BN = await apiWrapper.getContentWorkingGroupMintCapacity() - - // Topping the balances - const proposalStake: BN = new BN(50000) - const runtimeProposalFee: BN = apiWrapper.estimateProposeContentWorkingGroupMintCapacityFee( - description, - description, - proposalStake, - initialMintingCapacity.add(mintingCapacityIncrement) - ) - await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake)) - await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee) - - // Proposal creation - const proposedMintingCapacity: BN = initialMintingCapacity.add(mintingCapacityIncrement) - const proposalPromise = apiWrapper.expectProposalCreated() - await apiWrapper.proposeContentWorkingGroupMintCapacity( - m1KeyPairs[0], - 'testing mint capacity' + uuid().substring(0, 8), - 'mint capacity to test proposal functionality' + uuid().substring(0, 8), - proposalStake, - proposedMintingCapacity - ) - const proposalNumber = await proposalPromise - - // Approving mint capacity proposal - const mintCapacityPromise = apiWrapper.expectProposalFinalized() - await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber) - await mintCapacityPromise - const newMintingCapacity: BN = await apiWrapper.getContentWorkingGroupMintCapacity() - assert( - proposedMintingCapacity.eq(newMintingCapacity), - `Content working group has unexpected minting capacity ${newMintingCapacity}, expected ${proposedMintingCapacity}` - ) - }) -} diff --git a/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts index 25ea7ce4c0..7279ec2cd5 100644 --- a/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts +++ b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts @@ -1,6 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -9,42 +7,47 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' import { - createWorkingGroupLeaderOpening, - voteForProposal, - beginWorkingGroupLeaderApplicationReview, - fillLeaderOpeningProposal, - terminateLeaderRoleProposal, - setLeaderRewardProposal, - decreaseLeaderStakeProposal, - slashLeaderProposal, + BeginWorkingGroupLeaderApplicationReviewFixture, + CreateWorkingGroupLeaderOpeningFixture, + DecreaseLeaderStakeProposalFixture, + FillLeaderOpeningProposalFixture, + SetLeaderRewardProposalFixture, + SlashLeaderProposalFixture, + TerminateLeaderRoleProposalFixture, + VoteForProposalFixture, } from './impl/proposalsModule' import { - applyForOpening, - expectLeadOpeningAdded, - expectLeaderSet, - expectBeganApplicationReview, - expectLeaderRoleTerminated, - expectLeaderRewardAmountUpdated, - expectLeaderStakeDecreased, - expectLeaderSlashed, + ApplyForOpeningFixture, + ExpectBeganApplicationReviewFixture, + ExpectLeaderRewardAmountUpdatedFixture, + ExpectLeaderRoleTerminatedFixture, + ExpectLeaderSetFixture, + ExpectLeaderSlashedFixture, + ExpectLeaderStakeDecreasedFixture, + ExpectLeadOpeningAddedFixture, } from '../workingGroup/impl/workingGroupModule' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Set lead proposal scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - const leadKeyPair: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) @@ -58,176 +61,243 @@ tap.mocha.describe('Set lead proposal scenario', async () => { const slashAmount: BN = new BN(process.env.SLASH_AMOUNT!) const durationInBlocks = 70 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - setTestTimeout(apiWrapper, durationInBlocks) - const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture() - tap.test('Buy membeship is accepted with sufficient funds', async () => - happyCaseFixture.runner(apiWrapper, sudo, m1KeyPairs, keyring, N, paidTerms) + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) - tap.test('Buy membeship is accepted with sufficient funds', async () => - happyCaseFixture.runner(apiWrapper, sudo, m2KeyPairs, keyring, N, paidTerms) + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) - tap.test('Buy membeship is accepted with sufficient funds', async () => - happyCaseFixture.runner(apiWrapper, sudo, leadKeyPair, keyring, 1, paidTerms) + const leaderMembershipFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + leadKeyPair, + paidTerms ) + tap.test('Buy membership for lead', async () => leaderMembershipFixture.runner(false)) - const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture() - tap.test('Elect council', async () => - electCouncilFixture.runner(apiWrapper, m1KeyPairs, m2KeyPairs, K, sudo, greaterStake, lesserStake) + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) - // membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - // membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - // membershipTest(apiWrapper, leadKeyPair, keyring, 1, paidTerms, sudoUri) - // councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - - let createOpeningProposalId: BN - let openingId: BN - tap.test( - 'Propose create leader opening', - async () => - (createOpeningProposalId = await createWorkingGroupLeaderOpening( - apiWrapper, - m1KeyPairs, - sudo, - applicationStake, - roleStake, - 'Storage' - )) + const createWorkingGroupLeaderOpeningFixture: CreateWorkingGroupLeaderOpeningFixture = new CreateWorkingGroupLeaderOpeningFixture( + apiWrapper, + m1KeyPairs, + sudo, + applicationStake, + roleStake, + 'Storage' ) + tap.test('Propose create leader opening', async () => createWorkingGroupLeaderOpeningFixture.runner(false)) + + let voteForCreateOpeningProposalFixture: VoteForProposalFixture + let expectLeadOpeningAddedFixture: ExpectLeadOpeningAddedFixture = new ExpectLeadOpeningAddedFixture(apiWrapper) tap.test('Approve add opening proposal', async () => { - voteForProposal(apiWrapper, m2KeyPairs, sudo, createOpeningProposalId) - openingId = await expectLeadOpeningAdded(apiWrapper) + voteForCreateOpeningProposalFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + createWorkingGroupLeaderOpeningFixture.getResult()! + ) + voteForCreateOpeningProposalFixture.runner(false) + await expectLeadOpeningAddedFixture.runner(false) }) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - new BN(openingId), - WorkingGroups.StorageWorkingGroup, - false - ) - ) - let beginReviewProposalId: BN - tap.test( - 'Propose begin leader application review', - async () => - (beginReviewProposalId = await beginWorkingGroupLeaderApplicationReview( - apiWrapper, - m1KeyPairs, - sudo, - new BN(openingId), - 'Storage' - )) + let applyForLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForLeaderOpeningFixture = new ApplyForOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + new BN(expectLeadOpeningAddedFixture.getResult()!), + WorkingGroups.StorageWorkingGroup + ) + await applyForLeaderOpeningFixture.runner(false) + }) + + let beginWorkingGroupLeaderApplicationReviewFixture: BeginWorkingGroupLeaderApplicationReviewFixture + tap.test('Propose begin leader application review', async () => { + beginWorkingGroupLeaderApplicationReviewFixture = new BeginWorkingGroupLeaderApplicationReviewFixture( + apiWrapper, + m1KeyPairs, + sudo, + new BN(expectLeadOpeningAddedFixture.getResult()!), + 'Storage' + ) + await beginWorkingGroupLeaderApplicationReviewFixture.runner(false) + }) + + let voteForBeginReviewProposal: VoteForProposalFixture + let expectBeganApplicationReviewFixture: ExpectBeganApplicationReviewFixture = new ExpectBeganApplicationReviewFixture( + apiWrapper ) - tap.test('Approve begin review proposal', async () => { - voteForProposal(apiWrapper, m2KeyPairs, sudo, beginReviewProposalId) - expectBeganApplicationReview(apiWrapper) + tap.test('Approve begin application review', async () => { + voteForBeginReviewProposal = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + beginWorkingGroupLeaderApplicationReviewFixture.getResult()! + ) + voteForBeginReviewProposal.runner(false) + await expectBeganApplicationReviewFixture.runner(false) + }) + + let fillLeaderOpeningProposalFixture: FillLeaderOpeningProposalFixture + tap.test('Propose fill leader opening', async () => { + fillLeaderOpeningProposalFixture = new FillLeaderOpeningProposalFixture( + apiWrapper, + m1KeyPairs, + leadKeyPair[0].address, + sudo, + firstRewardInterval, + rewardInterval, + payoutAmount, + new BN(expectLeadOpeningAddedFixture.getResult()!), + WorkingGroups.StorageWorkingGroup + ) + await fillLeaderOpeningProposalFixture.runner(false) }) - let fillLeaderOpeningProposalId: BN - tap.test( - 'Propose fill leader opening', - async () => - (fillLeaderOpeningProposalId = await fillLeaderOpeningProposal( - apiWrapper, - m1KeyPairs, - leadKeyPair[0].address, - sudo, - firstRewardInterval, - rewardInterval, - payoutAmount, - new BN(openingId), - WorkingGroups.StorageWorkingGroup - )) + let voteForFillLeaderProposalFixture: VoteForProposalFixture + const expectLeaderSetFixture: ExpectLeaderSetFixture = new ExpectLeaderSetFixture( + apiWrapper, + leadKeyPair[0].address, + WorkingGroups.StorageWorkingGroup ) tap.test('Approve fill leader opening', async () => { - voteForProposal(apiWrapper, m2KeyPairs, sudo, fillLeaderOpeningProposalId) - await expectLeaderSet(apiWrapper, leadKeyPair[0].address, WorkingGroups.StorageWorkingGroup) + voteForFillLeaderProposalFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + fillLeaderOpeningProposalFixture.getResult()! + ) + voteForFillLeaderProposalFixture.runner(false) + await expectLeaderSetFixture.runner(false) }) - let rewardProposalId: BN - tap.test( - 'Propose leader reward', - async () => - (rewardProposalId = await setLeaderRewardProposal( - apiWrapper, - m1KeyPairs, - sudo, - alteredPayoutAmount, - WorkingGroups.StorageWorkingGroup - )) + const setLeaderRewardProposalFixture: SetLeaderRewardProposalFixture = new SetLeaderRewardProposalFixture( + apiWrapper, + m1KeyPairs, + sudo, + alteredPayoutAmount, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Propose leader reward', async () => setLeaderRewardProposalFixture.runner(false)) + + let voteForeLeaderRewardFixture: VoteForProposalFixture + const expectLeaderRewardAmountUpdatedFixture: ExpectLeaderRewardAmountUpdatedFixture = new ExpectLeaderRewardAmountUpdatedFixture( + apiWrapper, + alteredPayoutAmount, + WorkingGroups.StorageWorkingGroup ) tap.test('Approve new leader reward', async () => { - voteForProposal(apiWrapper, m2KeyPairs, sudo, rewardProposalId) - await expectLeaderRewardAmountUpdated(apiWrapper, alteredPayoutAmount, WorkingGroups.StorageWorkingGroup) + voteForeLeaderRewardFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + setLeaderRewardProposalFixture.getResult()! + ) + voteForeLeaderRewardFixture.runner(false) + await expectLeaderRewardAmountUpdatedFixture.runner(false) }) - let decreaseStakeProposalId: BN - let newStake: BN - tap.test( - 'Propose decrease stake', - async () => - (decreaseStakeProposalId = await decreaseLeaderStakeProposal( - apiWrapper, - m1KeyPairs, - sudo, - stakeDecrement, - WorkingGroups.StorageWorkingGroup - )) + const decreaseLeaderStakeProposalFixture: DecreaseLeaderStakeProposalFixture = new DecreaseLeaderStakeProposalFixture( + apiWrapper, + m1KeyPairs, + sudo, + stakeDecrement, + WorkingGroups.StorageWorkingGroup ) + let newStake: BN + tap.test('Propose decrease stake', async () => decreaseLeaderStakeProposalFixture.runner(false)) + + let voteForDecreaseStakeProposal: VoteForProposalFixture + let expectLeaderStakeDecreasedFixture: ExpectLeaderStakeDecreasedFixture tap.test('Approve decreased leader stake', async () => { newStake = applicationStake.sub(stakeDecrement) - voteForProposal(apiWrapper, m2KeyPairs, sudo, decreaseStakeProposalId) - await expectLeaderStakeDecreased(apiWrapper, newStake, WorkingGroups.StorageWorkingGroup) + voteForFillLeaderProposalFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + decreaseLeaderStakeProposalFixture.getResult()! + ) + voteForFillLeaderProposalFixture.runner(false) + expectLeaderStakeDecreasedFixture = new ExpectLeaderStakeDecreasedFixture( + apiWrapper, + newStake, + WorkingGroups.StorageWorkingGroup + ) + await expectLeaderStakeDecreasedFixture.runner(false) }) - let slashProposalId: BN - tap.test( - 'Propose leader slash', - async () => - (slashProposalId = await slashLeaderProposal( - apiWrapper, - m1KeyPairs, - sudo, - slashAmount, - WorkingGroups.StorageWorkingGroup - )) + const slashLeaderProposalFixture: SlashLeaderProposalFixture = new SlashLeaderProposalFixture( + apiWrapper, + m1KeyPairs, + sudo, + slashAmount, + WorkingGroups.StorageWorkingGroup ) + tap.test('Propose leader slash', async () => slashLeaderProposalFixture.runner(false)) + + let voteForSlashProposalFixture: VoteForProposalFixture + let expectLeaderSlashedFixture: ExpectLeaderSlashedFixture tap.test('Approve leader slash', async () => { newStake = newStake.sub(slashAmount) - voteForProposal(apiWrapper, m2KeyPairs, sudo, slashProposalId) - await expectLeaderSlashed(apiWrapper, newStake, WorkingGroups.StorageWorkingGroup) + voteForSlashProposalFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + slashLeaderProposalFixture.getResult()! + ) + voteForSlashProposalFixture.runner(false) + expectLeaderSlashedFixture = new ExpectLeaderSlashedFixture(apiWrapper, newStake, WorkingGroups.StorageWorkingGroup) + await expectLeaderSlashedFixture.runner(false) }) - let terminateLeaderRoleProposalId: BN - tap.test( - 'Propose terminate leader role', - async () => - (terminateLeaderRoleProposalId = await terminateLeaderRoleProposal( - apiWrapper, - m1KeyPairs, - leadKeyPair[0].address, - sudo, - false, - WorkingGroups.StorageWorkingGroup - )) + const terminateLeaderRoleProposalFixture: TerminateLeaderRoleProposalFixture = new TerminateLeaderRoleProposalFixture( + apiWrapper, + m1KeyPairs, + leadKeyPair[0].address, + sudo, + false, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Propose terminate leader role', async () => terminateLeaderRoleProposalFixture.runner(false)) + + let voteForLeaderRoleTerminationFixture: VoteForProposalFixture + const expectLeaderRoleTerminatedFixture: ExpectLeaderRoleTerminatedFixture = new ExpectLeaderRoleTerminatedFixture( + apiWrapper, + WorkingGroups.StorageWorkingGroup ) tap.test('Approve leader role termination', async () => { - voteForProposal(apiWrapper, m2KeyPairs, sudo, terminateLeaderRoleProposalId) - await expectLeaderRoleTerminated(apiWrapper, WorkingGroups.StorageWorkingGroup) + voteForLeaderRoleTerminationFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + terminateLeaderRoleProposalFixture.getResult()! + ) + voteForLeaderRoleTerminationFixture.runner(false) + await expectLeaderRoleTerminatedFixture.runner(false) }) closeApi(apiWrapper) diff --git a/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts index e7a93d468b..9e9552b9b1 100644 --- a/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts @@ -1,7 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' -import { setLeadProposalTest } from './impl/setLeadProposal' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -10,31 +7,69 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' +import { Utils } from '../../utils/utils' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { SetLeadProposalFixture } from './impl/proposalsModule' tap.mocha.describe('Set lead proposal scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) - const durationInBlocks = 29 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const durationInBlocks = 29 setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - setLeadProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + + const setLeadProposalFixture: SetLeadProposalFixture = new SetLeadProposalFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + sudo + ) + tap.test('Set lead proposal test', async () => setLeadProposalFixture.runner(false)) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts index e5dc4eef81..ff57336c01 100644 --- a/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts @@ -1,7 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' -import { spendingProposalTest } from './impl/spendingProposal' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -10,19 +7,27 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' +import { Utils } from '../../utils/utils' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { SpendingProposalFixture } from './impl/proposalsModule' tap.mocha.describe('Spending proposal scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) @@ -30,13 +35,44 @@ tap.mocha.describe('Spending proposal scenario', async () => { const mintCapacity: BN = new BN(+process.env.COUNCIL_MINTING_CAPACITY!) const durationInBlocks = 29 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - spendingProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri, spendingBalance, mintCapacity) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + + const spendingProposalFixture: SpendingProposalFixture = new SpendingProposalFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + sudo, + spendingBalance, + mintCapacity + ) + tap.test('Spending proposal test', async () => spendingProposalFixture.runner(false)) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts index be7a44c066..77093901be 100644 --- a/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts @@ -1,7 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' -import { textProposalTest } from './impl/textProposal' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -10,31 +7,63 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' +import { Utils } from '../../utils/utils' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { TextProposalFixture } from './impl/proposalsModule' tap.mocha.describe('Text proposal scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) const durationInBlocks = 28 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - textProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + + const textProposalFixture: TextProposalFixture = new TextProposalFixture(apiWrapper, m1KeyPairs, m2KeyPairs, sudo) + tap.test('Text proposal test', async () => textProposalFixture.runner(false)) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts b/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts index 00f8a094f7..b01fa11e39 100644 --- a/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts @@ -1,7 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' -import { updateRuntimeTest } from './impl/updateRuntime' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -10,32 +7,71 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' +import { Utils } from '../../utils/utils' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { UpdateRuntimeFixture } from './impl/proposalsModule' tap.mocha.describe('Update runtime scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) const durationInBlocks = 54 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - updateRuntimeTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri) - membershipTest(apiWrapper, new Array(), keyring, N, paidTerms, sudoUri) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + + const updateRuntimeFixture: UpdateRuntimeFixture = new UpdateRuntimeFixture(apiWrapper, m1KeyPairs, m2KeyPairs, sudo) + tap.test('Upgrade runtime', async () => updateRuntimeFixture.runner(false)) + + const thirdMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + Utils.createKeyPairs(keyring, N), + paidTerms + ) + tap.test('Creating third set of members', async () => thirdMemberSetFixture.runner(false)) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts index b306b08a51..59f22fd610 100644 --- a/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts @@ -1,7 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' -import { validatorCountProposal } from './impl/validatorCountProposal' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -10,32 +7,70 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' +import { Utils } from '../../utils/utils' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { ValidatorCountProposalFixture } from './impl/proposalsModule' tap.mocha.describe('Validator count proposal scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) const validatorCountIncrement: BN = new BN(+process.env.VALIDATOR_COUNT_INCREMENT!) const durationInBlocks = 29 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - validatorCountProposal(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri, validatorCountIncrement) + + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + + const validatorCountProposalFixture: ValidatorCountProposalFixture = new ValidatorCountProposalFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + sudo, + validatorCountIncrement + ) + tap.test('Validator count proposal', async () => validatorCountProposalFixture.runner(false)) + closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts index 61da31ccf4..a86307e827 100644 --- a/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts @@ -1,6 +1,4 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { membershipTest } from '../impl/membershipCreation' -import { councilTest } from '../impl/electingCouncil' import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' import BN from 'bn.js' @@ -9,54 +7,89 @@ import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' import { closeApi } from '../impl/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' -import { voteForProposal, workingGroupMintCapacityProposal } from './impl/proposalsModule' -import { expectMintCapacityChanged } from '../workingGroup/impl/workingGroupModule' +import { Utils } from '../../utils/utils' +import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { VoteForProposalFixture, WorkingGroupMintCapacityProposalFixture } from './impl/proposalsModule' +import { ExpectMintCapacityChangedFixture } from '../workingGroup/impl/workingGroupModule' tap.mocha.describe('Set storage working group mint capacity scenario', async () => { initConfig() registerJoystreamTypes() - const m1KeyPairs: KeyringPair[] = [] - const m2KeyPairs: KeyringPair[] = [] - + const nodeUrl: string = process.env.NODE_URL! + const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const keyring = new Keyring({ type: 'sr25519' }) + const provider = new WsProvider(nodeUrl) + const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) + const sudo: KeyringPair = keyring.addFromUri(sudoUri) + const N: number = +process.env.MEMBERSHIP_CREATION_N! + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! - const nodeUrl: string = process.env.NODE_URL! - const sudoUri: string = process.env.SUDO_ACCOUNT_URI! const K: number = +process.env.COUNCIL_ELECTION_K! const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) const mintCapacityIncrement: BN = new BN(process.env.MINT_CAPACITY_INCREMENT!) const durationInBlocks = 30 - const provider = new WsProvider(nodeUrl) - const apiWrapper: ApiWrapper = await ApiWrapper.create(provider) - const sudo: KeyringPair = keyring.addFromUri(sudoUri) - setTestTimeout(apiWrapper, durationInBlocks) - membershipTest(apiWrapper, m1KeyPairs, keyring, N, paidTerms, sudoUri) - membershipTest(apiWrapper, m2KeyPairs, keyring, N, paidTerms, sudoUri) - councilTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, K, sudoUri, greaterStake, lesserStake) - let mintCapacityProposalId: BN + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m1KeyPairs, + paidTerms + ) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) + const newMintCapacity: BN = (await apiWrapper.getWorkingGroupMintCapacity(WorkingGroups.StorageWorkingGroup)).add( mintCapacityIncrement ) - tap.test( - 'Propose mint capacity', - async () => - (mintCapacityProposalId = await workingGroupMintCapacityProposal( - apiWrapper, - m1KeyPairs, - sudo, - newMintCapacity, - WorkingGroups.StorageWorkingGroup - )) + const workingGroupMintCapacityProposalFixture: WorkingGroupMintCapacityProposalFixture = new WorkingGroupMintCapacityProposalFixture( + apiWrapper, + m1KeyPairs, + sudo, + newMintCapacity, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Propose mint capacity', async () => workingGroupMintCapacityProposalFixture.runner(false)) + + let voteForProposalFixture: VoteForProposalFixture + const expectMintCapacityChanged: ExpectMintCapacityChangedFixture = new ExpectMintCapacityChangedFixture( + apiWrapper, + newMintCapacity ) tap.test('Approve mint capacity', async () => { - voteForProposal(apiWrapper, m2KeyPairs, sudo, mintCapacityProposalId) - await expectMintCapacityChanged(apiWrapper, newMintCapacity) + voteForProposalFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + workingGroupMintCapacityProposalFixture.getResult()! + ) + voteForProposalFixture.runner(false) + await expectMintCapacityChanged.runner(false) }) closeApi(apiWrapper) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts index 4f75bf527c..40d8616824 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts @@ -6,12 +6,12 @@ import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' import { - addWorkerOpening, - applyForOpening, - addLeaderOpening, - beginLeaderApplicationReview, - fillLeaderOpening, - leaveRole, + AddLeaderOpeningFixture, + AddWorkerOpeningFixture, + ApplyForOpeningFixture, + BeginLeaderApplicationReviewFixture, + FillLeaderOpeningFixture, + LeaveRoleFixture, } from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' @@ -61,85 +61,95 @@ tap.mocha.describe('Worker application happy case scenario', async () => { ) tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) - let leadOpenignId: BN - tap.test( - 'Add lead opening', - async () => - (leadOpenignId = await addLeaderOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openingActivationDelay, - WorkingGroups.StorageWorkingGroup - )) - ) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - leadOpenignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin lead application review', async () => - beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + const addLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill lead opening', async () => - fillLeaderOpening( + // let leadOpenignId: BN + tap.test('Add lead opening', async () => await addLeaderOpeningFixture.runner(false)) + + let applyForLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForLeaderOpeningFixture = new ApplyForOpeningFixture( apiWrapper, leadKeyPair, sudo, - leadOpenignId, + applicationStake, + roleStake, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForLeaderOpeningFixture.runner(false) + }) + + let beginLeaderApplicationReviewFixture: BeginLeaderApplicationReviewFixture + tap.test('Begin lead application review', async () => { + beginLeaderApplicationReviewFixture = new BeginLeaderApplicationReviewFixture( + apiWrapper, + sudo, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginLeaderApplicationReviewFixture.runner(false) + }) + + let fillLeaderOpeningFixture: FillLeaderOpeningFixture + tap.test('Fill lead opening', async () => { + fillLeaderOpeningFixture = new FillLeaderOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + addLeaderOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) + await fillLeaderOpeningFixture.runner(false) + }) + + const addWorkerOpeningWithoutStakeFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + new BN(0), + new BN(0), + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Add worker opening with 0 stake, expect failure', async () => + addWorkerOpeningWithoutStakeFixture.runner(true) ) - let workerOpenignId: BN - tap.test( - 'Add worker opening with 0 stake, expect failure', - async () => - (workerOpenignId = await addWorkerOpening( - apiWrapper, - nKeyPairs, - leadKeyPair[0], - sudo, - new BN(0), - new BN(0), - openingActivationDelay, - unstakingPeriod, - WorkingGroups.StorageWorkingGroup, - true - )) + const addWorkerOpeningWithoutUnstakingPeriodFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + new BN(0), + WorkingGroups.StorageWorkingGroup ) - tap.test( - 'Add worker opening with 0 unstaking period, expect failure', - async () => - (workerOpenignId = await addWorkerOpening( - apiWrapper, - nKeyPairs, - leadKeyPair[0], - sudo, - applicationStake, - roleStake, - openingActivationDelay, - new BN(0), - WorkingGroups.StorageWorkingGroup, - true - )) + tap.test('Add worker opening with 0 unstaking period, expect failure', async () => + addWorkerOpeningWithoutUnstakingPeriodFixture.runner(true) ) - tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + const leaveRoleFixture: LeaveRoleFixture = new LeaveRoleFixture( + apiWrapper, + leadKeyPair, + sudo, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Leaving lead role', async () => leaveRoleFixture.runner(false)) closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts b/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts index 1929731740..022a46395d 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts @@ -83,10 +83,11 @@ export class AddWorkerOpeningFixture implements Fixture { await this.apiWrapper.transferBalance(this.sudo, this.lead.address, addOpeningFee) // Worker opening creation - const addOpeningPromise: Promise = this.apiWrapper.expectOpeningAdded() + const addOpeningPromise: Promise = this.apiWrapper.expectEvent('OpeningAdded') await this.apiWrapper.addOpening(this.lead, opening, this.module, expectFailure) if (!expectFailure) { - const openingId: BN = await addOpeningPromise + const openingId: BN = ((await addOpeningPromise).data[0] as unknown) as BN + console.log('received opening id ' + openingId) this.result = openingId } } @@ -152,9 +153,9 @@ export class AddLeaderOpeningFixture implements Fixture { .setText(uuid().substring(0, 8)) .setOpeningType('leader') - const addOpeningPromise: Promise = this.apiWrapper.expectOpeningAdded() + const addOpeningPromise: Promise = this.apiWrapper.expectEvent('OpeningAdded') await this.apiWrapper.sudoAddOpening(this.sudo, opening, this.module) - const openingId: BN = await addOpeningPromise + const openingId: BN = ((await addOpeningPromise).data[0] as unknown) as BN this.result = openingId } @@ -202,7 +203,6 @@ export class ApplyForOpeningFixture implements Fixture { private roleStake: BN private openingId: BN private module: WorkingGroups - private expectFailure: boolean public constructor( apiWrapper: ApiWrapper, @@ -211,8 +211,7 @@ export class ApplyForOpeningFixture implements Fixture { applicationStake: BN, roleStake: BN, openingId: BN, - module: WorkingGroups, - expectFailure: boolean + module: WorkingGroups ) { this.apiWrapper = apiWrapper this.membersKeyPairs = membersKeyPairs @@ -221,7 +220,6 @@ export class ApplyForOpeningFixture implements Fixture { this.roleStake = roleStake this.openingId = openingId this.module = module - this.expectFailure = expectFailure } public async runner(expectFailure: boolean): Promise { @@ -240,7 +238,7 @@ export class ApplyForOpeningFixture implements Fixture { this.applicationStake, uuid().substring(0, 8), this.module, - this.expectFailure + expectFailure ) } } @@ -644,8 +642,7 @@ export class DecreaseStakeFixture implements Fixture { membersKeyPairs: KeyringPair[], lead: KeyringPair, sudo: KeyringPair, - module: WorkingGroups, - expectFailure: boolean + module: WorkingGroups ) { this.apiWrapper = apiWrapper this.membersKeyPairs = membersKeyPairs @@ -912,7 +909,7 @@ export class ExpectLeaderSetFixture implements Fixture { } } -export class ExpectBeganApplicationReview implements Fixture { +export class ExpectBeganApplicationReviewFixture implements Fixture { private apiWrapper: ApiWrapper private result: BN | undefined @@ -1069,7 +1066,7 @@ export class ExpectLeaderSlashedFixture implements Fixture { } } -export class ExpectMintCapacityChanged implements Fixture { +export class ExpectMintCapacityChangedFixture implements Fixture { private apiWrapper: ApiWrapper private expectedMintCapacity: BN diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts index 1f8217da85..f77164ad5c 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts @@ -6,17 +6,18 @@ import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' import { - addWorkerOpening, - applyForOpening, - beginApplicationReview, - fillOpening, - decreaseStake, - slash, - terminateRole, - addLeaderOpening, - beginLeaderApplicationReview, - fillLeaderOpening, - leaveRole, + AddLeaderOpeningFixture, + ApplyForOpeningFixture, + BeginLeaderApplicationReviewFixture, + FillLeaderOpeningFixture, + AddWorkerOpeningFixture, + WithdrawApplicationFixture, + BeginApplicationReviewFixture, + FillOpeningFixture, + LeaveRoleFixture, + DecreaseStakeFixture, + SlashFixture, + TerminateRoleFixture, } from './impl/workingGroupModule' import BN from 'bn.js' import tap = require('tap') @@ -66,157 +67,214 @@ tap.mocha.describe('Manage worker as worker scenario', async () => { ) tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) - let leadOpenignId: BN - tap.test( - 'Add lead opening', - async () => - (leadOpenignId = await addLeaderOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openingActivationDelay, - WorkingGroups.StorageWorkingGroup - )) - ) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - leadOpenignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin lead application review', async () => - beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + const addLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill lead opening', async () => - fillLeaderOpening( + tap.test('Add lead opening', async () => await addLeaderOpeningFixture.runner(false)) + + let applyForLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForLeaderOpeningFixture = new ApplyForOpeningFixture( apiWrapper, leadKeyPair, sudo, - leadOpenignId, + applicationStake, + roleStake, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForLeaderOpeningFixture.runner(false) + }) + + let beginLeaderApplicationReviewFixture: BeginLeaderApplicationReviewFixture + tap.test('Begin lead application review', async () => { + beginLeaderApplicationReviewFixture = new BeginLeaderApplicationReviewFixture( + apiWrapper, + sudo, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginLeaderApplicationReviewFixture.runner(false) + }) + + let fillLeaderOpeningFixture: FillLeaderOpeningFixture + tap.test('Fill lead opening', async () => { + fillLeaderOpeningFixture = new FillLeaderOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + addLeaderOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillLeaderOpeningFixture.runner(false) + }) - let openignId: BN - tap.test( - 'Add worker opening', - async () => - (openignId = await addWorkerOpening( - apiWrapper, - nKeyPairs, - leadKeyPair[0], - sudo, - applicationStake, - roleStake, - openingActivationDelay, - unstakingPeriod, - WorkingGroups.StorageWorkingGroup, - false - )) - ) - tap.test( - 'Apply for worker opening', - async () => - await applyForOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin application review', async () => - beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, openignId, WorkingGroups.StorageWorkingGroup) + const addWorkerOpeningFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill worker opening', async () => - fillOpening( + tap.test('Add worker opening', async () => addWorkerOpeningFixture.runner(false)) + + let applyForWorkerOpeningFixture: ApplyForOpeningFixture + tap.test('First apply for worker opening', async () => { + applyForWorkerOpeningFixture = new ApplyForOpeningFixture( apiWrapper, nKeyPairs, + sudo, + applicationStake, + roleStake, + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForWorkerOpeningFixture.runner(false) + }) + + let beginApplicationReviewFixture: BeginApplicationReviewFixture + tap.test('Begin application review', async () => { + beginApplicationReviewFixture = new BeginApplicationReviewFixture( + apiWrapper, leadKeyPair[0], sudo, - openignId, + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginApplicationReviewFixture.runner(false) + }) + + let fillOpeningFixture: FillOpeningFixture + tap.test('Fill worker opening', async () => { + fillOpeningFixture = new FillOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + addWorkerOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillOpeningFixture.runner(false) + }) - tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) - tap.test('Decrease worker stake, expect failure', async () => - decreaseStake(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, true) + const leaveRoleFixture: LeaveRoleFixture = new LeaveRoleFixture( + apiWrapper, + leadKeyPair, + sudo, + WorkingGroups.StorageWorkingGroup ) + tap.test('Leaving lead role', async () => leaveRoleFixture.runner(false)) - tap.test( - 'Add lead opening', - async () => - (leadOpenignId = await addLeaderOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openingActivationDelay, - WorkingGroups.StorageWorkingGroup - )) - ) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - leadOpenignId, - WorkingGroups.StorageWorkingGroup, - false - ) + const decreaseStakeFailureFixture: DecreaseStakeFixture = new DecreaseStakeFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + WorkingGroups.StorageWorkingGroup ) - tap.test('Begin lead application review', async () => - beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + tap.test('Decrease worker stake, expect failure', async () => decreaseStakeFailureFixture.runner(true)) + + const addNewLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill lead opening', async () => - fillLeaderOpening( + tap.test('Add lead opening', async () => await addNewLeaderOpeningFixture.runner(false)) + + let applyForNewLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForNewLeaderOpeningFixture = new ApplyForOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + addNewLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForNewLeaderOpeningFixture.runner(false) + }) + + let beginNewLeaderApplicationReviewFixture: BeginLeaderApplicationReviewFixture + tap.test('Begin lead application review', async () => { + beginNewLeaderApplicationReviewFixture = new BeginLeaderApplicationReviewFixture( + apiWrapper, + sudo, + addNewLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginNewLeaderApplicationReviewFixture.runner(false) + }) + + let fillNewLeaderOpeningFixture: FillLeaderOpeningFixture + tap.test('Fill lead opening', async () => { + fillNewLeaderOpeningFixture = new FillLeaderOpeningFixture( apiWrapper, leadKeyPair, sudo, - leadOpenignId, + addNewLeaderOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillNewLeaderOpeningFixture.runner(false) + }) - tap.test('Decrease worker stake', async () => - decreaseStake(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, false) + const decreaseStakeFixture: DecreaseStakeFixture = new DecreaseStakeFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + WorkingGroups.StorageWorkingGroup ) - tap.test('Slash worker', async () => - slash(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, false) + tap.test('Decrease worker stake', async () => decreaseStakeFixture.runner(false)) + + const slashFixture: SlashFixture = new SlashFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + WorkingGroups.StorageWorkingGroup ) - tap.test('Terminate worker role', async () => - terminateRole(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup, false) + tap.test('Slash worker', async () => slashFixture.runner(false)) + + const terminateRoleFixture: TerminateRoleFixture = new TerminateRoleFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + WorkingGroups.StorageWorkingGroup ) + tap.test('Terminate worker role', async () => terminateRoleFixture.runner(false)) - tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + const newLeaveRoleFixture: LeaveRoleFixture = new LeaveRoleFixture( + apiWrapper, + leadKeyPair, + sudo, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Leaving lead role', async () => newLeaveRoleFixture.runner(false)) closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts index 632f22f902..0b48ff6f49 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts @@ -6,17 +6,16 @@ import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' import { - addWorkerOpening, - applyForOpening, - beginApplicationReview, - fillOpening, - increaseStake, - updateRewardAccount, - updateRoleAccount, - addLeaderOpening, - beginLeaderApplicationReview, - fillLeaderOpening, - leaveRole, + AddLeaderOpeningFixture, + AddWorkerOpeningFixture, + ApplyForOpeningFixture, + BeginApplicationReviewFixture, + BeginLeaderApplicationReviewFixture, + FillLeaderOpeningFixture, + FillOpeningFixture, + IncreaseStakeFixture, + LeaveRoleFixture, + UpdateRewardAccountFixture, } from './impl/workingGroupModule' import BN from 'bn.js' import tap = require('tap') @@ -66,109 +65,146 @@ tap.mocha.describe('Manage worker as worker scenario', async () => { ) tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) - let leadOpenignId: BN - tap.test( - 'Add lead opening', - async () => - (leadOpenignId = await addLeaderOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openingActivationDelay, - WorkingGroups.StorageWorkingGroup - )) - ) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - leadOpenignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin lead application review', async () => - beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + const addLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill lead opening', async () => - fillLeaderOpening( + // let leadOpenignId: BN + tap.test('Add lead opening', async () => await addLeaderOpeningFixture.runner(false)) + + let applyForLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForLeaderOpeningFixture = new ApplyForOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForLeaderOpeningFixture.runner(false) + }) + + let beginLeaderApplicationReviewFixture: BeginLeaderApplicationReviewFixture + tap.test('Begin lead application review', async () => { + beginLeaderApplicationReviewFixture = new BeginLeaderApplicationReviewFixture( + apiWrapper, + sudo, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginLeaderApplicationReviewFixture.runner(false) + }) + + let fillLeaderOpeningFixture: FillLeaderOpeningFixture + tap.test('Fill lead opening', async () => { + fillLeaderOpeningFixture = new FillLeaderOpeningFixture( apiWrapper, leadKeyPair, sudo, - leadOpenignId, + addLeaderOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillLeaderOpeningFixture.runner(false) + }) - let openignId: BN - tap.test( - 'Add worker opening', - async () => - (openignId = await addWorkerOpening( - apiWrapper, - nKeyPairs, - leadKeyPair[0], - sudo, - applicationStake, - roleStake, - openingActivationDelay, - unstakingPeriod, - WorkingGroups.StorageWorkingGroup, - false - )) - ) - tap.test( - 'Apply for worker opening', - async () => - await applyForOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin application review', async () => - beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, openignId, WorkingGroups.StorageWorkingGroup) + const addWorkerOpeningFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill worker opening', async () => - fillOpening( + tap.test('Add worker opening', async () => addWorkerOpeningFixture.runner(false)) + + let applyForWorkerOpeningFixture: ApplyForOpeningFixture + tap.test('First apply for worker opening', async () => { + applyForWorkerOpeningFixture = new ApplyForOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForWorkerOpeningFixture.runner(false) + }) + + let beginApplicationReviewFixture: BeginApplicationReviewFixture + tap.test('Begin application review', async () => { + beginApplicationReviewFixture = new BeginApplicationReviewFixture( + apiWrapper, + leadKeyPair[0], + sudo, + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginApplicationReviewFixture.runner(false) + }) + + let fillOpeningFixture: FillOpeningFixture + tap.test('Fill worker opening', async () => { + fillOpeningFixture = new FillOpeningFixture( apiWrapper, nKeyPairs, leadKeyPair[0], sudo, - openignId, + addWorkerOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillOpeningFixture.runner(false) + }) - tap.test('Increase worker stake', async () => - increaseStake(apiWrapper, nKeyPairs, sudo, WorkingGroups.StorageWorkingGroup) + const increaseStakeFixture: IncreaseStakeFixture = new IncreaseStakeFixture( + apiWrapper, + nKeyPairs, + sudo, + WorkingGroups.StorageWorkingGroup ) - tap.test('Update reward account', async () => - updateRewardAccount(apiWrapper, nKeyPairs, keyring, sudo, WorkingGroups.StorageWorkingGroup) + tap.test('Increase worker stake', async () => increaseStakeFixture.runner(false)) + + const updateRewardAccountFixture: UpdateRewardAccountFixture = new UpdateRewardAccountFixture( + apiWrapper, + nKeyPairs, + keyring, + sudo, + WorkingGroups.StorageWorkingGroup ) - tap.test('Update role account', async () => - updateRoleAccount(apiWrapper, nKeyPairs, keyring, sudo, WorkingGroups.StorageWorkingGroup) + tap.test('Update reward account', async () => updateRewardAccountFixture.runner(false)) + + const updateRoleAccountFixture: UpdateRewardAccountFixture = new UpdateRewardAccountFixture( + apiWrapper, + nKeyPairs, + keyring, + sudo, + WorkingGroups.StorageWorkingGroup ) + tap.test('Update role account', async () => updateRoleAccountFixture.runner(false)) - tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + const newLeaveRoleFixture: LeaveRoleFixture = new LeaveRoleFixture( + apiWrapper, + leadKeyPair, + sudo, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Leaving lead role', async () => newLeaveRoleFixture.runner(false)) closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts index 59ac353880..2f38d2fe9e 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts @@ -5,21 +5,21 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { - addWorkerOpening, - applyForOpening, - beginApplicationReview, - fillOpening, - withdrawApplicaiton, - addLeaderOpening, - beginLeaderApplicationReview, - fillLeaderOpening, - leaveRole, -} from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' import { Utils } from '../../utils/utils' +import { + AddLeaderOpeningFixture, + AddWorkerOpeningFixture, + ApplyForOpeningFixture, + BeginApplicationReviewFixture, + BeginLeaderApplicationReviewFixture, + FillLeaderOpeningFixture, + FillOpeningFixture, + LeaveRoleFixture, + WithdrawApplicationFixture, +} from './impl/workingGroupModule' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() @@ -64,112 +64,142 @@ tap.mocha.describe('Worker application happy case scenario', async () => { ) tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) - let leadOpenignId: BN - tap.test( - 'Add lead opening', - async () => - (leadOpenignId = await addLeaderOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openingActivationDelay, - WorkingGroups.StorageWorkingGroup - )) - ) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - leadOpenignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin lead application review', async () => - beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + const addLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill lead opening', async () => - fillLeaderOpening( + // let leadOpenignId: BN + tap.test('Add lead opening', async () => await addLeaderOpeningFixture.runner(false)) + + let applyForLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForLeaderOpeningFixture = new ApplyForOpeningFixture( apiWrapper, leadKeyPair, sudo, - leadOpenignId, + applicationStake, + roleStake, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForLeaderOpeningFixture.runner(false) + }) + + let beginLeaderApplicationReviewFixture: BeginLeaderApplicationReviewFixture + tap.test('Begin lead application review', async () => { + beginLeaderApplicationReviewFixture = new BeginLeaderApplicationReviewFixture( + apiWrapper, + sudo, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginLeaderApplicationReviewFixture.runner(false) + }) + + let fillLeaderOpeningFixture: FillLeaderOpeningFixture + tap.test('Fill lead opening', async () => { + fillLeaderOpeningFixture = new FillLeaderOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + addLeaderOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillLeaderOpeningFixture.runner(false) + }) - let workerOpenignId: BN - tap.test( - 'Add worker opening', - async () => - (workerOpenignId = await addWorkerOpening( - apiWrapper, - nKeyPairs, - leadKeyPair[0], - sudo, - applicationStake, - roleStake, - openingActivationDelay, - unstakingPeriod, - WorkingGroups.StorageWorkingGroup, - false - )) + const addWorkerOpeningFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup ) - tap.test('Apply for worker opening', async () => - applyForOpening( + tap.test('Add worker opening', async () => addWorkerOpeningFixture.runner(false)) + + let firstApplyForWorkerOpeningFixture: ApplyForOpeningFixture + tap.test('First apply for worker opening', async () => { + firstApplyForWorkerOpeningFixture = new ApplyForOpeningFixture( apiWrapper, nKeyPairs, sudo, applicationStake, roleStake, - workerOpenignId, - WorkingGroups.StorageWorkingGroup, - false + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup ) + await firstApplyForWorkerOpeningFixture.runner(false) + }) + + const withdrawApplicationFixture: WithdrawApplicationFixture = new WithdrawApplicationFixture( + apiWrapper, + nKeyPairs, + sudo, + WorkingGroups.StorageWorkingGroup ) - tap.test('Withdraw worker application', async () => - withdrawApplicaiton(apiWrapper, nKeyPairs, sudo, WorkingGroups.StorageWorkingGroup) - ) - tap.test('Apply for worker opening', async () => - applyForOpening( + tap.test('Withdraw worker application', async () => withdrawApplicationFixture.runner(false)) + + let secondApplyForWorkerOpeningFixture: ApplyForOpeningFixture + tap.test('Second apply for worker opening', async () => { + secondApplyForWorkerOpeningFixture = new ApplyForOpeningFixture( apiWrapper, nKeyPairs, sudo, applicationStake, roleStake, - workerOpenignId, - WorkingGroups.StorageWorkingGroup, - false + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup ) - ) - tap.test('Begin application review', async () => - beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, workerOpenignId, WorkingGroups.StorageWorkingGroup) - ) - tap.test('Fill worker opening', async () => - fillOpening( + await secondApplyForWorkerOpeningFixture.runner(false) + }) + + let beginApplicationReviewFixture: BeginApplicationReviewFixture + tap.test('Begin application review', async () => { + beginApplicationReviewFixture = new BeginApplicationReviewFixture( + apiWrapper, + leadKeyPair[0], + sudo, + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginApplicationReviewFixture.runner(false) + }) + + let fillOpeningFixture: FillOpeningFixture + tap.test('Fill worker opening', async () => { + fillOpeningFixture = new FillOpeningFixture( apiWrapper, nKeyPairs, leadKeyPair[0], sudo, - workerOpenignId, + addWorkerOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillOpeningFixture.runner(false) + }) - tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + const leaveRoleFixture: LeaveRoleFixture = new LeaveRoleFixture( + apiWrapper, + leadKeyPair, + sudo, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Leaving lead role', async () => leaveRoleFixture.runner(false)) closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts index fe67895355..843b5b5451 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts @@ -5,20 +5,20 @@ import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' -import { - addWorkerOpening, - applyForOpening, - acceptApplications, - terminateApplications, - addLeaderOpening, - beginLeaderApplicationReview, - fillLeaderOpening, - leaveRole, -} from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' import { Utils } from '../../utils/utils' +import { + AcceptApplicationsFixture, + AddLeaderOpeningFixture, + AddWorkerOpeningFixture, + ApplyForOpeningFixture, + BeginLeaderApplicationReviewFixture, + FillLeaderOpeningFixture, + LeaveRoleFixture, + TerminateApplicationsFixture, +} from './impl/workingGroupModule' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() @@ -65,111 +65,141 @@ tap.mocha.describe('Worker application happy case scenario', async () => { ) tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) - let leadOpenignId: BN - tap.test( - 'Add lead opening', - async () => - (leadOpenignId = await addLeaderOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - leadOpeningActivationDelay, - WorkingGroups.StorageWorkingGroup - )) - ) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - leadOpenignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin lead application review', async () => - beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + const addLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + leadOpeningActivationDelay, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill lead opening', async () => - fillLeaderOpening( + // let leadOpenignId: BN + tap.test('Add lead opening', async () => await addLeaderOpeningFixture.runner(false)) + + let applyForLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForLeaderOpeningFixture = new ApplyForOpeningFixture( apiWrapper, leadKeyPair, sudo, - leadOpenignId, + applicationStake, + roleStake, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForLeaderOpeningFixture.runner(false) + }) + + let beginLeaderApplicationReviewFixture: BeginLeaderApplicationReviewFixture + tap.test('Begin lead application review', async () => { + beginLeaderApplicationReviewFixture = new BeginLeaderApplicationReviewFixture( + apiWrapper, + sudo, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginLeaderApplicationReviewFixture.runner(false) + }) + + let fillLeaderOpeningFixture: FillLeaderOpeningFixture + tap.test('Fill lead opening', async () => { + fillLeaderOpeningFixture = new FillLeaderOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + addLeaderOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillLeaderOpeningFixture.runner(false) + }) - let openignId: BN - tap.test( - 'Add worker opening', - async () => - (openignId = await addWorkerOpening( - apiWrapper, - nKeyPairs, - leadKeyPair[0], - sudo, - applicationStake, - roleStake, - openingActivationDelay, - unstakingPeriod, - WorkingGroups.StorageWorkingGroup, - false - )) + const addWorkerOpeningFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup ) - tap.test('Apply for worker opening, expect failure', async () => - applyForOpening( + tap.test('Add worker opening', async () => addWorkerOpeningFixture.runner(false)) + + let applyForWorkerOpeningBeforeAcceptanceFixture: ApplyForOpeningFixture + tap.test('Apply for worker opening, expect failure', async () => { + applyForWorkerOpeningBeforeAcceptanceFixture = new ApplyForOpeningFixture( apiWrapper, nKeyPairs, sudo, applicationStake, roleStake, - openignId, - WorkingGroups.StorageWorkingGroup, - true + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup ) - ) - tap.test('Begin accepting worker applications', async () => - acceptApplications(apiWrapper, leadKeyPair[0], sudo, openignId, WorkingGroups.StorageWorkingGroup) - ) - tap.test('Apply for worker opening as non-member, expect failure', async () => - applyForOpening( + await applyForWorkerOpeningBeforeAcceptanceFixture.runner(true) + }) + + let acceptApplicationsFixture: AcceptApplicationsFixture + tap.test('Begin accepting worker applications', async () => { + acceptApplicationsFixture = new AcceptApplicationsFixture( + apiWrapper, + leadKeyPair[0], + sudo, + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + acceptApplicationsFixture.runner(false) + }) + + let applyForWorkerOpeningAsNonMemberFixture: ApplyForOpeningFixture + tap.test('Apply for worker opening as non-member, expect failure', async () => { + applyForWorkerOpeningAsNonMemberFixture = new ApplyForOpeningFixture( apiWrapper, nonMemberKeyPairs, sudo, applicationStake, roleStake, - openignId, - WorkingGroups.StorageWorkingGroup, - true + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup ) - ) - tap.test('Apply for worker opening as member', async () => - applyForOpening( + await applyForWorkerOpeningAsNonMemberFixture.runner(true) + }) + + let applyForWorkerOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for worker opening', async () => { + applyForWorkerOpeningFixture = new ApplyForOpeningFixture( apiWrapper, nKeyPairs, sudo, applicationStake, roleStake, - openignId, - WorkingGroups.StorageWorkingGroup, - false + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup ) + await applyForWorkerOpeningFixture.runner(false) + }) + + const terminateApplicationsFixture: TerminateApplicationsFixture = new TerminateApplicationsFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + WorkingGroups.StorageWorkingGroup ) - tap.test('Terminate worker applicaitons', async () => - terminateApplications(apiWrapper, nKeyPairs, leadKeyPair[0], sudo, WorkingGroups.StorageWorkingGroup) - ) + tap.test('Terminate worker applicaitons', async () => terminateApplicationsFixture.runner(false)) - tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + const leaveRoleFixture: LeaveRoleFixture = new LeaveRoleFixture( + apiWrapper, + leadKeyPair, + sudo, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Leaving lead role', async () => leaveRoleFixture.runner(false)) closeApi(apiWrapper) }) diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts index 01764a2e6f..0dadcfdc44 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts @@ -6,16 +6,15 @@ import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' import { - addWorkerOpening, - applyForOpening, - beginApplicationReview, - fillOpening, - addLeaderOpening, - beginLeaderApplicationReview, - fillLeaderOpening, - leaveRole, - awaitPayout, - setMintCapacity, + AddLeaderOpeningFixture, + AddWorkerOpeningFixture, + ApplyForOpeningFixture, + AwaitPayoutFixture, + BeginApplicationReviewFixture, + BeginLeaderApplicationReviewFixture, + FillLeaderOpeningFixture, + FillOpeningFixture, + LeaveRoleFixture, } from './impl/workingGroupModule' import BN from 'bn.js' import tap from 'tap' @@ -66,102 +65,127 @@ tap.mocha.describe('Worker application happy case scenario', async () => { ) tap.test('Buying membership for leader account', async () => leaderHappyCaseFixture.runner(false)) - let leadOpenignId: BN - tap.test( - 'Add lead opening', - async () => - (leadOpenignId = await addLeaderOpening( - apiWrapper, - nKeyPairs, - sudo, - applicationStake, - roleStake, - openingActivationDelay, - WorkingGroups.StorageWorkingGroup - )) - ) - tap.test( - 'Apply for lead opening', - async () => - await applyForOpening( - apiWrapper, - leadKeyPair, - sudo, - applicationStake, - roleStake, - leadOpenignId, - WorkingGroups.StorageWorkingGroup, - false - ) - ) - tap.test('Begin lead application review', async () => - beginLeaderApplicationReview(apiWrapper, sudo, leadOpenignId, WorkingGroups.StorageWorkingGroup) + const addLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( + apiWrapper, + nKeyPairs, + sudo, + applicationStake, + roleStake, + openingActivationDelay, + WorkingGroups.StorageWorkingGroup ) - tap.test('Fill lead opening', async () => - fillLeaderOpening( + // let leadOpenignId: BN + tap.test('Add lead opening', async () => await addLeaderOpeningFixture.runner(false)) + + let applyForLeaderOpeningFixture: ApplyForOpeningFixture + tap.test('Apply for lead opening', async () => { + applyForLeaderOpeningFixture = new ApplyForOpeningFixture( + apiWrapper, + leadKeyPair, + sudo, + applicationStake, + roleStake, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await applyForLeaderOpeningFixture.runner(false) + }) + + let beginLeaderApplicationReviewFixture: BeginLeaderApplicationReviewFixture + tap.test('Begin lead application review', async () => { + beginLeaderApplicationReviewFixture = new BeginLeaderApplicationReviewFixture( + apiWrapper, + sudo, + addLeaderOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginLeaderApplicationReviewFixture.runner(false) + }) + + let fillLeaderOpeningFixture: FillLeaderOpeningFixture + tap.test('Fill lead opening', async () => { + fillLeaderOpeningFixture = new FillLeaderOpeningFixture( apiWrapper, leadKeyPair, sudo, - leadOpenignId, + addLeaderOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillLeaderOpeningFixture.runner(false) + }) - let workerOpenignId: BN - tap.test( - 'Add worker opening', - async () => - (workerOpenignId = await addWorkerOpening( - apiWrapper, - nKeyPairs, - leadKeyPair[0], - sudo, - applicationStake, - roleStake, - openingActivationDelay, - unstakingPeriod, - WorkingGroups.StorageWorkingGroup, - false - )) + const addWorkerOpeningFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( + apiWrapper, + nKeyPairs, + leadKeyPair[0], + sudo, + applicationStake, + roleStake, + openingActivationDelay, + unstakingPeriod, + WorkingGroups.StorageWorkingGroup ) - tap.test('Apply for worker opening', async () => - applyForOpening( + tap.test('Add worker opening', async () => addWorkerOpeningFixture.runner(false)) + + let applyForWorkerOpeningFixture: ApplyForOpeningFixture + tap.test('First apply for worker opening', async () => { + applyForWorkerOpeningFixture = new ApplyForOpeningFixture( apiWrapper, nKeyPairs, sudo, applicationStake, roleStake, - workerOpenignId, - WorkingGroups.StorageWorkingGroup, - false + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup ) - ) - tap.test('Begin application review', async () => - beginApplicationReview(apiWrapper, leadKeyPair[0], sudo, workerOpenignId, WorkingGroups.StorageWorkingGroup) - ) - tap.test('Set mint capacity', async () => - setMintCapacity(apiWrapper, sudo, mintCapacity, WorkingGroups.StorageWorkingGroup) - ) - tap.test('Fill worker opening', async () => - fillOpening( + await applyForWorkerOpeningFixture.runner(false) + }) + + let beginApplicationReviewFixture: BeginApplicationReviewFixture + tap.test('Begin application review', async () => { + beginApplicationReviewFixture = new BeginApplicationReviewFixture( + apiWrapper, + leadKeyPair[0], + sudo, + addWorkerOpeningFixture.getResult()!, + WorkingGroups.StorageWorkingGroup + ) + await beginApplicationReviewFixture.runner(false) + }) + + let fillOpeningFixture: FillOpeningFixture + tap.test('Fill worker opening', async () => { + fillOpeningFixture = new FillOpeningFixture( apiWrapper, nKeyPairs, leadKeyPair[0], sudo, - workerOpenignId, + addWorkerOpeningFixture.getResult()!, firstRewardInterval, rewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) - ) + await fillOpeningFixture.runner(false) + }) - tap.test('Await worker payout', async () => awaitPayout(apiWrapper, nKeyPairs, WorkingGroups.StorageWorkingGroup)) + const awaitPayoutFixture: AwaitPayoutFixture = new AwaitPayoutFixture( + apiWrapper, + nKeyPairs, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Await worker payout', async () => awaitPayoutFixture.runner(false)) - tap.test('Leaving lead role', async () => leaveRole(apiWrapper, leadKeyPair, sudo, WorkingGroups.StorageWorkingGroup)) + const leaveRoleFixture: LeaveRoleFixture = new LeaveRoleFixture( + apiWrapper, + leadKeyPair, + sudo, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Leaving lead role', async () => leaveRoleFixture.runner(false)) closeApi(apiWrapper) }) From 0c860cc843cbe13a5a0446a4689812f8012c88ed Mon Sep 17 00:00:00 2001 From: Gleb Urvanov Date: Wed, 29 Jul 2020 13:45:42 +0200 Subject: [PATCH 6/6] bug fixing, code cleaning --- .prettierrc.js | 2 +- tests/network-tests/package.json | 2 +- .../{ => council}/electingCouncilTest.ts | 14 +-- .../councilElectionModule.ts | 7 +- .../fixtures/interfaces}/fixture.ts | 0 .../{impl => fixtures}/membershipModule.ts | 8 +- .../impl => fixtures}/proposalsModule.ts | 77 ++++++++++++---- .../impl => fixtures}/workingGroupModule.ts | 90 +++++++++++++------ .../membershipCreationTest.ts | 14 +-- ...entWorkingGroupMintCapacityProposalTest.ts | 8 +- .../electionParametersProposalTest.ts | 8 +- .../iznik/tests/proposals/manageLeaderRole.ts | 14 +-- .../tests/proposals/setLeadProposalTest.ts | 8 +- .../tests/proposals/spendingProposalTest.ts | 8 +- .../iznik/tests/proposals/textProposalTest.ts | 8 +- ...updateRuntimeTest.ts => updateRuntimet.ts} | 8 +- .../proposals/validatorCountProposalTest.ts | 8 +- .../workingGroupMintCapacityProposalTest.ts | 10 +-- .../tests/workingGroup/atLeastValueBugTest.ts | 6 +- .../workingGroup/manageWorkerAsLeadTest.ts | 10 +-- .../workingGroup/manageWorkerAsWorkerTest.ts | 10 +-- .../workerApplicationHappyCaseTest.ts | 6 +- .../workerApplicationRejectionCaseTest.ts | 6 +- .../tests/workingGroup/workerPayoutTest.ts | 82 +++++++++++++---- .../iznik/{tests/impl => utils}/closeApi.ts | 2 +- 25 files changed, 279 insertions(+), 137 deletions(-) rename tests/network-tests/src/iznik/tests/{ => council}/electingCouncilTest.ts (83%) rename tests/network-tests/src/iznik/tests/{impl => fixtures}/councilElectionModule.ts (94%) rename tests/network-tests/src/iznik/{utils => tests/fixtures/interfaces}/fixture.ts (100%) rename tests/network-tests/src/iznik/tests/{impl => fixtures}/membershipModule.ts (92%) rename tests/network-tests/src/iznik/tests/{proposals/impl => fixtures}/proposalsModule.ts (94%) rename tests/network-tests/src/iznik/tests/{workingGroup/impl => fixtures}/workingGroupModule.ts (94%) rename tests/network-tests/src/iznik/tests/{ => membership}/membershipCreationTest.ts (82%) rename tests/network-tests/src/iznik/tests/proposals/{updateRuntimeTest.ts => updateRuntimet.ts} (90%) rename tests/network-tests/src/iznik/{tests/impl => utils}/closeApi.ts (70%) diff --git a/.prettierrc.js b/.prettierrc.js index 03b543c4bd..f2c1c07c33 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,3 +1,3 @@ module.exports = { - ...require('./devops/prettier-config'), + ...require('@joystream/prettier-config'), } diff --git a/tests/network-tests/package.json b/tests/network-tests/package.json index a1a1dd418a..acac02ad75 100644 --- a/tests/network-tests/package.json +++ b/tests/network-tests/package.json @@ -7,7 +7,7 @@ "test": "tap --files src/nicaea/tests/proposals/*Test.ts --files src/nicaea/tests/workingGroup/*Test.ts -T", "test-migration-constantinople": "tap --files src/rome/tests/romeRuntimeUpgradeTest.ts --files src/constantinople/tests/electingCouncilTest.ts -T", "test-migration-nicaea": "tap --files src/constantinople/tests/proposals/updateRuntimeTest.ts --files src/nicaea/tests/electingCouncilTest.ts -T", - "debug": "tap --files src/iznik/tests/proposals/manageLeaderRole.ts -T", + "debug": "tap --files src/iznik/tests/workingGroup/*Test.ts -T", "lint": "eslint . --quiet --ext .ts", "checks": "yarn lint && tsc --noEmit --pretty && prettier ./ --check", "format": "prettier ./ --write " diff --git a/tests/network-tests/src/iznik/tests/electingCouncilTest.ts b/tests/network-tests/src/iznik/tests/council/electingCouncilTest.ts similarity index 83% rename from tests/network-tests/src/iznik/tests/electingCouncilTest.ts rename to tests/network-tests/src/iznik/tests/council/electingCouncilTest.ts index 279895ad05..a888c6cc2f 100644 --- a/tests/network-tests/src/iznik/tests/electingCouncilTest.ts +++ b/tests/network-tests/src/iznik/tests/council/electingCouncilTest.ts @@ -1,15 +1,15 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { initConfig } from '../utils/config' +import { initConfig } from '../../utils/config' import { Keyring, WsProvider } from '@polkadot/api' -import { setTestTimeout } from '../utils/setTestTimeout' +import { setTestTimeout } from '../../utils/setTestTimeout' import BN from 'bn.js' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { ApiWrapper } from '../utils/apiWrapper' -import { closeApi } from './impl/closeApi' -import { BuyMembershipHappyCaseFixture } from './impl/membershipModule' -import { ElectCouncilFixture } from './impl/councilElectionModule' -import { Utils } from '../utils/utils' +import { ApiWrapper } from '../../utils/apiWrapper' +import { closeApi } from '../../utils/closeApi' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Electing council scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/impl/councilElectionModule.ts b/tests/network-tests/src/iznik/tests/fixtures/councilElectionModule.ts similarity index 94% rename from tests/network-tests/src/iznik/tests/impl/councilElectionModule.ts rename to tests/network-tests/src/iznik/tests/fixtures/councilElectionModule.ts index 09ceeeed4f..067ac6c390 100644 --- a/tests/network-tests/src/iznik/tests/impl/councilElectionModule.ts +++ b/tests/network-tests/src/iznik/tests/fixtures/councilElectionModule.ts @@ -5,7 +5,7 @@ import { assert } from 'chai' import { Seat } from '@nicaea/types/council' import { v4 as uuid } from 'uuid' import { Utils } from '../../utils/utils' -import { Fixture } from '../../utils/fixture' +import { Fixture } from './interfaces/fixture' export class ElectCouncilFixture implements Fixture { private apiWrapper: ApiWrapper @@ -67,7 +67,7 @@ export class ElectCouncilFixture implements Fixture { this.apiWrapper.getCouncilElectionStake(keyPair.address).then((stake) => { assert( stake.eq(this.greaterStake), - `${keyPair.address} not applied correctrly for council election with stake ${stake} versus expected ${this.greaterStake}` + `${keyPair.address} not applied correctly for council election with stake ${stake} versus expected ${this.greaterStake}` ) }) ) @@ -133,5 +133,8 @@ export class ElectCouncilFixture implements Fixture { `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}` ) ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } diff --git a/tests/network-tests/src/iznik/utils/fixture.ts b/tests/network-tests/src/iznik/tests/fixtures/interfaces/fixture.ts similarity index 100% rename from tests/network-tests/src/iznik/utils/fixture.ts rename to tests/network-tests/src/iznik/tests/fixtures/interfaces/fixture.ts diff --git a/tests/network-tests/src/iznik/tests/impl/membershipModule.ts b/tests/network-tests/src/iznik/tests/fixtures/membershipModule.ts similarity index 92% rename from tests/network-tests/src/iznik/tests/impl/membershipModule.ts rename to tests/network-tests/src/iznik/tests/fixtures/membershipModule.ts index 7e141fd3a7..4c8a824f92 100644 --- a/tests/network-tests/src/iznik/tests/impl/membershipModule.ts +++ b/tests/network-tests/src/iznik/tests/fixtures/membershipModule.ts @@ -2,7 +2,7 @@ import { ApiWrapper } from '../../utils/apiWrapper' import { KeyringPair } from '@polkadot/keyring/types' import BN from 'bn.js' import { assert } from 'chai' -import { Fixture } from '../../utils/fixture' +import { Fixture } from './interfaces/fixture' export class BuyMembershipHappyCaseFixture implements Fixture { private apiWrapper: ApiWrapper @@ -48,6 +48,9 @@ export class BuyMembershipHappyCaseFixture implements Fixture { .getMemberIds(keyPair.address) .then((membership) => assert(membership.length > 0, `Account ${keyPair.address} is not a member`)) ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -96,5 +99,8 @@ export class BuyMembershipWithInsufficienFundsFixture implements Fixture { this.apiWrapper .getMemberIds(this.aKeyPair.address) .then((membership) => assert(membership.length === 0, 'Account A is a member')) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } diff --git a/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts b/tests/network-tests/src/iznik/tests/fixtures/proposalsModule.ts similarity index 94% rename from tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts rename to tests/network-tests/src/iznik/tests/fixtures/proposalsModule.ts index c903a2b6e9..7190933465 100644 --- a/tests/network-tests/src/iznik/tests/proposals/impl/proposalsModule.ts +++ b/tests/network-tests/src/iznik/tests/fixtures/proposalsModule.ts @@ -1,10 +1,10 @@ import { KeyringPair } from '@polkadot/keyring/types' -import { ApiWrapper, WorkingGroups } from '../../../utils/apiWrapper' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { v4 as uuid } from 'uuid' import BN from 'bn.js' -import { WorkingGroupOpening } from '../../../dto/workingGroupOpening' -import { FillOpeningParameters } from '../../../dto/fillOpeningParameters' -import { Fixture } from '../../../utils/fixture' +import { WorkingGroupOpening } from '../../dto/workingGroupOpening' +import { FillOpeningParameters } from '../../dto/fillOpeningParameters' +import { Fixture } from './interfaces/fixture' import { Bytes } from '@polkadot/types' import { assert } from 'chai' @@ -81,6 +81,9 @@ export class CreateWorkingGroupLeaderOpeningFixture implements Fixture { ) const proposalNumber: BN = await proposalPromise this.result = proposalNumber + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -131,8 +134,10 @@ export class BeginWorkingGroupLeaderApplicationReviewFixture implements Fixture this.openingId, this.workingGroup ) - const proposalNumber: BN = await proposalPromise - this.result = proposalNumber + this.result = await proposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -207,8 +212,10 @@ export class FillLeaderOpeningProposalFixture implements Fixture { proposalStake, fillOpeningParameters ) - const proposalNumber: BN = await proposalPromise - this.result = proposalNumber + this.result = await proposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -270,8 +277,10 @@ export class TerminateLeaderRoleProposalFixture implements Fixture { this.slash, workingGroupString ) - const proposalNumber: BN = await proposalPromise - this.result = proposalNumber + this.result = await proposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -325,8 +334,10 @@ export class SetLeaderRewardProposalFixture implements Fixture { this.payoutAmount, workingGroupString ) - const proposalNumber: BN = await proposalPromise - this.result = proposalNumber + this.result = await proposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -380,8 +391,10 @@ export class DecreaseLeaderStakeProposalFixture implements Fixture { this.stakeDecrement, workingGroupString ) - const proposalNumber: BN = await proposalPromise - this.result = proposalNumber + this.result = await proposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -435,8 +448,10 @@ export class SlashLeaderProposalFixture implements Fixture { this.slashAmount, workingGroupString ) - const proposalNumber: BN = await proposalPromise - this.result = proposalNumber + this.result = await proposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -488,8 +503,10 @@ export class WorkingGroupMintCapacityProposalFixture implements Fixture { this.mintCapacity, workingGroupString ) - const proposalNumber: BN = await proposalPromise - this.result = proposalNumber + this.result = await proposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -610,6 +627,9 @@ export class ElectionParametersProposalFixture implements Fixture { proposedMinVotingStake.eq(newMinVotingStake), `Min voting stake has unexpected value ${newMinVotingStake}, expected ${proposedMinVotingStake}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -657,6 +677,9 @@ export class SetLeadProposalFixture implements Fixture { newLead === this.m1KeyPairs[1].address, `New lead has unexpected value ${newLead}, expected ${this.m1KeyPairs[1].address}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -726,6 +749,9 @@ export class SpendingProposalFixture implements Fixture { this.m1KeyPairs[0].address } has unexpected balance ${balanceAfterMinting}, expected ${balanceBeforeMinting.add(this.spendingBalance)}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -769,6 +795,9 @@ export class TextProposalFixture implements Fixture { const textProposalPromise = this.apiWrapper.expectProposalFinalized() await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) await textProposalPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -827,6 +856,9 @@ export class ValidatorCountProposalFixture implements Fixture { proposedValidatorCount.eq(newValidatorCount), `Validator count has unexpeccted value ${newValidatorCount}, expected ${proposedValidatorCount}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -889,6 +921,9 @@ export class ContentWorkingGroupMintCapacityProposalFixture implements Fixture { proposedMintingCapacity.eq(newMintingCapacity), `Content working group has unexpected minting capacity ${newMintingCapacity}, expected ${proposedMintingCapacity}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -937,6 +972,9 @@ export class UpdateRuntimeFixture implements Fixture { const runtimePromise = this.apiWrapper.expectProposalFinalized() await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, proposalNumber) await runtimePromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -961,5 +999,8 @@ export class VoteForProposalFixture implements Fixture { const proposalExecutionPromise = this.apiWrapper.expectProposalFinalized() await this.apiWrapper.batchApproveProposal(this.m2KeyPairs, this.proposalNumber) await proposalExecutionPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } diff --git a/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts b/tests/network-tests/src/iznik/tests/fixtures/workingGroupModule.ts similarity index 94% rename from tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts rename to tests/network-tests/src/iznik/tests/fixtures/workingGroupModule.ts index 022a46395d..97328e4d7a 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/impl/workingGroupModule.ts +++ b/tests/network-tests/src/iznik/tests/fixtures/workingGroupModule.ts @@ -1,16 +1,16 @@ import BN from 'bn.js' import { assert } from 'chai' -import { ApiWrapper, WorkingGroups } from '../../../utils/apiWrapper' +import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { KeyringPair } from '@polkadot/keyring/types' import { Balance, Event } from '@polkadot/types/interfaces' import { Keyring } from '@polkadot/api' import { v4 as uuid } from 'uuid' import { RewardRelationship } from '@nicaea/types/recurring-rewards' import { Worker, ApplicationIdToWorkerIdMap, Application } from '@nicaea/types/working-group' -import { Utils } from '../../../utils/utils' +import { Utils } from '../../utils/utils' import { Opening as HiringOpening } from '@nicaea/types/hiring' -import { WorkingGroupOpening } from '../../../dto/workingGroupOpening' -import { Fixture } from '../../../utils/fixture' +import { WorkingGroupOpening } from '../../dto/workingGroupOpening' +import { Fixture } from './interfaces/fixture' export class AddWorkerOpeningFixture implements Fixture { private apiWrapper: ApiWrapper @@ -156,8 +156,10 @@ export class AddLeaderOpeningFixture implements Fixture { const addOpeningPromise: Promise = this.apiWrapper.expectEvent('OpeningAdded') await this.apiWrapper.sudoAddOpening(this.sudo, opening, this.module) const openingId: BN = ((await addOpeningPromise).data[0] as unknown) as BN - this.result = openingId + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -192,6 +194,9 @@ export class AcceptApplicationsFixture implements Fixture { const opening: HiringOpening = await this.apiWrapper.getHiringOpening(this.openingId) assert(opening.is_active, `Opening ${this.openingId} is not active`) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -272,6 +277,9 @@ export class WithdrawApplicationFixture implements Fixture { ) assert(activeApplications.length === 0, `Unexpected active application found for ${keyPair.address}`) }) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -299,6 +307,9 @@ export class BeginApplicationReviewFixture implements Fixture { const beginApplicantReviewPromise: Promise = this.apiWrapper.expectApplicationReviewBegan() await this.apiWrapper.beginApplicantReview(this.lead, this.openingId, this.module) await beginApplicantReviewPromise + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -318,6 +329,9 @@ export class BeginLeaderApplicationReviewFixture implements Fixture { public async runner(expectFailure: boolean): Promise { // Begin application review await this.apiWrapper.sudoBeginApplicantReview(this.sudo, this.openingId, this.module) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -395,6 +409,9 @@ export class FillOpeningFixture implements Fixture { this.membersKeyPairs.forEach((keyPair) => assert(openingWorkersAccounts.includes(keyPair.address), `Account ${keyPair.address} is not worker`) ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -468,6 +485,9 @@ export class FillLeaderOpeningFixture implements Fixture { openingLeaderAccount === this.membersKeyPairs[0].address, `Unexpected leader account ${openingLeaderAccount}, expected ${this.membersKeyPairs[0].address}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -505,6 +525,9 @@ export class IncreaseStakeFixture implements Fixture { increasedWorkerStake.eq(newWorkerStake), `Unexpected worker stake ${newWorkerStake}, expected ${increasedWorkerStake}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -543,6 +566,9 @@ export class UpdateRewardAccountFixture implements Fixture { newRewardAccount === createdAccount.address, `Unexpected role account ${newRewardAccount}, expected ${createdAccount.address}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -585,6 +611,9 @@ export class UpdateRoleAccountFixture implements Fixture { ) this.membersKeyPairs[0] = createdAccount + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -627,6 +656,9 @@ export class TerminateApplicationsFixture implements Fixture { ) assert(activeApplications.length === 0, `Account ${keyPair.address} has unexpected active applications`) }) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -768,7 +800,7 @@ export class LeaveRoleFixture implements Fixture { const leaveRoleFee = this.apiWrapper.estimateLeaveRoleFee(this.module) await this.apiWrapper.transferBalanceToAccounts(this.sudo, this.membersKeyPairs, leaveRoleFee) - await this.apiWrapper.batchLeaveRole(this.membersKeyPairs, uuid().substring(0, 8), false, this.module) + await this.apiWrapper.batchLeaveRole(this.membersKeyPairs, uuid().substring(0, 8), expectFailure, this.module) // Assertions this.membersKeyPairs.forEach(async (keyPair) => { @@ -821,28 +853,12 @@ export class AwaitPayoutFixture implements Fixture { balanceAfterSecondPayout.eq(expectedBalanceSecond), `Unexpected balance, expected ${expectedBalanceSecond} got ${balanceAfterSecondPayout}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } -// export class SetMintCapacityFixture implements Fixture { -// private apiWrapper: ApiWrapper -// private sudo: KeyringPair -// private capacity: BN -// private module: WorkingGroups -// -// constructor(apiWrapper: ApiWrapper, sudo: KeyringPair, capacity:, module: WorkingGroups) { -// this.apiWrapper = apiWrapper; -// this.sudo = sudo; -// this.capacity = capacity; -// this.module = module; -// } -// -// public async runner(expectFailure: boolean): Promise { -// await this.apiWrapper.sudoSetWorkingGroupMintCapacity(this.sudo, this.capacity, this.module) -// } -// -// } - export class ExpectLeadOpeningAddedFixture implements Fixture { private apiWrapper: ApiWrapper @@ -866,6 +882,9 @@ export class ExpectLeadOpeningAddedFixture implements Fixture { const event: Event = await this.apiWrapper.expectEvent('OpeningAdded') this.events.push(event) this.result = (event.data as unknown) as BN + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -906,6 +925,9 @@ export class ExpectLeaderSetFixture implements Fixture { `Role account ids does not match, leader account: ${worker.role_account_id}, application account ${application.role_account_id}` ) this.result = leadWorkerId + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -931,6 +953,9 @@ export class ExpectBeganApplicationReviewFixture implements Fixture { const event: Event = await this.apiWrapper.expectEvent('BeganApplicationReview') this.events.push(event) this.result = (event.data as unknown) as BN + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -959,6 +984,9 @@ export class ExpectLeaderRoleTerminatedFixture implements Fixture { this.events.push(event) const leadWorkerId: BN | undefined = await this.apiWrapper.getLeadWorkerId(this.module) assert(leadWorkerId === undefined, `Unexpected lead worker id: ${leadWorkerId}, expected none`) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -995,6 +1023,9 @@ export class ExpectLeaderRewardAmountUpdatedFixture implements Fixture { receivedReward.eq(this.expectedReward), `Unexpected reward amount for worker with id ${leadWorkerId}: ${receivedReward}, expected ${this.expectedReward}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -1029,6 +1060,9 @@ export class ExpectLeaderStakeDecreasedFixture implements Fixture { receivedStake.eq(this.expectedStake), `Unexpected stake amount for worker with id ${leadWorkerId}: ${receivedStake}, expected ${this.expectedStake}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -1063,6 +1097,9 @@ export class ExpectLeaderSlashedFixture implements Fixture { receivedStake.eq(this.expectedStake), `Unexpected stake amount for worker with id after slash ${leadWorkerId}: ${receivedStake}, expected ${this.expectedStake}` ) + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } @@ -1095,5 +1132,8 @@ export class ExpectMintCapacityChangedFixture implements Fixture { `Unexpected mint capacity: ${receivedMintCapacity}, expected ${this.expectedMintCapacity}` ) this.result = receivedMintCapacity + if (expectFailure) { + throw new Error('Successful fixture run while expecting failure') + } } } diff --git a/tests/network-tests/src/iznik/tests/membershipCreationTest.ts b/tests/network-tests/src/iznik/tests/membership/membershipCreationTest.ts similarity index 82% rename from tests/network-tests/src/iznik/tests/membershipCreationTest.ts rename to tests/network-tests/src/iznik/tests/membership/membershipCreationTest.ts index 71516b2233..1592f58655 100644 --- a/tests/network-tests/src/iznik/tests/membershipCreationTest.ts +++ b/tests/network-tests/src/iznik/tests/membership/membershipCreationTest.ts @@ -1,13 +1,13 @@ import { KeyringPair } from '@polkadot/keyring/types' import { Keyring, WsProvider } from '@polkadot/api' -import { initConfig } from '../utils/config' -import { setTestTimeout } from '../utils/setTestTimeout' +import { initConfig } from '../../utils/config' +import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { ApiWrapper } from '../utils/apiWrapper' -import { closeApi } from './impl/closeApi' -import { BuyMembershipHappyCaseFixture, BuyMembershipWithInsufficienFundsFixture } from './impl/membershipModule' -import { Utils } from '../utils/utils' +import { ApiWrapper } from '../../utils/apiWrapper' +import { closeApi } from '../../utils/closeApi' +import { BuyMembershipHappyCaseFixture, BuyMembershipWithInsufficienFundsFixture } from '../fixtures/membershipModule' +import { Utils } from '../../utils/utils' tap.mocha.describe('Membership creation scenario', async () => { initConfig() @@ -22,7 +22,7 @@ tap.mocha.describe('Membership creation scenario', async () => { const N: number = +process.env.MEMBERSHIP_CREATION_N! const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) - let aKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) + const aKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! const durationInBlocks = 7 diff --git a/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts index 2b1dfca516..d7d7ba3b90 100644 --- a/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/contentWorkingGroupMintCapacityProposalTest.ts @@ -5,11 +5,11 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' -import { ContentWorkingGroupMintCapacityProposalFixture } from './impl/proposalsModule' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { ContentWorkingGroupMintCapacityProposalFixture } from '../fixtures/proposalsModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' import { Utils } from '../../utils/utils' tap.mocha.describe('Validator count proposal scenario', async () => { diff --git a/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts index f63cfa1a9a..208810c924 100644 --- a/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/electionParametersProposalTest.ts @@ -5,12 +5,12 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' import { Utils } from '../../utils/utils' -import { ElectionParametersProposalFixture } from './impl/proposalsModule' +import { ElectionParametersProposalFixture } from '../fixtures/proposalsModule' tap.mocha.describe('Election parameters proposal scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts index 7279ec2cd5..0c698d172d 100644 --- a/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts +++ b/tests/network-tests/src/iznik/tests/proposals/manageLeaderRole.ts @@ -5,10 +5,10 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' import { BeginWorkingGroupLeaderApplicationReviewFixture, CreateWorkingGroupLeaderOpeningFixture, @@ -18,7 +18,7 @@ import { SlashLeaderProposalFixture, TerminateLeaderRoleProposalFixture, VoteForProposalFixture, -} from './impl/proposalsModule' +} from '../fixtures/proposalsModule' import { ApplyForOpeningFixture, ExpectBeganApplicationReviewFixture, @@ -28,7 +28,7 @@ import { ExpectLeaderSlashedFixture, ExpectLeaderStakeDecreasedFixture, ExpectLeadOpeningAddedFixture, -} from '../workingGroup/impl/workingGroupModule' +} from '../fixtures/workingGroupModule' import { Utils } from '../../utils/utils' tap.mocha.describe('Set lead proposal scenario', async () => { @@ -109,7 +109,7 @@ tap.mocha.describe('Set lead proposal scenario', async () => { tap.test('Propose create leader opening', async () => createWorkingGroupLeaderOpeningFixture.runner(false)) let voteForCreateOpeningProposalFixture: VoteForProposalFixture - let expectLeadOpeningAddedFixture: ExpectLeadOpeningAddedFixture = new ExpectLeadOpeningAddedFixture(apiWrapper) + const expectLeadOpeningAddedFixture: ExpectLeadOpeningAddedFixture = new ExpectLeadOpeningAddedFixture(apiWrapper) tap.test('Approve add opening proposal', async () => { voteForCreateOpeningProposalFixture = new VoteForProposalFixture( apiWrapper, @@ -148,7 +148,7 @@ tap.mocha.describe('Set lead proposal scenario', async () => { }) let voteForBeginReviewProposal: VoteForProposalFixture - let expectBeganApplicationReviewFixture: ExpectBeganApplicationReviewFixture = new ExpectBeganApplicationReviewFixture( + const expectBeganApplicationReviewFixture: ExpectBeganApplicationReviewFixture = new ExpectBeganApplicationReviewFixture( apiWrapper ) tap.test('Approve begin application review', async () => { diff --git a/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts index 9e9552b9b1..815f9edbd5 100644 --- a/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/setLeadProposalTest.ts @@ -5,12 +5,12 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' import { Utils } from '../../utils/utils' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' -import { SetLeadProposalFixture } from './impl/proposalsModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { SetLeadProposalFixture } from '../fixtures/proposalsModule' tap.mocha.describe('Set lead proposal scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts index ff57336c01..c821575c5c 100644 --- a/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/spendingProposalTest.ts @@ -5,12 +5,12 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' import { Utils } from '../../utils/utils' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' -import { SpendingProposalFixture } from './impl/proposalsModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { SpendingProposalFixture } from '../fixtures/proposalsModule' tap.mocha.describe('Spending proposal scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts index 77093901be..f1a3d2b35b 100644 --- a/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/textProposalTest.ts @@ -5,12 +5,12 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' import { Utils } from '../../utils/utils' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' -import { TextProposalFixture } from './impl/proposalsModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { TextProposalFixture } from '../fixtures/proposalsModule' tap.mocha.describe('Text proposal scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts b/tests/network-tests/src/iznik/tests/proposals/updateRuntimet.ts similarity index 90% rename from tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts rename to tests/network-tests/src/iznik/tests/proposals/updateRuntimet.ts index b01fa11e39..772718f6e8 100644 --- a/tests/network-tests/src/iznik/tests/proposals/updateRuntimeTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/updateRuntimet.ts @@ -5,12 +5,12 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' import { Utils } from '../../utils/utils' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' -import { UpdateRuntimeFixture } from './impl/proposalsModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { UpdateRuntimeFixture } from '../fixtures/proposalsModule' tap.mocha.describe('Update runtime scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts index 59f22fd610..9564a009cd 100644 --- a/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/validatorCountProposalTest.ts @@ -5,12 +5,12 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper } from '../../utils/apiWrapper' import { Utils } from '../../utils/utils' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' -import { ValidatorCountProposalFixture } from './impl/proposalsModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { ValidatorCountProposalFixture } from '../fixtures/proposalsModule' tap.mocha.describe('Validator count proposal scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts b/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts index a86307e827..9ec7bba452 100644 --- a/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts +++ b/tests/network-tests/src/iznik/tests/proposals/workingGroupMintCapacityProposalTest.ts @@ -5,13 +5,13 @@ import BN from 'bn.js' import { setTestTimeout } from '../../utils/setTestTimeout' import tap from 'tap' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { Utils } from '../../utils/utils' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' -import { ElectCouncilFixture } from '../impl/councilElectionModule' -import { VoteForProposalFixture, WorkingGroupMintCapacityProposalFixture } from './impl/proposalsModule' -import { ExpectMintCapacityChangedFixture } from '../workingGroup/impl/workingGroupModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { VoteForProposalFixture, WorkingGroupMintCapacityProposalFixture } from '../fixtures/proposalsModule' +import { ExpectMintCapacityChangedFixture } from '../fixtures/workingGroupModule' tap.mocha.describe('Set storage working group mint capacity scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts index 40d8616824..e26f4bf9f4 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/atLeastValueBugTest.ts @@ -1,6 +1,6 @@ import { initConfig } from '../../utils/config' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' @@ -12,10 +12,10 @@ import { BeginLeaderApplicationReviewFixture, FillLeaderOpeningFixture, LeaveRoleFixture, -} from './impl/workingGroupModule' +} from '../fixtures/workingGroupModule' import BN from 'bn.js' import tap from 'tap' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' import { Utils } from '../../utils/utils' tap.mocha.describe('Worker application happy case scenario', async () => { diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts index f77164ad5c..3df2b5d494 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsLeadTest.ts @@ -1,6 +1,6 @@ import { initConfig } from '../../utils/config' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' @@ -18,11 +18,11 @@ import { DecreaseStakeFixture, SlashFixture, TerminateRoleFixture, -} from './impl/workingGroupModule' -import BN from 'bn.js' -import tap = require('tap') -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +} from '../fixtures/workingGroupModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' import { Utils } from '../../utils/utils' +import BN from 'bn.js' +import tap from 'tap' tap.mocha.describe('Manage worker as worker scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts index 0b48ff6f49..ebd0c800b4 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/manageWorkerAsWorkerTest.ts @@ -1,6 +1,6 @@ import { initConfig } from '../../utils/config' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' @@ -16,11 +16,11 @@ import { IncreaseStakeFixture, LeaveRoleFixture, UpdateRewardAccountFixture, -} from './impl/workingGroupModule' -import BN from 'bn.js' -import tap = require('tap') -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +} from '../fixtures/workingGroupModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' import { Utils } from '../../utils/utils' +import BN from 'bn.js' +import tap from 'tap' tap.mocha.describe('Manage worker as worker scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts index 2f38d2fe9e..e881af38dd 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationHappyCaseTest.ts @@ -1,13 +1,13 @@ import { initConfig } from '../../utils/config' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' import BN from 'bn.js' import tap from 'tap' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' import { Utils } from '../../utils/utils' import { AddLeaderOpeningFixture, @@ -19,7 +19,7 @@ import { FillOpeningFixture, LeaveRoleFixture, WithdrawApplicationFixture, -} from './impl/workingGroupModule' +} from '../fixtures/workingGroupModule' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts index 843b5b5451..5c90b1df62 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerApplicationRejectionCaseTest.ts @@ -1,13 +1,13 @@ import { initConfig } from '../../utils/config' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' import { setTestTimeout } from '../../utils/setTestTimeout' import BN from 'bn.js' import tap from 'tap' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' import { Utils } from '../../utils/utils' import { AcceptApplicationsFixture, @@ -18,7 +18,7 @@ import { FillLeaderOpeningFixture, LeaveRoleFixture, TerminateApplicationsFixture, -} from './impl/workingGroupModule' +} from '../fixtures/workingGroupModule' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() diff --git a/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts b/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts index 0dadcfdc44..1c335afe10 100644 --- a/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts +++ b/tests/network-tests/src/iznik/tests/workingGroup/workerPayoutTest.ts @@ -1,6 +1,6 @@ import { initConfig } from '../../utils/config' import { registerJoystreamTypes } from '@nicaea/types' -import { closeApi } from '../impl/closeApi' +import { closeApi } from '../../utils/closeApi' import { ApiWrapper, WorkingGroups } from '../../utils/apiWrapper' import { WsProvider, Keyring } from '@polkadot/api' import { KeyringPair } from '@polkadot/keyring/types' @@ -12,14 +12,17 @@ import { AwaitPayoutFixture, BeginApplicationReviewFixture, BeginLeaderApplicationReviewFixture, + ExpectMintCapacityChangedFixture, FillLeaderOpeningFixture, FillOpeningFixture, LeaveRoleFixture, -} from './impl/workingGroupModule' +} from '../fixtures/workingGroupModule' import BN from 'bn.js' import tap from 'tap' -import { BuyMembershipHappyCaseFixture } from '../impl/membershipModule' +import { BuyMembershipHappyCaseFixture } from '../fixtures/membershipModule' import { Utils } from '../../utils/utils' +import { ElectCouncilFixture } from '../fixtures/councilElectionModule' +import { VoteForProposalFixture, WorkingGroupMintCapacityProposalFixture } from '../fixtures/proposalsModule' tap.mocha.describe('Worker application happy case scenario', async () => { initConfig() @@ -33,12 +36,18 @@ tap.mocha.describe('Worker application happy case scenario', async () => { const sudo: KeyringPair = keyring.addFromUri(sudoUri) const N: number = +process.env.WORKING_GROUP_N! - const nKeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m1KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) + const m2KeyPairs: KeyringPair[] = Utils.createKeyPairs(keyring, N) const leadKeyPair: KeyringPair[] = Utils.createKeyPairs(keyring, 1) const paidTerms: number = +process.env.MEMBERSHIP_PAID_TERMS! + const K: number = +process.env.COUNCIL_ELECTION_K! + const greaterStake: BN = new BN(+process.env.COUNCIL_STAKE_GREATER_AMOUNT!) + const lesserStake: BN = new BN(+process.env.COUNCIL_STAKE_LESSER_AMOUNT!) const applicationStake: BN = new BN(process.env.WORKING_GROUP_APPLICATION_STAKE!) const roleStake: BN = new BN(process.env.WORKING_GROUP_ROLE_STAKE!) + const leaderFirstRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) + const leaderRewardInterval: BN = new BN(process.env.LONG_REWARD_INTERVAL!) const firstRewardInterval: BN = new BN(process.env.SHORT_FIRST_REWARD_INTERVAL!) const rewardInterval: BN = new BN(process.env.SHORT_REWARD_INTERVAL!) const payoutAmount: BN = new BN(process.env.PAYOUT_AMOUNT!) @@ -49,13 +58,32 @@ tap.mocha.describe('Worker application happy case scenario', async () => { setTestTimeout(apiWrapper, durationInBlocks) - const happyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + const firstMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( apiWrapper, sudo, - nKeyPairs, + m1KeyPairs, paidTerms ) - tap.test('Creating a set of members', async () => happyCaseFixture.runner(false)) + tap.test('Creating first set of members', async () => firstMemberSetFixture.runner(false)) + + const secondMemberSetFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( + apiWrapper, + sudo, + m2KeyPairs, + paidTerms + ) + tap.test('Creating second set of members', async () => secondMemberSetFixture.runner(false)) + + const electCouncilFixture: ElectCouncilFixture = new ElectCouncilFixture( + apiWrapper, + m1KeyPairs, + m2KeyPairs, + K, + sudo, + greaterStake, + lesserStake + ) + tap.test('Elect council', async () => electCouncilFixture.runner(false)) const leaderHappyCaseFixture: BuyMembershipHappyCaseFixture = new BuyMembershipHappyCaseFixture( apiWrapper, @@ -67,14 +95,13 @@ tap.mocha.describe('Worker application happy case scenario', async () => { const addLeaderOpeningFixture: AddLeaderOpeningFixture = new AddLeaderOpeningFixture( apiWrapper, - nKeyPairs, + m1KeyPairs, sudo, applicationStake, roleStake, openingActivationDelay, WorkingGroups.StorageWorkingGroup ) - // let leadOpenignId: BN tap.test('Add lead opening', async () => await addLeaderOpeningFixture.runner(false)) let applyForLeaderOpeningFixture: ApplyForOpeningFixture @@ -109,17 +136,42 @@ tap.mocha.describe('Worker application happy case scenario', async () => { leadKeyPair, sudo, addLeaderOpeningFixture.getResult()!, - firstRewardInterval, - rewardInterval, + leaderFirstRewardInterval, + leaderRewardInterval, payoutAmount, WorkingGroups.StorageWorkingGroup ) await fillLeaderOpeningFixture.runner(false) }) + const workingGroupMintCapacityProposalFixture: WorkingGroupMintCapacityProposalFixture = new WorkingGroupMintCapacityProposalFixture( + apiWrapper, + m1KeyPairs, + sudo, + mintCapacity, + WorkingGroups.StorageWorkingGroup + ) + tap.test('Propose mint capacity', async () => workingGroupMintCapacityProposalFixture.runner(false)) + + let voteForProposalFixture: VoteForProposalFixture + const expectMintCapacityChanged: ExpectMintCapacityChangedFixture = new ExpectMintCapacityChangedFixture( + apiWrapper, + mintCapacity + ) + tap.test('Approve mint capacity', async () => { + voteForProposalFixture = new VoteForProposalFixture( + apiWrapper, + m2KeyPairs, + sudo, + workingGroupMintCapacityProposalFixture.getResult()! + ) + voteForProposalFixture.runner(false) + await expectMintCapacityChanged.runner(false) + }) + const addWorkerOpeningFixture: AddWorkerOpeningFixture = new AddWorkerOpeningFixture( apiWrapper, - nKeyPairs, + m1KeyPairs, leadKeyPair[0], sudo, applicationStake, @@ -134,7 +186,7 @@ tap.mocha.describe('Worker application happy case scenario', async () => { tap.test('First apply for worker opening', async () => { applyForWorkerOpeningFixture = new ApplyForOpeningFixture( apiWrapper, - nKeyPairs, + m1KeyPairs, sudo, applicationStake, roleStake, @@ -160,7 +212,7 @@ tap.mocha.describe('Worker application happy case scenario', async () => { tap.test('Fill worker opening', async () => { fillOpeningFixture = new FillOpeningFixture( apiWrapper, - nKeyPairs, + m1KeyPairs, leadKeyPair[0], sudo, addWorkerOpeningFixture.getResult()!, @@ -174,7 +226,7 @@ tap.mocha.describe('Worker application happy case scenario', async () => { const awaitPayoutFixture: AwaitPayoutFixture = new AwaitPayoutFixture( apiWrapper, - nKeyPairs, + m1KeyPairs, WorkingGroups.StorageWorkingGroup ) tap.test('Await worker payout', async () => awaitPayoutFixture.runner(false)) diff --git a/tests/network-tests/src/iznik/tests/impl/closeApi.ts b/tests/network-tests/src/iznik/utils/closeApi.ts similarity index 70% rename from tests/network-tests/src/iznik/tests/impl/closeApi.ts rename to tests/network-tests/src/iznik/utils/closeApi.ts index 6d16dd237f..f783623d84 100644 --- a/tests/network-tests/src/iznik/tests/impl/closeApi.ts +++ b/tests/network-tests/src/iznik/utils/closeApi.ts @@ -1,4 +1,4 @@ -import { ApiWrapper } from '../../utils/apiWrapper' +import { ApiWrapper } from './apiWrapper' import tap from 'tap' export function closeApi(apiWrapper: ApiWrapper) {