1import type {IKeyringPair} from '@polkadot/types/types';2import {xxhashAsHex} from '@polkadot/util-crypto';3import type {u32} from '@polkadot/types-codec';4import {usingPlaygrounds, expect} from '@unique/test-utils/util.js';5import {UniqueHelper} from '@unique-nft/playgrounds/unique.js';6import {DevUniqueHelper} from '@unique/test-utils';78export const democracyLaunchPeriod = 35;9export const democracyVotingPeriod = 35;10export const councilMotionDuration = 35;11export const democracyEnactmentPeriod = 40;12export const democracyFastTrackVotingPeriod = 5;1314export const fellowshipRankLimit = 7;15export const fellowshipPropositionOrigin = 'FellowshipProposition';16export const fellowshipPreparePeriod = 3;17export const fellowshipConfirmPeriod = 3;18export const fellowshipMinEnactPeriod = 1;1920export const defaultEnactmentMoment = {After: 0};2122export const democracyTrackId = 10;23export const democracyTrackMinRank = 3;24const twox128 = (data: any) => xxhashAsHex(data, 128);25export interface ICounselors {26 alex: IKeyringPair;27 ildar: IKeyringPair;28 charu: IKeyringPair;29 filip: IKeyringPair;30 irina: IKeyringPair;31}32export interface ITechComms {33 greg: IKeyringPair;34 andy: IKeyringPair;35 constantine: IKeyringPair;36}3738export async function initCouncil(donor: IKeyringPair, superuser: IKeyringPair) {39 let counselors: IKeyringPair[] = [];4041 await usingPlaygrounds(async (helper) => {42 const [alex, ildar, charu, filip, irina] = await helper.arrange.createAccounts([10_000n, 10_000n, 10_000n, 10_000n, 10_000n], donor);43 const sudo = helper.getSudo();44 {45 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON() as [];46 if(members.length != 0) {47 await clearCouncil(superuser);48 }49 }50 const expectedMembers = [alex, ildar, charu, filip, irina];51 for(const member of expectedMembers) {52 await sudo.executeExtrinsic(superuser, 'api.tx.councilMembership.addMember', [member.address]);53 }54 await sudo.executeExtrinsic(superuser, 'api.tx.councilMembership.setPrime', [alex.address]);55 {56 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();57 expect(members).to.containSubset(expectedMembers.map((x: IKeyringPair) => x.address));58 expect(members.length).to.be.equal(expectedMembers.length);59 }6061 counselors = [alex, ildar, charu, filip, irina];62 });63 return {64 alex: counselors[0],65 ildar: counselors[1],66 charu: counselors[2],67 filip: counselors[3],68 irina: counselors[4],69 };70}7172export async function clearCouncil(superuser: IKeyringPair) {73 await usingPlaygrounds(async (helper) => {74 let members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();75 if(members.length) {76 const sudo = helper.getSudo();77 for(const address of members) {78 await sudo.executeExtrinsic(superuser, 'api.tx.councilMembership.removeMember', [address]);79 }80 members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();81 }82 expect(members).to.be.deep.equal([]);83 });84}858687export async function initTechComm(donor: IKeyringPair, superuser: IKeyringPair) {88 let techcomms: IKeyringPair[] = [];8990 await usingPlaygrounds(async (helper) => {91 const [greg, andy, constantine] = await helper.arrange.createAccounts([10_000n, 10_000n, 10_000n], donor);92 const sudo = helper.getSudo();93 {94 const members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON() as [];95 if(members.length != 0) {96 await clearTechComm(superuser);97 }98 }99 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.addMember', [greg.address]);100 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.addMember', [andy.address]);101 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.addMember', [constantine.address]);102 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.setPrime', [greg.address]);103 {104 const members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();105 expect(members).to.containSubset([greg.address, andy.address, constantine.address]);106 expect(members.length).to.be.equal(3);107 }108109 techcomms = [greg, andy, constantine];110 });111112 return {113 greg: techcomms[0],114 andy: techcomms[1],115 constantine: techcomms[2],116 };117}118119export async function clearTechComm(superuser: IKeyringPair) {120 await usingPlaygrounds(async (helper) => {121 let members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();122 if(members.length) {123 const sudo = helper.getSudo();124 for(const address of members) {125 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.removeMember', [address]);126 }127 members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();128 }129 expect(members).to.be.deep.equal([]);130 });131}132133export async function initFellowship(donor: IKeyringPair, sudoer: IKeyringPair) {134 const numMembersInRank = 3;135 const memberBalance = 5000n;136 const members: IKeyringPair[][] = [];137138 await usingPlaygrounds(async (helper) => {139 const currentFellows = await helper.getApi().query.fellowshipCollective.members.keys();140141 if(currentFellows.length != 0) {142 await clearFellowship(sudoer);143 }144 for(let i = 0; i < fellowshipRankLimit; i++) {145 const rankMembers = await helper.arrange.createAccounts(146 Array(numMembersInRank).fill(memberBalance),147 donor,148 );149150 for(const member of rankMembers) {151 await helper.getSudo().fellowship.collective.addMember(sudoer, member.address);152153 for(let rank = 0; rank < i; rank++) {154 await helper.getSudo().fellowship.collective.promote(sudoer, member.address);155 }156 }157158 members.push(rankMembers);159 }160 });161162 return members;163}164165export async function clearFellowship(sudoer: IKeyringPair) {166 await usingPlaygrounds(async (helper) => {167 const fellowship = (await helper.getApi().query.fellowshipCollective.members.keys())168 .map((key) => key.args[0].toString());169 for(const member of fellowship) {170 await helper.getSudo().fellowship.collective.removeMember(sudoer, member, fellowshipRankLimit);171 }172 });173}174175export async function clearFellowshipReferenda(sudoer: IKeyringPair) {176 await usingPlaygrounds(async (helper) => {177 const proposalsCount = (await helper.getApi().query.fellowshipReferenda.referendumCount()) as u32;178 for(let i = 0; i < proposalsCount.toNumber(); i++) {179 await helper.getSudo().fellowship.referenda.cancel(sudoer, i);180 }181 });182}183184export async function hardResetFellowshipReferenda(sudoer: IKeyringPair) {185 await usingPlaygrounds(async (helper) => {186 const api = helper.getApi();187 const prefix = twox128('FellowshipReferenda');188 await helper.signTransaction(sudoer, api.tx.sudo.sudo(api.tx.system.killPrefix(prefix, 100)));189 });190}191192export async function hardResetDemocracy(sudoer: IKeyringPair) {193 await usingPlaygrounds(async (helper) => {194 const api = helper.getApi();195 const prefix = twox128('Democracy');196 await helper.signTransaction(sudoer, api.tx.sudo.sudo(api.tx.system.killPrefix(prefix, 100)));197 });198}199200export async function hardResetGovScheduler(sudoer: IKeyringPair) {201 await usingPlaygrounds(async (helper) => {202 const api = helper.getApi();203 const prefix = twox128('GovScheduler');204 await helper.signTransaction(sudoer, api.tx.sudo.sudo(api.tx.system.killPrefix(prefix, 500)));205 });206}207208export async function voteUnanimouslyInFellowship(helper: DevUniqueHelper, fellows: IKeyringPair[][], minRank: number, referendumIndex: number) {209 for(let rank = minRank; rank < fellowshipRankLimit; rank++) {210 for(const member of fellows[rank]) {211 await helper.fellowship.collective.vote(member, referendumIndex, true);212 }213 }214}215216export function dummyProposalCall(helper: UniqueHelper) {217 return helper.constructApiCall('api.tx.system.remark', ['dummy proposal' + (new Date()).getTime()]);218}219220export function dummyProposal(helper: UniqueHelper) {221 return {222 Inline: dummyProposalCall(helper).method.toHex(),223 };224}