فهرست منبع

Rome Constantinople migration test implementation

Gleb Urvanov 4 سال پیش
والد
کامیت
6fc4a5fead

+ 4 - 2
tests/network-tests/.env

@@ -12,5 +12,7 @@ COUNCIL_STAKE_GREATER_AMOUNT = 1500
 COUNCIL_STAKE_LESSER_AMOUNT = 1000
 # Number of members with greater stake in council election test.
 COUNCIL_ELECTION_K = 2
-# Stake for runtime upgrade proposal test
-RUNTIME_UPGRADE_PROPOSAL_STAKE = 200
+# Balance to spend using spending proposal
+SPENDING_BALANCE = 1000
+# Minting capacity for content working group minting capacity test.
+MINTING_CAPACITY = 100020

BIN
tests/network-tests/joystream_node_runtime.wasm


+ 3 - 2
tests/network-tests/package.json

@@ -4,17 +4,18 @@
   "license": "GPL-3.0-only",
   "scripts": {
     "build": "tsc --build tsconfig.json",
-    "test": "mocha -r ts-node/register src/tests/*",
+    "test": "mocha -r ts-node/register src/tests/**/*",
     "lint": "tslint --project tsconfig.json",
     "prettier": "prettier --write ./src"
   },
   "dependencies": {
-    "@joystream/types": "^0.7.0",
+    "@joystream/types": "../joystream-apps/packages/joy-types",
     "@polkadot/api": "^0.96.1",
     "@polkadot/keyring": "^1.7.0-beta.5",
     "@types/bn.js": "^4.11.5",
     "bn.js": "^4.11.8",
     "dotenv": "^8.2.0",
+    "fs": "^0.0.1-security",
     "uuid": "^7.0.3"
   },
   "devDependencies": {

+ 7 - 5
tests/network-tests/src/tests/membershipCreationTest.ts

@@ -50,8 +50,8 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
     );
     nKeyPairs.forEach((keyPair, index) =>
       apiWrapper
-        .getMembership(keyPair.address)
-        .then(membership => assert(!membership.isEmpty, `Account ${keyPair.address} is not a member`))
+        .getMemberIds(keyPair.address)
+        .then(membership => assert(membership.length > 0, `Account ${keyPair.address} is not a member`))
     );
   }).timeout(defaultTimeout);
 
@@ -65,7 +65,9 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
         )
       );
     await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`, true);
-    apiWrapper.getMembership(aKeyPair.address).then(membership => assert(membership.isEmpty, 'Account A is a member'));
+    apiWrapper
+      .getMemberIds(aKeyPair.address)
+      .then(membership => assert(membership.length === 0, 'Account A is a member'));
   }).timeout(defaultTimeout);
 
   it('Account A was able to buy the membership with sufficient funds', async () => {
@@ -77,8 +79,8 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
       );
     await apiWrapper.buyMembership(aKeyPair, paidTerms, `late_member_${aKeyPair.address.substring(0, 8)}`);
     apiWrapper
-      .getMembership(aKeyPair.address)
-      .then(membership => assert(!membership.isEmpty, 'Account A is a not member'));
+      .getMemberIds(aKeyPair.address)
+      .then(membership => assert(membership.length > 0, 'Account A is a not member'));
   }).timeout(defaultTimeout);
 
   after(() => {

+ 75 - 0
tests/network-tests/src/tests/proposals/spendingProposalTest.ts

@@ -0,0 +1,75 @@
+import { initConfig } from '../../utils/config';
+import { Keyring, WsProvider } from '@polkadot/api';
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from '../membershipCreationTest';
+import { councilTest } from '../electingCouncilTest';
+import { registerJoystreamTypes } from '@joystream/types';
+import { ApiWrapper } from '../../utils/apiWrapper';
+import { v4 as uuid } from 'uuid';
+import BN = require('bn.js');
+
+describe.skip('Spending proposal network tests', () => {
+  initConfig();
+  const keyring = new Keyring({ type: 'sr25519' });
+  const nodeUrl: string = process.env.NODE_URL!;
+  const sudoUri: string = process.env.SUDO_ACCOUNT_URI!;
+  const spendingBalance: BN = new BN(+process.env.SPENDING_BALANCE!);
+  const defaultTimeout: number = 120000;
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  let apiWrapper: ApiWrapper;
+  let sudo: KeyringPair;
+
+  before(async function () {
+    this.timeout(defaultTimeout);
+    registerJoystreamTypes();
+    const provider = new WsProvider(nodeUrl);
+    apiWrapper = await ApiWrapper.create(provider);
+  });
+
+  membershipTest(m1KeyPairs);
+  membershipTest(m2KeyPairs);
+  councilTest(m1KeyPairs, m2KeyPairs);
+
+  it('Spending proposal test', async () => {
+    // Setup
+    sudo = keyring.addFromUri(sudoUri);
+    const description: string = 'spending proposal which is used for API network testing with some mock data';
+    const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee();
+
+    // Topping the balances
+    const proposalStake: BN = await apiWrapper.getRequiredProposalStake(25, 10000);
+    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);
+
+    // 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 runtime update proposal
+    const runtimePromise = apiWrapper.expectProposalFinalized();
+    await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
+    await runtimePromise;
+  }).timeout(defaultTimeout);
+
+  after(() => {
+    apiWrapper.close();
+  });
+});

+ 68 - 0
tests/network-tests/src/tests/proposals/textProposalTest.ts

@@ -0,0 +1,68 @@
+import { initConfig } from '../../utils/config';
+import { Keyring, WsProvider } from '@polkadot/api';
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from '../membershipCreationTest';
+import { councilTest } from '../electingCouncilTest';
+import { registerJoystreamTypes } from '@joystream/types';
+import { ApiWrapper } from '../../utils/apiWrapper';
+import { v4 as uuid } from 'uuid';
+import BN = require('bn.js');
+
+describe.skip('Text proposal network tests', () => {
+  initConfig();
+  const keyring = new Keyring({ type: 'sr25519' });
+  const nodeUrl: string = process.env.NODE_URL!;
+  const sudoUri: string = process.env.SUDO_ACCOUNT_URI!;
+  const defaultTimeout: number = 120000;
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  let apiWrapper: ApiWrapper;
+  let sudo: KeyringPair;
+
+  before(async function () {
+    this.timeout(defaultTimeout);
+    registerJoystreamTypes();
+    const provider = new WsProvider(nodeUrl);
+    apiWrapper = await ApiWrapper.create(provider);
+  });
+
+  membershipTest(m1KeyPairs);
+  membershipTest(m2KeyPairs);
+  councilTest(m1KeyPairs, m2KeyPairs);
+
+  it('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 = await apiWrapper.getRequiredProposalStake(25, 10000);
+    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 runtime update proposal
+    const textProposalPromise = apiWrapper.expectProposalFinalized();
+    await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
+    await textProposalPromise;
+  }).timeout(defaultTimeout);
+
+  after(() => {
+    apiWrapper.close();
+  });
+});

+ 19 - 13
tests/network-tests/src/tests/updateRuntimeTest.ts → tests/network-tests/src/tests/proposals/updateRuntimeTest.ts

@@ -1,19 +1,19 @@
-import { initConfig } from '../utils/config';
+import { initConfig } from '../../utils/config';
 import { Keyring, WsProvider } from '@polkadot/api';
 import { Bytes } from '@polkadot/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import { membershipTest } from './membershipCreationTest';
-import { councilTest } from './electingCouncilTest';
+import { membershipTest } from '../membershipCreationTest';
+import { councilTest } from '../electingCouncilTest';
 import { registerJoystreamTypes } from '@joystream/types';
-import { ApiWrapper } from '../utils/apiWrapper';
+import { ApiWrapper } from '../../utils/apiWrapper';
+import { v4 as uuid } from 'uuid';
 import BN = require('bn.js');
 
-describe('Runtime upgrade integration tests', () => {
+describe.skip('Runtime upgrade networt tests', () => {
   initConfig();
   const keyring = new Keyring({ type: 'sr25519' });
   const nodeUrl: string = process.env.NODE_URL!;
   const sudoUri: string = process.env.SUDO_ACCOUNT_URI!;
-  const proposalStake: BN = new BN(+process.env.RUNTIME_UPGRADE_PROPOSAL_STAKE!);
   const defaultTimeout: number = 120000;
 
   const m1KeyPairs: KeyringPair[] = new Array();
@@ -37,32 +37,38 @@ describe('Runtime upgrade integration tests', () => {
     // Setup
     sudo = keyring.addFromUri(sudoUri);
     const runtime: Bytes = await apiWrapper.getRuntime();
-    const description: string = 'runtime upgrade proposal which is used for API integration testing';
+    const description: string = 'runtime upgrade proposal which is used for API network testing';
+    const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee();
+
+    // Topping the balances
+    const proposalStake: BN = await apiWrapper.getRequiredProposalStake(1, 100);
     const runtimeProposalFee: BN = apiWrapper.estimateProposeRuntimeUpgradeFee(
       proposalStake,
       description,
       description,
       runtime
     );
-    const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee();
-
-    // Topping the balances
     await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake));
     await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee);
 
     // Proposal creation
+    console.log('proposing new runtime');
     const proposalPromise = apiWrapper.expectProposalCreated();
+    console.log('sending extr');
     await apiWrapper.proposeRuntime(
       m1KeyPairs[0],
       proposalStake,
-      'testing runtime',
-      'runtime to test proposal functionality',
+      'testing runtime' + uuid().substring(0, 8),
+      'runtime to test proposal functionality' + uuid().substring(0, 8),
       runtime
     );
     const proposalNumber = await proposalPromise;
+    console.log('proposed');
 
     // Approving runtime update proposal
-    const runtimePromise = apiWrapper.expectRuntimeUpgraded();
+    console.log('block number ' + apiWrapper.getBestBlock());
+    console.log('approving new runtime');
+    const runtimePromise = apiWrapper.expectProposalFinalized();
     await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
     await runtimePromise;
   }).timeout(defaultTimeout);

+ 80 - 0
tests/network-tests/src/tests/proposals/workingGroupMmintCapacityProposalTest.ts

@@ -0,0 +1,80 @@
+import { initConfig } from '../../utils/config';
+import { Keyring, WsProvider } from '@polkadot/api';
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from '../membershipCreationTest';
+import { councilTest } from '../electingCouncilTest';
+import { registerJoystreamTypes } from '@joystream/types';
+import { ApiWrapper } from '../../utils/apiWrapper';
+import { v4 as uuid } from 'uuid';
+import BN = require('bn.js');
+
+describe.skip('Mint capacity proposal network tests', () => {
+  initConfig();
+  const keyring = new Keyring({ type: 'sr25519' });
+  const nodeUrl: string = process.env.NODE_URL!;
+  const sudoUri: string = process.env.SUDO_ACCOUNT_URI!;
+  const mintingCapacity: BN = new BN(+process.env.MINTING_CAPACITY!);
+  const defaultTimeout: number = 120000;
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  let apiWrapper: ApiWrapper;
+  let sudo: KeyringPair;
+
+  before(async function () {
+    this.timeout(defaultTimeout);
+    registerJoystreamTypes();
+    const provider = new WsProvider(nodeUrl);
+    apiWrapper = await ApiWrapper.create(provider);
+  });
+
+  membershipTest(m1KeyPairs);
+  membershipTest(m2KeyPairs);
+  councilTest(m1KeyPairs, m2KeyPairs);
+
+  // TODO implement the test
+  it('Mint capacity proposal test', async () => {
+    // Setup
+    sudo = keyring.addFromUri(sudoUri);
+    const description: string = 'spending proposal which is used for API network testing';
+    const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee();
+
+    // Topping the balances
+    const proposalStake: BN = await apiWrapper.getRequiredProposalStake(25, 10000);
+    const runtimeProposalFee: BN = apiWrapper.estimateProposeWorkingGroupMintCapacityFee(
+      description,
+      description,
+      proposalStake,
+      mintingCapacity
+    );
+    await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake));
+    await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee);
+
+    // Proposal creation
+    console.log('proposing new mint capacity');
+    const proposalPromise = apiWrapper.expectProposalCreated();
+    console.log('sending extr with capacity ' + mintingCapacity);
+    await apiWrapper.proposeWorkingGroupMintCapacity(
+      m1KeyPairs[0],
+      'testing mint capacity' + uuid().substring(0, 8),
+      'mint capacity to test proposal functionality' + uuid().substring(0, 8),
+      proposalStake,
+      mintingCapacity
+    );
+    const proposalNumber = await proposalPromise;
+    console.log('proposed');
+    //await apiWrapper.getProposal(proposalNumber);
+
+    // Approving runtime update proposal
+    console.log('block number ' + (await apiWrapper.getBestBlock()));
+    console.log('approving new mint capacity');
+    const runtimePromise = apiWrapper.expectProposalFinalized();
+    await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
+    await runtimePromise;
+  }).timeout(defaultTimeout);
+
+  after(() => {
+    apiWrapper.close();
+  });
+});

+ 85 - 0
tests/network-tests/src/tests/upgrade/romeRuntimeUpgradeTest.ts

@@ -0,0 +1,85 @@
+import { initConfig } from '../../utils/config';
+import { Keyring, WsProvider } from '@polkadot/api';
+import { Bytes } from '@polkadot/types';
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from '../membershipCreationTest';
+import { councilTest } from '../electingCouncilTest';
+import { registerJoystreamTypes } from '@joystream/types';
+import { ApiWrapper } from '../../utils/apiWrapper';
+import BN = require('bn.js');
+import { Utils } from '../../utils/utils';
+
+describe('Runtime upgrade integration tests', () => {
+  initConfig();
+  const keyring = new Keyring({ type: 'sr25519' });
+  const nodeUrl: string = process.env.NODE_URL!;
+  const sudoUri: string = process.env.SUDO_ACCOUNT_URI!;
+  const proposalStake: BN = new BN(+process.env.RUNTIME_UPGRADE_PROPOSAL_STAKE!);
+  const defaultTimeout: number = 120000;
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  let apiWrapper: ApiWrapper;
+  let sudo: KeyringPair;
+
+  before(async function () {
+    console.log('before the test');
+    this.timeout(defaultTimeout);
+    registerJoystreamTypes();
+    const provider = new WsProvider(nodeUrl);
+    console.log('1');
+    apiWrapper = await ApiWrapper.create(provider);
+    console.log('2');
+  });
+
+  console.log('3');
+  membershipTest(m1KeyPairs);
+  console.log('4');
+  membershipTest(m2KeyPairs);
+  console.log('5');
+  councilTest(m1KeyPairs, m2KeyPairs);
+  console.log('6');
+
+  it('Upgrading the runtime test', async () => {
+    // Setup
+    console.log('7');
+    sudo = keyring.addFromUri(sudoUri);
+    const runtime: string = Utils.readRuntimeFromFile('joystream_node_runtime.wasm');
+    console.log('runtime read ' + runtime);
+    const description: string = 'runtime upgrade proposal which is used for API integration testing';
+    const runtimeProposalFee: BN = apiWrapper.estimateRomeProposeRuntimeUpgradeFee(
+      proposalStake,
+      description,
+      description,
+      runtime
+    );
+    const runtimeVoteFee: BN = apiWrapper.estimateVoteForRomeRuntimeProposalFee();
+
+    // Topping the balances
+    await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, runtimeProposalFee.add(proposalStake));
+    await apiWrapper.transferBalanceToAccounts(sudo, m2KeyPairs, runtimeVoteFee);
+
+    // Proposal creation
+    const proposalPromise = apiWrapper.expectProposalCreated();
+    await apiWrapper.proposeRuntimeRome(
+      m1KeyPairs[0],
+      proposalStake,
+      'testing runtime',
+      'runtime to test proposal functionality',
+      runtime
+    );
+    const proposalNumber = await proposalPromise;
+
+    // Approving runtime update proposal
+    const runtimePromise = apiWrapper.expectRomeRuntimeUpgraded();
+    await apiWrapper.batchApproveRomeProposal(m2KeyPairs, proposalNumber);
+    await runtimePromise;
+  }).timeout(defaultTimeout);
+
+  membershipTest(new Array<KeyringPair>());
+
+  after(() => {
+    apiWrapper.close();
+  });
+});

+ 178 - 11
tests/network-tests/src/utils/apiWrapper.ts

@@ -1,8 +1,8 @@
 import { ApiPromise, WsProvider } from '@polkadot/api';
-import { Option, Vec, Bytes } from '@polkadot/types';
+import { Option, Vec, Bytes, u32 } from '@polkadot/types';
 import { Codec } from '@polkadot/types/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import { UserInfo, PaidMembershipTerms } from '@joystream/types/lib/members';
+import { UserInfo, PaidMembershipTerms, MemberId } from '@joystream/types/lib/members';
 import { Seat, VoteKind } from '@joystream/types';
 import { Balance, EventRecord } from '@polkadot/types/interfaces';
 import BN = require('bn.js');
@@ -41,8 +41,8 @@ export class ApiWrapper {
     );
   }
 
-  public getMembership(address: string): Promise<any> {
-    return this.api.query.members.memberIdsByControllerAccountId(address);
+  public getMemberIds(address: string): Promise<MemberId[]> {
+    return this.api.query.members.memberIdsByControllerAccountId<Vec<MemberId>>(address);
   }
 
   public getBalance(address: string): Promise<Balance> {
@@ -99,12 +99,51 @@ export class ApiWrapper {
     return this.estimateTxFee(this.api.tx.councilElection.reveal(hashedVote, nominee, salt));
   }
 
-  public estimateProposeRuntimeUpgradeFee(stake: BN, name: string, description: string, runtime: Bytes): BN {
+  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 estimateRomeProposeRuntimeUpgradeFee(
+    stake: BN,
+    name: string,
+    description: string,
+    runtime: Bytes | string
+  ): BN {
     return this.estimateTxFee(this.api.tx.proposals.createProposal(stake, name, description, 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 estimateProposeWorkingGroupMintCapacityFee(title: string, description: string, stake: BN, balance: BN): BN {
+    return this.estimateTxFee(
+      this.api.tx.proposalsCodex.createSetContentWorkingGroupMintCapacityProposal(
+        stake,
+        title,
+        description,
+        stake,
+        balance
+      )
+    );
+  }
+
   public estimateVoteForProposalFee(): BN {
-    return this.estimateTxFee(this.api.tx.proposals.voteOnProposal(0, 'Approve'));
+    return this.estimateTxFee(this.api.tx.proposalsEngine.vote(0, 0, 'Approve'));
   }
 
   private applyForCouncilElection(account: KeyringPair, amount: BN): Promise<void> {
@@ -197,12 +236,27 @@ export class ApiWrapper {
     return this.api.query.substrate.code<Bytes>();
   }
 
-  public proposeRuntime(
+  public async proposeRuntime(
+    account: KeyringPair,
+    stake: BN,
+    name: string,
+    description: string,
+    runtime: Bytes | string
+  ): Promise<void> {
+    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 proposeRuntimeRome(
     account: KeyringPair,
     stake: BN,
     name: string,
     description: string,
-    runtime: Bytes
+    runtime: Bytes | string
   ): Promise<void> {
     return this.sender.signAndSend(
       this.api.tx.proposals.createProposal(stake, name, description, runtime),
@@ -211,18 +265,83 @@ export class ApiWrapper {
     );
   }
 
-  public approveProposal(account: KeyringPair, proposal: BN): Promise<void> {
+  public async proposeText(
+    account: KeyringPair,
+    stake: BN,
+    name: string,
+    description: string,
+    text: string
+  ): Promise<void> {
+    const memberId: BN = (await this.getMemberIds(account.address))[0].toBn();
     return this.sender.signAndSend(
-      this.api.tx.proposals.voteOnProposal(proposal, new VoteKind('Approve')),
+      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<void> {
+    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 proposeWorkingGroupMintCapacity(
+    account: KeyringPair,
+    title: string,
+    description: string,
+    stake: BN,
+    balance: BN
+  ): Promise<void> {
+    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 approveProposal(account: KeyringPair, memberId: BN, proposal: BN): Promise<void> {
+    return this.sender.signAndSend(this.api.tx.proposalsEngine.vote(memberId, proposal, 'Approve'), account, false);
+  }
+
   public batchApproveProposal(council: KeyringPair[], proposal: BN): Promise<void[]> {
     return Promise.all(
       council.map(async keyPair => {
-        await this.approveProposal(keyPair, proposal);
+        const memberId: BN = (await this.getMemberIds(keyPair.address))[0].toBn();
+        await this.approveProposal(keyPair, memberId, proposal);
+      })
+    );
+  }
+
+  public approveRomeProposal(account: KeyringPair, proposal: BN): Promise<void> {
+    return this.sender.signAndSend(
+      this.api.tx.proposals.voteOnProposal(proposal, new VoteKind('Approve')),
+      account,
+      false
+    );
+  }
+
+  public batchApproveRomeProposal(council: KeyringPair[], proposal: BN): Promise<void[]> {
+    return Promise.all(
+      council.map(async keyPair => {
+        await this.approveRomeProposal(keyPair, proposal);
       })
     );
   }
@@ -254,4 +373,52 @@ export class ApiWrapper {
       });
     });
   }
+
+  public expectRomeRuntimeUpgraded(): Promise<void> {
+    return new Promise(async resolve => {
+      await this.api.query.system.events<Vec<EventRecord>>(events => {
+        events.forEach(record => {
+          if (record.event.method.toString() === 'RuntimeUpdated') {
+            resolve();
+          }
+        });
+      });
+    });
+  }
+
+  public expectProposalFinalized(): Promise<void> {
+    return new Promise(async resolve => {
+      await this.api.query.system.events<Vec<EventRecord>>(events => {
+        events.forEach(record => {
+          if (
+            record.event.method.toString() === 'ProposalStatusUpdated' &&
+            record.event.data[1].toString().includes('Finalized')
+          ) {
+            resolve();
+          }
+        });
+      });
+    });
+  }
+
+  public getTotalIssuance(): Promise<BN> {
+    return this.api.query.balances.totalIssuance<Balance>();
+  }
+
+  public async getProposal(id: BN) {
+    const proposal = await this.api.query.proposalsEngine.proposals(id);
+    console.log('proposal to string ' + proposal.toString());
+    console.log('proposal to raw ' + proposal.toRawType());
+    return;
+  }
+
+  public async getRequiredProposalStake(numerator: number, denominator: number): Promise<BN> {
+    const issuance: number = await (await this.getTotalIssuance()).toNumber();
+    const stake = (issuance * numerator) / denominator;
+    return new BN(stake.toFixed(0));
+  }
+
+  public getProposalCount(): Promise<BN> {
+    return this.api.query.proposalsEngine.proposalCount<u32>();
+  }
 }

+ 0 - 1
tests/network-tests/src/utils/sender.ts

@@ -37,7 +37,6 @@ export class Sender {
   ): Promise<void> {
     return new Promise(async (resolve, reject) => {
       const nonce: BN = await this.getNonce(account.address);
-      // console.log('sending transaction from ' + account.address + ' with nonce ' + nonce);
       const signedTx = tx.sign(account, { nonce });
       await signedTx
         .send(async result => {

+ 5 - 0
tests/network-tests/src/utils/utils.ts

@@ -2,6 +2,7 @@ import { IExtrinsic } from '@polkadot/types/types';
 import { compactToU8a, stringToU8a } from '@polkadot/util';
 import { blake2AsHex } from '@polkadot/util-crypto';
 import BN = require('bn.js');
+import fs = require('fs');
 import { decodeAddress } from '@polkadot/keyring';
 import { Seat } from '@joystream/types';
 
@@ -42,4 +43,8 @@ export class Utils {
   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');
+  }
 }