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}3233export interface IFinCounselors {34 greg: IKeyringPair;35 ildar: IKeyringPair;36 andy: IKeyringPair;37}3839export interface ITechComms {40 greg: IKeyringPair;41 andy: IKeyringPair;42 constantine: IKeyringPair;43}4445export function initFinCouncil(donor: IKeyringPair, superuser: IKeyringPair): Promise<IFinCounselors> {46 return usingPlaygrounds(async (helper) => {47 const [greg, ildar, andy] = await helper.arrange.createAccounts([10_000n, 10_000n, 10_000n], donor);48 const sudo = helper.getSudo();49 {50 const members = (await helper.callRpc('api.query.financialCouncilMembership.members')).toJSON() as [];51 if(members.length != 0) {52 await clearFinCouncil(superuser);53 }54 }55 const expectedMembers = [greg, ildar, andy];56 for(const member of expectedMembers) {57 await sudo.executeExtrinsic(superuser, 'api.tx.financialCouncilMembership.addMember', [member.address]);58 }59 await sudo.executeExtrinsic(superuser, 'api.tx.financialCouncilMembership.setPrime', [greg.address]);60 {61 const members = (await helper.callRpc('api.query.financialCouncilMembership.members')).toJSON();62 expect(members).to.containSubset(expectedMembers.map((x: IKeyringPair) => x.address));63 expect(members.length).to.be.equal(expectedMembers.length);64 }6566 return {67 greg,68 ildar,69 andy,70 };71 });72}7374export async function clearFinCouncil(superuser: IKeyringPair) {75 await usingPlaygrounds(async (helper) => {76 let members = (await helper.callRpc('api.query.financialCouncilMembership.members')).toJSON();77 if(members.length) {78 const sudo = helper.getSudo();79 for(const address of members) {80 await sudo.executeExtrinsic(superuser, 'api.tx.financialCouncilMembership.removeMember', [address]);81 }82 members = (await helper.callRpc('api.query.financialCouncilMembership.members')).toJSON();83 }84 expect(members).to.be.deep.equal([]);85 });86}8788export async function initCouncil(donor: IKeyringPair, superuser: IKeyringPair) {89 let counselors: IKeyringPair[] = [];9091 await usingPlaygrounds(async (helper) => {92 const [alex, ildar, charu, filip, irina] = await helper.arrange.createAccounts([10_000n, 10_000n, 10_000n, 10_000n, 10_000n], donor);93 const sudo = helper.getSudo();94 {95 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON() as [];96 if(members.length != 0) {97 await clearCouncil(superuser);98 }99 }100 const expectedMembers = [alex, ildar, charu, filip, irina];101 for(const member of expectedMembers) {102 await sudo.executeExtrinsic(superuser, 'api.tx.councilMembership.addMember', [member.address]);103 }104 await sudo.executeExtrinsic(superuser, 'api.tx.councilMembership.setPrime', [alex.address]);105 {106 const members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();107 expect(members).to.containSubset(expectedMembers.map((x: IKeyringPair) => x.address));108 expect(members.length).to.be.equal(expectedMembers.length);109 }110111 counselors = [alex, ildar, charu, filip, irina];112 });113 return {114 alex: counselors[0],115 ildar: counselors[1],116 charu: counselors[2],117 filip: counselors[3],118 irina: counselors[4],119 };120}121122export async function clearCouncil(superuser: IKeyringPair) {123 await usingPlaygrounds(async (helper) => {124 let members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();125 if(members.length) {126 const sudo = helper.getSudo();127 for(const address of members) {128 await sudo.executeExtrinsic(superuser, 'api.tx.councilMembership.removeMember', [address]);129 }130 members = (await helper.callRpc('api.query.councilMembership.members')).toJSON();131 }132 expect(members).to.be.deep.equal([]);133 });134}135136137export async function initTechComm(donor: IKeyringPair, superuser: IKeyringPair) {138 let techcomms: IKeyringPair[] = [];139140 await usingPlaygrounds(async (helper) => {141 const [greg, andy, constantine] = await helper.arrange.createAccounts([10_000n, 10_000n, 10_000n], donor);142 const sudo = helper.getSudo();143 {144 const members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON() as [];145 if(members.length != 0) {146 await clearTechComm(superuser);147 }148 }149 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.addMember', [greg.address]);150 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.addMember', [andy.address]);151 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.addMember', [constantine.address]);152 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.setPrime', [greg.address]);153 {154 const members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();155 expect(members).to.containSubset([greg.address, andy.address, constantine.address]);156 expect(members.length).to.be.equal(3);157 }158159 techcomms = [greg, andy, constantine];160 });161162 return {163 greg: techcomms[0],164 andy: techcomms[1],165 constantine: techcomms[2],166 };167}168169export async function clearTechComm(superuser: IKeyringPair) {170 await usingPlaygrounds(async (helper) => {171 let members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();172 if(members.length) {173 const sudo = helper.getSudo();174 for(const address of members) {175 await sudo.executeExtrinsic(superuser, 'api.tx.technicalCommitteeMembership.removeMember', [address]);176 }177 members = (await helper.callRpc('api.query.technicalCommitteeMembership.members')).toJSON();178 }179 expect(members).to.be.deep.equal([]);180 });181}182183export async function initFellowship(donor: IKeyringPair, sudoer: IKeyringPair) {184 const numMembersInRank = 3;185 const memberBalance = 5000n;186 const members: IKeyringPair[][] = [];187188 await usingPlaygrounds(async (helper) => {189 const currentFellows = await helper.getApi().query.fellowshipCollective.members.keys();190191 if(currentFellows.length != 0) {192 await clearFellowship(sudoer);193 }194 for(let i = 0; i < fellowshipRankLimit; i++) {195 const rankMembers = await helper.arrange.createAccounts(196 Array(numMembersInRank).fill(memberBalance),197 donor,198 );199200 for(const member of rankMembers) {201 await helper.getSudo().fellowship.collective.addMember(sudoer, member.address);202203 for(let rank = 0; rank < i; rank++) {204 await helper.getSudo().fellowship.collective.promote(sudoer, member.address);205 }206 }207208 members.push(rankMembers);209 }210 });211212 return members;213}214215export async function clearFellowship(sudoer: IKeyringPair) {216 await usingPlaygrounds(async (helper) => {217 const fellowship = (await helper.getApi().query.fellowshipCollective.members.keys())218 .map((key) => key.args[0].toString());219 for(const member of fellowship) {220 await helper.getSudo().fellowship.collective.removeMember(sudoer, member, fellowshipRankLimit);221 }222 });223}224225export async function clearFellowshipReferenda(sudoer: IKeyringPair) {226 await usingPlaygrounds(async (helper) => {227 const proposalsCount = (await helper.getApi().query.fellowshipReferenda.referendumCount()) as u32;228 for(let i = 0; i < proposalsCount.toNumber(); i++) {229 await helper.getSudo().fellowship.referenda.cancel(sudoer, i);230 }231 });232}233234export async function hardResetFellowshipReferenda(sudoer: IKeyringPair) {235 await usingPlaygrounds(async (helper) => {236 const api = helper.getApi();237 const prefix = twox128('FellowshipReferenda');238 await helper.signTransaction(sudoer, api.tx.sudo.sudo(api.tx.system.killPrefix(prefix, 100)));239 });240}241242export async function hardResetDemocracy(sudoer: IKeyringPair) {243 await usingPlaygrounds(async (helper) => {244 const api = helper.getApi();245 const prefix = twox128('Democracy');246 await helper.signTransaction(sudoer, api.tx.sudo.sudo(api.tx.system.killPrefix(prefix, 100)));247 });248}249250export async function hardResetGovScheduler(sudoer: IKeyringPair) {251 await usingPlaygrounds(async (helper) => {252 const api = helper.getApi();253 const prefix = twox128('GovScheduler');254 await helper.signTransaction(sudoer, api.tx.sudo.sudo(api.tx.system.killPrefix(prefix, 500)));255 });256}257258export async function voteUnanimouslyInFellowship(helper: DevUniqueHelper, fellows: IKeyringPair[][], minRank: number, referendumIndex: number) {259 for(let rank = minRank; rank < fellowshipRankLimit; rank++) {260 for(const member of fellows[rank]) {261 await helper.fellowship.collective.vote(member, referendumIndex, true);262 }263 }264}265266export function dummyProposalCall(helper: UniqueHelper) {267 return helper.constructApiCall('api.tx.system.remark', ['dummy proposal' + (new Date()).getTime()]);268}269270export function dummyProposal(helper: UniqueHelper) {271 return {272 Inline: dummyProposalCall(helper).method.toHex(),273 };274}