Browse Source

Merge 'development' and resolve conflicts

Leszek Wiesner 4 years ago
parent
commit
82de73addf
55 changed files with 2114 additions and 273 deletions
  1. 8 8
      .github/workflows/pioneer-pr.yml
  2. 6 0
      .gitignore
  3. 11 2
      README.md
  4. 14 4
      pioneer/packages/app-explorer/src/SummarySession.tsx
  5. 3 2
      pioneer/packages/apps-routing/src/index.ts
  6. 6 2
      pioneer/packages/apps-routing/src/joy-pages.ts
  7. 1 1
      pioneer/packages/joy-utils/src/react/context/transport.tsx
  8. 6 6
      runtime-modules/proposals/discussion/src/lib.rs
  9. 2 2
      runtime-modules/proposals/discussion/src/tests/mod.rs
  10. 2 2
      runtime-modules/proposals/discussion/src/types.rs
  11. 14 0
      scripts/run-test-chain.sh
  12. 9 5
      tests/network-tests/.env
  13. 6 6
      tests/network-tests/package.json
  14. 0 0
      tests/network-tests/src/constantinople/tap-parallel-not-ok
  15. 39 0
      tests/network-tests/src/constantinople/tests/electingCouncilTest.ts
  16. 8 0
      tests/network-tests/src/constantinople/tests/impl/closeApi.ts
  17. 17 37
      tests/network-tests/src/constantinople/tests/impl/electingCouncil.ts
  18. 17 33
      tests/network-tests/src/constantinople/tests/impl/membershipCreation.ts
  19. 29 0
      tests/network-tests/src/constantinople/tests/membershipCreationTest.ts
  20. 40 0
      tests/network-tests/src/constantinople/tests/proposals/electionParametersProposalTest.ts
  21. 40 0
      tests/network-tests/src/constantinople/tests/proposals/evictStorageProviderTest.ts
  22. 124 0
      tests/network-tests/src/constantinople/tests/proposals/impl/electionParametersProposal.ts
  23. 62 0
      tests/network-tests/src/constantinople/tests/proposals/impl/evictStoraveProvider.ts
  24. 46 0
      tests/network-tests/src/constantinople/tests/proposals/impl/setLeadProposal.ts
  25. 64 0
      tests/network-tests/src/constantinople/tests/proposals/impl/spendingProposal.ts
  26. 120 0
      tests/network-tests/src/constantinople/tests/proposals/impl/storageRoleParametersProposal.ts
  27. 46 0
      tests/network-tests/src/constantinople/tests/proposals/impl/textProposal.ts
  28. 52 0
      tests/network-tests/src/constantinople/tests/proposals/impl/updateRuntime.ts
  29. 55 0
      tests/network-tests/src/constantinople/tests/proposals/impl/validatorCountProposal.ts
  30. 59 0
      tests/network-tests/src/constantinople/tests/proposals/impl/workingGroupMintCapacityProposal.ts
  31. 40 0
      tests/network-tests/src/constantinople/tests/proposals/setLeadProposalTest.ts
  32. 42 0
      tests/network-tests/src/constantinople/tests/proposals/spendingProposalTest.ts
  33. 40 0
      tests/network-tests/src/constantinople/tests/proposals/storageRoleParametersProposalTest.ts
  34. 40 0
      tests/network-tests/src/constantinople/tests/proposals/textProposalTest.ts
  35. 41 0
      tests/network-tests/src/constantinople/tests/proposals/updateRuntimeTest.ts
  36. 41 0
      tests/network-tests/src/constantinople/tests/proposals/validatorCountProposalTest.ts
  37. 41 0
      tests/network-tests/src/constantinople/tests/proposals/workingGroupMintCapacityProposalTest.ts
  38. 287 14
      tests/network-tests/src/constantinople/utils/apiWrapper.ts
  39. 0 0
      tests/network-tests/src/constantinople/utils/config.ts
  40. 1 1
      tests/network-tests/src/constantinople/utils/sender.ts
  41. 7 0
      tests/network-tests/src/constantinople/utils/setTestTimeout.ts
  42. 3 4
      tests/network-tests/src/constantinople/utils/utils.ts
  43. 0 0
      tests/network-tests/src/rome/tap-parallel-not-ok
  44. 27 0
      tests/network-tests/src/rome/tests/electingCouncilTest.ts
  45. 18 27
      tests/network-tests/src/rome/tests/impl/electingCouncil.ts
  46. 19 25
      tests/network-tests/src/rome/tests/impl/membershipCreation.ts
  47. 19 30
      tests/network-tests/src/rome/tests/impl/romeRuntimeUpgrade.ts
  48. 20 0
      tests/network-tests/src/rome/tests/impl/setTimeout.ts
  49. 19 0
      tests/network-tests/src/rome/tests/membershipCreationTest.ts
  50. 31 0
      tests/network-tests/src/rome/tests/romeRuntimeUpgradeTest.ts
  51. 1 1
      tests/network-tests/src/rome/utils/apiWrapper.ts
  52. 0 0
      tests/network-tests/src/rome/utils/config.ts
  53. 1 1
      tests/network-tests/src/rome/utils/sender.ts
  54. 2 2
      tests/network-tests/src/rome/utils/utils.ts
  55. 468 58
      yarn.lock

+ 8 - 8
.github/workflows/pioneer-pr.yml

@@ -1,9 +1,9 @@
-name: Pioneer-PR
+name: Pioneer
 on: [pull_request, push]
 on: [pull_request, push]
 
 
 jobs:
 jobs:
-  pioneer_build_code:
-    name: Pioneer Build Code
+  pioneer_build_ubuntu:
+    name: Ubuntu Build
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     strategy:
     strategy:
       matrix:
       matrix:
@@ -17,11 +17,11 @@ jobs:
     - name: build
     - name: build
       run: |
       run: |
         yarn install --frozen-lockfile
         yarn install --frozen-lockfile
-        yarn workspace pioneer run build:code
+        yarn workspace pioneer run build
 
 
-  pioneer_build_i18n:
-    name: Pioneer Build i18n
-    runs-on: ubuntu-latest
+  pioneer_build_osx:
+    name: MacOS Build
+    runs-on: macos-latest
     strategy:
     strategy:
       matrix:
       matrix:
         node-version: [12.x]
         node-version: [12.x]
@@ -34,4 +34,4 @@ jobs:
     - name: build
     - name: build
       run: |
       run: |
         yarn install --frozen-lockfile
         yarn install --frozen-lockfile
-        yarn workspace pioneer run build:i18n
+        yarn workspace pioneer run build

+ 6 - 0
.gitignore

@@ -26,3 +26,9 @@ yarn*
 
 
 # Compiled WASM code
 # Compiled WASM code
 *.wasm
 *.wasm
+
+# Temporary files
+.tmp/
+
+# Istanbul report output
+**.nyc_output/

+ 11 - 2
README.md

@@ -85,14 +85,23 @@ This will build and run a fresh new local development chain purging existing one
 cargo test
 cargo test
 ```
 ```
 
 
-### API integration tests
+### Network tests
 
 
 ```bash
 ```bash
-./scripts/run-dev-chain.sh
+./scripts/run-test-chain.sh
 yarn test
 yarn test
 ```
 ```
 
 
 To run the integration tests with a different chain, you can omit step running the local development chain and set the node URL using `NODE_URL` environment variable.
 To run the integration tests with a different chain, you can omit step running the local development chain and set the node URL using `NODE_URL` environment variable.
+Proposal grace periods should be set to 0, otherwise proposal network tests will fail.
+
+### Rome-Constantinople migration network test
+
+Ensure Rome node is up and running, and node URL is set using `NODE_URL` environment variable (default value is `localhost:9944`).
+
+```bash
+yarn test-migration
+```
 
 
 ## Joystream Runtime
 ## Joystream Runtime
 
 

+ 14 - 4
pioneer/packages/app-explorer/src/SummarySession.tsx

@@ -12,10 +12,15 @@ import { withCalls } from '@polkadot/react-api';
 import translate from './translate';
 import translate from './translate';
 import { formatNumber } from '@polkadot/util';
 import { formatNumber } from '@polkadot/util';
 
 
+import { SessionIndex } from '@polkadot/types/interfaces';
+import { u64 } from '@polkadot/types/primitive';
+
 interface Props extends I18nProps {
 interface Props extends I18nProps {
   sessionInfo?: DerivedSessionInfo;
   sessionInfo?: DerivedSessionInfo;
   withEra?: boolean;
   withEra?: boolean;
   withSession?: boolean;
   withSession?: boolean;
+  epochIndex?: u64,
+  currentEraStartSessionIndex?: SessionIndex
 }
 }
 
 
 function renderSession ({ sessionInfo, t, withSession = true }: Props): React.ReactNode {
 function renderSession ({ sessionInfo, t, withSession = true }: Props): React.ReactNode {
@@ -44,12 +49,15 @@ function renderSession ({ sessionInfo, t, withSession = true }: Props): React.Re
     );
     );
 }
 }
 
 
-function renderEra ({ sessionInfo, t, withEra = true }: Props): React.ReactNode {
-  if (!withEra || !sessionInfo) {
+function renderEra ({ sessionInfo, t, withEra = true, epochIndex, currentEraStartSessionIndex }: Props): React.ReactNode {
+  if (!withEra || !sessionInfo || !epochIndex || !currentEraStartSessionIndex) {
     return null;
     return null;
   }
   }
 
 
   const label = t('era');
   const label = t('era');
+  const { sessionLength, sessionProgress } = sessionInfo;
+  // eraProgress is calculated the wrong way in polkadot/api v0.96.1 (fixed in v0.97.1)
+  const eraProgress = epochIndex.sub(currentEraStartSessionIndex).mul(sessionLength).add(sessionProgress);
 
 
   return sessionInfo.sessionLength.gtn(0)
   return sessionInfo.sessionLength.gtn(0)
     ? (
     ? (
@@ -57,7 +65,7 @@ function renderEra ({ sessionInfo, t, withEra = true }: Props): React.ReactNode
         label={label}
         label={label}
         progress={{
         progress={{
           total: sessionInfo.eraLength,
           total: sessionInfo.eraLength,
-          value: sessionInfo.eraProgress
+          value: eraProgress
         }}
         }}
       />
       />
     )
     )
@@ -79,6 +87,8 @@ function SummarySession (props: Props): React.ReactElement<Props> {
 
 
 export default translate(
 export default translate(
   withCalls<Props>(
   withCalls<Props>(
-    ['derive.session.info', { propName: 'sessionInfo' }]
+    ['derive.session.info', { propName: 'sessionInfo' }],
+    ['query.babe.epochIndex', { propName: 'epochIndex' }],
+    ['query.staking.currentEraStartSessionIndex', { propName: 'currentEraStartSessionIndex'}]
   )(SummarySession)
   )(SummarySession)
 );
 );

+ 3 - 2
pioneer/packages/apps-routing/src/index.ts

@@ -14,7 +14,7 @@ import members from './joy-members';
 import proposals from './joy-proposals';
 import proposals from './joy-proposals';
 import roles from './joy-roles';
 import roles from './joy-roles';
 import storageRoles from './joy-storage';
 import storageRoles from './joy-storage';
-// import pages from './joy-pages';
+import pages from './joy-pages';
 
 
 // import template from './123code';
 // import template from './123code';
 import accounts from './accounts';
 import accounts from './accounts';
@@ -73,7 +73,8 @@ if (appSettings.isFullMode) {
 }
 }
 
 
 routes = routes.concat(
 routes = routes.concat(
-  settings
+  settings,
+  pages
 );
 );
 
 
 const setup: Routing = {
 const setup: Routing = {

+ 6 - 2
pioneer/packages/apps-routing/src/joy-pages.ts

@@ -5,7 +5,9 @@ import { ToS, Privacy } from '@polkadot/joy-pages/index';
 export default ([
 export default ([
   {
   {
     Component: ToS,
     Component: ToS,
-    display: {},
+    display: {
+      isHidden: true
+    },
     i18n: {
     i18n: {
       defaultValue: 'Terms of Service'
       defaultValue: 'Terms of Service'
     },
     },
@@ -14,7 +16,9 @@ export default ([
   },
   },
   {
   {
     Component: Privacy,
     Component: Privacy,
-    display: {},
+    display: {
+      isHidden: true
+    },
     i18n: {
     i18n: {
       defaultValue: 'Privacy Policy'
       defaultValue: 'Privacy Policy'
     },
     },

+ 1 - 1
pioneer/packages/joy-utils/src/react/context/transport.tsx

@@ -2,7 +2,7 @@ import React, { createContext, useContext } from 'react';
 import { ApiContext } from '@polkadot/react-api';
 import { ApiContext } from '@polkadot/react-api';
 import { ApiProps } from '@polkadot/react-api/types';
 import { ApiProps } from '@polkadot/react-api/types';
 
 
-import Transport from '../../transport';
+import Transport from '../../transport/index';
 
 
 export const TransportContext = createContext<Transport>((null as unknown) as Transport);
 export const TransportContext = createContext<Transport>((null as unknown) as Transport);
 
 

+ 6 - 6
runtime-modules/proposals/discussion/src/lib.rs

@@ -56,7 +56,7 @@ use rstd::vec::Vec;
 use srml_support::{decl_error, decl_event, decl_module, decl_storage, ensure, Parameter};
 use srml_support::{decl_error, decl_event, decl_module, decl_storage, ensure, Parameter};
 
 
 use srml_support::traits::Get;
 use srml_support::traits::Get;
-use types::{Post, Thread, ThreadCounter};
+use types::{DiscussionPost, DiscussionThread, ThreadCounter};
 
 
 use common::origin_validator::ActorOriginValidator;
 use common::origin_validator::ActorOriginValidator;
 use srml_support::dispatch::DispatchResult;
 use srml_support::dispatch::DispatchResult;
@@ -163,14 +163,14 @@ decl_storage! {
     pub trait Store for Module<T: Trait> as ProposalDiscussion {
     pub trait Store for Module<T: Trait> as ProposalDiscussion {
         /// Map thread identifier to corresponding thread.
         /// Map thread identifier to corresponding thread.
         pub ThreadById get(thread_by_id): map T::ThreadId =>
         pub ThreadById get(thread_by_id): map T::ThreadId =>
-            Thread<MemberId<T>, T::BlockNumber>;
+            DiscussionThread<MemberId<T>, T::BlockNumber>;
 
 
         /// Count of all threads that have been created.
         /// Count of all threads that have been created.
         pub ThreadCount get(fn thread_count): u64;
         pub ThreadCount get(fn thread_count): u64;
 
 
         /// Map thread id and post id to corresponding post.
         /// Map thread id and post id to corresponding post.
         pub PostThreadIdByPostId: double_map T::ThreadId, twox_128(T::PostId) =>
         pub PostThreadIdByPostId: double_map T::ThreadId, twox_128(T::PostId) =>
-             Post<MemberId<T>, T::BlockNumber, T::ThreadId>;
+             DiscussionPost<MemberId<T>, T::BlockNumber, T::ThreadId>;
 
 
         /// Count of all posts that have been created.
         /// Count of all posts that have been created.
         pub PostCount get(fn post_count): u64;
         pub PostCount get(fn post_count): u64;
@@ -226,7 +226,7 @@ decl_module! {
             let next_post_count_value = Self::post_count() + 1;
             let next_post_count_value = Self::post_count() + 1;
             let new_post_id = next_post_count_value;
             let new_post_id = next_post_count_value;
 
 
-            let new_post = Post {
+            let new_post = DiscussionPost {
                 text,
                 text,
                 created_at: Self::current_block(),
                 created_at: Self::current_block(),
                 updated_at: Self::current_block(),
                 updated_at: Self::current_block(),
@@ -269,7 +269,7 @@ decl_module! {
             ensure!(post.edition_number < T::MaxPostEditionNumber::get(),
             ensure!(post.edition_number < T::MaxPostEditionNumber::get(),
                 Error::PostEditionNumberExceeded);
                 Error::PostEditionNumberExceeded);
 
 
-            let new_post = Post {
+            let new_post = DiscussionPost {
                 text,
                 text,
                 updated_at: Self::current_block(),
                 updated_at: Self::current_block(),
                 edition_number: post.edition_number + 1,
                 edition_number: post.edition_number + 1,
@@ -296,7 +296,7 @@ impl<T: Trait> Module<T> {
         let next_thread_count_value = Self::thread_count() + 1;
         let next_thread_count_value = Self::thread_count() + 1;
         let new_thread_id = next_thread_count_value;
         let new_thread_id = next_thread_count_value;
 
 
-        let new_thread = Thread {
+        let new_thread = DiscussionThread {
             title,
             title,
             created_at: Self::current_block(),
             created_at: Self::current_block(),
             author_id: thread_author_id,
             author_id: thread_author_id,

+ 2 - 2
runtime-modules/proposals/discussion/src/tests/mod.rs

@@ -37,7 +37,7 @@ fn assert_thread_content(thread_entry: TestThreadEntry, post_entries: Vec<TestPo
     assert!(<ThreadById<Test>>::exists(thread_entry.thread_id));
     assert!(<ThreadById<Test>>::exists(thread_entry.thread_id));
 
 
     let actual_thread = <ThreadById<Test>>::get(thread_entry.thread_id);
     let actual_thread = <ThreadById<Test>>::get(thread_entry.thread_id);
-    let expected_thread = Thread {
+    let expected_thread = DiscussionThread {
         title: thread_entry.title,
         title: thread_entry.title,
         created_at: 1,
         created_at: 1,
         author_id: 1,
         author_id: 1,
@@ -47,7 +47,7 @@ fn assert_thread_content(thread_entry: TestThreadEntry, post_entries: Vec<TestPo
     for post_entry in post_entries {
     for post_entry in post_entries {
         let actual_post =
         let actual_post =
             <PostThreadIdByPostId<Test>>::get(thread_entry.thread_id, post_entry.post_id);
             <PostThreadIdByPostId<Test>>::get(thread_entry.thread_id, post_entry.post_id);
-        let expected_post = Post {
+        let expected_post = DiscussionPost {
             text: post_entry.text,
             text: post_entry.text,
             created_at: 1,
             created_at: 1,
             updated_at: 1,
             updated_at: 1,

+ 2 - 2
runtime-modules/proposals/discussion/src/types.rs

@@ -9,7 +9,7 @@ use rstd::prelude::*;
 /// Represents a discussion thread
 /// Represents a discussion thread
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq)]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq)]
-pub struct Thread<ThreadAuthorId, BlockNumber> {
+pub struct DiscussionThread<ThreadAuthorId, BlockNumber> {
     /// Title
     /// Title
     pub title: Vec<u8>,
     pub title: Vec<u8>,
 
 
@@ -23,7 +23,7 @@ pub struct Thread<ThreadAuthorId, BlockNumber> {
 /// Post for the discussion thread
 /// Post for the discussion thread
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq)]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq)]
-pub struct Post<PostAuthorId, BlockNumber, ThreadId> {
+pub struct DiscussionPost<PostAuthorId, BlockNumber, ThreadId> {
     /// Text
     /// Text
     pub text: Vec<u8>,
     pub text: Vec<u8>,
 
 

+ 14 - 0
scripts/run-test-chain.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+mkdir -p .tmp
+cargo run --release -p joystream-node build-spec --chain dev > .tmp/chainspec.json
+perl -i -pe's/"setValidatorCountProposalGracePeriod":.*/"setValidatorCountProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"runtimeUpgradeProposalGracePeriod":.*/"runtimeUpgradeProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"setElectionParametersProposalGracePeriod":.*/"setElectionParametersProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"textProposalGracePeriod":.*/"textProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"setContentWorkingGroupMintCapacityProposalGracePeriod":.*/"setContentWorkingGroupMintCapacityProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"setLeadProposalGracePeriod":.*/"setLeadProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"spendingProposalGracePeriod":.*/"spendingProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"evictStorageProviderProposalGracePeriod":.*/"evictStorageProviderProposalGracePeriod": 0,/' .tmp/chainspec.json
+perl -i -pe's/"setStorageRoleParametersProposalGracePeriod":.*/"setStorageRoleParametersProposalGracePeriod": 0/' .tmp/chainspec.json
+yes | cargo run --release -p joystream-node -- purge-chain --dev
+cargo run --release -p joystream-node -- --chain=.tmp/chainspec.json --alice --validator

+ 9 - 5
tests/network-tests/.env

@@ -7,16 +7,20 @@ MEMBERSHIP_CREATION_N = 2
 # ID of the membership paid terms used in membership creation test.
 # ID of the membership paid terms used in membership creation test.
 MEMBERSHIP_PAID_TERMS = 0
 MEMBERSHIP_PAID_TERMS = 0
 # Council stake amount for first K accounts in council election test.
 # Council stake amount for first K accounts in council election test.
-COUNCIL_STAKE_GREATER_AMOUNT = 1500
+COUNCIL_STAKE_GREATER_AMOUNT = 3000
 # Council stake amount for first the rest participants in council election test.
 # Council stake amount for first the rest participants in council election test.
-COUNCIL_STAKE_LESSER_AMOUNT = 1000
+COUNCIL_STAKE_LESSER_AMOUNT = 2000
 # Number of members with greater stake in council election test.
 # Number of members with greater stake in council election test.
 COUNCIL_ELECTION_K = 2
 COUNCIL_ELECTION_K = 2
 # Balance to spend using spending proposal
 # Balance to spend using spending proposal
 SPENDING_BALANCE = 1000
 SPENDING_BALANCE = 1000
-# Minting capacity for content working group minting capacity test.
-MINTING_CAPACITY = 100020
+# Minting capacity increment for content working group minting capacity test.
+MINTING_CAPACITY_INCREMENT = 20
+# Minting capacity for council mint for spending proposal.
+COUNCIL_MINTING_CAPACITY = 100000
 # Stake amount for Rome runtime upgrade proposal
 # Stake amount for Rome runtime upgrade proposal
 RUNTIME_UPGRADE_PROPOSAL_STAKE = 100000
 RUNTIME_UPGRADE_PROPOSAL_STAKE = 100000
+# Validator count increment for Validator count test.
+VALIDATOR_COUNT_INCREMENT = 2
 # Constantinople runtime path
 # Constantinople runtime path
-RUNTIME_WASM_PATH = ../../target/release/wbuild/joystream-node-runtime/joystream_node_runtime.compact.wasm
+RUNTIME_WASM_PATH = ../../target/release/wbuild/joystream-node-runtime/joystream_node_runtime.compact.wasm

+ 6 - 6
tests/network-tests/package.json

@@ -4,16 +4,16 @@
   "license": "GPL-3.0-only",
   "license": "GPL-3.0-only",
   "scripts": {
   "scripts": {
     "build": "tsc --build tsconfig.json",
     "build": "tsc --build tsconfig.json",
-    "test": "mocha -r ts-node/register src/tests/constantinople/*",
-    "test-migration": "mocha -r ts-node/register src/tests/rome/* && mocha -r ts-node/register src/tests/constantinople/*",
+    "test": "tap --files ts-node/register src/constantinople/tests/proposals/*Test.ts",
+    "test-migration": "tap --files src/rome/tests/romeRuntimeUpgradeTest.ts --files src/constantinople/tests/electingCouncilTest.ts",
     "lint": "tslint --project tsconfig.json",
     "lint": "tslint --project tsconfig.json",
     "prettier": "prettier --write ./src"
     "prettier": "prettier --write ./src"
   },
   },
   "dependencies": {
   "dependencies": {
-    "@joystream/types": "",
-    "@rome/types@npm:@joystream/types": "^0.7.0",
+    "@constantinople/types@npm:@joystream/types": "^0.9.1",
     "@polkadot/api": "^0.96.1",
     "@polkadot/api": "^0.96.1",
     "@polkadot/keyring": "^1.7.0-beta.5",
     "@polkadot/keyring": "^1.7.0-beta.5",
+    "@rome/types@npm:@joystream/types": "^0.7.0",
     "@types/bn.js": "^4.11.5",
     "@types/bn.js": "^4.11.5",
     "bn.js": "^4.11.8",
     "bn.js": "^4.11.8",
     "dotenv": "^8.2.0",
     "dotenv": "^8.2.0",
@@ -23,11 +23,11 @@
   "devDependencies": {
   "devDependencies": {
     "@polkadot/ts": "^0.3.14",
     "@polkadot/ts": "^0.3.14",
     "@types/chai": "^4.2.11",
     "@types/chai": "^4.2.11",
-    "@types/mocha": "^7.0.2",
+    "@types/tap": "^14.10.0",
     "@types/uuid": "^7.0.2",
     "@types/uuid": "^7.0.2",
     "chai": "^4.2.0",
     "chai": "^4.2.0",
-    "mocha": "^7.1.1",
     "prettier": "2.0.2",
     "prettier": "2.0.2",
+    "tap": "^14.10.7",
     "ts-node": "^8.8.1",
     "ts-node": "^8.8.1",
     "tslint": "^6.1.0",
     "tslint": "^6.1.0",
     "typescript": "^3.8.3"
     "typescript": "^3.8.3"

+ 0 - 0
tests/network-tests/src/constantinople/tap-parallel-not-ok


+ 39 - 0
tests/network-tests/src/constantinople/tests/electingCouncilTest.ts

@@ -0,0 +1,39 @@
+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 '@constantinople/types';
+import { ApiWrapper } from '../utils/apiWrapper';
+import { closeApi } from './impl/closeApi';
+
+tap.mocha.describe('Electing council scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+});

+ 8 - 0
tests/network-tests/src/constantinople/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();
+  });
+}

+ 17 - 37
tests/network-tests/src/tests/constantinople/electingCouncilTest.ts → tests/network-tests/src/constantinople/tests/impl/electingCouncil.ts

@@ -1,34 +1,26 @@
-import { membershipTest } from './membershipCreationTest';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import { ApiWrapper } from './utils/apiWrapper';
-import { WsProvider, Keyring } from '@polkadot/api';
-import { initConfig } from './utils/config';
-import BN = require('bn.js');
-import { registerJoystreamTypes, Seat } from '@joystream/types/';
+import { ApiWrapper } from '../../utils/apiWrapper';
+import { Keyring } from '@polkadot/api';
+import BN from 'bn.js';
+import { Seat } from '@constantinople/types';
 import { assert } from 'chai';
 import { assert } from 'chai';
 import { v4 as uuid } from 'uuid';
 import { v4 as uuid } from 'uuid';
-import { Utils } from './utils/utils';
+import { Utils } from '../../utils/utils';
+import tap from 'tap';
 
 
-export function councilTest(m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[]) {
-  initConfig();
-  const keyring = new Keyring({ type: 'sr25519' });
-  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 defaultTimeout: number = 120000;
+export function councilTest(
+  apiWrapper: ApiWrapper,
+  m1KeyPairs: KeyringPair[],
+  m2KeyPairs: KeyringPair[],
+  keyring: Keyring,
+  K: number,
+  sudoUri: string,
+  greaterStake: BN,
+  lesserStake: BN
+) {
   let sudo: KeyringPair;
   let sudo: KeyringPair;
-  let apiWrapper: ApiWrapper;
 
 
-  before(async function () {
-    this.timeout(defaultTimeout);
-    registerJoystreamTypes();
-    const provider = new WsProvider(nodeUrl);
-    apiWrapper = await ApiWrapper.create(provider);
-  });
-
-  it('Electing a council test', async () => {
+  tap.test('Electing a council test', async () => {
     // Setup goes here because M keypairs are generated after before() function
     // Setup goes here because M keypairs are generated after before() function
     sudo = keyring.addFromUri(sudoUri);
     sudo = keyring.addFromUri(sudoUri);
     let now = await apiWrapper.getBestBlock();
     let now = await apiWrapper.getBestBlock();
@@ -111,17 +103,5 @@ export function councilTest(m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[]
         `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}`
         `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}`
       )
       )
     );
     );
-  }).timeout(defaultTimeout);
-
-  after(() => {
-    apiWrapper.close();
   });
   });
 }
 }
-
-describe('Council integration tests', () => {
-  const m1KeyPairs: KeyringPair[] = new Array();
-  const m2KeyPairs: KeyringPair[] = new Array();
-  membershipTest(m1KeyPairs);
-  membershipTest(m2KeyPairs);
-  councilTest(m1KeyPairs, m2KeyPairs);
-});

+ 17 - 33
tests/network-tests/src/tests/constantinople/membershipCreationTest.ts → tests/network-tests/src/constantinople/tests/impl/membershipCreation.ts

@@ -1,32 +1,25 @@
-import { WsProvider } from '@polkadot/api';
-import { registerJoystreamTypes } from '@joystream/types/';
 import { Keyring } from '@polkadot/keyring';
 import { Keyring } from '@polkadot/keyring';
 import { assert } from 'chai';
 import { assert } from 'chai';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import BN = require('bn.js');
-import { ApiWrapper } from './utils/apiWrapper';
-import { initConfig } from './utils/config';
+import BN from 'bn.js';
+import { ApiWrapper } from '../../utils/apiWrapper';
 import { v4 as uuid } from 'uuid';
 import { v4 as uuid } from 'uuid';
+import tap from 'tap';
 
 
-export function membershipTest(nKeyPairs: KeyringPair[]) {
-  initConfig();
-  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 defaultTimeout: number = 30000;
-  let apiWrapper: ApiWrapper;
+export function membershipTest(
+  apiWrapper: ApiWrapper,
+  nKeyPairs: KeyringPair[],
+  keyring: Keyring,
+  N: number,
+  paidTerms: number,
+  sudoUri: string
+) {
   let sudo: KeyringPair;
   let sudo: KeyringPair;
   let aKeyPair: KeyringPair;
   let aKeyPair: KeyringPair;
   let membershipFee: BN;
   let membershipFee: BN;
   let membershipTransactionFee: BN;
   let membershipTransactionFee: BN;
 
 
-  before(async function () {
-    this.timeout(defaultTimeout);
-    registerJoystreamTypes();
-    const provider = new WsProvider(nodeUrl);
-    apiWrapper = await ApiWrapper.create(provider);
+  tap.test('Membership creation test setup', async () => {
     sudo = keyring.addFromUri(sudoUri);
     sudo = keyring.addFromUri(sudoUri);
     for (let i = 0; i < N; i++) {
     for (let i = 0; i < N; i++) {
       nKeyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8)));
       nKeyPairs.push(keyring.addFromUri(i + uuid().substring(0, 8)));
@@ -42,7 +35,7 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee);
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee);
   });
   });
 
 
-  it('Buy membeship is accepted with sufficient funds', async () => {
+  tap.test('Buy membeship is accepted with sufficient funds', async () => {
     await Promise.all(
     await Promise.all(
       nKeyPairs.map(async (keyPair, index) => {
       nKeyPairs.map(async (keyPair, index) => {
         await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`);
         await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`);
@@ -53,9 +46,9 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
         .getMemberIds(keyPair.address)
         .getMemberIds(keyPair.address)
         .then(membership => assert(membership.length > 0, `Account ${keyPair.address} is not a member`))
         .then(membership => assert(membership.length > 0, `Account ${keyPair.address} is not a member`))
     );
     );
-  }).timeout(defaultTimeout);
+  });
 
 
-  it('Account A can not buy the membership with insufficient funds', async () => {
+  tap.test('Account A can not buy the membership with insufficient funds', async () => {
     await apiWrapper
     await apiWrapper
       .getBalance(aKeyPair.address)
       .getBalance(aKeyPair.address)
       .then(balance =>
       .then(balance =>
@@ -68,9 +61,9 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
     apiWrapper
     apiWrapper
       .getMemberIds(aKeyPair.address)
       .getMemberIds(aKeyPair.address)
       .then(membership => assert(membership.length === 0, 'Account A is a member'));
       .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 () => {
+  tap.test('Account A was able to buy the membership with sufficient funds', async () => {
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipFee.add(membershipTransactionFee));
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipFee.add(membershipTransactionFee));
     apiWrapper
     apiWrapper
       .getBalance(aKeyPair.address)
       .getBalance(aKeyPair.address)
@@ -81,14 +74,5 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
     apiWrapper
     apiWrapper
       .getMemberIds(aKeyPair.address)
       .getMemberIds(aKeyPair.address)
       .then(membership => assert(membership.length > 0, 'Account A is a not member'));
       .then(membership => assert(membership.length > 0, 'Account A is a not member'));
-  }).timeout(defaultTimeout);
-
-  after(() => {
-    apiWrapper.close();
   });
   });
 }
 }
-
-describe.skip('Membership integration tests', () => {
-  const nKeyPairs: KeyringPair[] = new Array();
-  membershipTest(nKeyPairs);
-});

+ 29 - 0
tests/network-tests/src/constantinople/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 '@constantinople/types';
+import { ApiWrapper } from '../utils/apiWrapper';
+import { closeApi } from './impl/closeApi';
+
+tap.mocha.describe('Membership creation scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const nKeyPairs: KeyringPair[] = new Array();
+  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: number = 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);
+});

+ 40 - 0
tests/network-tests/src/constantinople/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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Election parameters proposal scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+});

+ 40 - 0
tests/network-tests/src/constantinople/tests/proposals/evictStorageProviderTest.ts

@@ -0,0 +1,40 @@
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from '../impl/membershipCreation';
+import { councilTest } from '../impl/electingCouncil';
+import { evictStorageProviderTest } from './impl/evictStoraveProvider';
+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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Evict Storage provider scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 32;
+
+  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);
+  evictStorageProviderTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri);
+  closeApi(apiWrapper);
+});

+ 124 - 0
tests/network-tests/src/constantinople/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}`
+    );
+  });
+}

+ 62 - 0
tests/network-tests/src/constantinople/tests/proposals/impl/evictStoraveProvider.ts

@@ -0,0 +1,62 @@
+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 { Utils } from '../../../utils/utils';
+import tap from 'tap';
+
+export function evictStorageProviderTest(
+  apiWrapper: ApiWrapper,
+  m1KeyPairs: KeyringPair[],
+  m2KeyPairs: KeyringPair[],
+  keyring: Keyring,
+  sudoUri: string
+) {
+  let sudo: KeyringPair;
+
+  tap.test('Evict storage provider 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);
+    if (!(await apiWrapper.isStorageProvider(sudo.address))) {
+      await apiWrapper.createStorageProvider(sudo);
+    }
+    assert(await apiWrapper.isStorageProvider(sudo.address), `Account ${sudo.address} is not storage provider`);
+
+    // Proposal stake calculation
+    const proposalStake: BN = new BN(25000);
+    const proposalFee: BN = apiWrapper.estimateProposeEvictStorageProviderFee(
+      description,
+      description,
+      proposalStake,
+      sudo.address
+    );
+    await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake));
+
+    // Proposal creation
+    const proposalPromise = apiWrapper.expectProposalCreated();
+    await apiWrapper.proposeEvictStorageProvider(
+      m1KeyPairs[0],
+      proposalTitle,
+      description,
+      proposalStake,
+      sudo.address
+    );
+    const proposalNumber = await proposalPromise;
+
+    // Approving the proposal
+    const proposalExecutionPromise = apiWrapper.expectProposalFinalized();
+    await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
+    await proposalExecutionPromise;
+    await Utils.wait(apiWrapper.getBlockDuration().toNumber());
+    assert(
+      !(await apiWrapper.isStorageProvider(sudo.address)),
+      `Account ${sudo.address} is storage provider after eviction`
+    );
+  });
+}

+ 46 - 0
tests/network-tests/src/constantinople/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}`
+    );
+  });
+}

+ 64 - 0
tests/network-tests/src/constantinople/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: 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 = 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)}`
+    );
+  });
+}

+ 120 - 0
tests/network-tests/src/constantinople/tests/proposals/impl/storageRoleParametersProposal.ts

@@ -0,0 +1,120 @@
+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 { RoleParameters } from '@constantinople/types/lib/roles';
+import tap from 'tap';
+
+export function storageRoleParametersProposalTest(
+  apiWrapper: ApiWrapper,
+  m1KeyPairs: KeyringPair[],
+  m2KeyPairs: KeyringPair[],
+  keyring: Keyring,
+  sudoUri: string
+) {
+  let sudo: KeyringPair;
+
+  tap.test('Storage role 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 roleParameters: RoleParameters = ((await apiWrapper.getStorageRoleParameters()) as unknown) as RoleParameters;
+
+    // Proposal stake calculation
+    const proposalStake: BN = new BN(100000);
+    const proposalFee: BN = apiWrapper.estimateProposeStorageRoleParametersFee(
+      description,
+      description,
+      proposalStake,
+      roleParameters.min_stake.toBn(),
+      roleParameters.min_actors.toBn(),
+      roleParameters.max_actors.toBn(),
+      roleParameters.reward.toBn(),
+      roleParameters.reward_period.toBn(),
+      roleParameters.bonding_period.toBn(),
+      roleParameters.unbonding_period.toBn(),
+      roleParameters.min_service_period.toBn(),
+      roleParameters.startup_grace_period.toBn(),
+      roleParameters.entry_request_fee.toBn()
+    );
+    await apiWrapper.transferBalance(sudo, m1KeyPairs[0].address, proposalFee.add(proposalStake));
+
+    // Proposal creation
+    const proposedMinStake: BN = roleParameters.min_stake.toBn().addn(1);
+    const proposedMaxActors: BN = roleParameters.max_actors.toBn().addn(1);
+    const proposedReward: BN = roleParameters.reward.toBn().addn(1);
+    const proposedRewardPeriod: BN = roleParameters.reward_period.toBn().addn(1);
+    const proposedBondingPeriod: BN = roleParameters.bonding_period.toBn().addn(1);
+    const proposedUnbondingPeriod: BN = roleParameters.unbonding_period.toBn().addn(1);
+    const proposedMinServicePeriod: BN = roleParameters.min_service_period.toBn().addn(1);
+    const proposedStartupGracePeriod: BN = roleParameters.startup_grace_period.toBn().addn(1);
+    const proposedEntryRequestFee: BN = roleParameters.entry_request_fee.toBn().addn(1);
+    const proposalPromise = apiWrapper.expectProposalCreated();
+    await apiWrapper.proposeStorageRoleParameters(
+      m1KeyPairs[0],
+      proposalTitle,
+      description,
+      proposalStake,
+      proposedMinStake,
+      roleParameters.min_actors.toBn(),
+      proposedMaxActors,
+      proposedReward,
+      proposedRewardPeriod,
+      proposedBondingPeriod,
+      proposedUnbondingPeriod,
+      proposedMinServicePeriod,
+      proposedStartupGracePeriod,
+      proposedEntryRequestFee
+    );
+    const proposalNumber = await proposalPromise;
+
+    // Approving the proposal
+    const proposalExecutionPromise = apiWrapper.expectProposalFinalized();
+    await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
+    await proposalExecutionPromise;
+
+    // Assertions
+    const newRoleParameters: RoleParameters = await apiWrapper.getStorageRoleParameters();
+    assert(
+      proposedMinStake.eq(newRoleParameters.min_stake.toBn()),
+      `Min stake has unexpected value ${newRoleParameters.min_stake.toBn()}, expected ${proposedMinStake}`
+    );
+    assert(
+      proposedMaxActors.eq(newRoleParameters.max_actors.toBn()),
+      `Max actors has unexpected value ${newRoleParameters.max_actors.toBn()}, expected ${proposedMaxActors}`
+    );
+    assert(
+      proposedReward.eq(newRoleParameters.reward.toBn()),
+      `Reward has unexpected value ${newRoleParameters.reward.toBn()}, expected ${proposedReward}`
+    );
+    assert(
+      proposedRewardPeriod.eq(newRoleParameters.reward_period.toBn()),
+      `Reward period has unexpected value ${newRoleParameters.reward_period.toBn()}, expected ${proposedRewardPeriod}`
+    );
+    assert(
+      proposedBondingPeriod.eq(newRoleParameters.bonding_period.toBn()),
+      `Bonding period has unexpected value ${newRoleParameters.bonding_period.toBn()}, expected ${proposedBondingPeriod}`
+    );
+    assert(
+      proposedUnbondingPeriod.eq(newRoleParameters.unbonding_period.toBn()),
+      `Unbonding period has unexpected value ${newRoleParameters.unbonding_period.toBn()}, expected ${proposedUnbondingPeriod}`
+    );
+    assert(
+      proposedMinServicePeriod.eq(newRoleParameters.min_service_period.toBn()),
+      `Min service period has unexpected value ${newRoleParameters.min_service_period.toBn()}, expected ${proposedMinServicePeriod}`
+    );
+    assert(
+      proposedStartupGracePeriod.eq(newRoleParameters.startup_grace_period.toBn()),
+      `Startup grace period has unexpected value ${newRoleParameters.startup_grace_period.toBn()}, expected ${proposedStartupGracePeriod}`
+    );
+    assert(
+      proposedEntryRequestFee.eq(newRoleParameters.entry_request_fee.toBn()),
+      `Entry request fee has unexpected value ${newRoleParameters.entry_request_fee.toBn()}, expected ${proposedEntryRequestFee}`
+    );
+  });
+}

+ 46 - 0
tests/network-tests/src/constantinople/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;
+  });
+}

+ 52 - 0
tests/network-tests/src/constantinople/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: string = '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;
+  });
+}

+ 55 - 0
tests/network-tests/src/constantinople/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}`
+    );
+  });
+}

+ 59 - 0
tests/network-tests/src/constantinople/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: string = 'spending proposal which is used for API network testing';
+    const runtimeVoteFee: BN = apiWrapper.estimateVoteForProposalFee();
+    const initialMintingCapacity: BN = await apiWrapper.getWorkingGroupMintCapacity();
+
+    // Topping the balances
+    const proposalStake: BN = new BN(50000);
+    const runtimeProposalFee: BN = apiWrapper.estimateProposeWorkingGroupMintCapacityFee(
+      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.proposeWorkingGroupMintCapacity(
+      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.getWorkingGroupMintCapacity();
+    assert(
+      proposedMintingCapacity.eq(newMintingCapacity),
+      `Content working group has unexpected minting capacity ${newMintingCapacity}, expected ${proposedMintingCapacity}`
+    );
+  });
+}

+ 40 - 0
tests/network-tests/src/constantinople/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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Set lead proposal scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+});

+ 42 - 0
tests/network-tests/src/constantinople/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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Spending proposal scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+});

+ 40 - 0
tests/network-tests/src/constantinople/tests/proposals/storageRoleParametersProposalTest.ts

@@ -0,0 +1,40 @@
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from '../impl/membershipCreation';
+import { councilTest } from '../impl/electingCouncil';
+import { storageRoleParametersProposalTest } from './impl/storageRoleParametersProposal';
+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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Storage role parameters proposal scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+  storageRoleParametersProposalTest(apiWrapper, m1KeyPairs, m2KeyPairs, keyring, sudoUri);
+  closeApi(apiWrapper);
+});

+ 40 - 0
tests/network-tests/src/constantinople/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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Text proposal scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+});

+ 41 - 0
tests/network-tests/src/constantinople/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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Update runtime scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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<KeyringPair>(), keyring, N, paidTerms, sudoUri);
+  closeApi(apiWrapper);
+});

+ 41 - 0
tests/network-tests/src/constantinople/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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Validator count proposal scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+});

+ 41 - 0
tests/network-tests/src/constantinople/tests/proposals/workingGroupMintCapacityProposalTest.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 '@constantinople/types';
+import { closeApi } from '../impl/closeApi';
+import { ApiWrapper } from '../../utils/apiWrapper';
+
+tap.mocha.describe('Validator count proposal scenario', async () => {
+  initConfig();
+  registerJoystreamTypes();
+
+  const m1KeyPairs: KeyringPair[] = new Array();
+  const m2KeyPairs: KeyringPair[] = new Array();
+
+  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: number = 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);
+});

+ 287 - 14
tests/network-tests/src/tests/constantinople/utils/apiWrapper.ts → tests/network-tests/src/constantinople/utils/apiWrapper.ts

@@ -2,10 +2,13 @@ import { ApiPromise, WsProvider } from '@polkadot/api';
 import { Option, Vec, Bytes, u32 } from '@polkadot/types';
 import { Option, Vec, Bytes, u32 } from '@polkadot/types';
 import { Codec } from '@polkadot/types/types';
 import { Codec } from '@polkadot/types/types';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-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');
+import { UserInfo, PaidMembershipTerms, MemberId } from '@constantinople/types/lib/members';
+import { Mint, MintId } from '@constantinople/types/lib/mint';
+import { Lead, LeadId } from '@constantinople/types/lib/content-working-group';
+import { RoleParameters } from '@constantinople/types/lib/roles';
+import { Seat } from '@constantinople/types';
+import { Balance, EventRecord, AccountId, BlockNumber, BalanceOf } from '@polkadot/types/interfaces';
+import BN from 'bn.js';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
 import { Sender } from './sender';
 import { Sender } from './sender';
 import { Utils } from './utils';
 import { Utils } from './utils';
@@ -61,11 +64,12 @@ export class ApiWrapper {
     return this.getPaidMembershipTerms(paidTermsId).then(terms => terms.unwrap().fee.toBn());
     return this.getPaidMembershipTerms(paidTermsId).then(terms => terms.unwrap().fee.toBn());
   }
   }
 
 
-  public async transferBalanceToAccounts(from: KeyringPair, to: KeyringPair[], amount: BN): Promise<void> {
-    for (const keyPair of to) {
-      await this.transferBalance(from, keyPair.address, amount);
-    }
-    return;
+  public async transferBalanceToAccounts(from: KeyringPair, to: KeyringPair[], amount: BN): Promise<void[]> {
+    return Promise.all(
+      to.map(async keyPair => {
+        await this.transferBalance(from, keyPair.address, amount);
+      })
+    );
   }
   }
 
 
   private getBaseTxFee(): BN {
   private getBaseTxFee(): BN {
@@ -132,6 +136,82 @@ export class ApiWrapper {
     );
     );
   }
   }
 
 
+  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 {
   public estimateVoteForProposalFee(): BN {
     return this.estimateTxFee(this.api.tx.proposalsEngine.vote(0, 0, 'Approve'));
     return this.estimateTxFee(this.api.tx.proposalsEngine.vote(0, 0, 'Approve'));
   }
   }
@@ -212,6 +292,14 @@ export class ApiWrapper {
     );
     );
   }
   }
 
 
+  public sudoSetCouncilMintCapacity(sudo: KeyringPair, capacity: BN): Promise<void> {
+    return this.sender.signAndSend(
+      this.api.tx.sudo.sudo(this.api.tx.council.setCouncilMintCapacity(capacity)),
+      sudo,
+      false
+    );
+  }
+
   public getBestBlock(): Promise<BN> {
   public getBestBlock(): Promise<BN> {
     return this.api.derive.chain.bestNumber();
     return this.api.derive.chain.bestNumber();
   }
   }
@@ -293,6 +381,128 @@ export class ApiWrapper {
     );
     );
   }
   }
 
 
+  public async proposeValidatorCount(
+    account: KeyringPair,
+    title: string,
+    description: string,
+    stake: BN,
+    validatorCount: BN
+  ): Promise<void> {
+    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<void> {
+    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<void> {
+    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<void> {
+    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<void> {
+    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 approveProposal(account: KeyringPair, memberId: BN, proposal: BN): Promise<void> {
   public approveProposal(account: KeyringPair, memberId: BN, proposal: BN): Promise<void> {
     return this.sender.signAndSend(this.api.tx.proposalsEngine.vote(memberId, proposal, 'Approve'), account, false);
     return this.sender.signAndSend(this.api.tx.proposalsEngine.vote(memberId, proposal, 'Approve'), account, false);
   }
   }
@@ -354,11 +564,6 @@ export class ApiWrapper {
     return this.api.query.balances.totalIssuance<Balance>();
     return this.api.query.balances.totalIssuance<Balance>();
   }
   }
 
 
-  public async getProposal(id: BN) {
-    const proposal = await this.api.query.proposalsEngine.proposals(id);
-    return;
-  }
-
   public async getRequiredProposalStake(numerator: number, denominator: number): Promise<BN> {
   public async getRequiredProposalStake(numerator: number, denominator: number): Promise<BN> {
     const issuance: number = await (await this.getTotalIssuance()).toNumber();
     const issuance: number = await (await this.getTotalIssuance()).toNumber();
     const stake = (issuance * numerator) / denominator;
     const stake = (issuance * numerator) / denominator;
@@ -368,4 +573,72 @@ export class ApiWrapper {
   public getProposalCount(): Promise<BN> {
   public getProposalCount(): Promise<BN> {
     return this.api.query.proposalsEngine.proposalCount<u32>();
     return this.api.query.proposalsEngine.proposalCount<u32>();
   }
   }
+
+  public async getWorkingGroupMintCapacity(): Promise<BN> {
+    const mintId: MintId = await this.api.query.contentWorkingGroup.mint<MintId>();
+    const mintCodec = await this.api.query.minting.mints<Codec[]>(mintId);
+    const mint: Mint = (mintCodec[0] as unknown) as Mint;
+    return mint.getField<Balance>('capacity');
+  }
+
+  public getValidatorCount(): Promise<BN> {
+    return this.api.query.staking.validatorCount<u32>();
+  }
+
+  public async getCurrentLeadAddress(): Promise<string> {
+    const leadId: Option<LeadId> = await this.api.query.contentWorkingGroup.currentLeadId<Option<LeadId>>();
+    const leadCodec = await this.api.query.contentWorkingGroup.leadById<Codec[]>(leadId.unwrap());
+    const lead = (leadCodec[0] as unknown) as Lead;
+    return lead.role_account.toString();
+  }
+
+  public async createStorageProvider(account: KeyringPair): Promise<void> {
+    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<boolean> {
+    const storageProviders: Vec<AccountId> = await this.api.query.actors.accountIdsByRole<Vec<AccountId>>(
+      'StorageProvider'
+    );
+    return storageProviders.map(accountId => accountId.toString()).includes(address);
+  }
+
+  public async getStorageRoleParameters(): Promise<RoleParameters> {
+    return (await this.api.query.actors.parameters<Option<RoleParameters>>('StorageProvider')).unwrap();
+  }
+
+  public async getAnnouncingPeriod(): Promise<BN> {
+    return await this.api.query.councilElection.announcingPeriod<BlockNumber>();
+  }
+
+  public async getVotingPeriod(): Promise<BN> {
+    return await this.api.query.councilElection.votingPeriod<BlockNumber>();
+  }
+
+  public async getRevealingPeriod(): Promise<BN> {
+    return await this.api.query.councilElection.revealingPeriod<BlockNumber>();
+  }
+
+  public async getCouncilSize(): Promise<BN> {
+    return await this.api.query.councilElection.councilSize<u32>();
+  }
+
+  public async getCandidacyLimit(): Promise<BN> {
+    return await this.api.query.councilElection.candidacyLimit<u32>();
+  }
+
+  public async getNewTermDuration(): Promise<BN> {
+    return await this.api.query.councilElection.newTermDuration<BlockNumber>();
+  }
+
+  public async getMinCouncilStake(): Promise<BN> {
+    return await this.api.query.councilElection.minCouncilStake<BalanceOf>();
+  }
+
+  public async getMinVotingStake(): Promise<BN> {
+    return await this.api.query.councilElection.minVotingStake<BalanceOf>();
+  }
 }
 }

+ 0 - 0
tests/network-tests/src/tests/constantinople/utils/config.ts → tests/network-tests/src/constantinople/utils/config.ts


+ 1 - 1
tests/network-tests/src/tests/constantinople/utils/sender.ts → tests/network-tests/src/constantinople/utils/sender.ts

@@ -1,4 +1,4 @@
-import BN = require('bn.js');
+import BN from 'bn.js';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 import { Index } from '@polkadot/types/interfaces';
 import { Index } from '@polkadot/types/interfaces';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
 import { SubmittableExtrinsic } from '@polkadot/api/types';

+ 7 - 0
tests/network-tests/src/constantinople/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);
+}

+ 3 - 4
tests/network-tests/src/tests/constantinople/utils/utils.ts → tests/network-tests/src/constantinople/utils/utils.ts

@@ -1,11 +1,10 @@
 import { IExtrinsic } from '@polkadot/types/types';
 import { IExtrinsic } from '@polkadot/types/types';
-import { Bytes } from '@polkadot/types';
 import { compactToU8a, stringToU8a } from '@polkadot/util';
 import { compactToU8a, stringToU8a } from '@polkadot/util';
 import { blake2AsHex } from '@polkadot/util-crypto';
 import { blake2AsHex } from '@polkadot/util-crypto';
-import BN = require('bn.js');
-import fs = require('fs');
+import BN from 'bn.js';
+import fs from 'fs';
 import { decodeAddress } from '@polkadot/keyring';
 import { decodeAddress } from '@polkadot/keyring';
-import { Seat } from '@joystream/types/';
+import { Seat } from '@constantinople/types';
 
 
 export class Utils {
 export class Utils {
   private static LENGTH_ADDRESS = 32 + 1; // publicKey + prefix
   private static LENGTH_ADDRESS = 32 + 1; // publicKey + prefix

+ 0 - 0
tests/network-tests/src/rome/tap-parallel-not-ok


+ 27 - 0
tests/network-tests/src/rome/tests/electingCouncilTest.ts

@@ -0,0 +1,27 @@
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from './impl/membershipCreation';
+import { councilTest } from './impl/electingCouncil';
+import { initConfig } from '../utils/config';
+import { Keyring } from '@polkadot/api';
+import BN from 'bn.js';
+import { setTimeout } from './impl/setTimeout';
+
+initConfig();
+
+const m1KeyPairs: KeyringPair[] = new Array();
+const m2KeyPairs: KeyringPair[] = new Array();
+
+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: number = 25;
+
+setTimeout(nodeUrl, durationInBlocks);
+membershipTest(m1KeyPairs, keyring, N, paidTerms, nodeUrl, sudoUri);
+membershipTest(m2KeyPairs, keyring, N, paidTerms, nodeUrl, sudoUri);
+councilTest(m1KeyPairs, m2KeyPairs, keyring, K, nodeUrl, sudoUri, greaterStake, lesserStake);

+ 18 - 27
tests/network-tests/src/tests/rome/electingCouncilTest.ts → tests/network-tests/src/rome/tests/impl/electingCouncil.ts

@@ -1,34 +1,33 @@
-import { membershipTest } from './membershipCreationTest';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import { ApiWrapper } from './utils/apiWrapper';
+import { ApiWrapper } from '../../utils/apiWrapper';
 import { WsProvider, Keyring } from '@polkadot/api';
 import { WsProvider, Keyring } from '@polkadot/api';
-import { initConfig } from './utils/config';
-import BN = require('bn.js');
+import BN from 'bn.js';
 import { registerJoystreamTypes, Seat } from '@rome/types';
 import { registerJoystreamTypes, Seat } from '@rome/types';
 import { assert } from 'chai';
 import { assert } from 'chai';
 import { v4 as uuid } from 'uuid';
 import { v4 as uuid } from 'uuid';
-import { Utils } from './utils/utils';
+import { Utils } from '../../utils/utils';
+import tap from 'tap';
 
 
-export function councilTest(m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[]) {
-  initConfig();
-  const keyring = new Keyring({ type: 'sr25519' });
-  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 defaultTimeout: number = 120000;
+export function councilTest(
+  m1KeyPairs: KeyringPair[],
+  m2KeyPairs: KeyringPair[],
+  keyring: Keyring,
+  K: number,
+  nodeUrl: string,
+  sudoUri: string,
+  greaterStake: BN,
+  lesserStake: BN
+) {
   let sudo: KeyringPair;
   let sudo: KeyringPair;
   let apiWrapper: ApiWrapper;
   let apiWrapper: ApiWrapper;
 
 
-  before(async function () {
-    this.timeout(defaultTimeout);
+  tap.test('Electing council test setup', async () => {
     registerJoystreamTypes();
     registerJoystreamTypes();
     const provider = new WsProvider(nodeUrl);
     const provider = new WsProvider(nodeUrl);
     apiWrapper = await ApiWrapper.create(provider);
     apiWrapper = await ApiWrapper.create(provider);
   });
   });
 
 
-  it('Electing a council test', async () => {
+  tap.test('Electing a council test', async () => {
     // Setup goes here because M keypairs are generated after before() function
     // Setup goes here because M keypairs are generated after before() function
     sudo = keyring.addFromUri(sudoUri);
     sudo = keyring.addFromUri(sudoUri);
     let now = await apiWrapper.getBestBlock();
     let now = await apiWrapper.getBestBlock();
@@ -111,17 +110,9 @@ export function councilTest(m1KeyPairs: KeyringPair[], m2KeyPairs: KeyringPair[]
         `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}`
         `Member ${seat.member} has unexpected stake ${Utils.getTotalStake(seat)}`
       )
       )
     );
     );
-  }).timeout(defaultTimeout);
+  });
 
 
-  after(() => {
+  tap.teardown(() => {
     apiWrapper.close();
     apiWrapper.close();
   });
   });
 }
 }
-
-describe.skip('Council integration tests', () => {
-  const m1KeyPairs: KeyringPair[] = new Array();
-  const m2KeyPairs: KeyringPair[] = new Array();
-  membershipTest(m1KeyPairs);
-  membershipTest(m2KeyPairs);
-  councilTest(m1KeyPairs, m2KeyPairs);
-});

+ 19 - 25
tests/network-tests/src/tests/rome/membershipCreationTest.ts → tests/network-tests/src/rome/tests/impl/membershipCreation.ts

@@ -3,27 +3,26 @@ import { registerJoystreamTypes } from '@rome/types';
 import { Keyring } from '@polkadot/keyring';
 import { Keyring } from '@polkadot/keyring';
 import { assert } from 'chai';
 import { assert } from 'chai';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import BN = require('bn.js');
-import { ApiWrapper } from './utils/apiWrapper';
-import { initConfig } from './utils/config';
+import BN from 'bn.js';
+import { ApiWrapper } from '../../utils/apiWrapper';
 import { v4 as uuid } from 'uuid';
 import { v4 as uuid } from 'uuid';
+import tap from 'tap';
 
 
-export function membershipTest(nKeyPairs: KeyringPair[]) {
-  initConfig();
-  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 defaultTimeout: number = 30000;
+export function membershipTest(
+  nKeyPairs: KeyringPair[],
+  keyring: Keyring,
+  N: number,
+  paidTerms: number,
+  nodeUrl: string,
+  sudoUri: string
+) {
   let apiWrapper: ApiWrapper;
   let apiWrapper: ApiWrapper;
   let sudo: KeyringPair;
   let sudo: KeyringPair;
   let aKeyPair: KeyringPair;
   let aKeyPair: KeyringPair;
   let membershipFee: BN;
   let membershipFee: BN;
   let membershipTransactionFee: BN;
   let membershipTransactionFee: BN;
 
 
-  before(async function () {
-    this.timeout(defaultTimeout);
+  tap.test('Membership creation test setup', async () => {
     registerJoystreamTypes();
     registerJoystreamTypes();
     const provider = new WsProvider(nodeUrl);
     const provider = new WsProvider(nodeUrl);
     apiWrapper = await ApiWrapper.create(provider);
     apiWrapper = await ApiWrapper.create(provider);
@@ -42,7 +41,7 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee);
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipTransactionFee);
   });
   });
 
 
-  it('Buy membeship is accepted with sufficient funds', async () => {
+  tap.test('Buy membeship is accepted with sufficient funds', async () => {
     await Promise.all(
     await Promise.all(
       nKeyPairs.map(async (keyPair, index) => {
       nKeyPairs.map(async (keyPair, index) => {
         await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`);
         await apiWrapper.buyMembership(keyPair, paidTerms, `new_member_${index}${keyPair.address.substring(0, 8)}`);
@@ -53,9 +52,9 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
         .getMemberIds(keyPair.address)
         .getMemberIds(keyPair.address)
         .then(membership => assert(membership.length > 0, `Account ${keyPair.address} is not a member`))
         .then(membership => assert(membership.length > 0, `Account ${keyPair.address} is not a member`))
     );
     );
-  }).timeout(defaultTimeout);
+  });
 
 
-  it('Account A can not buy the membership with insufficient funds', async () => {
+  tap.test('Account A can not buy the membership with insufficient funds', async () => {
     await apiWrapper
     await apiWrapper
       .getBalance(aKeyPair.address)
       .getBalance(aKeyPair.address)
       .then(balance =>
       .then(balance =>
@@ -68,9 +67,9 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
     apiWrapper
     apiWrapper
       .getMemberIds(aKeyPair.address)
       .getMemberIds(aKeyPair.address)
       .then(membership => assert(membership.length === 0, 'Account A is a member'));
       .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 () => {
+  tap.test('Account A was able to buy the membership with sufficient funds', async () => {
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipFee.add(membershipTransactionFee));
     await apiWrapper.transferBalance(sudo, aKeyPair.address, membershipFee.add(membershipTransactionFee));
     apiWrapper
     apiWrapper
       .getBalance(aKeyPair.address)
       .getBalance(aKeyPair.address)
@@ -81,14 +80,9 @@ export function membershipTest(nKeyPairs: KeyringPair[]) {
     apiWrapper
     apiWrapper
       .getMemberIds(aKeyPair.address)
       .getMemberIds(aKeyPair.address)
       .then(membership => assert(membership.length > 0, 'Account A is a not member'));
       .then(membership => assert(membership.length > 0, 'Account A is a not member'));
-  }).timeout(defaultTimeout);
+  });
 
 
-  after(() => {
+  tap.teardown(() => {
     apiWrapper.close();
     apiWrapper.close();
   });
   });
 }
 }
-
-describe.skip('Membership integration tests', () => {
-  const nKeyPairs: KeyringPair[] = new Array();
-  membershipTest(nKeyPairs);
-});

+ 19 - 30
tests/network-tests/src/tests/rome/romeRuntimeUpgradeTest.ts → tests/network-tests/src/rome/tests/impl/romeRuntimeUpgrade.ts

@@ -1,41 +1,30 @@
-import { initConfig } from './utils/config';
 import { Keyring, WsProvider } from '@polkadot/api';
 import { Keyring, WsProvider } from '@polkadot/api';
 import { KeyringPair } from '@polkadot/keyring/types';
 import { KeyringPair } from '@polkadot/keyring/types';
-import { membershipTest } from './membershipCreationTest';
-import { councilTest } from './electingCouncilTest';
 import { registerJoystreamTypes } from '@rome/types';
 import { registerJoystreamTypes } from '@rome/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 runtimePath: string = process.env.RUNTIME_WASM_PATH!;
-  const defaultTimeout: number = 180000;
-
-  const m1KeyPairs: KeyringPair[] = new Array();
-  const m2KeyPairs: KeyringPair[] = new Array();
+import { ApiWrapper } from '../../utils/apiWrapper';
+import BN from 'bn.js';
+import { Utils } from '../../utils/utils';
+import tap from 'tap';
 
 
+export function romeRuntimeUpgradeTest(
+  m1KeyPairs: KeyringPair[],
+  m2KeyPairs: KeyringPair[],
+  keyring: Keyring,
+  nodeUrl: string,
+  sudoUri: string,
+  proposalStake: BN,
+  runtimePath: string
+) {
   let apiWrapper: ApiWrapper;
   let apiWrapper: ApiWrapper;
   let sudo: KeyringPair;
   let sudo: KeyringPair;
-  let provider: WsProvider;
 
 
-  before(async function () {
-    this.timeout(defaultTimeout);
+  tap.test('Rome runtime upgrade test setup', async () => {
     registerJoystreamTypes();
     registerJoystreamTypes();
-    provider = new WsProvider(nodeUrl);
+    const provider = new WsProvider(nodeUrl);
     apiWrapper = await ApiWrapper.create(provider);
     apiWrapper = await ApiWrapper.create(provider);
   });
   });
 
 
-  membershipTest(m1KeyPairs);
-  membershipTest(m2KeyPairs);
-  councilTest(m1KeyPairs, m2KeyPairs);
-
-  it('Upgrading the runtime test', async () => {
+  tap.test('Upgrading the runtime test', async () => {
     // Setup
     // Setup
     sudo = keyring.addFromUri(sudoUri);
     sudo = keyring.addFromUri(sudoUri);
     const runtime: string = Utils.readRuntimeFromFile(runtimePath);
     const runtime: string = Utils.readRuntimeFromFile(runtimePath);
@@ -67,9 +56,9 @@ describe('Runtime upgrade integration tests', () => {
     const runtimePromise = apiWrapper.expectRuntimeUpgraded();
     const runtimePromise = apiWrapper.expectRuntimeUpgraded();
     await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
     await apiWrapper.batchApproveProposal(m2KeyPairs, proposalNumber);
     await runtimePromise;
     await runtimePromise;
-  }).timeout(defaultTimeout);
+  });
 
 
-  after(() => {
+  tap.teardown(() => {
     apiWrapper.close();
     apiWrapper.close();
   });
   });
-});
+}

+ 20 - 0
tests/network-tests/src/rome/tests/impl/setTimeout.ts

@@ -0,0 +1,20 @@
+import tap from 'tap';
+import { ApiWrapper } from '../../utils/apiWrapper';
+import { WsProvider } from '@polkadot/api';
+import { registerJoystreamTypes } from '@rome/types';
+
+export function setTimeout(nodeUrl: string, durationInBlocks: number) {
+  let apiWrapper: ApiWrapper;
+  registerJoystreamTypes();
+
+  tap.test('retrieving time necessary for the test', async () => {
+    const provider = new WsProvider(nodeUrl);
+    apiWrapper = await ApiWrapper.create(provider);
+    const durationInMillis = (await apiWrapper.getBlockDuration()).muln(durationInBlocks).toNumber();
+    tap.setTimeout(durationInMillis);
+  });
+
+  tap.teardown(() => {
+    apiWrapper.close();
+  });
+}

+ 19 - 0
tests/network-tests/src/rome/tests/membershipCreationTest.ts

@@ -0,0 +1,19 @@
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from './impl/membershipCreation';
+import { Keyring } from '@polkadot/api';
+import { initConfig } from '../utils/config';
+import { setTimeout } from './impl/setTimeout';
+
+initConfig();
+
+const nKeyPairs: KeyringPair[] = new Array();
+
+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: number = 7;
+
+setTimeout(nodeUrl, durationInBlocks);
+membershipTest(nKeyPairs, keyring, N, paidTerms, nodeUrl, sudoUri);

+ 31 - 0
tests/network-tests/src/rome/tests/romeRuntimeUpgradeTest.ts

@@ -0,0 +1,31 @@
+import { KeyringPair } from '@polkadot/keyring/types';
+import { membershipTest } from './impl/membershipCreation';
+import { councilTest } from './impl/electingCouncil';
+import { romeRuntimeUpgradeTest } from './impl/romeRuntimeUpgrade';
+import { initConfig } from '../utils/config';
+import { Keyring } from '@polkadot/api';
+import BN from 'bn.js';
+import { setTimeout } from './impl/setTimeout';
+
+initConfig();
+
+const m1KeyPairs: KeyringPair[] = new Array();
+const m2KeyPairs: KeyringPair[] = new Array();
+
+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 proposalStake: BN = new BN(+process.env.RUNTIME_UPGRADE_PROPOSAL_STAKE!);
+const runtimePath: string = process.env.RUNTIME_WASM_PATH!;
+const durationInBlocks: number = 30;
+
+setTimeout(nodeUrl, durationInBlocks);
+membershipTest(m1KeyPairs, keyring, N, paidTerms, nodeUrl, sudoUri);
+membershipTest(m2KeyPairs, keyring, N, paidTerms, nodeUrl, sudoUri);
+councilTest(m1KeyPairs, m2KeyPairs, keyring, K, nodeUrl, sudoUri, greaterStake, lesserStake);
+romeRuntimeUpgradeTest(m1KeyPairs, m2KeyPairs, keyring, nodeUrl, sudoUri, proposalStake, runtimePath);

+ 1 - 1
tests/network-tests/src/tests/rome/utils/apiWrapper.ts → tests/network-tests/src/rome/utils/apiWrapper.ts

@@ -5,7 +5,7 @@ import { KeyringPair } from '@polkadot/keyring/types';
 import { UserInfo, PaidMembershipTerms, MemberId } from '@rome/types/lib/members';
 import { UserInfo, PaidMembershipTerms, MemberId } from '@rome/types/lib/members';
 import { Seat, VoteKind } from '@rome/types';
 import { Seat, VoteKind } from '@rome/types';
 import { Balance, EventRecord } from '@polkadot/types/interfaces';
 import { Balance, EventRecord } from '@polkadot/types/interfaces';
-import BN = require('bn.js');
+import BN from 'bn.js';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
 import { Sender } from './sender';
 import { Sender } from './sender';
 import { Utils } from './utils';
 import { Utils } from './utils';

+ 0 - 0
tests/network-tests/src/tests/rome/utils/config.ts → tests/network-tests/src/rome/utils/config.ts


+ 1 - 1
tests/network-tests/src/tests/rome/utils/sender.ts → tests/network-tests/src/rome/utils/sender.ts

@@ -1,4 +1,4 @@
-import BN = require('bn.js');
+import BN from 'bn.js';
 import { ApiPromise } from '@polkadot/api';
 import { ApiPromise } from '@polkadot/api';
 import { Index } from '@polkadot/types/interfaces';
 import { Index } from '@polkadot/types/interfaces';
 import { SubmittableExtrinsic } from '@polkadot/api/types';
 import { SubmittableExtrinsic } from '@polkadot/api/types';

+ 2 - 2
tests/network-tests/src/tests/rome/utils/utils.ts → tests/network-tests/src/rome/utils/utils.ts

@@ -1,8 +1,8 @@
 import { IExtrinsic } from '@polkadot/types/types';
 import { IExtrinsic } from '@polkadot/types/types';
 import { compactToU8a, stringToU8a, u8aToHex } from '@polkadot/util';
 import { compactToU8a, stringToU8a, u8aToHex } from '@polkadot/util';
 import { blake2AsHex } from '@polkadot/util-crypto';
 import { blake2AsHex } from '@polkadot/util-crypto';
-import BN = require('bn.js');
-import fs = require('fs');
+import BN from 'bn.js';
+import fs from 'fs';
 import { decodeAddress } from '@polkadot/keyring';
 import { decodeAddress } from '@polkadot/keyring';
 import { Seat } from '@rome/types';
 import { Seat } from '@rome/types';
 
 

File diff suppressed because it is too large
+ 468 - 58
yarn.lock


Some files were not shown because too many files changed in this diff