ElectCouncilFixture.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { BaseQueryNodeFixture, FixtureRunner } from '../../Fixture'
  2. import { AddStakingAccountsHappyCaseFixture, BuyMembershipHappyCaseFixture } from '../membership'
  3. import { assertCouncilMembersRuntimeQnMatch } from './common'
  4. import { blake2AsHex } from '@polkadot/util-crypto'
  5. import { MINIMUM_STAKING_ACCOUNT_BALANCE } from '../../consts'
  6. import { assert } from 'chai'
  7. export class ElectCouncilFixture extends BaseQueryNodeFixture {
  8. public async execute(): Promise<void> {
  9. const { api, query } = this
  10. const { councilSize, minNumberOfExtraCandidates } = api.consts.council
  11. const numberOfCandidates = councilSize.add(minNumberOfExtraCandidates).toNumber()
  12. const numberOfVoters = numberOfCandidates
  13. // Prepare memberships
  14. const candidatesMemberAccounts = (await this.api.createKeyPairs(numberOfCandidates)).map((kp) => kp.address)
  15. const buyMembershipsFixture = new BuyMembershipHappyCaseFixture(api, query, candidatesMemberAccounts)
  16. await new FixtureRunner(buyMembershipsFixture).run()
  17. const candidatesMemberIds = buyMembershipsFixture.getCreatedMembers()
  18. // Prepare staking accounts
  19. const councilCandidateStake = api.consts.council.minCandidateStake
  20. const voteStake = api.consts.referendum.minimumStake
  21. const candidatesStakingAccounts = (await this.api.createKeyPairs(numberOfCandidates)).map((kp) => kp.address)
  22. const addStakingAccountsFixture = new AddStakingAccountsHappyCaseFixture(
  23. api,
  24. query,
  25. candidatesStakingAccounts.map((account, i) => ({
  26. asMember: candidatesMemberIds[i],
  27. account,
  28. stakeAmount: councilCandidateStake,
  29. }))
  30. )
  31. await new FixtureRunner(addStakingAccountsFixture).run()
  32. const votersStakingAccounts = (await this.api.createKeyPairs(numberOfVoters)).map((kp) => kp.address)
  33. await api.treasuryTransferBalanceToAccounts(votersStakingAccounts, voteStake.addn(MINIMUM_STAKING_ACCOUNT_BALANCE))
  34. // Announcing stage
  35. await this.api.untilCouncilStage('Announcing')
  36. const applyForCouncilTxs = candidatesMemberIds.map((memberId, i) =>
  37. api.tx.council.announceCandidacy(
  38. memberId,
  39. candidatesStakingAccounts[i],
  40. candidatesMemberAccounts[i],
  41. councilCandidateStake
  42. )
  43. )
  44. await api.prepareAccountsForFeeExpenses(candidatesMemberAccounts, applyForCouncilTxs)
  45. await api.sendExtrinsicsAndGetResults(applyForCouncilTxs, candidatesMemberAccounts)
  46. // Voting stage
  47. await this.api.untilCouncilStage('Voting')
  48. const cycleId = (await this.api.query.referendum.stage()).asType('Voting').current_cycle_id
  49. const votingTxs = votersStakingAccounts.map((account, i) => {
  50. const accountId = api.createType('AccountId', account)
  51. const optionId = candidatesMemberIds[i % numberOfCandidates]
  52. const salt = api.createType('Bytes', `salt${i}`)
  53. const payload = Buffer.concat([accountId.toU8a(), optionId.toU8a(), salt.toU8a(), cycleId.toU8a()])
  54. const commitment = blake2AsHex(payload)
  55. return api.tx.referendum.vote(commitment, voteStake)
  56. })
  57. await api.prepareAccountsForFeeExpenses(votersStakingAccounts, votingTxs)
  58. await api.sendExtrinsicsAndGetResults(votingTxs, votersStakingAccounts)
  59. // Revealing stage
  60. await this.api.untilCouncilStage('Revealing')
  61. const revealingTxs = votersStakingAccounts.map((account, i) => {
  62. const optionId = candidatesMemberIds[i % numberOfCandidates]
  63. return api.tx.referendum.revealVote(`salt${i}`, optionId)
  64. })
  65. await api.prepareAccountsForFeeExpenses(votersStakingAccounts, votingTxs)
  66. await api.sendExtrinsicsAndGetResults(revealingTxs, votersStakingAccounts)
  67. const candidatesToWinIds = candidatesMemberIds.slice(0, councilSize.toNumber()).map((id) => id.toString())
  68. // check intermediate election winners are properly set
  69. await query.tryQueryWithTimeout(
  70. () => query.getReferendumIntermediateWinners(cycleId.toNumber(), councilSize.toNumber()),
  71. (qnReferendumIntermediateWinners) => {
  72. assert.sameMembers(
  73. qnReferendumIntermediateWinners.map((item) => item.member.id.toString()),
  74. candidatesToWinIds
  75. )
  76. }
  77. )
  78. await this.api.untilCouncilStage('Idle')
  79. const councilMembers = await api.query.council.councilMembers()
  80. assert.sameMembers(
  81. councilMembers.map((m) => m.membership_id.toString()),
  82. candidatesToWinIds
  83. )
  84. await assertCouncilMembersRuntimeQnMatch(this.api, this.query)
  85. }
  86. }