Browse Source

Merge pull request #2330 from Joystream/antioch

Antioch Release
Martin 3 years ago
parent
commit
d15668954e
100 changed files with 1465 additions and 23483 deletions
  1. 2 0
      .dockerignore
  2. 1 21
      .env
  3. 3 0
      .github/workflows/content-directory-schemas.yml
  4. 6 0
      .github/workflows/joystream-cli.yml
  5. 2 0
      .github/workflows/joystream-types.yml
  6. 6 0
      .github/workflows/network-tests.yml
  7. 4 0
      .github/workflows/pioneer.yml
  8. 22 8
      .github/workflows/run-network-tests.yml
  9. 4 0
      .github/workflows/storage-node.yml
  10. 4 0
      .gitignore
  11. 389 169
      Cargo.lock
  12. 7 7
      README.md
  13. 21 3
      apps.Dockerfile
  14. 37 0
      build-docker-images.sh
  15. 12 0
      build-npm-packages.sh
  16. 0 55
      build.sh
  17. 1 1
      cli/README.md
  18. 5 5
      cli/package.json
  19. 4 4
      cli/src/Api.ts
  20. 1 1
      cli/src/base/ApiCommandBase.ts
  21. 2 3
      cli/src/base/ContentDirectoryCommandBase.ts
  22. 1 1
      cli/src/commands/api/inspect.ts
  23. 23 0
      cli/src/commands/media/createChannel.ts
  24. 4 4
      content-directory-schemas/package.json
  25. 1 1
      devops/git-hooks/pre-push
  26. 23 24
      docker-compose.yml
  27. 7 7
      joystream-node.Dockerfile
  28. 51 50
      node/Cargo.toml
  29. 4 4
      node/README.md
  30. 36 12
      node/src/chain_spec/mod.rs
  31. 44 10
      node/src/cli.rs
  32. 112 24
      node/src/command.rs
  33. 35 19
      node/src/node_rpc.rs
  34. 503 401
      node/src/service.rs
  35. 13 10
      package.json
  36. 18 0
      pioneer.Dockerfile
  37. 1 1
      pioneer/README.md
  38. 1 1
      pioneer/package.json
  39. 0 23
      pioneer/packages/apps-routing/src/claims.ts
  40. 0 22
      pioneer/packages/apps-routing/src/contracts.ts
  41. 0 25
      pioneer/packages/apps-routing/src/council.ts
  42. 0 22
      pioneer/packages/apps-routing/src/democracy.ts
  43. 0 21
      pioneer/packages/apps-routing/src/parachains.ts
  44. 0 23
      pioneer/packages/apps-routing/src/techcomm.ts
  45. 0 22
      pioneer/packages/apps-routing/src/treasury.ts
  46. 1 1
      pioneer/packages/apps/public/locales/en/app-staking.json
  47. 1 0
      pioneer/packages/apps/public/locales/en/joy-media.json
  48. 1 1
      pioneer/packages/apps/public/locales/es/translation.json
  49. 1 1
      pioneer/packages/apps/public/locales/pt/translation.json
  50. 2 2
      pioneer/packages/joy-election/src/utils.tsx
  51. 7 7
      pioneer/packages/joy-proposals/src/validationSchema.ts
  52. 1 1
      pioneer/packages/joy-roles/src/flows/apply.controller.tsx
  53. 1 1
      pioneer/packages/joy-roles/src/flows/apply.tsx
  54. 3 3
      pioneer/packages/joy-roles/src/transport.substrate.ts
  55. 3 3
      pioneer/packages/joy-utils/src/consts/proposals.ts
  56. 2 2
      pioneer/packages/joy-utils/src/react/hocs/accounts.tsx
  57. 1 1
      pioneer/packages/joy-utils/src/transport/APIQueryCache.ts
  58. 2 4
      pioneer/packages/joy-utils/src/transport/proposals.ts
  59. 0 19300
      pioneer/packages/joy-utils/src/transport/static/historical-proposals.json
  60. 2 2
      pioneer/packages/joy-utils/src/types/proposals.ts
  61. 0 26
      pioneer/packages/page-accounts/src/Accounts/BannerClaims.tsx
  62. 0 2
      pioneer/packages/page-accounts/src/Accounts/index.tsx
  63. 27 6
      pioneer/packages/page-accounts/src/Accounts/useProxies.ts
  64. 0 0
      pioneer/packages/page-claims/.skip-build
  65. 0 0
      pioneer/packages/page-claims/.skip-npm
  66. 0 201
      pioneer/packages/page-claims/LICENSE
  67. 0 1
      pioneer/packages/page-claims/README.md
  68. 0 19
      pioneer/packages/page-claims/package.json
  69. 0 104
      pioneer/packages/page-claims/src/Attest.tsx
  70. 0 135
      pioneer/packages/page-claims/src/Claim.tsx
  71. 0 84
      pioneer/packages/page-claims/src/Statement.tsx
  72. 0 57
      pioneer/packages/page-claims/src/Warning.tsx
  73. 0 311
      pioneer/packages/page-claims/src/index.tsx
  74. 0 8
      pioneer/packages/page-claims/src/secp256k1.d.ts
  75. 0 11
      pioneer/packages/page-claims/src/translate.ts
  76. 0 11
      pioneer/packages/page-claims/src/useCounter.ts
  77. 0 50
      pioneer/packages/page-claims/src/usePolkadotPreclaims.ts
  78. 0 25
      pioneer/packages/page-claims/src/util.spec.ts
  79. 0 144
      pioneer/packages/page-claims/src/util.ts
  80. 0 0
      pioneer/packages/page-contracts/.skip-build
  81. 0 0
      pioneer/packages/page-contracts/.skip-npm
  82. 0 201
      pioneer/packages/page-contracts/LICENSE
  83. 0 3
      pioneer/packages/page-contracts/README.md
  84. 0 17
      pioneer/packages/page-contracts/package.json
  85. 0 106
      pioneer/packages/page-contracts/src/Codes/Add.tsx
  86. 0 138
      pioneer/packages/page-contracts/src/Codes/Code.tsx
  87. 0 125
      pioneer/packages/page-contracts/src/Codes/Upload.tsx
  88. 0 57
      pioneer/packages/page-contracts/src/Codes/ValidateCode.tsx
  89. 0 45
      pioneer/packages/page-contracts/src/Codes/index.tsx
  90. 0 129
      pioneer/packages/page-contracts/src/Contracts/Add.tsx
  91. 0 265
      pioneer/packages/page-contracts/src/Contracts/Call.tsx
  92. 0 110
      pioneer/packages/page-contracts/src/Contracts/Contract.tsx
  93. 0 103
      pioneer/packages/page-contracts/src/Contracts/Outcome.tsx
  94. 0 58
      pioneer/packages/page-contracts/src/Contracts/ValidateAddr.tsx
  95. 0 103
      pioneer/packages/page-contracts/src/Contracts/index.tsx
  96. 0 51
      pioneer/packages/page-contracts/src/Contracts/util.tsx
  97. 0 250
      pioneer/packages/page-contracts/src/Deploy.tsx
  98. 0 56
      pioneer/packages/page-contracts/src/RemoveABI.tsx
  99. 0 10
      pioneer/packages/page-contracts/src/constants.ts
  100. 0 128
      pioneer/packages/page-contracts/src/index.tsx

+ 2 - 0
.dockerignore

@@ -5,3 +5,5 @@ target/
 query-node/generated
 query-node/**/dist
 query-node/lib
+cli/
+tests/

+ 1 - 21
.env

@@ -3,7 +3,7 @@ PROJECT_NAME=query_node
 
 # We will use a single postgres service with multiple databases
 INDEXER_DB_NAME=query_node_indexer
-PROCESSOR_DB_NAME=query_node_processor
+DB_NAME=query_node_processor
 DB_USER=postgres
 DB_PASS=postgres
 DB_HOST=localhost
@@ -16,30 +16,10 @@ TYPEORM_LOGGING=error
 #    Indexer options      #
 ###########################
 
-# Substrate endpoint to source events from
-WS_PROVIDER_ENDPOINT_URI=ws://localhost:9944/
-
 # Block height to start indexing from.
 # Note, that if there are already some indexed events, this setting is ignored
 BLOCK_HEIGHT=0
 
-# Redis cache server
-REDIS_URI=redis://localhost:6379/0
-
-###########################
-#    Processor options    #
-###########################
-
-# Where the mapping scripts are located, relative to ./generated/indexer
-TYPES_JSON=../../../types/augment/all/defs.json
-
-# Indexer GraphQL API endpoint to fetch indexed events
-INDEXER_ENDPOINT_URL=http://localhost:4000/graphql
-
-# Block height from which the processor starts. Note that if
-# there are already processed events in the database, this setting is ignored
-BLOCK_HEIGHT=0
-
 ###############################
 #    Processor GraphQL API    #
 ###############################

+ 3 - 0
.github/workflows/content-directory-schemas.yml

@@ -17,4 +17,7 @@ jobs:
     - name: validate
       run: |
         yarn install --frozen-lockfile
+        yarn workspace @joystream/types build
+        yarn workspace @joystream/cd-schemas generate:all
+        yarn workspace @joystream/cd-schemas build
         yarn workspace @joystream/cd-schemas checks --quiet

+ 6 - 0
.github/workflows/joystream-cli.yml

@@ -17,6 +17,9 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile
+        yarn workspace @joystream/types build
+        yarn workspace @joystream/cd-schemas generate:all
+        yarn workspace @joystream/cd-schemas build
         yarn workspace @joystream/cli checks --quiet
     - name: yarn pack test
       run: |
@@ -39,6 +42,9 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn workspace @joystream/types build
+        yarn workspace @joystream/cd-schemas generate:all
+        yarn workspace @joystream/cd-schemas build        
         yarn workspace @joystream/cli checks --quiet
     - name: yarn pack test
       run: |

+ 2 - 0
.github/workflows/joystream-types.yml

@@ -17,6 +17,7 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile
+        yarn workspace @joystream/types build
         yarn workspace @joystream/types checks --quiet
     - name: npm pack test
       run: |
@@ -40,6 +41,7 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn workspace @joystream/types build
         yarn workspace @joystream/types checks --quiet
     - name: npm pack test
       run: |

+ 6 - 0
.github/workflows/network-tests.yml

@@ -17,6 +17,9 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile
+        yarn workspace @joystream/types build
+        yarn workspace @joystream/cd-schemas generate:all
+        yarn workspace @joystream/cd-schemas build
         yarn workspace network-tests checks --quiet
 
   network_build_osx:
@@ -34,4 +37,7 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn workspace @joystream/types build
+        yarn workspace @joystream/cd-schemas generate:all
+        yarn workspace @joystream/cd-schemas build
         yarn workspace network-tests checks --quiet

+ 4 - 0
.github/workflows/pioneer.yml

@@ -17,6 +17,7 @@ jobs:
     - name: build
       run: |
         yarn install --frozen-lockfile
+        yarn workspace @joystream/types build
         yarn workspace pioneer build
 
   pioneer_build_osx:
@@ -34,6 +35,7 @@ jobs:
     - name: build
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn workspace @joystream/types build
         yarn workspace pioneer build
 
   pioneer_lint_ubuntu:
@@ -51,6 +53,7 @@ jobs:
     - name: lint
       run: |
         yarn install --frozen-lockfile
+        yarn workspace @joystream/types build
         yarn workspace pioneer lint --quiet
 
   pioneer_lint_osx:
@@ -68,4 +71,5 @@ jobs:
     - name: lint
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn workspace @joystream/types build
         yarn workspace pioneer lint --quiet

+ 22 - 8
.github/workflows/run-network-tests.yml

@@ -79,6 +79,7 @@ jobs:
           path: joystream-node-docker-image.tar.gz
 
   basic_runtime_with_upgrade:
+    if: ${{ false }}  # Antioch will be a new chain
     name: Integration Tests (Runtime Upgrade)
     needs: build_images
     runs-on: ubuntu-latest
@@ -96,11 +97,13 @@ jobs:
           docker load --input joystream-node-docker-image.tar.gz
           docker images
       - name: Install packages and dependencies
-        run: yarn install --frozen-lockfile
+        run: |
+          yarn install --frozen-lockfile
+          yarn build:packages
       - name: Ensure tests are runnable
         run: yarn workspace network-tests build
       - name: Execute network tests
-        run: RUNTIME=babylon tests/network-tests/run-tests.sh full
+        run: RUNTIME=antioch tests/network-tests/run-tests.sh full
 
   basic_runtime:
     name: Integration Tests (New Chain)
@@ -120,7 +123,9 @@ jobs:
           docker load --input joystream-node-docker-image.tar.gz
           docker images
       - name: Install packages and dependencies
-        run: yarn install --frozen-lockfile
+        run: |
+          yarn install --frozen-lockfile
+          yarn build:packages
       - name: Ensure tests are runnable
         run: yarn workspace network-tests build
       - name: Execute network tests
@@ -144,7 +149,11 @@ jobs:
           docker load --input joystream-node-docker-image.tar.gz
           docker images
       - name: Install packages and dependencies
-        run: yarn install --frozen-lockfile
+        run: |
+          yarn install --frozen-lockfile
+          yarn workspace @joystream/types build
+          yarn workspace @joystream/cd-schemas generate:all
+          yarn workspace @joystream/cd-schemas build
       - name: Ensure tests are runnable
         run: yarn workspace @joystream/cd-schemas checks --quiet
       - name: Start chain
@@ -170,9 +179,12 @@ jobs:
           docker load --input joystream-node-docker-image.tar.gz
           docker images
       - name: Install packages and dependencies
-        run: yarn install --frozen-lockfile
-      - name: Ensure query-node builds
-        run: yarn workspace query-node-root build
+        run: |
+          yarn install --frozen-lockfile
+          yarn workspace @joystream/types build
+          yarn workspace @joystream/cd-schemas generate:all
+          yarn workspace @joystream/cd-schemas build
+          yarn workspace query-node-root build
       - name: Ensure tests are runnable
         run: yarn workspace network-tests build
       # Bring up hydra query-node development instance, then run content directory
@@ -198,7 +210,9 @@ jobs:
           docker load --input joystream-node-docker-image.tar.gz
           docker images
       - name: Install packages and dependencies
-        run: yarn install --frozen-lockfile
+        run: |
+          yarn install --frozen-lockfile
+          yarn workspace @joystream/types build
       - name: Build storage node
         run: yarn workspace storage-node build
       - name: Start Services

+ 4 - 0
.github/workflows/storage-node.yml

@@ -17,7 +17,9 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile
+        yarn workspace @joystream/types build
         yarn workspace storage-node checks --quiet
+        yarn workspace storage-node build
 
   storage_node_build_osx:
     name: MacOS Checks
@@ -34,4 +36,6 @@ jobs:
     - name: checks
       run: |
         yarn install --frozen-lockfile --network-timeout 120000
+        yarn workspace @joystream/types build
         yarn workspace storage-node checks --quiet
+        yarn workspace storage-node build

+ 4 - 0
.gitignore

@@ -35,3 +35,7 @@ yarn*
 
 # eslint cache
 **/.eslintcache
+
+# test data for local node tests
+test-data/
+tmp.*

File diff suppressed because it is too large
+ 389 - 169
Cargo.lock


+ 7 - 7
README.md

@@ -25,12 +25,11 @@ After cloning the repo run the following initialization scripts:
 # Install rust toolchain
 ./setup.sh
 
-# Install npm package dependencies
-# Also good habit to run this when switching between branches
-yarn install
+# Install npm package dependencies, build packages and docker images
+yarn build
 
-# run some tests
-yarn cargo-checks
+# start a local development network
+yarn start
 ```
 
 ## Software
@@ -75,6 +74,7 @@ The HEAD of the master branch should always be used for the correct version of t
 ```sh
 git checkout master
 yarn install
+yarn build:packages
 yarn workspace pioneer start
 ```
 
@@ -89,8 +89,8 @@ You can also run your our own joystream-node:
 
 ```sh
 git checkout master
-WASM_BUILD_TOOLCHAIN=nightly-2020-05-23 cargo build --release
-./target/release/joystream-node -- --pruning archive --chain testnets/joy-testnet-4.json
+WASM_BUILD_TOOLCHAIN=nightly-2021-03-24 cargo build --release
+./target/release/joystream-node -- --pruning archive --chain testnets/joy-testnet-5.json
 ```
 
 Wait for the node to sync to the latest block, then change pioneer settings "remote node" option to "Local Node", or follow the link below:

+ 21 - 3
apps.Dockerfile

@@ -2,13 +2,31 @@ FROM node:12 as builder
 
 WORKDIR /joystream
 COPY . /joystream
+RUN  rm -fr /joystream/pioneer
 
 # Do not set NODE_ENV=production until after running yarn install
 # to ensure dev dependencies are installed.
-RUN yarn install --frozen-lockfile
+RUN yarn --forzen-lockfile
 
-RUN yarn workspace pioneer build
-RUN yarn workspace storage-node build
+RUN yarn workspace @joystream/types build
 RUN yarn workspace query-node-root build
+RUN yarn workspace storage-node build
+
+# Second stage to reduce image size, enable it when
+# all packages have correctly identified what is a devDependency and what is not.
+# It will reduce the image size by about 500MB (down from 2.2GB to 1.7GB)
+
+# # Remove files that are not needed after build.
+# # We will re-fetch only dependencies needed for running the apps.
+# RUN rm -fr node_modules/
+# RUN rm -fr .git/
+
+# FROM node:12
+# WORKDIR /joystream
+# COPY --from=builder /joystream/ /joystream/
+
+# # Skip installing devDependencies, since we have already built the packages.
+# ENV NODE_ENV=production
+# RUN yarn install --forzen-lockfile --production
 
 ENTRYPOINT [ "yarn" ]

+ 37 - 0
build-docker-images.sh

@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+set -e
+
+if ! command -v docker-compose &> /dev/null
+then
+  echo "docker-compose not found. Skipping docker image builds."
+  exit 0
+fi
+
+# Build or fetch cached joystream/node docker image
+if [[ "$SKIP_JOYSTREAM_NODE" = 1 || "$SKIP_JOYSTREAM_NODE" = "true" ]]; then
+  echo "Skipping build of joystream/node docker image."
+else
+  # Fetch a cached joystream/node image if one is found matching code shasum instead of building
+  CODE_HASH=`scripts/runtime-code-shasum.sh`
+  IMAGE=joystream/node:${CODE_HASH}
+  echo "Trying to fetch cached ${IMAGE} image"
+  docker pull ${IMAGE} || :
+
+  if ! docker inspect ${IMAGE} > /dev/null;
+  then
+    echo "Fetch failed, building image locally"
+    docker-compose build joystream-node
+  else
+    echo "Tagging cached image as 'latest'"
+    docker image tag ${IMAGE} joystream/node:latest
+  fi
+fi
+
+# Build joystream/apps docker image
+echo "Building 'joystream/apps' docker image..."
+docker-compose build colossus
+
+# Build the pioneer docker image
+echo "Building pioneer docker image"
+docker-compose build pioneer

+ 12 - 0
build-npm-packages.sh

@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -e
+
+yarn
+yarn workspace @joystream/types build
+yarn workspace @joystream/cd-schemas generate:all
+yarn workspace @joystream/cd-schemas build
+yarn workspace query-node-root build
+yarn workspace @joystream/cli build
+yarn workspace storage-node build
+yarn workspace pioneer build

+ 0 - 55
build.sh

@@ -1,55 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-yarn
-yarn workspace @joystream/types build
-yarn workspace @joystream/cd-schemas generate:all
-yarn workspace @joystream/cd-schemas build
-yarn workspace @joystream/cli build
-yarn workspace query-node-root build
-yarn workspace storage-node build
-# Not strictly needed during development, we run "yarn workspace pioneer start" to start
-# a dev instance, but will show highlight build issues
-yarn workspace pioneer build
-
-if ! command -v docker-compose &> /dev/null
-then
-  echo "docker-compose not found, skipping docker build!"
-else
-  # Build joystream/apps docker image
-  docker-compose build pioneer
-
-  # Optionally build joystream/node docker image
-  # TODO: Try to fetch a cached joystream/node image
-  # if one is found matching code shasum instead of building
-  while true
-  do
-    read -p "Rebuild joystream/node docker image? (y/N): " answer2
-
-    case $answer2 in
-    [yY]* ) docker-compose build joystream-node
-            break;;
-
-    [nN]* ) break;;
-
-    * )     break;;
-    esac
-  done
-fi
-
-# Build cargo crates: native binaries joystream/node, wasm runtime, and chainspec builder.
-while true
-do
-  read -p "Compile joystream node native binary? (y/N): " answer1
-
-  case $answer1 in
-   [yY]* ) yarn cargo-checks
-           yarn cargo-build
-           break;;
-
-   [nN]* ) break;;
-
-   * )     break;;
-  esac
-done

+ 1 - 1
cli/README.md

@@ -44,7 +44,7 @@ $ npm install -g @joystream/cli
 $ joystream-cli COMMAND
 running command...
 $ joystream-cli (-v|--version|version)
-@joystream/cli/0.3.2 linux-x64 node-v13.12.0
+@joystream/cli/0.4.0 darwin-x64 node-v12.18.2
 $ joystream-cli --help [COMMAND]
 USAGE
   $ joystream-cli COMMAND

+ 5 - 5
cli/package.json

@@ -1,7 +1,7 @@
 {
   "name": "@joystream/cli",
   "description": "Command Line Interface for Joystream community and governance activities",
-  "version": "0.3.2",
+  "version": "0.4.0",
   "author": "Leszek Wiesner",
   "bin": {
     "joystream-cli": "./bin/run"
@@ -10,15 +10,15 @@
   "dependencies": {
     "@apidevtools/json-schema-ref-parser": "^9.0.6",
     "@ffprobe-installer/ffprobe": "^1.1.0",
-    "@joystream/types": "^0.14.0",
-    "@joystream/cd-schemas": "^0.1.0",
+    "@joystream/types": "^0.15.0",
+    "@joystream/cd-schemas": "^0.2.0",
     "@oclif/command": "^1.5.19",
     "@oclif/config": "^1.14.0",
     "@oclif/plugin-autocomplete": "^0.2.0",
     "@oclif/plugin-help": "^2.2.3",
     "@oclif/plugin-not-found": "^1.2.4",
     "@oclif/plugin-warn-if-update-available": "^1.7.0",
-    "@polkadot/api": "1.26.1",
+    "@polkadot/api": "4.2.1",
     "@types/fluent-ffmpeg": "^2.1.16",
     "@types/inquirer": "^6.5.0",
     "@types/proper-lockfile": "^4.1.1",
@@ -44,7 +44,7 @@
   "devDependencies": {
     "@oclif/dev-cli": "^1.22.2",
     "@oclif/test": "^1.2.5",
-    "@polkadot/ts": "^0.1.56",
+    "@polkadot/ts": "^0.3.62",
     "@types/chai": "^4.2.11",
     "@types/mocha": "^5.2.7",
     "@types/node": "^10.17.18",

+ 4 - 4
cli/src/Api.ts

@@ -54,7 +54,6 @@ import { ServiceProviderRecord, Url } from '@joystream/types/discovery'
 import _ from 'lodash'
 
 export const DEFAULT_API_URI = 'ws://localhost:9944/'
-const DEFAULT_DECIMALS = new BN(12)
 
 // Mapping of working group to api module
 export const apiModuleByGroup: { [key in WorkingGroups]: string } = {
@@ -80,13 +79,14 @@ export default class Api {
     metadataCache: Record<string, any>
   ): Promise<ApiPromise> {
     const wsProvider: WsProvider = new WsProvider(apiUri)
-    const api = await ApiPromise.create({ provider: wsProvider, types, metadata: metadataCache })
+    const api = new ApiPromise({ provider: wsProvider, types, metadata: metadataCache })
+    await api.isReadyOrError
 
     // Initializing some api params based on pioneer/packages/react-api/Api.tsx
     const [properties] = await Promise.all([api.rpc.system.properties()])
 
-    const tokenSymbol = properties.tokenSymbol.unwrapOr('DEV').toString()
-    const tokenDecimals = properties.tokenDecimals.unwrapOr(DEFAULT_DECIMALS).toNumber()
+    const tokenSymbol = properties.tokenSymbol.unwrap()[0].toString()
+    const tokenDecimals = properties.tokenDecimals.unwrap()[0].toNumber()
 
     // formatBlanace config
     formatBalance.setDefaults({

+ 1 - 1
cli/src/base/ApiCommandBase.ts

@@ -383,7 +383,7 @@ export default abstract class ApiCommandBase extends StateAwareCommandBase {
                 }
                 reject(new ExtrinsicFailedError(`Extrinsic execution error: ${errorMsg}`))
               } else if (event.method === 'ExtrinsicSuccess') {
-                resolve()
+                resolve(result)
               }
             })
         } else if (result.isError) {

+ 2 - 3
cli/src/base/ContentDirectoryCommandBase.ts

@@ -16,9 +16,8 @@ import {
 } from '@joystream/types/content-directory'
 import { Worker } from '@joystream/types/working-group'
 import { CLIError } from '@oclif/errors'
-import { Codec } from '@polkadot/types/types'
-import AbstractInt from '@polkadot/types/codec/AbstractInt'
-import { AnyJson } from '@polkadot/types/types/helpers'
+import { Codec, AnyJson } from '@polkadot/types/types'
+import { AbstractInt } from '@polkadot/types/codec/AbstractInt'
 import _ from 'lodash'
 import { RolesCommandBase } from './WorkingGroupsCommandBase'
 import { createType } from '@joystream/types'

+ 1 - 1
cli/src/commands/api/inspect.ts

@@ -3,7 +3,7 @@ import { CLIError } from '@oclif/errors'
 import { displayNameValueTable } from '../../helpers/display'
 import { ApiPromise } from '@polkadot/api'
 import { Codec } from '@polkadot/types/types'
-import { ConstantCodec } from '@polkadot/metadata/Decorated/consts/types'
+import { ConstantCodec } from '@polkadot/metadata/decorate/types'
 import ExitCodes from '../../ExitCodes'
 import chalk from 'chalk'
 import { NameValueObj, ApiMethodArg } from '../../Types'

+ 23 - 0
cli/src/commands/media/createChannel.ts

@@ -5,6 +5,7 @@ import { InputParser } from '@joystream/cd-schemas'
 import { IOFlags, getInputJson, saveOutputJson } from '../../helpers/InputOutput'
 import { JSONSchema } from '@apidevtools/json-schema-ref-parser'
 import { JsonSchemaCustomPrompts, JsonSchemaPrompter } from '../../helpers/JsonSchemaPrompt'
+import { cli } from 'cli-ux'
 
 import { flags } from '@oclif/command'
 import _ from 'lodash'
@@ -16,6 +17,21 @@ export default class CreateChannelCommand extends ContentDirectoryCommandBase {
     confirm: flags.boolean({ char: 'y', name: 'confirm', required: false, description: 'Confirm the provided input' }),
   }
 
+  async getExistingChannelHandles(): Promise<string[]> {
+    cli.action.start('Fetching chain data...')
+    const result = await Promise.all(
+      (await this.entitiesByClassAndOwner('Channel'))
+        .filter(([, c]) => c.supported_schemas.toArray().length)
+        .map(async ([, channel]) => {
+          const { handle } = await this.parseToEntityJson<ChannelEntity>(channel)
+          return handle
+        })
+    )
+    cli.action.stop()
+
+    return result
+  }
+
   async run() {
     const account = await this.getRequiredSelectedAccount()
     const memberId = await this.getRequiredMemberId()
@@ -27,9 +43,16 @@ export default class CreateChannelCommand extends ContentDirectoryCommandBase {
 
     const { input, output, confirm } = this.parse(CreateChannelCommand).flags
 
+    // Can potentially slow things down quite a bit
+    const existingHandles = await this.getExistingChannelHandles()
+
     let inputJson = await getInputJson<ChannelEntity>(input, channelJsonSchema)
     if (!inputJson) {
       const customPrompts: JsonSchemaCustomPrompts = [
+        [
+          'handle',
+          { validate: (h) => (existingHandles.includes(h) ? 'Channel with such handle already exists' : true) },
+        ],
         ['language', () => this.promptForEntityId('Choose channel language', 'Language', 'name')],
         ['isCensored', 'skip'],
       ]

+ 4 - 4
content-directory-schemas/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@joystream/cd-schemas",
-  "version": "0.1.0",
+  "version": "0.2.0",
   "description": "JSON schemas, inputs and related tooling for Joystream content directory 2.0",
   "author": "Joystream contributors",
   "main": "lib/index.js",
@@ -26,9 +26,9 @@
   "dependencies": {
     "ajv": "6.12.5",
     "@joystream/prettier-config": "*",
-    "@polkadot/api": "1.26.1",
-    "@polkadot/keyring": "^3.0.1",
-    "@joystream/types": "^0.14.0",
+    "@polkadot/api": "4.2.1",
+    "@polkadot/keyring": "^6.0.5",
+    "@joystream/types": "^0.15.0",
     "@apidevtools/json-schema-ref-parser": "^9.0.6"
   },
   "devDependencies": {

+ 1 - 1
devops/git-hooks/pre-push

@@ -1,7 +1,7 @@
 #!/bin/sh
 set -e
 
-export WASM_BUILD_TOOLCHAIN=nightly-2020-05-23
+export WASM_BUILD_TOOLCHAIN=nightly-2021-03-24
 
 echo 'running clippy (rust linter)'
 # When custom build.rs triggers wasm-build-runner-impl to build we get error:

+ 23 - 24
docker-compose.yml

@@ -13,9 +13,10 @@ services:
     container_name: joystream-node
     volumes:
       - /data
-    command: --dev --alice --validator --unsafe-ws-external --rpc-cors=all --log runtime --base-path /data
+    command: --dev --alice --validator --unsafe-ws-external --unsafe-rpc-external --rpc-methods Unsafe --rpc-cors=all --log runtime --base-path /data
     ports:
       - "127.0.0.1:9944:9944"
+      - "127.0.0.1:9933:9933"
 
   ipfs:
     image: ipfs/go-ipfs:latest
@@ -66,7 +67,7 @@ services:
   graphql-server:
     image: joystream/apps
     restart: unless-stopped
-    build: 
+    build:
       context: .
       dockerfile: apps.Dockerfile
     env_file:
@@ -74,55 +75,54 @@ services:
       - .env
     environment:
       - DB_HOST=db
-      - DB_NAME=${PROCESSOR_DB_NAME}
+      - DB_NAME=${DB_NAME}
     ports:
       - "127.0.0.1:8081:${GRAPHQL_SERVER_PORT}"
-    depends_on: 
+    depends_on:
       - db
     command: ["workspace", "query-node-root", "server:start:prod"]
 
   processor:
     image: joystream/apps
     restart: unless-stopped
-    build: 
+    build:
       context: .
       dockerfile: apps.Dockerfile
     env_file:
       # relative to working directory where docker-compose was run from
       - .env
     environment:
-      - INDEXER_ENDPOINT_URL=http://indexer-api-gateway:${WARTHOG_APP_PORT}/graphql
-      - TYPEORM_HOST=db
-      - TYPEORM_DATABASE=${PROCESSOR_DB_NAME}
-      - DEBUG=index-builder:*
-      - WS_PROVIDER_ENDPOINT_URI=ws://joystream-node:9944
+      - POLL_INTERVAL_MS=300
+      - DEBUG=hydra-processor:*
+      - DB_HOST=db
+      - INDEXER_ENDPOINT_URL=http://indexer-api-gateway:4002/graphql
     depends_on:
       - indexer-api-gateway
     command: ["workspace", "query-node-root", "processor:start"]
 
   indexer:
-    image: joystream/apps
+    image: joystream/hydra-indexer:2.1.0-beta.5
     restart: unless-stopped
-    build: 
-      context: .
-      dockerfile: apps.Dockerfile
     env_file:
       # relative to working directory where docker-compose was run from
       - .env
     environment:
-      - TYPEORM_HOST=db
-      - TYPEORM_DATABASE=${INDEXER_DB_NAME}
       - INDEXER_WORKERS=5
-      - PROCESSOR_POLL_INTERVAL=1000 # refresh every second 
       - REDIS_URI=redis://redis:6379/0
       - DEBUG=index-builder:*
       - WS_PROVIDER_ENDPOINT_URI=ws://joystream-node:9944
-    depends_on: 
+      - TYPES_JSON=types.json
+      - DB_NAME=${INDEXER_DB_NAME}
+      - DB_HOST=db
+    depends_on:
       - db
-    command: ["workspace", "query-node-root", "indexer:start"] 
+    volumes:
+      - ./types/augment/all/defs.json:/home/hydra/packages/hydra-indexer/types.json
+    command: >
+      sh -c 'yarn db:bootstrap && yarn start:prod'
 
   indexer-api-gateway:
-    image: joystream/hydra-indexer-gateway:latest
+    image: joystream/hydra-indexer-gateway:2.1.0-beta.5
     restart: unless-stopped
     env_file:
       # relative to working directory where docker-compose was run from
@@ -151,10 +151,9 @@ services:
       - "127.0.0.1:6379:6379"
 
   pioneer:
-    image: joystream/apps
+    image: joystream/pioneer
     build:
       context: .
-      dockerfile: apps.Dockerfile
+      dockerfile: pioneer.Dockerfile
     ports:
-      - "127.0.0.1:3000:3000"
-    command: workspace pioneer start
+      - "127.0.0.1:3000:80"

+ 7 - 7
joystream-node.Dockerfile

@@ -1,9 +1,9 @@
-FROM liuchong/rustup:1.46.0 AS rustup
-RUN rustup component add rustfmt clippy
-RUN rustup install nightly-2020-05-23 --force
-RUN rustup target add wasm32-unknown-unknown --toolchain nightly-2020-05-23
+FROM liuchong/rustup:nightly AS rustup
+RUN rustup install nightly-2021-03-24
+RUN rustup default nightly-2021-03-24
+RUN rustup target add wasm32-unknown-unknown --toolchain nightly-2021-03-24
 RUN apt-get update && \
-  apt-get install -y curl git gcc xz-utils sudo pkg-config unzip clang libc6-dev-i386
+  apt-get install -y curl git gcc xz-utils sudo pkg-config unzip clang llvm libc6-dev
 
 FROM rustup AS builder
 LABEL description="Compiles all workspace artifacts"
@@ -12,12 +12,12 @@ COPY . /joystream
 
 # Build all cargo crates
 # Ensure our tests and linter pass before actual build
-ENV WASM_BUILD_TOOLCHAIN=nightly-2020-05-23
+ENV WASM_BUILD_TOOLCHAIN=nightly-2021-03-24
 RUN BUILD_DUMMY_WASM_BINARY=1 cargo clippy --release --all -- -D warnings && \
     cargo test --release --all && \
     cargo build --release
 
-FROM debian:stretch
+FROM debian:buster
 LABEL description="Joystream node"
 WORKDIR /joystream
 COPY --from=builder /joystream/target/release/joystream-node /joystream/node

+ 51 - 50
node/Cargo.toml

@@ -3,7 +3,7 @@ authors = ['Joystream contributors']
 build = 'build.rs'
 edition = '2018'
 name = 'joystream-node'
-version = '3.5.0'
+version = '5.1.0'
 default-run = "joystream-node"
 
 [[bin]]
@@ -17,79 +17,80 @@ crate-type = ["cdylib", "rlib"]
 # third-party dependencies
 serde = { version = "1.0.102", features = ["derive"] }
 futures = { version = "0.3.1", features = ["compat"] }
-jsonrpc-core = "14.2.0"
+jsonrpc-core = "15.0.0"
 structopt = { version = "0.3.8", optional = true}
 serde_json = '1.0'
-codec = { package = "parity-scale-codec", version = "1.3.1" }
+codec = { package = "parity-scale-codec", version = "1.3.4" }
 hex = { package = "hex", version = "0.4.2" }
 
 # primitives
-sp-authority-discovery = { package = 'sp-authority-discovery', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-consensus-babe = { package = 'sp-consensus-babe', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-finality-grandpa = { package = 'sp-finality-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-core = { package = 'sp-core', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-runtime = { package = 'sp-runtime', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-finality-tracker = { package = 'sp-finality-tracker', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-inherents = { package = 'sp-inherents', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-consensus = { package = 'sp-consensus', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-transaction-pool = { package = 'sp-transaction-pool', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-api = { package = 'sp-api', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-blockchain = { package = 'sp-blockchain', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-block-builder = { package = 'sp-block-builder', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-authority-discovery = { package = 'sp-authority-discovery', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-consensus-babe = { package = 'sp-consensus-babe', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-finality-grandpa = { package = 'sp-finality-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-core = { package = 'sp-core', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-runtime = { package = 'sp-runtime', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-finality-tracker = { package = 'sp-finality-tracker', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-inherents = { package = 'sp-inherents', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-consensus = { package = 'sp-consensus', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-transaction-pool = { package = 'sp-transaction-pool', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-api = { package = 'sp-api', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-blockchain = { package = 'sp-blockchain', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-block-builder = { package = 'sp-block-builder', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
 
 # client dependencies
-sc-client-api = { package = 'sc-client-api', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-chain-spec = { package = 'sc-chain-spec', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-consensus = { package = 'sc-consensus', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-transaction-pool = { package = 'sc-transaction-pool', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-network = { package = 'sc-network', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-consensus-babe = { package = 'sc-consensus-babe', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4'}
-sc-finality-grandpa = { package = 'sc-finality-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-basic-authorship = { package = 'sc-basic-authorship', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-service = { package = 'sc-service', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-authority-discovery = { package = 'sc-authority-discovery', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-consensus-epochs = { package = 'sc-consensus-epochs', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-keystore = { package = 'sc-keystore', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-consensus-babe-rpc = { package = 'sc-consensus-babe-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-finality-grandpa-rpc = { package = 'sc-finality-grandpa-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-rpc-api = { package = 'sc-rpc-api', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-executor = { package = 'sc-executor', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sc-client-api = { package = 'sc-client-api', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-chain-spec = { package = 'sc-chain-spec', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-consensus = { package = 'sc-consensus', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-transaction-pool = { package = 'sc-transaction-pool', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-network = { package = 'sc-network', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-consensus-babe = { package = 'sc-consensus-babe', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62'}
+sc-finality-grandpa = { package = 'sc-finality-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-basic-authorship = { package = 'sc-basic-authorship', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-service = { package = 'sc-service', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-authority-discovery = { package = 'sc-authority-discovery', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-consensus-epochs = { package = 'sc-consensus-epochs', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-keystore = { package = 'sc-keystore', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-consensus-babe-rpc = { package = 'sc-consensus-babe-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-finality-grandpa-rpc = { package = 'sc-finality-grandpa-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-rpc-api = { package = 'sc-rpc-api', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-rpc = { package = 'sc-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-executor = { package = 'sc-executor', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
 
 # frame dependencies
-pallet-im-online = { package = 'pallet-im-online', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-pallet-transaction-payment-rpc = { package = 'pallet-transaction-payment-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-substrate-frame-rpc-system = { package = 'substrate-frame-rpc-system', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-frame-benchmarking = { package = 'frame-benchmarking', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+pallet-im-online = { package = 'pallet-im-online', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+pallet-transaction-payment-rpc = { package = 'pallet-transaction-payment-rpc', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+substrate-frame-rpc-system = { package = 'substrate-frame-rpc-system', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+frame-benchmarking = { package = 'frame-benchmarking', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
 
 # node-specific dependencies
 node-runtime = { package= "joystream-node-runtime", path = "../runtime" }
 
 # CLI-specific dependencies
-sc-cli = { package = 'sc-cli', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true }
-frame-benchmarking-cli = { package = 'frame-benchmarking-cli', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true }
-node-inspect = { package = 'node-inspect', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true }
+sc-cli = { package = 'sc-cli', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true }
+frame-benchmarking-cli = { package = 'frame-benchmarking-cli', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true }
+node-inspect = { package = 'node-inspect', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true }
 
 # WASM-specific dependencies
 wasm-bindgen = { version = "0.2.57", optional = true }
 wasm-bindgen-futures = { version = "0.4.7", optional = true }
-browser-utils = { package = 'substrate-browser-utils', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true}
+browser-utils = { package = 'substrate-browser-utils', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true}
 
 [dev-dependencies]
 tempfile = "3.1.0"
-sp-timestamp = { package = 'sp-timestamp', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sp-keyring = { package = 'sp-keyring', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-sc-consensus-babe = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', features = ["test-helpers"]}
-sc-service-test = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-frame-system = { package = 'frame-system', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-pallet-transaction-payment = { package = 'pallet-transaction-payment', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
-pallet-grandpa = { package = 'pallet-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4' }
+sp-timestamp = { package = 'sp-timestamp', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sp-keyring = { package = 'sp-keyring', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+sc-consensus-babe = { git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', features = ["test-helpers"]}
+sc-service-test = { git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+frame-system = { package = 'frame-system', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+pallet-transaction-payment = { package = 'pallet-transaction-payment', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
+pallet-grandpa = { package = 'pallet-grandpa', git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62' }
 
 [build-dependencies]
 structopt = { version = "0.3.8", optional = true }
-node-inspect = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true}
-sc-cli = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true}
-frame-benchmarking-cli = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true }
-substrate-build-script-utils = { git = 'https://github.com/paritytech/substrate.git', rev = '00768a1f21a579c478fe5d4f51e1fa71f7db9fd4', optional = true }
+node-inspect = { git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true}
+sc-cli = { git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true}
+frame-benchmarking-cli = { git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true }
+substrate-build-script-utils = { git = 'https://github.com/paritytech/substrate.git', rev = '2cd20966cc09b059817c3ebe12fc130cdd850d62', optional = true }
 
 [features]
 default = [ "cli" ]

+ 4 - 4
node/README.md

@@ -26,7 +26,7 @@ cd joystream/
 Compile the node and runtime:
 
 ```bash
-WASM_BUILD_TOOLCHAIN=nightly-2020-05-23 cargo build --release
+WASM_BUILD_TOOLCHAIN=nightly-2021-03-24 cargo build --release
 ```
 
 This produces the binary in `./target/release/joystream-node`
@@ -49,7 +49,7 @@ this script will build and run a fresh new local development chain (purging exis
 Use the `--chain` argument, and specify the path to the genesis `chain.json` file for that public network. The JSON "chain spec" files for Joystream public networks can be found in [../testnets/](../testnets/).
 
 ```bash
-./target/release/joystream-node --chain testnets/joy-testnet-4.json
+./target/release/joystream-node --chain testnets/joy-testnet-5.json
 ```
 
 ### Tests and code quality
@@ -79,11 +79,11 @@ If you are building a tagged release from `master` branch and want to install th
 This will install the executable `joystream-node` to your `~/.cargo/bin` folder, which you would normally have in your `$PATH` environment.
 
 ```bash
-WASM_BUILD_TOOLCHAIN=nightly-2020-05-23 cargo install joystream-node --path node/ --locked
+WASM_BUILD_TOOLCHAIN=nightly-2021-03-24 cargo install joystream-node --path node/ --locked
 ```
 
 Now you can run and connect to the testnet:
 
 ```bash
-joystream-node --chain testnets/joy-testnet-4.json
+joystream-node --chain testnets/joy-testnet-5.json
 ```

+ 36 - 12
node/src/chain_spec/mod.rs

@@ -18,6 +18,8 @@
 // Disable it because we use such syntax for a code readability.
 // Example:  voting_period: 1 * DAY
 #![allow(clippy::identity_op)]
+// Remove after the Antioch release.
+#![allow(clippy::unnecessary_wraps)]
 
 use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
 use serde_json as json;
@@ -29,13 +31,13 @@ use sp_runtime::traits::{IdentifyAccount, Verify};
 use sp_runtime::Perbill;
 
 use node_runtime::{
-    membership, AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig,
+    membership, wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig,
     ContentDirectoryConfig, ContentDirectoryWorkingGroupConfig, ContentWorkingGroupConfig,
     CouncilConfig, CouncilElectionConfig, DataDirectoryConfig, DataObjectStorageRegistryConfig,
     DataObjectTypeRegistryConfig, ElectionParameters, ForumConfig, GrandpaConfig, ImOnlineConfig,
     MembersConfig, Moment, ProposalsCodexConfig, SessionConfig, SessionKeys, Signature,
     StakerStatus, StakingConfig, StorageWorkingGroupConfig, SudoConfig, SystemConfig,
-    VersionedStoreConfig, VersionedStorePermissionsConfig, DAYS, WASM_BINARY,
+    VersionedStoreConfig, VersionedStorePermissionsConfig, DAYS,
 };
 
 // Exported to be used by chain-spec-builder
@@ -235,8 +237,8 @@ pub fn testnet_genesis(
     let default_text_constraint = node_runtime::working_group::default_text_constraint();
 
     GenesisConfig {
-        system: Some(SystemConfig {
-            code: WASM_BINARY.to_vec(),
+        frame_system: Some(SystemConfig {
+            code: wasm_binary_unwrap().to_vec(),
             changes_trie_config: Default::default(),
         }),
         pallet_balances: Some(BalancesConfig {
@@ -253,7 +255,7 @@ pub fn testnet_genesis(
                 .collect(),
         }),
         pallet_staking: Some(StakingConfig {
-            validator_count: 20,
+            validator_count: 100,
             minimum_validator_count: initial_authorities.len() as u32,
             stakers: initial_authorities
                 .iter()
@@ -292,13 +294,13 @@ pub fn testnet_genesis(
         election: Some(CouncilElectionConfig {
             auto_start: true,
             election_parameters: ElectionParameters {
-                announcing_period: 2 * DAYS,
+                announcing_period: 4 * DAYS,
                 voting_period: 1 * DAYS,
                 revealing_period: 1 * DAYS,
-                council_size: 6,
-                candidacy_limit: 25,
+                council_size: 16,
+                candidacy_limit: 50,
                 min_council_stake: 1_000,
-                new_term_duration: 10 * DAYS,
+                new_term_duration: 1 * DAYS,
                 min_voting_stake: 100,
             },
         }),
@@ -395,7 +397,7 @@ pub fn testnet_genesis(
 #[cfg(test)]
 pub(crate) mod tests {
     use super::*;
-    use crate::service::{new_full, new_light};
+    use crate::service::{new_full_base, new_light_base, NewFullBase};
     use sc_service_test;
 
     fn local_testnet_genesis_instant_single() -> GenesisConfig {
@@ -471,8 +473,30 @@ pub(crate) mod tests {
     fn test_connectivity() {
         sc_service_test::connectivity(
             integration_test_config_with_two_authorities(),
-            |config| new_full(config),
-            |config| new_light(config),
+            |config| {
+                let NewFullBase {
+                    task_manager,
+                    client,
+                    network,
+                    transaction_pool,
+                    ..
+                } = new_full_base(config, |_, _| ())?;
+                Ok(sc_service_test::TestNetComponents::new(
+                    task_manager,
+                    client,
+                    network,
+                    transaction_pool,
+                ))
+            },
+            |config| {
+                let (keep_alive, _, client, network, transaction_pool) = new_light_base(config)?;
+                Ok(sc_service_test::TestNetComponents::new(
+                    keep_alive,
+                    client,
+                    network,
+                    transaction_pool,
+                ))
+            },
         );
     }
 }

+ 44 - 10
node/src/cli.rs

@@ -1,20 +1,22 @@
-// Copyright 2019 Joystream Contributors
-// This file is part of Joystream node.
+// This file is part of Substrate.
 
-// Joystream node is free software: you can redistribute it and/or modify
+// Copyright (C) 2018-2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
 // the Free Software Foundation, either version 3 of the License, or
 // (at your option) any later version.
 
-// Joystream node is distributed in the hope that it will be useful,
+// This program is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 // GNU General Public License for more details.
 
 // You should have received a copy of the GNU General Public License
-// along with Joystream node.  If not, see <http://www.gnu.org/licenses/>.
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-use sc_cli::RunCmd;
+use sc_cli::{KeySubcommand, RunCmd, SignCmd, VanityCmd, VerifyCmd};
 use structopt::StructOpt;
 
 /// An overarching CLI command definition.
@@ -31,9 +33,8 @@ pub struct Cli {
 /// Possible subcommands of the main binary.
 #[derive(Debug, StructOpt)]
 pub enum Subcommand {
-    /// A set of base subcommands handled by `sc_cli`.
-    #[structopt(flatten)]
-    Base(sc_cli::Subcommand),
+    /// Key management cli utilities
+    Key(KeySubcommand),
 
     /// The custom inspect subcommmand for decoding blocks and extrinsics.
     #[structopt(
@@ -45,4 +46,37 @@ pub enum Subcommand {
     /// The custom benchmark subcommmand benchmarking runtime pallets.
     #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
     Benchmark(frame_benchmarking_cli::BenchmarkCmd),
+
+    /// Verify a signature for a message, provided on STDIN, with a given (public or secret) key.
+    Verify(VerifyCmd),
+
+    /// Generate a seed that provides a vanity address.
+    Vanity(VanityCmd),
+
+    /// Sign a message, with a given (secret) key.
+    Sign(SignCmd),
+
+    /// Build a chain specification.
+    BuildSpec(sc_cli::BuildSpecCmd),
+
+    /// Build a chain specification with a light client sync state.
+    BuildSyncSpec(sc_cli::BuildSyncSpecCmd),
+
+    /// Validate blocks.
+    CheckBlock(sc_cli::CheckBlockCmd),
+
+    /// Export blocks.
+    ExportBlocks(sc_cli::ExportBlocksCmd),
+
+    /// Export the state of a given block into a chain spec.
+    ExportState(sc_cli::ExportStateCmd),
+
+    /// Import blocks.
+    ImportBlocks(sc_cli::ImportBlocksCmd),
+
+    /// Remove the whole chain.
+    PurgeChain(sc_cli::PurgeChainCmd),
+
+    /// Revert the chain to a previous state.
+    Revert(sc_cli::RevertCmd),
 }

+ 112 - 24
node/src/command.rs

@@ -16,41 +16,45 @@
 
 use crate::cli::{Cli, Subcommand};
 use crate::node_executor;
-use crate::node_rpc;
 use crate::{chain_spec, service};
 
+use crate::service::{new_full_base, new_partial, NewFullBase};
 use node_executor::Executor;
 use node_runtime::{opaque::Block, RuntimeApi};
-use sc_cli::{Result, SubstrateCli};
-use sc_finality_grandpa::{self as grandpa};
+use sc_cli::{ChainSpec, Result, Role, RuntimeVersion, SubstrateCli};
+use sc_service::PartialComponents;
 
 impl SubstrateCli for Cli {
-    fn impl_name() -> &'static str {
-        "Joystream Node"
+    fn impl_name() -> String {
+        "Joystream Node".into()
     }
 
-    fn support_url() -> &'static str {
-        "https://www.joystream.org/"
+    fn support_url() -> String {
+        "https://www.joystream.org/".into()
     }
 
     fn copyright_start_year() -> i32 {
         2019
     }
 
-    fn executable_name() -> &'static str {
-        "joystream-node"
+    fn executable_name() -> String {
+        "joystream-node".into()
     }
 
-    fn impl_version() -> &'static str {
-        env!("SUBSTRATE_CLI_IMPL_VERSION")
+    fn impl_version() -> String {
+        env!("SUBSTRATE_CLI_IMPL_VERSION").into()
     }
 
-    fn description() -> &'static str {
-        env!("CARGO_PKG_DESCRIPTION")
+    fn description() -> String {
+        env!("CARGO_PKG_DESCRIPTION").into()
     }
 
-    fn author() -> &'static str {
-        env!("CARGO_PKG_AUTHORS")
+    fn author() -> String {
+        env!("CARGO_PKG_AUTHORS").into()
+    }
+
+    fn native_runtime_version(_: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
+        &node_runtime::VERSION
     }
 
     fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
@@ -71,7 +75,10 @@ pub fn run() -> Result<()> {
     match &cli.subcommand {
         None => {
             let runner = cli.create_runner(&cli.run)?;
-            runner.run_node(service::new_light, service::new_full, node_runtime::VERSION)
+            runner.run_node_until_exit(|config| match config.role {
+                Role::Light => service::new_light(config),
+                _ => service::new_full(config),
+            })
         }
         Some(Subcommand::Inspect(cmd)) => {
             let runner = cli.create_runner(cmd)?;
@@ -84,17 +91,98 @@ pub fn run() -> Result<()> {
 
                 runner.sync_run(|config| cmd.run::<Block, Executor>(config))
             } else {
-                println!(
-                    "Benchmarking wasn't enabled when building the node. \
+                Err("Benchmarking wasn't enabled when building the node. \
 				You can enable it with `--features runtime-benchmarks`."
-                );
-                Ok(())
+                    .into())
             }
         }
-        Some(Subcommand::Base(subcommand)) => {
-            let runner = cli.create_runner(subcommand)?;
-
-            runner.run_subcommand(subcommand, |config| Ok(new_full_start!(config).0))
+        Some(Subcommand::Key(cmd)) => cmd.run(),
+        Some(Subcommand::Sign(cmd)) => cmd.run(),
+        Some(Subcommand::Verify(cmd)) => cmd.run(),
+        Some(Subcommand::Vanity(cmd)) => cmd.run(),
+        Some(Subcommand::BuildSpec(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
+        }
+        Some(Subcommand::BuildSyncSpec(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.async_run(|config| {
+                let chain_spec = config.chain_spec.cloned_box();
+                let network_config = config.network.clone();
+                let NewFullBase {
+                    task_manager,
+                    client,
+                    network_status_sinks,
+                    ..
+                } = new_full_base(config, |_, _| ())?;
+
+                Ok((
+                    cmd.run(chain_spec, network_config, client, network_status_sinks),
+                    task_manager,
+                ))
+            })
+        }
+        Some(Subcommand::CheckBlock(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.async_run(|config| {
+                let PartialComponents {
+                    client,
+                    task_manager,
+                    import_queue,
+                    ..
+                } = new_partial(&config)?;
+                Ok((cmd.run(client, import_queue), task_manager))
+            })
+        }
+        Some(Subcommand::ExportBlocks(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.async_run(|config| {
+                let PartialComponents {
+                    client,
+                    task_manager,
+                    ..
+                } = new_partial(&config)?;
+                Ok((cmd.run(client, config.database), task_manager))
+            })
+        }
+        Some(Subcommand::ExportState(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.async_run(|config| {
+                let PartialComponents {
+                    client,
+                    task_manager,
+                    ..
+                } = new_partial(&config)?;
+                Ok((cmd.run(client, config.chain_spec), task_manager))
+            })
+        }
+        Some(Subcommand::ImportBlocks(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.async_run(|config| {
+                let PartialComponents {
+                    client,
+                    task_manager,
+                    import_queue,
+                    ..
+                } = new_partial(&config)?;
+                Ok((cmd.run(client, import_queue), task_manager))
+            })
+        }
+        Some(Subcommand::PurgeChain(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.sync_run(|config| cmd.run(config.database))
+        }
+        Some(Subcommand::Revert(cmd)) => {
+            let runner = cli.create_runner(cmd)?;
+            runner.async_run(|config| {
+                let PartialComponents {
+                    client,
+                    task_manager,
+                    backend,
+                    ..
+                } = new_partial(&config)?;
+                Ok((cmd.run(client, backend), task_manager))
+            })
         }
     }
 }

+ 35 - 19
node/src/node_rpc.rs

@@ -30,23 +30,24 @@
 
 #![warn(missing_docs)]
 
-use std::sync::Arc;
-
-use node_runtime::UncheckedExtrinsic;
 use node_runtime::{opaque::Block, AccountId, Balance, BlockNumber, Hash, Index};
 use sc_consensus_babe::{Config, Epoch};
 use sc_consensus_babe_rpc::BabeRpcHandler;
 use sc_consensus_epochs::SharedEpochChanges;
-use sc_finality_grandpa::{SharedAuthoritySet, SharedVoterState};
+use sc_finality_grandpa::{
+    FinalityProofProvider, GrandpaJustificationStream, SharedAuthoritySet, SharedVoterState,
+};
 use sc_finality_grandpa_rpc::GrandpaRpcHandler;
 use sc_keystore::KeyStorePtr;
-use sc_rpc_api::DenyUnsafe;
+use sc_rpc::SubscriptionTaskExecutor;
+pub use sc_rpc_api::DenyUnsafe;
 use sp_api::ProvideRuntimeApi;
 use sp_block_builder::BlockBuilder;
 use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
 use sp_consensus::SelectChain;
 use sp_consensus_babe::BabeApi;
 use sp_transaction_pool::TransactionPool;
+use std::sync::Arc;
 
 /// Light client extra dependencies.
 pub struct LightDeps<C, F, P> {
@@ -71,15 +72,21 @@ pub struct BabeDeps {
 }
 
 /// Extra dependencies for GRANDPA
-pub struct GrandpaDeps {
+pub struct GrandpaDeps<B> {
     /// Voting round info.
     pub shared_voter_state: SharedVoterState,
     /// Authority set info.
     pub shared_authority_set: SharedAuthoritySet<Hash, BlockNumber>,
+    /// Receives notifications about justification events from Grandpa.
+    pub justification_stream: GrandpaJustificationStream<Block>,
+    /// Executor to drive the subscription manager in the Grandpa RPC handler.
+    pub subscription_executor: SubscriptionTaskExecutor,
+    /// Finality proof provider.
+    pub finality_provider: Arc<FinalityProofProvider<B, Block>>,
 }
 
 /// Full client dependencies.
-pub struct FullDeps<C, P, SC> {
+pub struct FullDeps<C, P, SC, B> {
     /// The client instance to use.
     pub client: Arc<C>,
     /// Transaction pool instance.
@@ -91,26 +98,28 @@ pub struct FullDeps<C, P, SC> {
     /// BABE specific dependencies.
     pub babe: BabeDeps,
     /// GRANDPA specific dependencies.
-    pub grandpa: GrandpaDeps,
+    pub grandpa: GrandpaDeps<B>,
 }
 
+/// A IO handler that uses all Full RPC extensions.
+pub type IoHandler = jsonrpc_core::IoHandler<sc_rpc::Metadata>;
+
 /// Instantiate all Full RPC extensions.
-pub fn create_full<C, P, M, SC>(deps: FullDeps<C, P, SC>) -> jsonrpc_core::IoHandler<M>
+pub fn create_full<C, P, SC, B>(
+    deps: FullDeps<C, P, SC, B>,
+) -> jsonrpc_core::IoHandler<sc_rpc_api::Metadata>
 where
     C: ProvideRuntimeApi<Block>,
     C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,
     C: Send + Sync + 'static,
     C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>,
-    C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<
-        Block,
-        Balance,
-        UncheckedExtrinsic,
-    >,
+    C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
     C::Api: BabeApi<Block>,
     C::Api: BlockBuilder<Block>,
     P: TransactionPool + 'static,
-    M: jsonrpc_core::Metadata + Default,
     SC: SelectChain<Block> + 'static,
+    B: sc_client_api::Backend<Block> + Send + Sync + 'static,
+    B::State: sc_client_api::backend::StateBackend<sp_runtime::traits::HashFor<Block>>,
 {
     use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
     use substrate_frame_rpc_system::{FullSystem, SystemApi};
@@ -124,6 +133,7 @@ where
         babe,
         grandpa,
     } = deps;
+
     let BabeDeps {
         keystore,
         babe_config,
@@ -132,6 +142,9 @@ where
     let GrandpaDeps {
         shared_voter_state,
         shared_authority_set,
+        justification_stream,
+        subscription_executor,
+        finality_provider,
     } = grandpa;
 
     io.extend_with(SystemApi::to_delegate(FullSystem::new(
@@ -139,9 +152,6 @@ where
         pool,
         deny_unsafe,
     )));
-    // Making synchronous calls in light client freezes the browser currently,
-    // more context: https://github.com/paritytech/substrate/pull/3480
-    // These RPCs should use an asynchronous caller instead.
     io.extend_with(TransactionPaymentApi::to_delegate(TransactionPayment::new(
         client.clone(),
     )));
@@ -156,7 +166,13 @@ where
         ),
     ));
     io.extend_with(sc_finality_grandpa_rpc::GrandpaApi::to_delegate(
-        GrandpaRpcHandler::new(shared_authority_set, shared_voter_state),
+        GrandpaRpcHandler::new(
+            shared_authority_set,
+            shared_voter_state,
+            justification_stream,
+            subscription_executor,
+            finality_provider,
+        ),
     ));
 
     io

File diff suppressed because it is too large
+ 503 - 401
node/src/service.rs


+ 13 - 10
package.json

@@ -4,8 +4,10 @@
   "version": "1.0.0",
   "license": "GPL-3.0-only",
   "scripts": {
-    "postinstall": "yarn workspace @joystream/types build && yarn workspace @joystream/cd-schemas generate:all && yarn workspace @joystream/cd-schemas build && yarn workspace @joystream/cli build",
-    "build": "./build.sh",
+    "build": "./build-npm-packages.sh && ./build-docker-images.sh",
+    "build:packages": "./build-npm-packages.sh",
+    "build:docker": "./build-docker-images.sh",
+    "setup": "./setup.sh",
     "start": "./start.sh",
     "cargo-checks": "devops/git-hooks/pre-commit && devops/git-hooks/pre-push",
     "cargo-build": "scripts/cargo-build.sh"
@@ -26,17 +28,18 @@
     "query-node/generated/*"
   ],
   "resolutions": {
-    "@polkadot/api": "1.26.1",
-    "@polkadot/api-contract": "1.26.1",
-    "@polkadot/keyring": "^3.0.1",
-    "@polkadot/types": "1.26.1",
-    "@polkadot/util": "^3.0.1",
-    "@polkadot/util-crypto": "^3.0.1",
-    "@polkadot/wasm-crypto": "^1.2.1",
+    "@polkadot/api": "4.2.1",
+    "@polkadot/api-contract": "4.2.1",
+    "@polkadot/keyring": "^6.0.5",
+    "@polkadot/types": "4.2.1",
+    "@polkadot/util": "^6.0.5",
+    "@polkadot/util-crypto": "^6.0.5",
+    "@polkadot/wasm-crypto": "^4.0.2",
     "babel-core": "^7.0.0-bridge.0",
     "typescript": "^3.9.7",
     "bn.js": "^5.1.2",
-    "@dzlzv/hydra-indexer-lib": "0.0.22-legacy.1.26.1"
+    "rxjs": "^6.6.2",
+    "typeorm": "^0.2.31"
   },
   "devDependencies": {
     "eslint": "^7.6.0",

+ 18 - 0
pioneer.Dockerfile

@@ -0,0 +1,18 @@
+FROM node:12 as builder
+
+WORKDIR /joystream
+COPY . /joystream
+
+RUN yarn
+RUN NODE_ENV=production yarn workspace @joystream/types build
+RUN NODE_ENV=production yarn workspace pioneer build
+
+FROM ubuntu:18.04
+
+RUN apt-get update && apt-get -y install nginx
+
+COPY --from=builder /joystream/pioneer/packages/apps/build /var/www/html
+
+EXPOSE 80
+
+CMD ["nginx", "-g", "daemon off;"]

+ 1 - 1
pioneer/README.md

@@ -37,7 +37,7 @@ To start off, this repo (along with others in the [@polkadot](https://github.com
 
 To get started -
 
-1. Clone the repo locally, via `git clone https://github.com/joystream/apps <optional local path>`
+1. Clone the repo locally, via `git clone https://github.com/joystream/joystream <optional local path>`
 2. Ensure that you have a recent LTS version of Node.js, for development purposes [Node >=10.13.0](https://nodejs.org/en/) is recommended.
 3. Ensure that you have a recent version of Yarn, for development purposes [Yarn >=1.10.1](https://yarnpkg.com/docs/install) is required.
 4. Install the dependencies by running `yarn`

+ 1 - 1
pioneer/package.json

@@ -34,7 +34,7 @@
     "@babel/runtime": "^7.10.5",
     "@pinata/sdk": "^1.1.10",
     "@polkadot/dev": "^0.55.28",
-    "@polkadot/ts": "^0.3.29",
+    "@polkadot/ts": "^0.3.62",
     "@types/bn.js": "^4.11.6",
     "@types/chart.js": "^2.9.23",
     "@types/file-saver": "^2.0.1",

+ 0 - 23
pioneer/packages/apps-routing/src/claims.ts

@@ -1,23 +0,0 @@
-// Copyright 2017-2020 @polkadot/apps-routing authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Route } from './types';
-
-import Component, { useCounter } from '@polkadot/app-claims';
-
-export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
-  return {
-    Component,
-    display: {
-      needsAccounts: true,
-      needsApi: [
-        'query.claims.claims'
-      ]
-    },
-    icon: 'star',
-    name: 'claims',
-    text: t<string>('nav.claims', 'Claim Tokens', { ns: 'apps-routing' }),
-    useCounter
-  };
-}

+ 0 - 22
pioneer/packages/apps-routing/src/contracts.ts

@@ -1,22 +0,0 @@
-// Copyright 2017-2020 @polkadot/apps-routing authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Route } from './types';
-
-import Component from '@polkadot/app-contracts';
-
-export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
-  return {
-    Component,
-    display: {
-      needsAccounts: true,
-      needsApi: [
-        'tx.contracts.call'
-      ]
-    },
-    icon: 'compress',
-    name: 'contracts',
-    text: t<string>('nav.contracts', 'Contracts', { ns: 'apps-routing' })
-  };
-}

+ 0 - 25
pioneer/packages/apps-routing/src/council.ts

@@ -1,25 +0,0 @@
-// Copyright 2017-2020 @polkadot/apps-routing authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Route } from './types';
-
-import Component, { useCounter } from '@polkadot/app-council';
-
-export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
-  return {
-    Component,
-    display: {
-      needsApi: [
-        [
-          'query.electionsPhragmen.candidates',
-          'query.elections.candidates'
-        ]
-      ]
-    },
-    icon: 'building',
-    name: 'council',
-    text: t<string>('nav.council', 'Council', { ns: 'apps-routing' }),
-    useCounter
-  };
-}

+ 0 - 22
pioneer/packages/apps-routing/src/democracy.ts

@@ -1,22 +0,0 @@
-// Copyright 2017-2020 @polkadot/apps-routing authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Route } from './types';
-
-import Component, { useCounter } from '@polkadot/app-democracy';
-
-export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
-  return {
-    Component,
-    display: {
-      needsApi: [
-        'tx.democracy.notePreimage'
-      ]
-    },
-    icon: 'calendar-check',
-    name: 'democracy',
-    text: t<string>('nav.democracy', 'Democracy', { ns: 'apps-routing' }),
-    useCounter
-  };
-}

+ 0 - 21
pioneer/packages/apps-routing/src/parachains.ts

@@ -1,21 +0,0 @@
-// Copyright 2017-2020 @polkadot/apps-routing authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Route } from './types';
-
-import Component from '@polkadot/app-parachains';
-
-export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
-  return {
-    Component,
-    display: {
-      needsApi: [
-        'query.parachains.code'
-      ]
-    },
-    icon: 'link',
-    name: 'parachains',
-    text: t<string>('nav.parachains', 'Parachains', { ns: 'apps-routing' })
-  };
-}

+ 0 - 23
pioneer/packages/apps-routing/src/techcomm.ts

@@ -1,23 +0,0 @@
-// Copyright 2017-2020 @polkadot/apps-routing authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Route } from './types';
-
-import Component, { useCounter } from '@polkadot/app-tech-comm';
-
-export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
-  return {
-    Component,
-    display: {
-      needsAccounts: true,
-      needsApi: [
-        'query.technicalCommittee.members'
-      ]
-    },
-    icon: 'microchip',
-    name: 'techcomm',
-    text: t<string>('nav.tech-comm', 'Tech. comm.', { ns: 'apps-routing' }),
-    useCounter
-  };
-}

+ 0 - 22
pioneer/packages/apps-routing/src/treasury.ts

@@ -1,22 +0,0 @@
-// Copyright 2017-2020 @polkadot/apps-routing authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Route } from './types';
-
-import Component, { useCounter } from '@polkadot/app-treasury';
-
-export default function create (t: <T = string> (key: string, text: string, options: { ns: string }) => T): Route {
-  return {
-    Component,
-    display: {
-      needsApi: [
-        'tx.treasury.proposeSpend'
-      ]
-    },
-    icon: 'gem',
-    name: 'treasury',
-    text: t<string>('nav.treasury', 'Treasury', { ns: 'apps-routing' }),
-    useCounter
-  };
-}

+ 1 - 1
pioneer/packages/apps/public/locales/en/app-staking.json

@@ -77,7 +77,7 @@
   "Targets": "Targets",
   "The Threshold must be a positive number": "The Threshold must be a positive number",
   "The Threshold must lower than 11": "The Threshold must lower than 11",
-  "The UI puts a limit of 40 payouts at a time, where each payout is a single validator for a single era.": "The UI puts a limit of 40 payouts at a time, where each payout is a single validator for a single era.",
+  "The UI puts a limit of 30 payouts at a time, where each payout is a single validator for a single era.": "The UI puts a limit of 30 payouts at a time, where each payout is a single validator for a single era.",
   "The amount of funds to unbond, this is adjusted using the bonded funds on the stash account.": "The amount of funds to unbond, this is adjusted using the bonded funds on the stash account.",
   "The amount placed at-stake should allow some free funds for future transactions.": "The amount placed at-stake should allow some free funds for future transactions.",
   "The amount placed at-stake should be no more that 95% of your available amount to protect against slashing events.": "The amount placed at-stake should be no more that 95% of your available amount to protect against slashing events.",

+ 1 - 0
pioneer/packages/apps/public/locales/en/joy-media.json

@@ -0,0 +1 @@
+{}

+ 1 - 1
pioneer/packages/apps/public/locales/es/translation.json

@@ -433,7 +433,7 @@
   "The RPC node can be selected from the pre-defined list or manually entered, depending on the chain you wish to connect to.": "El nodo RPC puede ser seleccionado de la lista preestablecida o introducido manualmente, dependiendo de la cadena a la que se desee conectar.",
   "The Threshold must be a positive number": "El umbral debe ser un número positivo",
   "The Threshold must lower than 11": "El umbral debe ser menor que 11",
-  "The UI puts a limit of 40 payouts at a time, where each payout is a single validator for a single era.": "La UI pone un límite de 40 remuneraciones a la vez, donde cada pago es un único validador para una sola era.",
+  "The UI puts a limit of 30 payouts at a time, where each payout is a single validator for a single era.": "La UI pone un límite de 30 remuneraciones a la vez, donde cada pago es un único validador para una sola era.",
   "The account password as specified when creating the account. This is used to encrypt the backup file and subsequently decrypt it when restoring the account.": "La contraseña de la cuenta, tal como se indicó al crear la cuenta. Se utiliza para cifrar el archivo de copia de seguridad y posteriormente se desencripta cuando se restaura la cuenta.",
   "The account that signed the input": "La cuenta que firmó la entrada",
   "The account to which the proposed balance will be transferred if approved": "La cuenta a la que se transferirá el saldo propuesto si se aprueba",

+ 1 - 1
pioneer/packages/apps/public/locales/pt/translation.json

@@ -436,7 +436,7 @@
   "The RPC node can be selected from the pre-defined list or manually entered, depending on the chain you wish to connect to.": "O nó RPC pode ser selecionado da lista predefinida ou inserido manualmente, dependendo da cadeia à qual você deseja se conectar.",
   "The Threshold must be a positive number": "O mínimo deve ser um número positivo",
   "The Threshold must lower than 11": "O mínimo deve ser menor que 11",
-  "The UI puts a limit of 40 payouts at a time, where each payout is a single validator for a single era.": "A interface do usuário coloca um limite de 40 pagamentos por vez, em que cada pagamento é um validador único para uma única era.",
+  "The UI puts a limit of 30 payouts at a time, where each payout is a single validator for a single era.": "A interface do usuário coloca um limite de 30 pagamentos por vez, em que cada pagamento é um validador único para uma única era.",
   "The account password as specified when creating the account. This is used to encrypt the backup file and subsequently decrypt it when restoring the account.": "A senha da conta, conforme especificado ao criar a conta. Isso é usado para criptografar o arquivo de backup e, posteriormente, descriptografá-lo ao restaurar a conta.",
   "The account that signed the input": "A conta que assinou a entrada",
   "The account to which the proposed balance will be transferred if approved": "A conta para a qual o saldo proposto será transferido se aprovado",

+ 2 - 2
pioneer/packages/joy-election/src/utils.tsx

@@ -4,7 +4,7 @@ import { AccountId } from '@polkadot/types/interfaces';
 // Keyring / identicon / address
 // -----------------------------------
 
-import createItem from '@polkadot/ui-keyring/options/item';
+import { createOptionItem } from '@polkadot/ui-keyring/options/item';
 import { findNameByAddress } from '@polkadot/joy-utils/functions/misc';
 
 // Hash
@@ -23,7 +23,7 @@ export type HashedVote = {
 const createAddressOption = (address: string) => {
   const name = findNameByAddress(address);
 
-  return createItem(address, name);
+  return createOptionItem(address, name);
 };
 
 export const accountIdsToOptions = (applicants: Array<AccountId>) => {

+ 7 - 7
pioneer/packages/joy-proposals/src/validationSchema.ts

@@ -40,18 +40,18 @@ const REVEALING_PERIOD_MIN = 14400;
 const REVEALING_PERIOD_MAX = 28800;
 const MIN_COUNCIL_STAKE_MIN = 1;
 const MIN_COUNCIL_STAKE_MAX = 100000;
-const NEW_TERM_DURATION_MIN = 14400;
-const NEW_TERM_DURATION_MAX = 432000;
+const NEW_TERM_DURATION_MIN = 1;
+const NEW_TERM_DURATION_MAX = 144000;
 const CANDIDACY_LIMIT_MIN = 50;
-const CANDIDACY_LIMIT_MAX = 100;
-const COUNCIL_SIZE_MIN = 4;
-const COUNCIL_SIZE_MAX = 20;
+const CANDIDACY_LIMIT_MAX = 200;
+const COUNCIL_SIZE_MIN = 6;
+const COUNCIL_SIZE_MAX = 40;
 const MIN_VOTING_STAKE_MIN = 1;
 const MIN_VOTING_STAKE_MAX = 100000;
 
 // Spending
 const TOKENS_MIN = 0;
-const TOKENS_MAX = 5000000;
+const TOKENS_MAX = 50000000;
 
 // Set Validator Count
 const MAX_VALIDATOR_COUNT_MIN = 4;
@@ -83,7 +83,7 @@ const WG_MINT_CAP_MAX = 5000000;
 // TODO: Discuss the actual values
 const MIN_REWARD_AMOUNT = 1;
 const MAX_REWARD_AMOUNT = 100000;
-const MIN_REWARD_INTERVAL = 1;
+const MIN_REWARD_INTERVAL = 600; // 1 h
 const MAX_REWARD_INTERVAL = 30 * 14400; // 30 days
 // 3 days margin (voting_period) to prevent FillOpeningInvalidNextPaymentBlock
 // Should we worry that much about it though?

+ 1 - 1
pioneer/packages/joy-roles/src/flows/apply.controller.tsx

@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
 
 import { formatBalance } from '@polkadot/util';
 import { Balance } from '@polkadot/types/interfaces';
-import AccountId from '@polkadot/types/generic/AccountId';
+import { GenericAccountId as AccountId } from '@polkadot/types/generic/AccountId';
 
 import { Controller } from '@polkadot/joy-utils/react/helpers';
 import { View } from '@polkadot/joy-utils/react/hocs';

+ 1 - 1
pioneer/packages/joy-roles/src/flows/apply.tsx

@@ -24,7 +24,7 @@ import { Accordion,
   TextAreaProps } from 'semantic-ui-react';
 
 import Identicon from '@polkadot/react-identicon';
-import AccountId from '@polkadot/types/generic/AccountId';
+import { GenericAccountId as AccountId } from '@polkadot/types/generic/AccountId';
 
 import { GenericJoyStreamRoleSchema,
   ApplicationDetails,

+ 3 - 3
pioneer/packages/joy-roles/src/transport.substrate.ts

@@ -1,11 +1,11 @@
 import { map, switchMap } from 'rxjs/operators';
 
-import ApiPromise from '@polkadot/api/promise';
+import { ApiPromise } from '@polkadot/api/promise';
 import { Balance } from '@polkadot/types/interfaces';
 import { Option, Vec } from '@polkadot/types';
 import { Moment } from '@polkadot/types/interfaces/runtime';
 import { QueueTxExtrinsicAdd } from '@polkadot/react-components/Status/types';
-import keyringOption from '@polkadot/ui-keyring/options';
+import { keyring } from '@polkadot/ui-keyring';
 
 import { APIQueryCache } from '@polkadot/joy-utils/transport/APIQueryCache';
 import { Subscribable } from '@polkadot/joy-utils/react/helpers';
@@ -393,7 +393,7 @@ export class Transport extends BaseTransport implements ITransport {
   }
 
   accounts (): Subscribable<keyPairDetails[]> {
-    return keyringOption.optionsSubject.pipe(
+    return keyring.keyringOption.optionsSubject.pipe(
       map((accounts) => {
         return accounts.all
           .filter((x) => x.value)

+ 3 - 3
pioneer/packages/joy-utils/src/consts/proposals.ts

@@ -33,7 +33,7 @@ export const metadata: { [k in ProposalType]: ProposalMeta } = {
   SetValidatorCount: {
     description: 'Set Max Validator Count Proposal',
     category: 'Validators',
-    stake: 100000,
+    stake: 500000,
     approvalQuorum: 66,
     approvalThreshold: 80,
     slashingQuorum: 60,
@@ -71,7 +71,7 @@ export const metadata: { [k in ProposalType]: ProposalMeta } = {
   SetElectionParameters: {
     description: 'Set Election Parameters Proposal',
     category: 'Council',
-    stake: 200000,
+    stake: 1000000,
     approvalQuorum: 66,
     approvalThreshold: 80,
     slashingQuorum: 60,
@@ -80,7 +80,7 @@ export const metadata: { [k in ProposalType]: ProposalMeta } = {
   RuntimeUpgrade: {
     description: 'Runtime Upgrade Proposal',
     category: 'Other',
-    stake: 1000000,
+    stake: 5000000,
     approvalQuorum: 80,
     approvalThreshold: 100,
     slashingQuorum: 60,

+ 2 - 2
pioneer/packages/joy-utils/src/react/hocs/accounts.tsx

@@ -2,7 +2,7 @@ import React, { useContext } from 'react';
 
 import { AccountId } from '@polkadot/types/interfaces';
 import { Vec } from '@polkadot/types';
-import accountObservable from '@polkadot/ui-keyring/observable/accounts';
+import { keyring } from '@polkadot/ui-keyring';
 import { withCalls, withMulti, withObservable, ApiContext } from '@polkadot/react-api/index';
 import { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
 
@@ -105,7 +105,7 @@ const withMyProfile = <P extends MyAccountProps>(Component: React.ComponentType<
 export const withMyAccount = <P extends MyAccountProps>(Component: React.ComponentType<P>) =>
   withMulti(
     Component,
-    withObservable(accountObservable.subject, { propName: 'allAccounts' }),
+    withObservable(keyring.accounts.subject, { propName: 'allAccounts' }),
     withMyAddress,
     withMyMemberIds,
     withMyMembership,

+ 1 - 1
pioneer/packages/joy-utils/src/transport/APIQueryCache.ts

@@ -1,5 +1,5 @@
 import { Codec } from '@polkadot/types/types';
-import ApiPromise from '@polkadot/api/promise';
+import { ApiPromise } from '@polkadot/api/promise';
 
 type cacheQueryStorage = {
   (...args: any): Promise<Codec>;

+ 2 - 4
pioneer/packages/joy-utils/src/transport/proposals.ts

@@ -313,12 +313,10 @@ export default class ProposalsTransport extends BaseTransport {
     }
 
     if (type === 'Text') {
-      details[0] = this.replaceHistoricalProposalLinks(details[0] as string);
+      (details as { Text: string }).Text = this.replaceHistoricalProposalLinks((details as { Text: string }).Text);
     }
 
-    return this.api.createType('ProposalDetails', {
-      [type]: details.length > 1 ? details : details[0]
-    });
+    return this.api.createType('ProposalDetails', details);
   }
 
   // Historical proposals methods

File diff suppressed because it is too large
+ 0 - 19300
pioneer/packages/joy-utils/src/transport/static/historical-proposals.json


+ 2 - 2
pioneer/packages/joy-utils/src/types/proposals.ts

@@ -141,7 +141,7 @@ export type HistoricalProposalData = {
     createdAt: string,
     status: unknown, // JSON of ProposalStatus
     votingResults: unknown, // JSON of VotingResults
-    details: unknown[], // JSON of ParsedProposalDetails
+    details: Record<string, unknown> | unknown[], // JSON of ParsedProposalDetails
     type: string,
     proposer: ParsedMember,
     createdAtBlock: number,
@@ -150,7 +150,7 @@ export type HistoricalProposalData = {
   votes: {
     councilMembersLength: number,
     votes: {
-      vote: number;
+      vote: string;
       member: ParsedMember & { memberId: number },
     }[]
   },

+ 0 - 26
pioneer/packages/page-accounts/src/Accounts/BannerClaims.tsx

@@ -1,26 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-accounts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import React from 'react';
-import useClaimCounter from '@polkadot/app-claims/useCounter'; // exceptionally CRAP idea
-
-import { useTranslation } from '../translate';
-import Banner from './Banner';
-
-function BannerExtension (): React.ReactElement | null {
-  const claimCount = useClaimCounter();
-  const { t } = useTranslation();
-
-  if (!claimCount) {
-    return null;
-  }
-
-  return (
-    <Banner type='error'>
-      <p>{t<string>('You have {{claimCount}} accounts that need attestations. Use the Claim Tokens app on the left navigation bar to complete the process. Until you do, your balances for those accounts will not be reflected.', { replace: { claimCount } })}&nbsp;<a href='#/claims'>{t<string>('Claim tokens...')}</a></p>
-    </Banner>
-  );
-}
-
-export default React.memo(BannerExtension);

+ 0 - 2
pioneer/packages/page-accounts/src/Accounts/index.tsx

@@ -23,7 +23,6 @@ import Multisig from './modals/MultisigCreate';
 import Proxy from './modals/ProxyAdd';
 import Qr from './modals/Qr';
 import Account from './Account';
-import BannerClaims from './BannerClaims';
 import BannerExtension from './BannerExtension';
 import { sortAccounts } from '../util';
 
@@ -161,7 +160,6 @@ function Overview ({ className = '', onStatusChange }: Props): React.ReactElemen
   return (
     <div className={className}>
       <BannerExtension />
-      <BannerClaims />
       {isCreateOpen && (
         <CreateModal
           onClose={toggleCreate}

+ 27 - 6
pioneer/packages/page-accounts/src/Accounts/useProxies.ts

@@ -7,8 +7,16 @@ import { ProxyType } from '@polkadot/types/interfaces';
 import { useEffect, useState } from 'react';
 import { useAccounts, useApi, useIsMountedRef } from '@polkadot/react-hooks';
 
+import type { Vec } from '@polkadot/types';
+import type { AccountId, BalanceOf, ProxyDefinition } from '@polkadot/types/interfaces';
+import type { ITuple } from '@polkadot/types/types';
+
+import BN from 'bn.js';
+import { BN_ZERO } from '@polkadot/util';
+
 interface Proxy {
   address: string;
+  delay: BN;
   isOwned: boolean;
   type: ProxyType;
 }
@@ -25,6 +33,17 @@ const EMPTY_STATE: State = {
   proxies: []
 };
 
+function createProxy (allAccounts: string[], delegate: AccountId, type: ProxyType, delay = BN_ZERO): Proxy {
+  const address = delegate.toString();
+
+  return {
+    address,
+    delay,
+    isOwned: allAccounts.includes(address),
+    type
+  };
+}
+
 export default function useProxies (address?: string | null): State {
   const { api } = useApi();
   const { allAccounts } = useAccounts();
@@ -36,13 +55,15 @@ export default function useProxies (address?: string | null): State {
 
     address && api.query.proxy &&
       api.query.proxy
-        .proxies(address)
+        .proxies<ITuple<[Vec<ITuple<[AccountId, ProxyType]> | ProxyDefinition>, BalanceOf]>>(address)
         .then(([_proxies]): void => {
-          const proxies = _proxies.map(([accountId, type]): Proxy => ({
-            address: accountId.toString(),
-            isOwned: allAccounts.includes(accountId.toString()),
-            type
-          }));
+          const proxies = api.tx.proxy.addProxy.meta.args.length === 3
+            ? (_proxies as ProxyDefinition[]).map(({ delay, delegate, proxyType }) =>
+              createProxy(allAccounts, delegate, proxyType, delay)
+            )
+            : (_proxies as [AccountId, ProxyType][]).map(([delegate, proxyType]) =>
+              createProxy(allAccounts, delegate, proxyType)
+            );
           const owned = proxies.filter(({ isOwned }) => isOwned);
 
           mountedRef.current && setState({

+ 0 - 0
pioneer/packages/page-claims/.skip-build


+ 0 - 0
pioneer/packages/page-claims/.skip-npm


+ 0 - 201
pioneer/packages/page-claims/LICENSE

@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                    http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-  "License" shall mean the terms and conditions for use, reproduction,
-  and distribution as defined by Sections 1 through 9 of this document.
-
-  "Licensor" shall mean the copyright owner or entity authorized by
-  the copyright owner that is granting the License.
-
-  "Legal Entity" shall mean the union of the acting entity and all
-  other entities that control, are controlled by, or are under common
-  control with that entity. For the purposes of this definition,
-  "control" means (i) the power, direct or indirect, to cause the
-  direction or management of such entity, whether by contract or
-  otherwise, or (ii) ownership of fifty percent (50%) or more of the
-  outstanding shares, or (iii) beneficial ownership of such entity.
-
-  "You" (or "Your") shall mean an individual or Legal Entity
-  exercising permissions granted by this License.
-
-  "Source" form shall mean the preferred form for making modifications,
-  including but not limited to software source code, documentation
-  source, and configuration files.
-
-  "Object" form shall mean any form resulting from mechanical
-  transformation or translation of a Source form, including but
-  not limited to compiled object code, generated documentation,
-  and conversions to other media types.
-
-  "Work" shall mean the work of authorship, whether in Source or
-  Object form, made available under the License, as indicated by a
-  copyright notice that is included in or attached to the work
-  (an example is provided in the Appendix below).
-
-  "Derivative Works" shall mean any work, whether in Source or Object
-  form, that is based on (or derived from) the Work and for which the
-  editorial revisions, annotations, elaborations, or other modifications
-  represent, as a whole, an original work of authorship. For the purposes
-  of this License, Derivative Works shall not include works that remain
-  separable from, or merely link (or bind by name) to the interfaces of,
-  the Work and Derivative Works thereof.
-
-  "Contribution" shall mean any work of authorship, including
-  the original version of the Work and any modifications or additions
-  to that Work or Derivative Works thereof, that is intentionally
-  submitted to Licensor for inclusion in the Work by the copyright owner
-  or by an individual or Legal Entity authorized to submit on behalf of
-  the copyright owner. For the purposes of this definition, "submitted"
-  means any form of electronic, verbal, or written communication sent
-  to the Licensor or its representatives, including but not limited to
-  communication on electronic mailing lists, source code control systems,
-  and issue tracking systems that are managed by, or on behalf of, the
-  Licensor for the purpose of discussing and improving the Work, but
-  excluding communication that is conspicuously marked or otherwise
-  designated in writing by the copyright owner as "Not a Contribution."
-
-  "Contributor" shall mean Licensor and any individual or Legal Entity
-  on behalf of whom a Contribution has been received by Licensor and
-  subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-  this License, each Contributor hereby grants to You a perpetual,
-  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-  copyright license to reproduce, prepare Derivative Works of,
-  publicly display, publicly perform, sublicense, and distribute the
-  Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-  this License, each Contributor hereby grants to You a perpetual,
-  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-  (except as stated in this section) patent license to make, have made,
-  use, offer to sell, sell, import, and otherwise transfer the Work,
-  where such license applies only to those patent claims licensable
-  by such Contributor that are necessarily infringed by their
-  Contribution(s) alone or by combination of their Contribution(s)
-  with the Work to which such Contribution(s) was submitted. If You
-  institute patent litigation against any entity (including a
-  cross-claim or counterclaim in a lawsuit) alleging that the Work
-  or a Contribution incorporated within the Work constitutes direct
-  or contributory patent infringement, then any patent licenses
-  granted to You under this License for that Work shall terminate
-  as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-  Work or Derivative Works thereof in any medium, with or without
-  modifications, and in Source or Object form, provided that You
-  meet the following conditions:
-
-  (a) You must give any other recipients of the Work or
-      Derivative Works a copy of this License; and
-
-  (b) You must cause any modified files to carry prominent notices
-      stating that You changed the files; and
-
-  (c) You must retain, in the Source form of any Derivative Works
-      that You distribute, all copyright, patent, trademark, and
-      attribution notices from the Source form of the Work,
-      excluding those notices that do not pertain to any part of
-      the Derivative Works; and
-
-  (d) If the Work includes a "NOTICE" text file as part of its
-      distribution, then any Derivative Works that You distribute must
-      include a readable copy of the attribution notices contained
-      within such NOTICE file, excluding those notices that do not
-      pertain to any part of the Derivative Works, in at least one
-      of the following places: within a NOTICE text file distributed
-      as part of the Derivative Works; within the Source form or
-      documentation, if provided along with the Derivative Works; or,
-      within a display generated by the Derivative Works, if and
-      wherever such third-party notices normally appear. The contents
-      of the NOTICE file are for informational purposes only and
-      do not modify the License. You may add Your own attribution
-      notices within Derivative Works that You distribute, alongside
-      or as an addendum to the NOTICE text from the Work, provided
-      that such additional attribution notices cannot be construed
-      as modifying the License.
-
-  You may add Your own copyright statement to Your modifications and
-  may provide additional or different license terms and conditions
-  for use, reproduction, or distribution of Your modifications, or
-  for any such Derivative Works as a whole, provided Your use,
-  reproduction, and distribution of the Work otherwise complies with
-  the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-  any Contribution intentionally submitted for inclusion in the Work
-  by You to the Licensor shall be under the terms and conditions of
-  this License, without any additional terms or conditions.
-  Notwithstanding the above, nothing herein shall supersede or modify
-  the terms of any separate license agreement you may have executed
-  with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-  names, trademarks, service marks, or product names of the Licensor,
-  except as required for reasonable and customary use in describing the
-  origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-  agreed to in writing, Licensor provides the Work (and each
-  Contributor provides its Contributions) on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-  implied, including, without limitation, any warranties or conditions
-  of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-  PARTICULAR PURPOSE. You are solely responsible for determining the
-  appropriateness of using or redistributing the Work and assume any
-  risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-  whether in tort (including negligence), contract, or otherwise,
-  unless required by applicable law (such as deliberate and grossly
-  negligent acts) or agreed to in writing, shall any Contributor be
-  liable to You for damages, including any direct, indirect, special,
-  incidental, or consequential damages of any character arising as a
-  result of this License or out of the use or inability to use the
-  Work (including but not limited to damages for loss of goodwill,
-  work stoppage, computer failure or malfunction, or any and all
-  other commercial damages or losses), even if such Contributor
-  has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-  the Work or Derivative Works thereof, You may choose to offer,
-  and charge a fee for, acceptance of support, warranty, indemnity,
-  or other liability obligations and/or rights consistent with this
-  License. However, in accepting such obligations, You may act only
-  on Your own behalf and on Your sole responsibility, not on behalf
-  of any other Contributor, and only if You agree to indemnify,
-  defend, and hold each Contributor harmless for any liability
-  incurred by, or claims asserted against, such Contributor by reason
-  of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-  To apply the Apache License to your work, attach the following
-  boilerplate notice, with the fields enclosed by brackets "[]"
-  replaced with your own identifying information. (Don't include
-  the brackets!)  The text should be enclosed in the appropriate
-  comment syntax for the file format. We also recommend that a
-  file or class name and description of purpose be included on the
-  same "printed page" as the copyright notice for easier
-  identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.

+ 0 - 1
pioneer/packages/page-claims/README.md

@@ -1 +0,0 @@
-# @polkadot/app-claims

+ 0 - 19
pioneer/packages/page-claims/package.json

@@ -1,19 +0,0 @@
-{
-  "name": "@polkadot/app-claims",
-  "private": true,
-  "version": "0.51.1",
-  "description": "An app for claiming Polkadot tokens",
-  "main": "index.js",
-  "scripts": {},
-  "author": "Keith Ingram <keith@parity.io>",
-  "maintainers": [
-    "Keith Ingram <keith@parity.io>",
-    "Jaco Greeff <jacogr@gmail.com>"
-  ],
-  "license": "Apache-2.0",
-  "dependencies": {
-    "@babel/runtime": "^7.10.5",
-    "@polkadot/react-components": "0.51.1",
-    "secp256k1": "^3.8.0"
-  }
-}

+ 0 - 104
pioneer/packages/page-claims/src/Attest.tsx

@@ -1,104 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import React, { useEffect, useState } from 'react';
-import styled from 'styled-components';
-import { Button, Card, TxButton } from '@polkadot/react-components';
-import { TxCallback } from '@polkadot/react-components/Status/types';
-import { useAccounts, useApi } from '@polkadot/react-hooks';
-import { FormatBalance } from '@polkadot/react-query';
-import { Option } from '@polkadot/types';
-import { BalanceOf, EthereumAddress, StatementKind } from '@polkadot/types/interfaces';
-
-import { ClaimStyles } from './Claim';
-import Statement from './Statement';
-import { useTranslation } from './translate';
-import { getStatement } from './util';
-
-interface Props {
-  accountId: string;
-  className?: string;
-  ethereumAddress: EthereumAddress | null;
-  onSuccess?: TxCallback;
-  statementKind?: StatementKind;
-  systemChain: string;
-}
-
-function Attest ({ accountId, className, ethereumAddress, onSuccess, statementKind, systemChain }: Props): React.ReactElement<Props> | null {
-  const accounts = useAccounts();
-  const { t } = useTranslation();
-  const { api } = useApi();
-  const [claimValue, setClaimValue] = useState<BalanceOf | null>(null);
-  const [isBusy, setIsBusy] = useState(false);
-
-  useEffect((): void => {
-    if (!ethereumAddress) {
-      return;
-    }
-
-    setIsBusy(true);
-
-    api.query.claims
-      .claims<Option<BalanceOf>>(ethereumAddress)
-      .then((claim): void => {
-        setClaimValue(claim.unwrapOr(null));
-        setIsBusy(false);
-      })
-      .catch((): void => setIsBusy(false));
-  }, [api, ethereumAddress]);
-
-  if (isBusy) {
-    return null;
-  }
-
-  const hasClaim = claimValue && claimValue.gten(0);
-  const statementSentence = getStatement(systemChain, statementKind)?.sentence;
-
-  if (!hasClaim || !statementSentence) {
-    return null;
-  }
-
-  // Attesting is impossible if the account is not owned.
-  if (!accounts.isAccount(accountId)) {
-    return (
-      <Card isError>
-        <div className={className}>
-          {t<string>('We found a pre-claim with this Polkadot address. However, attesting requires signing with this account. To continue with attesting, please add this account as an owned account first.')}
-          <h3>
-            <FormatBalance
-              label={t<string>('Account balance:')}
-              value={claimValue}
-            />
-          </h3>
-        </div>
-      </Card>
-    );
-  }
-
-  return (
-    <Card isSuccess>
-      <div className={className}>
-        <Statement
-          kind={statementKind}
-          systemChain={systemChain}
-        />
-        <h3><FormatBalance label={t<string>('Account balance:')}
-          value={claimValue} /></h3>
-        <Button.Group>
-          <TxButton
-            accountId={accountId}
-            icon='paper-plane'
-            isDisabled={!statementSentence}
-            label={t<string>('I agree')}
-            onSuccess={onSuccess}
-            params={[statementSentence]}
-            tx='claims.attest'
-          />
-        </Button.Group>
-      </div>
-    </Card>
-  );
-}
-
-export default React.memo(styled(Attest)`${ClaimStyles}`);

+ 0 - 135
pioneer/packages/page-claims/src/Claim.tsx

@@ -1,135 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Option } from '@polkadot/types';
-import { BalanceOf, EthereumAddress, StatementKind } from '@polkadot/types/interfaces';
-
-import React, { useEffect, useState } from 'react';
-import styled from 'styled-components';
-import { Button, Card, TxButton } from '@polkadot/react-components';
-import { TxCallback } from '@polkadot/react-components/Status/types';
-import { useApi } from '@polkadot/react-hooks';
-import { FormatBalance } from '@polkadot/react-query';
-
-import { useTranslation } from './translate';
-import { addrToChecksum, getStatement } from './util';
-
-interface Props {
-  accountId: string;
-  className?: string;
-  ethereumAddress: EthereumAddress | null;
-  ethereumSignature: string | null;
-  // Do we sign with `claims.claimAttest` (new) instead of `claims.claim` (old)?
-  isOldClaimProcess: boolean;
-  onSuccess?: TxCallback;
-  statementKind?: StatementKind;
-  systemChain: string;
-}
-
-interface ConstructTx {
-  params?: any[];
-  tx?: string;
-}
-
-// Depending on isOldClaimProcess, construct the correct tx.
-function constructTx (systemChain: string, accountId: string, ethereumSignature: string | null, kind: StatementKind | undefined, isOldClaimProcess: boolean): ConstructTx {
-  if (!ethereumSignature) {
-    return {};
-  }
-
-  return isOldClaimProcess || !kind
-    ? { params: [accountId, ethereumSignature], tx: 'claims.claim' }
-    : { params: [accountId, ethereumSignature, getStatement(systemChain, kind)?.sentence], tx: 'claims.claimAttest' };
-}
-
-function Claim ({ accountId, className = '', ethereumAddress, ethereumSignature, isOldClaimProcess, onSuccess, statementKind, systemChain }: Props): React.ReactElement<Props> | null {
-  const { t } = useTranslation();
-  const { api } = useApi();
-  const [claimValue, setClaimValue] = useState<BalanceOf | null>(null);
-  const [isBusy, setIsBusy] = useState(false);
-
-  useEffect((): void => {
-    if (!ethereumAddress) {
-      return;
-    }
-
-    setIsBusy(true);
-
-    api.query.claims
-      .claims<Option<BalanceOf>>(ethereumAddress)
-      .then((claim): void => {
-        setClaimValue(claim.unwrapOr(null));
-        setIsBusy(false);
-      })
-      .catch((): void => setIsBusy(false));
-  }, [api, ethereumAddress]);
-
-  if (!ethereumAddress || isBusy) {
-    return null;
-  }
-
-  const hasClaim = claimValue && claimValue.gten(0);
-
-  return (
-    <Card
-      isError={!hasClaim}
-      isSuccess={!!hasClaim}
-    >
-      <div className={className}>
-        {t<string>('Your Ethereum account')}
-        <h3>{addrToChecksum(ethereumAddress.toString())}</h3>
-        {hasClaim && claimValue
-          ? (
-            <>
-              {t<string>('has a valid claim for')}
-              <h2><FormatBalance value={claimValue} /></h2>
-              <Button.Group>
-                <TxButton
-                  icon='paper-plane'
-                  isUnsigned
-                  label={t('Claim')}
-                  onSuccess={onSuccess}
-                  {...constructTx(systemChain, accountId, ethereumSignature, statementKind, isOldClaimProcess)}
-                />
-              </Button.Group>
-            </>
-          )
-          : (
-            <>
-              {t<string>('does not appear to have a valid claim. Please double check that you have signed the transaction correctly on the correct ETH account.')}
-            </>
-          )}
-      </div>
-    </Card>
-  );
-}
-
-export const ClaimStyles = `
-font-size: 1.15rem;
-display: flex;
-flex-direction: column;
-justify-content: center;
-min-height: 12rem;
-align-items: center;
-margin: 0 1rem;
-
-h3 {
-  font-family: monospace;
-  font-size: 1.5rem;
-  max-width: 100%;
-  margin: 0.5rem;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-h2 {
-  margin: 0.5rem 0 2rem;
-  font-family: monospace;
-  font-size: 2.5rem;
-  font-weight: 200;
-}
-`;
-
-export default React.memo(styled(Claim)`${ClaimStyles}`);

+ 0 - 84
pioneer/packages/page-claims/src/Statement.tsx

@@ -1,84 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { StatementKind } from '@polkadot/types/interfaces';
-
-import React from 'react';
-import styled from 'styled-components';
-
-import { useTranslation } from './translate';
-import { getStatement } from './util';
-
-export interface Props {
-  className?: string;
-  kind?: StatementKind;
-  systemChain: string;
-}
-
-// Get the full hardcoded text for a statement
-function StatementFullText ({ statementUrl, systemChain }: { statementUrl?: string; systemChain: string }): React.ReactElement | null {
-  const { t } = useTranslation();
-
-  switch (systemChain) {
-    case 'Polkadot':
-    case 'Polkadot CC1':
-      return statementUrl
-        ? <iframe src={statementUrl} />
-        : null;
-
-    default:
-      return <p>{t('Warning: we did not find any attest statement for {{chain}}', { replace: { chain: systemChain } })}</p>;
-  }
-}
-
-function Statement ({ className, kind, systemChain }: Props): React.ReactElement<Props> | null {
-  const { t } = useTranslation();
-  const statementUrl = getStatement(systemChain, kind)?.url;
-
-  if (!statementUrl) {
-    return null;
-  }
-
-  return (
-    <div className={className}>
-      {t('Please read these terms and conditions carefully. By submitting this statement, you are deemed to have accepted these Terms and Conditions. If you do not agree to these terms, please refrain from accessing or proceeding. You can also find them at:')}
-      <a className='statementUrl'
-        href={statementUrl}
-        rel='noopener noreferrer'
-        target='_blank'>{statementUrl}</a>
-      <div className='statement'>
-        <StatementFullText
-          statementUrl={statementUrl}
-          systemChain={systemChain}
-        />
-      </div>
-    </div>
-  );
-}
-
-export default React.memo(styled(Statement)`
-  .statement{
-    border: 1px solid #c2c2c2;
-    background: #f2f2f2;
-    height: 15rem;
-    padding: 1rem;
-    width: 100%;
-    margin: 1rem 0;
-    white-space: normal;
-
-    p {
-      color: #4e4e4e !important;
-    }
-
-    iframe {
-      border: 0;
-      height: 100%;
-      width: 100%;
-    }
-  }
-
-  .statementUrl{
-    margin-left: 0.3rem
-  }
-`);

+ 0 - 57
pioneer/packages/page-claims/src/Warning.tsx

@@ -1,57 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { AddressMini, Card } from '@polkadot/react-components';
-
-import React from 'react';
-import styled from 'styled-components';
-
-import { useTranslation } from './translate';
-import usePolkadotPreclaims from './usePolkadotPreclaims';
-
-export interface Props{
-  className?: string;
-}
-
-function Warning ({ className }: Props): React.ReactElement<Props> | null {
-  const { t } = useTranslation();
-  const needsAttest = usePolkadotPreclaims();
-
-  if (!needsAttest.length) {
-    return null;
-  }
-
-  return (
-    <Card isError>
-      <div className={className}>
-        {
-          needsAttest.length > 1
-            ? t('You need to sign an attestation for the following accounts:')
-            : t('You need to sign an attestation for the following account:')
-        }{
-          needsAttest.map((address) => (
-            <AddressMini
-              key={address}
-              value={address}
-            />
-          ))
-        }
-      </div>
-    </Card>
-  );
-}
-
-export default React.memo(styled(Warning)`
-  font-size: 1.15rem;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  min-height: 8rem;
-  align-items: center;
-  margin: 0 1rem;
-
-  .ui--AddressMini-address {
-    max-width: 20rem;
-  }
-`);

+ 0 - 311
pioneer/packages/page-claims/src/index.tsx

@@ -1,311 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Option } from '@polkadot/types';
-import { EcdsaSignature, EthereumAddress, StatementKind } from '@polkadot/types/interfaces';
-
-import React, { useState, useCallback, useEffect } from 'react';
-import { Trans } from 'react-i18next';
-import styled from 'styled-components';
-import CopyToClipboard from 'react-copy-to-clipboard';
-import { Button, Card, Columar, Column, Input, InputAddress, Tooltip } from '@polkadot/react-components';
-import { useApi, useCall } from '@polkadot/react-hooks';
-import { TokenUnit } from '@polkadot/react-components/InputNumber';
-import { u8aToHex, u8aToString } from '@polkadot/util';
-import { decodeAddress } from '@polkadot/util-crypto';
-
-import { useTranslation } from './translate';
-import { recoverFromJSON, getStatement } from './util';
-import AttestDisplay from './Attest';
-import ClaimDisplay from './Claim';
-import Statement from './Statement';
-import Warning from './Warning';
-
-export { default as useCounter } from './useCounter';
-
-enum Step {
-  Account = 0,
-  ETHAddress = 1,
-  Sign = 2,
-  Claim = 3,
-}
-
-const PRECLAIMS_LOADING = 'PRECLAIMS_LOADING';
-
-// FIXME no embedded components (hossible to tweak)
-const Payload = styled.pre`
-  cursor: copy;
-  font-family: monospace;
-  border: 1px dashed #c2c2c2;
-  background: #f2f2f2;
-  padding: 1rem;
-  width: 100%;
-  margin: 1rem 0;
-  white-space: normal;
-  word-break: break-all;
-`;
-
-const Signature = styled.textarea`
-  font-family: monospace;
-  padding: 1rem;
-  border: 1px solid rgba(34, 36, 38, 0.15);
-  border-radius: 0.25rem;
-  margin: 1rem 0;
-  resize: none;
-  width: 100%;
-
-  &::placeholder {
-    color: rgba(0, 0, 0, 0.5);
-  }
-
-  &::-ms-input-placeholder {
-    color: rgba(0, 0, 0, 0.5);
-  }
-
-  &:-ms-input-placeholder {
-    color: rgba(0, 0, 0, 0.5);
-  }
-`;
-
-function ClaimsApp (): React.ReactElement {
-  const [didCopy, setDidCopy] = useState(false);
-  const [ethereumAddress, setEthereumAddress] = useState<string | undefined | null>(null);
-  const [signature, setSignature] = useState<EcdsaSignature | null>(null);
-  const [step, setStep] = useState<Step>(Step.Account);
-  const [accountId, setAccountId] = useState<string | null>(null);
-  const { api, systemChain } = useApi();
-  const { t } = useTranslation();
-
-  // This preclaimEthereumAddress holds the result of `api.query.claims.preclaims`:
-  // - an `EthereumAddress` when there's a preclaim
-  // - null if no preclaim
-  // - `PRECLAIMS_LOADING` if we're fetching the results
-  const [preclaimEthereumAddress, setPreclaimEthereumAddress] = useState<string | null | undefined | typeof PRECLAIMS_LOADING>(PRECLAIMS_LOADING);
-  const isPreclaimed = !!preclaimEthereumAddress && preclaimEthereumAddress !== PRECLAIMS_LOADING;
-
-  // Everytime we change account, reset everything, and check if the accountId
-  // has a preclaim.
-  useEffect(() => {
-    if (!accountId) {
-      return;
-    }
-
-    setStep(Step.Account);
-    setEthereumAddress(null);
-    setPreclaimEthereumAddress(PRECLAIMS_LOADING);
-
-    if (!api.query.claims || !api.query.claims.preclaims) {
-      return setPreclaimEthereumAddress(null);
-    }
-
-    api.query.claims
-      .preclaims<Option<EthereumAddress>>(accountId)
-      .then((preclaim): void => {
-        const address = preclaim.unwrapOr(null)?.toString();
-
-        setEthereumAddress(address);
-        setPreclaimEthereumAddress(address);
-      })
-      .catch((): void => setPreclaimEthereumAddress(null));
-  }, [accountId, api.query.claims, api.query.claims.preclaims]);
-
-  // Old claim process used `api.tx.claims.claim`, and didn't have attest
-  const isOldClaimProcess = !api.tx.claims.claimAttest;
-
-  useEffect(() => {
-    if (didCopy) {
-      setTimeout((): void => {
-        setDidCopy(false);
-      }, 1000);
-    }
-  }, [didCopy]);
-
-  const goToStepAccount = useCallback(() => {
-    setStep(Step.Account);
-  }, []);
-
-  const goToStepSign = useCallback(() => {
-    setStep(Step.Sign);
-  }, []);
-
-  const goToStepClaim = useCallback(() => {
-    setStep(Step.Claim);
-  }, []);
-
-  // Depending on the account, decide which step to show.
-  const handleAccountStep = useCallback(() => {
-    if (isPreclaimed) {
-      goToStepClaim();
-    } else if (ethereumAddress || isOldClaimProcess) {
-      goToStepSign();
-    } else {
-      setStep(Step.ETHAddress);
-    }
-  }, [ethereumAddress, goToStepClaim, goToStepSign, isPreclaimed, isOldClaimProcess]);
-
-  const onChangeSignature = useCallback((event: React.SyntheticEvent<Element>) => {
-    const { value: signatureJson } = event.target as HTMLInputElement;
-
-    const { ethereumAddress, signature } = recoverFromJSON(signatureJson);
-
-    setEthereumAddress(ethereumAddress?.toString());
-    setSignature(signature);
-  }, []);
-
-  const onChangeEthereumAddress = useCallback((value: string) => {
-    // FIXME We surely need a better check than just a trim
-
-    setEthereumAddress(value.trim());
-  }, []);
-
-  const onCopy = useCallback(() => {
-    setDidCopy(true);
-  }, []);
-
-  // If it's 1/ not preclaimed and 2/ not the old claiming process, fetch the
-  // statement kind to sign.
-  const statementKind = useCall<StatementKind | null>(!isPreclaimed && !isOldClaimProcess && !!ethereumAddress && api.query.claims.signing, [ethereumAddress], {
-    transform: (option: Option<StatementKind>) => option.unwrapOr(null)
-  });
-
-  const statementSentence = getStatement(systemChain, statementKind)?.sentence || '';
-
-  const prefix = u8aToString(api.consts.claims.prefix.toU8a(true));
-  const payload = accountId
-    ? `${prefix}${u8aToHex(decodeAddress(accountId), -1, false)}${statementSentence}`
-    : '';
-
-  return (
-    <main>
-      <header />
-      {!isOldClaimProcess && <Warning />}
-      <h1>
-        <Trans>Claim your <em>{TokenUnit.abbr}</em> tokens</Trans>
-      </h1>
-      <Columar>
-        <Column>
-          <Card withBottomMargin>
-            <h3>{t<string>('1. Select your {{chain}} account', {
-              replace: {
-                chain: systemChain
-              }
-            })}</h3>
-            <InputAddress
-              defaultValue={accountId}
-              help={t<string>('The account you want to claim to.')}
-              label={t<string>('claim to account')}
-              onChange={setAccountId}
-              type='all'
-            />
-            {(step === Step.Account) && (
-              <Button.Group>
-                <Button
-                  icon='sign-in-alt'
-                  isDisabled={preclaimEthereumAddress === PRECLAIMS_LOADING}
-                  label={preclaimEthereumAddress === PRECLAIMS_LOADING
-                    ? t<string>('Loading')
-                    : t<string>('Continue')
-                  }
-                  onClick={handleAccountStep}
-                />
-              </Button.Group>
-            )}
-          </Card>
-          {
-            // We need to know the ethereuem address only for the new process
-            // to be able to know the statement kind so that the users can sign it
-            (step >= Step.ETHAddress && !isPreclaimed && !isOldClaimProcess) && (
-              <Card withBottomMargin>
-                <h3>{t<string>('2. Enter the ETH address from the sale.')}</h3>
-                <Input
-                  autoFocus
-                  className='full'
-                  help={t<string>('The the Ethereum address you used during the pre-sale (starting by "0x")')}
-                  label={t<string>('Pre-sale ethereum address')}
-                  onChange={onChangeEthereumAddress}
-                  value={ethereumAddress || ''}
-                />
-                {(step === Step.ETHAddress) && (
-                  <Button.Group>
-                    <Button
-                      icon='sign-in-alt'
-                      isDisabled={!ethereumAddress}
-                      label={t<string>('Continue')}
-                      onClick={goToStepSign}
-                    />
-                  </Button.Group>
-                )}
-              </Card>
-            )}
-          {(step >= Step.Sign && !isPreclaimed) && (
-            <Card>
-              <h3>{t<string>('{{step}}. Sign with your ETH address', { replace: { step: isOldClaimProcess ? '2' : '3' } })}</h3>
-              {!isOldClaimProcess && (
-                <Statement
-                  kind={statementKind}
-                  systemChain={systemChain}
-                />
-              )}
-              <div>{t<string>('Copy the following string and sign it with the Ethereum account you used during the pre-sale in the wallet of your choice, using the string as the payload, and then paste the transaction signature object below:')}</div>
-              <CopyToClipboard
-                onCopy={onCopy}
-                text={payload}
-              >
-                <Payload
-                  data-for='tx-payload'
-                  data-tip
-                >
-                  {payload}
-                </Payload>
-              </CopyToClipboard>
-              <Tooltip
-                place='right'
-                text={didCopy ? t<string>('copied') : t<string>('click to copy')}
-                trigger='tx-payload'
-              />
-              <Signature
-                onChange={onChangeSignature}
-                placeholder={`{\n  "address": "0x ...",\n  "msg": "${prefix}:...",\n  "sig": "0x ...",\n  "version": "2"\n}`}
-                rows={10}
-              />
-              {(step === Step.Sign) && (
-                <Button.Group>
-                  <Button
-                    icon='sign-in-alt'
-                    isDisabled={!accountId || !signature}
-                    label={t<string>('Confirm claim')}
-                    onClick={goToStepClaim}
-                  />
-                </Button.Group>
-              )}
-            </Card>
-          )}
-        </Column>
-        <Column showEmptyText={false}>
-          {(step >= Step.Claim) && (
-            isPreclaimed
-              ? <AttestDisplay
-                accountId={accountId}
-                ethereumAddress={ethereumAddress}
-                onSuccess={goToStepAccount}
-                statementKind={statementKind}
-                systemChain={systemChain}
-              />
-              : <ClaimDisplay
-                accountId={accountId}
-                ethereumAddress={ethereumAddress}
-                ethereumSignature={signature}
-                isOldClaimProcess={isOldClaimProcess}
-                onSuccess={goToStepAccount}
-                statementKind={statementKind}
-                systemChain={systemChain}
-              />
-          )}
-        </Column>
-      </Columar>
-    </main>
-  );
-}
-
-export default React.memo(ClaimsApp);

+ 0 - 8
pioneer/packages/page-claims/src/secp256k1.d.ts

@@ -1,8 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-declare module 'secp256k1/elliptic' {
-  export function publicKeyConvert (publicKey: Buffer, expanded: boolean): Buffer;
-  export function recover (msgHash: Buffer, signature: Buffer, recovery: number): Buffer;
-}

+ 0 - 11
pioneer/packages/page-claims/src/translate.ts

@@ -1,11 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { useTranslation as useTranslationBase, UseTranslationResponse, withTranslation } from 'react-i18next';
-
-export function useTranslation (): UseTranslationResponse {
-  return useTranslationBase('app-claims');
-}
-
-export default withTranslation(['app-claims']);

+ 0 - 11
pioneer/packages/page-claims/src/useCounter.ts

@@ -1,11 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-settings authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import usePolkadotPreclaims from './usePolkadotPreclaims';
-
-export default function useCounter (): number {
-  const needAttest = usePolkadotPreclaims();
-
-  return needAttest.length;
-}

+ 0 - 50
pioneer/packages/page-claims/src/usePolkadotPreclaims.ts

@@ -1,50 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-settings authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { QueryableStorageEntry } from '@polkadot/api/types';
-import { Codec } from '@polkadot/types/types';
-import { EthereumAddress } from '@polkadot/types/interfaces';
-
-import { useEffect, useState } from 'react';
-import { useAccounts, useApi, useCall, useIsMountedRef } from '@polkadot/react-hooks';
-import { Option } from '@polkadot/types';
-
-export default function usePolkadotPreclaims (): string[] {
-  const { allAccounts } = useAccounts();
-  const { api } = useApi();
-  const mountedRef = useIsMountedRef();
-  const [needsAttest, setNeedsAttest] = useState<string[]>([]);
-
-  // find all own preclaims
-  const preclaims = useCall<[string, EthereumAddress][]>(api.query.claims?.preclaims?.multi, [allAccounts], {
-    transform: (preclaims: Option<EthereumAddress>[]) =>
-      preclaims
-        .map((opt, index): [string, Option<EthereumAddress>] => [allAccounts[index], opt])
-        .filter(([, opt]) => opt.isSome)
-        .map(([address, opt]) => [address, opt.unwrap()])
-  });
-
-  // Filter the accounts that need attest. They are accounts that
-  // - already preclaimed
-  // - has a balance, either vested or normal
-  useEffect((): void => {
-    preclaims && api.queryMulti(
-      preclaims.reduce((result: [QueryableStorageEntry<'promise'>, EthereumAddress][], [, ethAddr]) =>
-        result.concat([
-          [api.query.claims.claims, ethAddr],
-          [api.query.claims.vesting, ethAddr]
-        ]),
-      []), (opts: Option<Codec>[]): void => {
-        // filter the cases where either claims or vesting has a value
-        mountedRef.current && setNeedsAttest(
-          preclaims
-            .filter((_, index) => opts[index * 2].isSome || opts[(index * 2) + 1].isSome)
-            .map(([address]) => address)
-        );
-      }
-    );
-  }, [api, allAccounts, mountedRef, preclaims]);
-
-  return needsAttest;
-}

+ 0 - 25
pioneer/packages/page-claims/src/util.spec.ts

@@ -1,25 +0,0 @@
-// Copyright 2017-2020 @polkadot/react-components authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { hexToU8a } from '@polkadot/util';
-
-import { publicToAddr, recoverFromJSON } from './util';
-
-describe('util', (): void => {
-  it('converts a publicKey to address via publicToAddr', (): void => {
-    expect(
-      publicToAddr(
-        hexToU8a(
-          '0x836b35a026743e823a90a0ee3b91bf615c6a757e2b60b9e1dc1826fd0dd16106f7bc1e8179f665015f43c6c81f39062fc2086ed849625c06e04697698b21855e'
-        )
-      )
-    ).toEqual('0x0BED7ABd61247635c1973eB38474A2516eD1D884');
-  });
-
-  it('converts to valid signature via recoverFromJSON', (): void => {
-    expect(
-      JSON.stringify(recoverFromJSON('{"address":"0x002309df96687e44280bb72c3818358faeeb699c","msg":"Pay KSMs to the Kusama account:88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee","sig":"0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01","version":"2"}'))
-    ).toEqual('{"error":null,"ethereumAddress":"0x002309df96687e44280bb72c3818358faeeb699c","signature":"0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01"}');
-  });
-});

+ 0 - 144
pioneer/packages/page-claims/src/util.ts

@@ -1,144 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-claims authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { EthereumAddress, EcdsaSignature, StatementKind } from '@polkadot/types/interfaces';
-
-import secp256k1 from 'secp256k1/elliptic';
-import { registry } from '@polkadot/react-api';
-import { assert, hexToU8a, stringToU8a, u8aToBuffer, u8aConcat } from '@polkadot/util';
-import { keccakAsHex, keccakAsU8a } from '@polkadot/util-crypto';
-
-interface RecoveredSignature {
-  error: Error | null;
-  ethereumAddress: EthereumAddress | null;
-  signature: EcdsaSignature | null;
-}
-
-interface SignatureParts {
-  recovery: number;
-  signature: Buffer;
-}
-
-// converts an Ethereum address to a checksum representation
-export function addrToChecksum (_address: string): string {
-  const address = _address.toLowerCase();
-  const hash = keccakAsHex(address.substr(2)).substr(2);
-  let result = '0x';
-
-  for (let n = 0; n < 40; n++) {
-    result = `${result}${
-      parseInt(hash[n], 16) > 7
-        ? address[n + 2].toUpperCase()
-        : address[n + 2]
-    }`;
-  }
-
-  return result;
-}
-
-// convert a give public key to an Ethereum address (the last 20 bytes of an _exapnded_ key keccack)
-export function publicToAddr (publicKey: Uint8Array): string {
-  return addrToChecksum(`0x${keccakAsHex(publicKey).slice(-40)}`);
-}
-
-// hash a message for use in signature recovery, adding the standard Ethereum header
-export function hashMessage (message: string): Buffer {
-  const expanded = stringToU8a(`\x19Ethereum Signed Message:\n${message.length.toString()}${message}`);
-  const hashed = keccakAsU8a(expanded);
-
-  return u8aToBuffer(hashed);
-}
-
-// split is 65-byte signature into the r, s (combined) and recovery number (derived from v)
-export function sigToParts (_signature: string): SignatureParts {
-  const signature = hexToU8a(_signature);
-
-  assert(signature.length === 65, `Invalid signature length, expected 65 found ${signature.length}`);
-
-  let v = signature[64];
-
-  if (v < 27) {
-    v += 27;
-  }
-
-  const recovery = v - 27;
-
-  assert(recovery === 0 || recovery === 1, 'Invalid signature v value');
-
-  return {
-    recovery,
-    signature: u8aToBuffer(signature.slice(0, 64))
-  };
-}
-
-// recover an address from a given message and a recover/signature combination
-export function recoverAddress (message: string, { recovery, signature }: SignatureParts): string {
-  const msgHash = hashMessage(message);
-  const senderPubKey = secp256k1.recover(msgHash, signature, recovery);
-
-  return publicToAddr(
-    secp256k1.publicKeyConvert(senderPubKey, false).slice(1)
-  );
-}
-
-// recover an address from a signature JSON (as supplied by e.g. MyCrypto)
-export function recoverFromJSON (signatureJson: string | null): RecoveredSignature {
-  try {
-    const { msg, sig } = JSON.parse(signatureJson || '{}') as Record<string, string>;
-
-    if (!msg || !sig) {
-      throw new Error('Invalid signature object');
-    }
-
-    const parts = sigToParts(sig);
-
-    return {
-      error: null,
-      ethereumAddress: registry.createType('EthereumAddress', recoverAddress(msg, parts)),
-      signature: registry.createType('EcdsaSignature', u8aConcat(parts.signature, new Uint8Array([parts.recovery])))
-    };
-  } catch (error) {
-    console.error(error);
-
-    return {
-      error: error as Error,
-      ethereumAddress: null,
-      signature: null
-    };
-  }
-}
-
-export interface Statement {
-  sentence: string;
-  url: string;
-}
-
-function getPolkadot (kind?: StatementKind | null): Statement | undefined {
-  if (!kind) {
-    return undefined;
-  }
-
-  const url = kind.isRegular
-    ? 'https://statement.polkadot.network/regular.html'
-    : 'https://statement.polkadot.network/saft.html';
-  const hash = kind.isRegular
-    ? 'Qmc1XYqT6S39WNp2UeiRUrZichUWUPpGEThDE6dAb3f6Ny'
-    : 'QmXEkMahfhHJPzT3RjkXiZVFi77ZeVeuxtAjhojGRNYckz';
-
-  return {
-    sentence: `I hereby agree to the terms of the statement whose SHA-256 multihash is ${hash}. (This may be found at the URL: ${url})`,
-    url
-  };
-}
-
-export function getStatement (network: string, kind?: StatementKind | null): Statement | undefined {
-  switch (network) {
-    case 'Polkadot':
-    case 'Polkadot CC1':
-      return getPolkadot(kind);
-
-    default:
-      return undefined;
-  }
-}

+ 0 - 0
pioneer/packages/page-contracts/.skip-build


+ 0 - 0
pioneer/packages/page-contracts/.skip-npm


+ 0 - 201
pioneer/packages/page-contracts/LICENSE

@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                    http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-  "License" shall mean the terms and conditions for use, reproduction,
-  and distribution as defined by Sections 1 through 9 of this document.
-
-  "Licensor" shall mean the copyright owner or entity authorized by
-  the copyright owner that is granting the License.
-
-  "Legal Entity" shall mean the union of the acting entity and all
-  other entities that control, are controlled by, or are under common
-  control with that entity. For the purposes of this definition,
-  "control" means (i) the power, direct or indirect, to cause the
-  direction or management of such entity, whether by contract or
-  otherwise, or (ii) ownership of fifty percent (50%) or more of the
-  outstanding shares, or (iii) beneficial ownership of such entity.
-
-  "You" (or "Your") shall mean an individual or Legal Entity
-  exercising permissions granted by this License.
-
-  "Source" form shall mean the preferred form for making modifications,
-  including but not limited to software source code, documentation
-  source, and configuration files.
-
-  "Object" form shall mean any form resulting from mechanical
-  transformation or translation of a Source form, including but
-  not limited to compiled object code, generated documentation,
-  and conversions to other media types.
-
-  "Work" shall mean the work of authorship, whether in Source or
-  Object form, made available under the License, as indicated by a
-  copyright notice that is included in or attached to the work
-  (an example is provided in the Appendix below).
-
-  "Derivative Works" shall mean any work, whether in Source or Object
-  form, that is based on (or derived from) the Work and for which the
-  editorial revisions, annotations, elaborations, or other modifications
-  represent, as a whole, an original work of authorship. For the purposes
-  of this License, Derivative Works shall not include works that remain
-  separable from, or merely link (or bind by name) to the interfaces of,
-  the Work and Derivative Works thereof.
-
-  "Contribution" shall mean any work of authorship, including
-  the original version of the Work and any modifications or additions
-  to that Work or Derivative Works thereof, that is intentionally
-  submitted to Licensor for inclusion in the Work by the copyright owner
-  or by an individual or Legal Entity authorized to submit on behalf of
-  the copyright owner. For the purposes of this definition, "submitted"
-  means any form of electronic, verbal, or written communication sent
-  to the Licensor or its representatives, including but not limited to
-  communication on electronic mailing lists, source code control systems,
-  and issue tracking systems that are managed by, or on behalf of, the
-  Licensor for the purpose of discussing and improving the Work, but
-  excluding communication that is conspicuously marked or otherwise
-  designated in writing by the copyright owner as "Not a Contribution."
-
-  "Contributor" shall mean Licensor and any individual or Legal Entity
-  on behalf of whom a Contribution has been received by Licensor and
-  subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-  this License, each Contributor hereby grants to You a perpetual,
-  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-  copyright license to reproduce, prepare Derivative Works of,
-  publicly display, publicly perform, sublicense, and distribute the
-  Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-  this License, each Contributor hereby grants to You a perpetual,
-  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-  (except as stated in this section) patent license to make, have made,
-  use, offer to sell, sell, import, and otherwise transfer the Work,
-  where such license applies only to those patent claims licensable
-  by such Contributor that are necessarily infringed by their
-  Contribution(s) alone or by combination of their Contribution(s)
-  with the Work to which such Contribution(s) was submitted. If You
-  institute patent litigation against any entity (including a
-  cross-claim or counterclaim in a lawsuit) alleging that the Work
-  or a Contribution incorporated within the Work constitutes direct
-  or contributory patent infringement, then any patent licenses
-  granted to You under this License for that Work shall terminate
-  as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-  Work or Derivative Works thereof in any medium, with or without
-  modifications, and in Source or Object form, provided that You
-  meet the following conditions:
-
-  (a) You must give any other recipients of the Work or
-      Derivative Works a copy of this License; and
-
-  (b) You must cause any modified files to carry prominent notices
-      stating that You changed the files; and
-
-  (c) You must retain, in the Source form of any Derivative Works
-      that You distribute, all copyright, patent, trademark, and
-      attribution notices from the Source form of the Work,
-      excluding those notices that do not pertain to any part of
-      the Derivative Works; and
-
-  (d) If the Work includes a "NOTICE" text file as part of its
-      distribution, then any Derivative Works that You distribute must
-      include a readable copy of the attribution notices contained
-      within such NOTICE file, excluding those notices that do not
-      pertain to any part of the Derivative Works, in at least one
-      of the following places: within a NOTICE text file distributed
-      as part of the Derivative Works; within the Source form or
-      documentation, if provided along with the Derivative Works; or,
-      within a display generated by the Derivative Works, if and
-      wherever such third-party notices normally appear. The contents
-      of the NOTICE file are for informational purposes only and
-      do not modify the License. You may add Your own attribution
-      notices within Derivative Works that You distribute, alongside
-      or as an addendum to the NOTICE text from the Work, provided
-      that such additional attribution notices cannot be construed
-      as modifying the License.
-
-  You may add Your own copyright statement to Your modifications and
-  may provide additional or different license terms and conditions
-  for use, reproduction, or distribution of Your modifications, or
-  for any such Derivative Works as a whole, provided Your use,
-  reproduction, and distribution of the Work otherwise complies with
-  the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-  any Contribution intentionally submitted for inclusion in the Work
-  by You to the Licensor shall be under the terms and conditions of
-  this License, without any additional terms or conditions.
-  Notwithstanding the above, nothing herein shall supersede or modify
-  the terms of any separate license agreement you may have executed
-  with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-  names, trademarks, service marks, or product names of the Licensor,
-  except as required for reasonable and customary use in describing the
-  origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-  agreed to in writing, Licensor provides the Work (and each
-  Contributor provides its Contributions) on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-  implied, including, without limitation, any warranties or conditions
-  of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-  PARTICULAR PURPOSE. You are solely responsible for determining the
-  appropriateness of using or redistributing the Work and assume any
-  risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-  whether in tort (including negligence), contract, or otherwise,
-  unless required by applicable law (such as deliberate and grossly
-  negligent acts) or agreed to in writing, shall any Contributor be
-  liable to You for damages, including any direct, indirect, special,
-  incidental, or consequential damages of any character arising as a
-  result of this License or out of the use or inability to use the
-  Work (including but not limited to damages for loss of goodwill,
-  work stoppage, computer failure or malfunction, or any and all
-  other commercial damages or losses), even if such Contributor
-  has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-  the Work or Derivative Works thereof, You may choose to offer,
-  and charge a fee for, acceptance of support, warranty, indemnity,
-  or other liability obligations and/or rights consistent with this
-  License. However, in accepting such obligations, You may act only
-  on Your own behalf and on Your sole responsibility, not on behalf
-  of any other Contributor, and only if You agree to indemnify,
-  defend, and hold each Contributor harmless for any liability
-  incurred by, or claims asserted against, such Contributor by reason
-  of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-  To apply the Apache License to your work, attach the following
-  boilerplate notice, with the fields enclosed by brackets "[]"
-  replaced with your own identifying information. (Don't include
-  the brackets!)  The text should be enclosed in the appropriate
-  comment syntax for the file format. We also recommend that a
-  file or class name and description of purpose be included on the
-  same "printed page" as the copyright notice for easier
-  identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.

+ 0 - 3
pioneer/packages/page-contracts/README.md

@@ -1,3 +0,0 @@
-# @polkadot/app-contracts
-
-Substrate contracts - code deployment, instance creation and messages.

+ 0 - 17
pioneer/packages/page-contracts/package.json

@@ -1,17 +0,0 @@
-{
-  "name": "@polkadot/app-contracts",
-  "private": true,
-  "version": "0.51.1",
-  "description": "Deployment and management of substrate contracts",
-  "main": "index.js",
-  "scripts": {},
-  "author": "Jaco Greeff <jacogr@gmail.com>",
-  "maintainers": [
-    "Jaco Greeff <jacogr@gmail.com>"
-  ],
-  "license": "Apache-2.0",
-  "dependencies": {
-    "@babel/runtime": "^7.10.5",
-    "@polkadot/api-contract": "^1.26.1"
-  }
-}

+ 0 - 106
pioneer/packages/page-contracts/src/Codes/Add.tsx

@@ -1,106 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { StringOrNull } from '@polkadot/react-components/types';
-
-import React, { useCallback, useMemo, useState } from 'react';
-import { createType } from '@polkadot/types';
-import { registry } from '@polkadot/react-api';
-import { Button, Input, Modal } from '@polkadot/react-components';
-import { useToggle } from '@polkadot/react-hooks';
-import { isNull } from '@polkadot/util';
-import { ABI, InputName } from '../shared';
-
-import ValidateCode from './ValidateCode';
-import store from '../store';
-import { useTranslation } from '../translate';
-import useAbi from '../useAbi';
-
-function Add (): React.ReactElement {
-  const { t } = useTranslation();
-  const [isOpen, toggleIsOpen, setIsOpen] = useToggle();
-  const [codeHash, setCodeHash] = useState('');
-  const [isCodeHashValid, setIsCodeHashValid] = useState(false);
-  const [name, setName] = useState<StringOrNull>(null);
-  const { abi, contractAbi, errorText, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi();
-
-  const isNameValid = useMemo(
-    (): boolean => !isNull(name) && name.length > 0,
-    [name]
-  );
-
-  const isValid = useMemo(
-    (): boolean => isCodeHashValid && isNameValid,
-    [isCodeHashValid, isNameValid]
-  );
-
-  const _onSave = useCallback(
-    (): void => {
-      if (!codeHash || !name) {
-        return;
-      }
-
-      store
-        .saveCode(createType(registry, 'Hash', codeHash), { abi, name, tags: [] })
-        .then((): void => setIsOpen(false))
-        .catch((error): void => {
-          console.error('Unable to save code', error);
-        });
-    },
-    [abi, codeHash, name, setIsOpen]
-  );
-
-  return (
-    <>
-      <Button
-        icon='plus'
-        label={t('Add an existing code hash')}
-        onClick={toggleIsOpen}
-      />
-      {isOpen && (
-        <Modal header={t('Add an existing code hash')}>
-          <Modal.Content>
-            <Input
-              autoFocus
-              help={t('The code hash for the on-chain deployed code.')}
-              isError={codeHash.length > 0 && !isCodeHashValid}
-              label={t('code hash')}
-              onChange={setCodeHash}
-              value={codeHash}
-            />
-            <ValidateCode
-              codeHash={codeHash}
-              onChange={setIsCodeHashValid}
-            />
-            <InputName
-              isError={!isNameValid}
-              onChange={setName}
-              value={name || undefined}
-            />
-            <ABI
-              contractAbi={contractAbi}
-              errorText={errorText}
-              isError={isAbiError}
-              isSupplied={isAbiSupplied}
-              isValid={isAbiValid}
-              onChange={onChangeAbi}
-              onRemove={onRemoveAbi}
-              withLabel
-            />
-          </Modal.Content>
-          <Modal.Actions onCancel={toggleIsOpen}>
-            <Button
-              icon='save'
-              isDisabled={!isValid}
-              label={t('Save')}
-              onClick={_onSave}
-            />
-          </Modal.Actions>
-        </Modal>
-      )}
-    </>
-  );
-}
-
-export default React.memo(Add);

+ 0 - 138
pioneer/packages/page-contracts/src/Codes/Code.tsx

@@ -1,138 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-staking authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { CodeStored } from '../types';
-
-import React, { useCallback } from 'react';
-import styled from 'styled-components';
-import { Button, Card, Expander, Forget } from '@polkadot/react-components';
-import { useToggle } from '@polkadot/react-hooks';
-
-import { ABI, CodeRow } from '../shared';
-import RemoveABI from '../RemoveABI';
-import store from '../store';
-import useAbi from '../useAbi';
-import { useTranslation } from '../translate';
-
-interface Props {
-  className?: string;
-  code: CodeStored;
-  onShowDeploy: (codeHash?: string, constructorIndex?: number) => () => void;
-}
-
-function Code ({ className, code, onShowDeploy }: Props): React.ReactElement<Props> {
-  const { json: { codeHash } } = code;
-  const { t } = useTranslation();
-  const [isAbiOpen, toggleIsAbiOpen] = useToggle();
-  const [isForgetOpen, toggleIsForgetOpen] = useToggle();
-  const [isRemoveABIOpen, toggleIsRemoveABIOpen] = useToggle();
-  const { contractAbi, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi([code.json.abi || null, code.contractAbi || null], codeHash, true);
-
-  const _onShowDeploy = useCallback(
-    () => onShowDeploy(codeHash)(),
-    [codeHash, onShowDeploy]
-  );
-
-  const _onDeployConstructor = useCallback(
-    (constructorIndex = 0) => codeHash && onShowDeploy && onShowDeploy(codeHash, constructorIndex)(),
-    [codeHash, onShowDeploy]
-  );
-
-  const _onForget = useCallback(
-    (): void => {
-      if (!codeHash) {
-        return;
-      }
-
-      try {
-        store.forgetCode(codeHash);
-      } catch (error) {
-        console.error(error);
-      } finally {
-        toggleIsForgetOpen();
-      }
-    },
-    [codeHash, toggleIsForgetOpen]
-  );
-
-  const abiNode = (
-    <ABI
-      contractAbi={contractAbi}
-      isError={isAbiError}
-      isSupplied={isAbiSupplied}
-      isValid={isAbiValid}
-      onChange={onChangeAbi}
-      onRemove={toggleIsRemoveABIOpen}
-      onSelectConstructor={_onDeployConstructor}
-    />
-  );
-
-  return (
-    <Card className={className}>
-      <CodeRow
-        buttons={
-          <>
-            <Button
-              icon='trash'
-              onClick={toggleIsForgetOpen}
-              tooltip={t('Forget this code hash')}
-            />
-            <Button
-              icon='upload'
-              label={t('deploy')}
-              onClick={_onShowDeploy}
-              tooltip={t('Deploy this code hash as a smart contract')}
-            />
-          </>
-        }
-        code={code}
-        withTags
-      >
-        {contractAbi
-          ? (
-            <Expander
-              isOpen={isAbiOpen}
-              onClick={toggleIsAbiOpen}
-              summary={t<string>('ABI')}
-            >
-              {abiNode}
-            </Expander>
-          )
-          : abiNode
-        }
-      </CodeRow>
-      {isForgetOpen && (
-        <Forget
-          key='modal-forget-account'
-          mode='code'
-          onClose={toggleIsForgetOpen}
-          onForget={_onForget}
-        >
-          <CodeRow
-            code={code || ''}
-            isInline
-          >
-            <p>{t<string>('You are about to remove this code from your list of available code hashes. Once completed, should you need to access it again, you will have to manually add the code hash again.')}</p>
-            <p>{t<string>('This operation does not remove the uploaded code WASM and ABI from the chain, nor any deployed contracts. The forget operation only limits your access to the code on this browser.')}</p>
-          </CodeRow>
-        </Forget>
-      )}
-      {isRemoveABIOpen && (
-        <RemoveABI
-          code={code}
-          key='modal-remove-abi'
-          onClose={toggleIsRemoveABIOpen}
-          onRemove={onRemoveAbi}
-        />
-      )}
-    </Card>
-  );
-}
-
-export default React.memo(
-  styled(Code)`
-    max-width: 100%;
-    min-width: 100%;
-  `
-);

+ 0 - 125
pioneer/packages/page-contracts/src/Codes/Upload.tsx

@@ -1,125 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { Hash } from '@polkadot/types/interfaces';
-
-import React, { useCallback, useMemo, useState } from 'react';
-import { SubmittableResult } from '@polkadot/api';
-import { Button, InputAddress, InputFile, Modal, TxButton } from '@polkadot/react-components';
-import { useAccountId, useApi, useNonEmptyString, useToggle } from '@polkadot/react-hooks';
-import { compactAddLength, isNull } from '@polkadot/util';
-
-import { ABI, InputName } from '../shared';
-import store from '../store';
-import { useTranslation } from '../translate';
-import useAbi from '../useAbi';
-
-function Upload (): React.ReactElement {
-  const { t } = useTranslation();
-  const { api } = useApi();
-  const [isOpen, toggleIsOpen] = useToggle();
-  const [accountId, setAccountId] = useAccountId();
-  const [[wasm, isWasmValid], setWasm] = useState<[Uint8Array | null, boolean]>([null, false]);
-  const [name, isNameValid, setName] = useNonEmptyString();
-  const { abi, contractAbi, errorText, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi();
-
-  const isSubmittable = useMemo(
-    (): boolean => !!accountId && (!isNull(name) && isNameValid) && isWasmValid && (!isAbiSupplied || isAbiValid),
-    [accountId, name, isAbiSupplied, isAbiValid, isNameValid, isWasmValid]
-  );
-
-  const _onAddWasm = useCallback(
-    (wasm: Uint8Array, name: string): void => {
-      setWasm([compactAddLength(wasm), wasm.subarray(0, 4).toString() === '0,97,115,109']);
-      setName(name);
-    },
-    [setName]
-  );
-
-  const _onSuccess = useCallback(
-    (result: SubmittableResult): void => {
-      const section = api.tx.contracts ? 'contracts' : 'contract';
-      const record = result.findRecord(section, 'CodeStored');
-
-      if (record) {
-        const codeHash = record.event.data[0];
-
-        if (!codeHash || !name) {
-          return;
-        }
-
-        store.saveCode(codeHash as Hash, { abi, name, tags: [] })
-          .then()
-          .catch((error: any): void => {
-            console.error('Unable to save code', error);
-          });
-      }
-    },
-    [api, abi, name]
-  );
-
-  return (
-    <>
-      <Button
-        icon='plus'
-        label={t('Upload WASM')}
-        onClick={toggleIsOpen}
-      />
-      {isOpen && (
-        <Modal header={t('Upload WASM')}>
-          <Modal.Content>
-            <InputAddress
-              help={t('Specify the user account to use for this deployment. Any fees will be deducted from this account.')}
-              isInput={false}
-              label={t('deployment account')}
-              onChange={setAccountId}
-              type='account'
-              value={accountId}
-            />
-            <InputFile
-              help={t<string>('The compiled WASM for the contract that you wish to deploy. Each unique code blob will be attached with a code hash that can be used to create new instances.')}
-              isError={!isWasmValid}
-              label={t<string>('compiled contract WASM')}
-              onChange={_onAddWasm}
-              placeholder={
-                wasm && !isWasmValid
-                  ? t<string>('The code is not recognized as being in valid WASM format')
-                  : null
-              }
-            />
-            <InputName
-              isError={!isNameValid}
-              onChange={setName}
-              value={name || undefined}
-            />
-            <ABI
-              contractAbi={contractAbi}
-              errorText={errorText}
-              isError={isAbiError}
-              isSupplied={isAbiSupplied}
-              isValid={isAbiValid}
-              onChange={onChangeAbi}
-              onRemove={onRemoveAbi}
-              withLabel
-            />
-          </Modal.Content>
-          <Modal.Actions onCancel={toggleIsOpen}>
-            <TxButton
-              accountId={accountId}
-              icon='upload'
-              isDisabled={!isSubmittable}
-              label={t('Upload')}
-              onClick={toggleIsOpen}
-              onSuccess={_onSuccess}
-              params={[wasm]}
-              tx={api.tx.contracts ? 'contracts.putCode' : 'contract.putCode'}
-            />
-          </Modal.Actions>
-        </Modal>
-      )}
-    </>
-  );
-}
-
-export default React.memo(Upload);

+ 0 - 57
pioneer/packages/page-contracts/src/Codes/ValidateCode.tsx

@@ -1,57 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-/* eslint-disable camelcase */
-
-import { PrefabWasmModule } from '@polkadot/types/interfaces';
-
-import React, { useMemo } from 'react';
-import { Option } from '@polkadot/types';
-import { InfoForInput } from '@polkadot/react-components';
-import { useApi, useCall } from '@polkadot/react-hooks';
-import { isHex } from '@polkadot/util';
-
-import { useTranslation } from '../translate';
-
-interface Props {
-  codeHash?: string | null;
-  onChange: React.Dispatch<boolean>;
-}
-
-function ValidateCode ({ codeHash, onChange }: Props): React.ReactElement<Props> | null {
-  const { api } = useApi();
-  const { t } = useTranslation();
-  const codeStorage = useCall<Option<PrefabWasmModule>>((api.query.contracts || api.query.contract).codeStorage, [codeHash]);
-  const [isValidHex, isValid] = useMemo(
-    (): [boolean, boolean] => {
-      const isValidHex = !!codeHash && isHex(codeHash) && codeHash.length === 66;
-      const isStored = !!codeStorage && codeStorage.isSome;
-      const isValid = isValidHex && isStored;
-
-      onChange(isValid);
-
-      return [
-        isValidHex,
-        isValid
-      ];
-    },
-    [codeHash, codeStorage, onChange]
-  );
-
-  if (isValid || !isValidHex) {
-    return null;
-  }
-
-  return (
-    <InfoForInput type='error'>
-      {
-        isValidHex
-          ? t('Unable to find on-chain WASM code for the supplied codeHash')
-          : t('The codeHash is not a valid hex hash')
-      }
-    </InfoForInput>
-  );
-}
-
-export default React.memo(ValidateCode);

+ 0 - 45
pioneer/packages/page-contracts/src/Codes/index.tsx

@@ -1,45 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-staking authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { ComponentProps as Props } from '../types';
-
-import React from 'react';
-import { Button, CardGrid } from '@polkadot/react-components';
-
-import contracts from '../store';
-import { useTranslation } from '../translate';
-
-import Code from './Code';
-import Upload from './Upload';
-import Add from './Add';
-
-function Codes ({ onShowDeploy }: Props): React.ReactElement<Props> {
-  const { t } = useTranslation();
-
-  return (
-    <>
-      <CardGrid
-        buttons={
-          <Button.Group isCentered>
-            <Upload />
-            <Add />
-          </Button.Group>
-        }
-        emptyText={t('No code hashes available')}
-      >
-        {contracts.getAllCode().map((code): React.ReactNode => {
-          return (
-            <Code
-              code={code}
-              key={code.json.codeHash}
-              onShowDeploy={onShowDeploy}
-            />
-          );
-        })}
-      </CardGrid>
-    </>
-  );
-}
-
-export default React.memo(Codes);

+ 0 - 129
pioneer/packages/page-contracts/src/Contracts/Add.tsx

@@ -1,129 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { StringOrNull } from '@polkadot/react-components/types';
-import { ActionStatus } from '@polkadot/react-components/Status/types';
-
-import React, { useCallback, useMemo, useState } from 'react';
-import { AddressRow, Button, Input, Modal } from '@polkadot/react-components';
-import { useApi, useNonEmptyString, useToggle } from '@polkadot/react-hooks';
-import keyring from '@polkadot/ui-keyring';
-
-import ValidateAddr from './ValidateAddr';
-import { ABI, InputName } from '../shared';
-import { useTranslation } from '../translate';
-import useAbi from '../useAbi';
-
-function Add (): React.ReactElement {
-  const { t } = useTranslation();
-  const { api } = useApi();
-  const [isOpen, toggleIsOpen, setIsOpen] = useToggle();
-  const [address, setAddress] = useState<StringOrNull>(null);
-  const [isAddressValid, setIsAddressValid] = useState(false);
-  const [name, isNameValid, setName] = useNonEmptyString('New Contract');
-  const { abi, contractAbi, errorText, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi([null, null], null, true);
-
-  const isValid = useMemo(
-    (): boolean => isAddressValid && isNameValid && isAbiValid,
-    [isAbiValid, isAddressValid, isNameValid]
-  );
-
-  const _onAdd = useCallback(
-    (): void => {
-      const status: Partial<ActionStatus> = { action: 'create' };
-
-      if (!address || !abi || !name) {
-        return;
-      }
-
-      try {
-        const json = {
-          contract: {
-            abi,
-            genesisHash: api.genesisHash.toHex()
-          },
-          name,
-          tags: []
-        };
-
-        keyring.saveContract(address, json);
-
-        status.account = address;
-        status.status = address ? 'success' : 'error';
-        status.message = 'contract added';
-
-        setIsOpen(false);
-      } catch (error) {
-        console.error(error);
-
-        status.status = 'error';
-        status.message = (error as Error).message;
-      }
-    },
-    [abi, address, api, name, setIsOpen]
-  );
-
-  return (
-    <>
-      <Button
-        icon='plus'
-        label={t('Add an existing contract')}
-        onClick={toggleIsOpen}
-      />
-      <Modal
-        header={t('Add an existing contract')}
-        onClose={toggleIsOpen}
-        open={isOpen}
-      >
-        <Modal.Content>
-          <AddressRow
-            defaultName={name}
-            isValid
-            value={address || null}
-          >
-            <Input
-              autoFocus
-              help={t<string>('The address for the deployed contract instance.')}
-              isError={!isAddressValid}
-              label={t<string>('contract address')}
-              onChange={setAddress}
-              value={address || ''}
-            />
-            <ValidateAddr
-              address={address}
-              onChange={setIsAddressValid}
-            />
-            <InputName
-              isContract
-              isError={!isNameValid}
-              onChange={setName}
-              value={name || undefined}
-            />
-            <ABI
-              contractAbi={contractAbi}
-              errorText={errorText}
-              isContract
-              isError={isAbiError}
-              isSupplied={isAbiSupplied}
-              isValid={isAbiValid}
-              onChange={onChangeAbi}
-              onRemove={onRemoveAbi}
-              withLabel
-            />
-          </AddressRow>
-        </Modal.Content>
-        <Modal.Actions onCancel={toggleIsOpen}>
-          <Button
-            icon='save'
-            isDisabled={!isValid}
-            label={t<string>('Save')}
-            onClick={_onAdd}
-          />
-        </Modal.Actions>
-      </Modal>
-    </>
-  );
-}
-
-export default React.memo(Add);

+ 0 - 265
pioneer/packages/page-contracts/src/Contracts/Call.tsx

@@ -1,265 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { ContractCallOutcome } from '@polkadot/api-contract/types';
-import { StringOrNull } from '@polkadot/react-components/types';
-
-import BN from 'bn.js';
-import React, { useCallback, useState, useEffect, useMemo } from 'react';
-import styled from 'styled-components';
-import { Button, ButtonCancel, Dropdown, IconLink, InputAddress, InputBalance, Modal, Toggle, TxButton } from '@polkadot/react-components';
-import { PromiseContract as ApiContract } from '@polkadot/api-contract';
-import { useAccountId, useFormField, useToggle } from '@polkadot/react-hooks';
-import { createValue } from '@polkadot/react-params/values';
-import { BN_ZERO, isNull } from '@polkadot/util';
-
-import { InputMegaGas, Params } from '../shared';
-import Outcome from './Outcome';
-import { useTranslation } from '../translate';
-import { getCallMessageOptions } from './util';
-import useWeight from '../useWeight';
-
-interface Props {
-  callContract: ApiContract | null;
-  callMessageIndex: number | null;
-  className?: string;
-  isOpen: boolean;
-  onChangeCallContractAddress: (callContractAddress: StringOrNull) => void;
-  onChangeCallMessageIndex: (callMessageIndex: number) => void;
-  onClose: () => void;
-}
-
-function Call (props: Props): React.ReactElement<Props> | null {
-  const { t } = useTranslation();
-  const { callContract, callMessageIndex, className = '', isOpen, onChangeCallContractAddress, onChangeCallMessageIndex, onClose } = props;
-  const hasRpc = callContract?.hasRpcContractsCall;
-  const callMessage = callContract?.getMessage(isNull(callMessageIndex) ? undefined : callMessageIndex);
-
-  const [accountId, setAccountId] = useAccountId();
-  const [endowment, isEndowmentValid, setEndowment] = useFormField<BN>(BN_ZERO);
-  const [isBusy, , setIsBusy] = useToggle();
-  const [outcomes, setOutcomes] = useState<ContractCallOutcome[]>([]);
-  const [params, setParams] = useState<any[]>(callMessage ? callMessage.def.args.map(({ type }): any => createValue({ type })) : []);
-  const [useRpc, setUseRpc] = useState(hasRpc && callMessage && !callMessage.def.mutates);
-  const useWeightHook = useWeight();
-  const { isValid: isWeightValid, weight } = useWeightHook;
-
-  useEffect((): void => {
-    if (callContract && callMessageIndex) {
-      const callMessage = callContract.getMessage(callMessageIndex);
-
-      setParams(callMessage ? callMessage.def.args.map(({ type }): any => createValue({ type })) : []);
-
-      if (hasRpc) {
-        if (!callMessage || callMessage.def.mutates) {
-          setUseRpc(false);
-        } else {
-          setUseRpc(true);
-        }
-      }
-    }
-  }, [callContract, callMessageIndex, hasRpc]);
-
-  useEffect((): void => {
-    setOutcomes([]);
-  }, [callContract]);
-
-  const _onChangeCallMessageIndexString = useCallback(
-    (callMessageIndexString: string): void => {
-      onChangeCallMessageIndex && onChangeCallMessageIndex(
-        parseInt(callMessageIndexString, 10) || 0
-      );
-    },
-    [onChangeCallMessageIndex]
-  );
-
-  const _constructTx = useCallback(
-    (): unknown[] => {
-      if (!accountId || !callMessage || !callMessage.fn || !callContract || !callContract.address) {
-        return [];
-      }
-
-      return [callContract.address.toString(), endowment, weight, callMessage.fn(...params)];
-    },
-    [accountId, callContract, callMessage, endowment, weight, params]
-  );
-
-  const _onSubmitRpc = useCallback(
-    (): void => {
-      if (!accountId || !callContract || !callMessage || !endowment || !weight) return;
-
-      !!callContract && callContract
-        .call('rpc', callMessage.def.name, endowment, weight, ...params)
-        .send(accountId)
-        .then(
-          (outcome: ContractCallOutcome): void => {
-            setOutcomes([outcome, ...outcomes]);
-          }
-        );
-    },
-    [accountId, callContract, callMessage, endowment, weight, outcomes, params]
-  );
-
-  const _onClearOutcomes = useCallback(
-    () => setOutcomes([]),
-    []
-  );
-
-  const _onClearOutcome = useCallback(
-    (outcomeIndex: number) => () => setOutcomes(outcomes.slice(0, outcomeIndex).concat(outcomes.slice(outcomeIndex + 1))),
-    [outcomes]
-  );
-
-  const isValid = useMemo(
-    (): boolean => !!accountId && !!callContract && !!callContract.address && !!callContract.abi && isWeightValid && isEndowmentValid,
-    [accountId, callContract, isEndowmentValid, isWeightValid]
-  );
-
-  if (isNull(callContract) || isNull(callMessageIndex) || !callMessage) {
-    return null;
-  }
-
-  return (
-    <Modal
-      className={[className || '', 'app--contracts-Modal'].join(' ')}
-      header={t<string>('Call a contract')}
-      onClose={onClose}
-      open={isOpen}
-    >
-      <Modal.Content>
-        {callContract && (
-          <div className='contracts--CallControls'>
-            <InputAddress
-              defaultValue={accountId}
-              help={t<string>('Specify the user account to use for this contract call. And fees will be deducted from this account.')}
-              isDisabled={isBusy}
-              label={t<string>('call from account')}
-              onChange={setAccountId}
-              type='account'
-              value={accountId}
-            />
-            <InputAddress
-              help={t<string>('A deployed contract that has either been deployed or attached. The address and ABI are used to construct the parameters.')}
-              isDisabled={isBusy}
-              label={t<string>('contract to use')}
-              onChange={onChangeCallContractAddress}
-              type='contract'
-              value={callContract.address.toString()}
-            />
-            {callMessageIndex !== null && (
-              <>
-                <Dropdown
-                  defaultValue={`${callMessage.index}`}
-                  help={t<string>('The message to send to this contract. Parameters are adjusted based on the ABI provided.')}
-                  isDisabled={isBusy}
-                  isError={callMessage === null}
-                  label={t<string>('message to send')}
-                  onChange={_onChangeCallMessageIndexString}
-                  options={getCallMessageOptions(callContract)}
-                  value={`${callMessage.index}`}
-                />
-                <Params
-                  isDisabled={isBusy}
-                  onChange={setParams}
-                  params={
-                    callMessage
-                      ? callMessage.def.args
-                      : undefined
-                  }
-                />
-              </>
-            )}
-            <InputBalance
-              help={t<string>('The allotted value for this contract, i.e. the amount transferred to the contract as part of this call.')}
-              isDisabled={isBusy}
-              isError={!isEndowmentValid}
-              isZeroable
-              label={t<string>('value')}
-              onChange={setEndowment}
-              value={endowment}
-            />
-            <InputMegaGas
-              help={t<string>('The maximum amount of gas to use for this contract call. If the call requires more, it will fail.')}
-              label={t<string>('maximum gas allowed')}
-              {...useWeightHook}
-            />
-          </div>
-        )}
-        {hasRpc && (
-          <Toggle
-            className='rpc-toggle'
-            label={
-              useRpc
-                ? t<string>('send as RPC call')
-                : t<string>('send as transaction')
-            }
-            onChange={setUseRpc}
-            value={useRpc || false}
-          />
-        )}
-        <Button.Group>
-          <ButtonCancel onClick={onClose} />
-          {useRpc
-            ? (
-              <Button
-                icon='sign-in-alt'
-                isDisabled={!isValid}
-                label={t<string>('Call')}
-                onClick={_onSubmitRpc}
-              />
-            )
-            : (
-              <TxButton
-                accountId={accountId}
-                icon='sign-in-alt'
-                isDisabled={!isValid}
-                label={t('Call')}
-                onClick={(): void => setIsBusy(true)}
-                onFailed={(): void => setIsBusy(false)}
-                onSuccess={(): void => setIsBusy(false)}
-                params={_constructTx}
-                tx='contracts.call'
-                withSpinner
-              />
-            )
-          }
-        </Button.Group>
-        {outcomes.length > 0 && (
-          <>
-            <h3>
-              {t<string>('Call results')}
-              <IconLink
-                className='clear-all'
-                icon='times'
-                label={t<string>('Clear all')}
-                onClick={_onClearOutcomes}
-              />
-            </h3>
-            <div>
-              {outcomes.map((outcome, index): React.ReactNode => (
-                <Outcome
-                  key={`outcome-${index}`}
-                  onClear={_onClearOutcome(index)}
-                  outcome={outcome}
-                />
-              ))}
-            </div>
-          </>
-        )}
-      </Modal.Content>
-    </Modal>
-  );
-}
-
-export default React.memo(styled(Call)`
-  .rpc-toggle {
-    margin-top: 1rem;
-    display: flex;
-    justify-content: flex-end;
-  }
-
-  .clear-all {
-    float: right;
-  }
-`);

+ 0 - 110
pioneer/packages/page-contracts/src/Contracts/Contract.tsx

@@ -1,110 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-staking authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { ActionStatus } from '@polkadot/react-components/Status/types';
-
-import React, { useCallback } from 'react';
-import styled from 'styled-components';
-import keyring from '@polkadot/ui-keyring';
-import { PromiseContract as ApiContract } from '@polkadot/api-contract';
-import { AddressRow, Button, Card, Expander, Forget } from '@polkadot/react-components';
-import { useToggle } from '@polkadot/react-hooks';
-
-import Messages from '../shared/Messages';
-import { useTranslation } from '../translate';
-
-interface Props {
-  className?: string;
-  contract: ApiContract;
-  onCall: (_?: number) => () => void;
-}
-
-function Contract ({ className, contract: { abi, address }, onCall }: Props): React.ReactElement<Props> | null {
-  const { t } = useTranslation();
-  const [isForgetOpen, toggleIsForgetOpen] = useToggle();
-
-  const _onForget = useCallback(
-    (): void => {
-      if (!address) {
-        return;
-      }
-
-      const status: Partial<ActionStatus> = {
-        account: address,
-        action: 'forget'
-      };
-
-      try {
-        keyring.forgetContract(address.toString());
-        status.status = 'success';
-        status.message = t<string>('address forgotten');
-      } catch (error) {
-        status.status = 'error';
-        status.message = (error as Error).message;
-      }
-
-      toggleIsForgetOpen();
-    },
-    [address, t, toggleIsForgetOpen]
-  );
-
-  if (!address || !abi) {
-    return null;
-  }
-
-  return (
-    <Card className={className}>
-      {isForgetOpen && (
-        <Forget
-          address={address.toString()}
-          key='modal-forget-contract'
-          mode='contract'
-          onClose={toggleIsForgetOpen}
-          onForget={_onForget}
-        />
-      )}
-      <AddressRow
-        buttons={
-          <div className='contracts--Contract-buttons'>
-            <Button
-              icon='trash'
-              onClick={toggleIsForgetOpen}
-              tooltip={t<string>('Forget this contract')}
-            />
-            <Button
-              icon='play'
-              label={t<string>('execute')}
-              onClick={onCall()}
-              tooltip={t<string>('Call a method on this contract')}
-            />
-          </div>
-        }
-        isContract
-        isEditableName
-        isEditableTags
-        type='contract'
-        value={address}
-        withBalance={false}
-        withNonce={false}
-        withTags
-      >
-        <Expander summary={t<string>('Messages')}>
-          <Messages
-            address={address.toString()}
-            contractAbi={abi}
-            isRemovable={false}
-            onSelect={onCall}
-          />
-        </Expander>
-      </AddressRow>
-    </Card>
-  );
-}
-
-export default React.memo(
-  styled(Contract)`
-    min-width: 100%;
-    max-width: 100%;
-  `
-);

+ 0 - 103
pioneer/packages/page-contracts/src/Contracts/Outcome.tsx

@@ -1,103 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { ContractCallOutcome } from '@polkadot/api-contract/types';
-
-import React from 'react';
-import styled from 'styled-components';
-import { AddressMini, Button, Output } from '@polkadot/react-components';
-
-import MessageSignature from '../shared/MessageSignature';
-
-interface Props {
-  className?: string;
-  onClear?: () => void;
-  outcome: ContractCallOutcome;
-}
-
-function Outcome ({ className = '', onClear, outcome: { isSuccess, message, origin, output, params, time } }: Props): React.ReactElement<Props> | null {
-  const dateTime = new Date(time);
-
-  return (
-    <div className={className}>
-      <div className='info'>
-        <AddressMini
-          className='origin'
-          isPadded={false}
-          value={origin}
-          withAddress={false}
-        />
-        <MessageSignature
-          message={message}
-          params={params}
-        />
-        <span className='date-time'>
-          {dateTime.toLocaleDateString()}
-          {' '}
-          {dateTime.toLocaleTimeString()}
-        </span>
-        <Button
-          className='icon-button clear-btn'
-          icon='times'
-          onClick={onClear}
-        />
-      </div>
-      <Output
-        className='output'
-        isError={!isSuccess}
-        value={(output || '()').toString()}
-        withCopy
-        withLabel={false}
-      />
-    </div>
-  );
-}
-
-export default React.memo(styled(Outcome)`
-  & {
-    .info {
-      display: inline-flex;
-      justify-content: center;
-      align-items: center;
-      padding: 0.5rem;
-
-      & > *:not(:first-child) {
-        padding-left: 1.5rem !important;
-      }
-    }
-
-    .clear-btn {
-      opacity: 0;
-    }
-
-    .date-time {
-      color: #aaa;
-      white-space: nowrap;
-    }
-
-    .origin {
-      padding-left: 0 !important;
-
-      * {
-        margin-left: 0 !important;
-      }
-    }
-
-    .output {
-      font-family: monospace;
-      margin-left: 3.5rem;
-
-      .ui--output {
-        border-color: #aaa;
-        margin: 0;
-      }
-    }
-
-    &:hover {
-      .clear-btn {
-        opacity: 1;
-      }
-    }
-  }
-`);

+ 0 - 58
pioneer/packages/page-contracts/src/Contracts/ValidateAddr.tsx

@@ -1,58 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { ContractInfo } from '@polkadot/types/interfaces';
-
-import React, { useEffect, useState } from 'react';
-import { Option } from '@polkadot/types';
-import { useApi, useCall } from '@polkadot/react-hooks';
-import { InfoForInput } from '@polkadot/react-components';
-import keyring from '@polkadot/ui-keyring';
-
-import { useTranslation } from '../translate';
-
-interface Props {
-  address?: string | null;
-  onChange: (isValid: boolean) => void;
-}
-
-function ValidateAddr ({ address, onChange }: Props): React.ReactElement<Props> | null {
-  const { t } = useTranslation();
-  const { api } = useApi();
-  const contractInfo = useCall<Option<ContractInfo>>(api.query.contracts.contractInfoOf, [address]);
-  const [isAddress, setIsAddress] = useState(false);
-  const [isStored, setIsStored] = useState(false);
-
-  useEffect((): void => {
-    try {
-      keyring.decodeAddress(address || '');
-      setIsAddress(true);
-    } catch (error) {
-      setIsAddress(false);
-    }
-  }, [address]);
-
-  useEffect((): void => {
-    setIsStored(!!contractInfo?.isSome);
-  }, [contractInfo?.isSome]);
-
-  useEffect((): void => {
-    onChange(isAddress && isStored);
-  }, [isAddress, isStored, onChange]);
-
-  if (isStored || !isAddress) {
-    return null;
-  }
-
-  return (
-    <InfoForInput type='error'>
-      {isAddress
-        ? t<string>('Unable to find deployed contract code at the specified address')
-        : t<string>('The value is not in a valid address format')
-      }
-    </InfoForInput>
-  );
-}
-
-export default React.memo(ValidateAddr);

+ 0 - 103
pioneer/packages/page-contracts/src/Contracts/index.tsx

@@ -1,103 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-staking authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { StringOrNull } from '@polkadot/react-components/types';
-import { ComponentProps as Props } from '../types';
-
-import React, { useState, useEffect } from 'react';
-import { ApiPromise } from '@polkadot/api';
-import { PromiseContract as ApiContract } from '@polkadot/api-contract';
-import { Button, CardGrid } from '@polkadot/react-components';
-import { useApi } from '@polkadot/react-hooks';
-
-import { useTranslation } from '../translate';
-import Add from './Add';
-import ContractCard from './Contract';
-import Call from './Call';
-import { getContractForAddress } from './util';
-
-function filterContracts (api: ApiPromise, { accounts, contracts: keyringContracts }: Props): ApiContract[] {
-  return accounts && keyringContracts && keyringContracts
-    .map((address): ApiContract | null => getContractForAddress(api, address.toString()))
-    .filter((contract: ApiContract | null): boolean => !!contract) as ApiContract[];
-}
-
-function Contracts (props: Props): React.ReactElement<Props> {
-  const { t } = useTranslation();
-  const { api } = useApi();
-  const { accounts, contracts: keyringContracts, hasCode, onShowDeploy } = props;
-  const [contracts, setContracts] = useState<ApiContract[]>(filterContracts(api, props));
-  const [callContractIndex, setCallContractIndex] = useState<number>(0);
-  const [callMessageIndex, setCallMessageIndex] = useState<number>(0);
-  const [isCallOpen, setIsCallOpen] = useState(false);
-
-  useEffect((): void => {
-    setContracts(filterContracts(api, props));
-  }, [accounts, api, keyringContracts, props]);
-
-  const callContract = contracts[callContractIndex] || null;
-
-  const _toggleCall = (): void => setIsCallOpen(!isCallOpen);
-
-  const _onChangeCallContractAddress = (newCallContractAddress: StringOrNull): void => {
-    const index = contracts.findIndex(({ address }: ApiContract): boolean => newCallContractAddress === address.toString());
-
-    if (index > -1) {
-      index !== callContractIndex && setCallMessageIndex(0);
-      setCallContractIndex(index);
-    }
-  };
-
-  const _onChangeCallMessageIndex = (callMessageIndex: number): void => {
-    !!callContract && setCallMessageIndex(callMessageIndex);
-  };
-
-  const _onCall = (callContractIndex: number): (_?: number) => () => void => {
-    return function (callMessageIndex?: number): () => void {
-      return function (): void {
-        setCallContractIndex(callContractIndex);
-        setCallMessageIndex(callMessageIndex || 0);
-        setIsCallOpen(true);
-      };
-    };
-  };
-
-  return (
-    <>
-      <CardGrid
-        buttons={
-          <Button.Group isCentered>
-            {hasCode && (
-              <Button
-                icon='upload'
-                label={t('Deploy a code hash')}
-                onClick={onShowDeploy()}
-              />
-            )}
-            <Add />
-          </Button.Group>
-        }
-        emptyText={t<string>('No contracts available')}
-      >
-        {contracts.map((contract: ApiContract, index): React.ReactNode => (
-          <ContractCard
-            contract={contract}
-            key={contract.address.toString()}
-            onCall={_onCall(index)}
-          />
-        ))}
-      </CardGrid>
-      <Call
-        callContract={callContract}
-        callMessageIndex={callMessageIndex}
-        isOpen={isCallOpen}
-        onChangeCallContractAddress={_onChangeCallContractAddress}
-        onChangeCallMessageIndex={_onChangeCallMessageIndex}
-        onClose={_toggleCall}
-      />
-    </>
-  );
-}
-
-export default React.memo(Contracts);

+ 0 - 51
pioneer/packages/page-contracts/src/Contracts/util.tsx

@@ -1,51 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { ContractABIFn, ContractABIMessage } from '@polkadot/api-contract/types';
-import { StringOrNull } from '@polkadot/react-components/types';
-
-import React from 'react';
-import { ApiPromise } from '@polkadot/api';
-import { PromiseContract as Contract } from '@polkadot/api-contract';
-import { getContractAbi } from '@polkadot/react-components/util';
-
-import MessageSignature from '../shared/MessageSignature';
-
-export function findCallMethod (callContract: Contract | null, callMethodIndex = 0): ContractABIMessage | null {
-  const message = callContract && callContract.abi.abi.contract.messages[callMethodIndex];
-
-  return message || null;
-}
-
-export function getContractMethodFn (callContract: Contract | null, callMethodIndex: number | null): ContractABIFn | null {
-  const fn = callContract && callContract.abi && callMethodIndex !== null && callContract.abi.messages[callMethodIndex];
-
-  return fn || null;
-}
-
-export function getContractForAddress (api: ApiPromise, address: StringOrNull): Contract | null {
-  if (!address) {
-    return null;
-  } else {
-    const abi = getContractAbi(address);
-
-    return abi
-      ? new Contract(api, abi, address)
-      : null;
-  }
-}
-
-export function getCallMessageOptions (callContract: Contract | null): any[] {
-  return callContract
-    ? callContract.messages.map(({ def: message, def: { name }, index }): { key: string; text: React.ReactNode; value: string } => {
-      return {
-        key: name,
-        text: (
-          <MessageSignature message={message} />
-        ),
-        value: `${index}`
-      };
-    })
-    : [];
-}

+ 0 - 250
pioneer/packages/page-contracts/src/Deploy.tsx

@@ -1,250 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { StringOrNull, VoidFn } from '@polkadot/react-components/types';
-import { AccountId } from '@polkadot/types/interfaces';
-import { CodecArg } from '@polkadot/types/types';
-import { CodeStored } from './types';
-
-import BN from 'bn.js';
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { useHistory } from 'react-router-dom';
-import { SubmittableResult } from '@polkadot/api';
-import { Dropdown, InputAddress, InputBalance, Modal, TxButton } from '@polkadot/react-components';
-import { useFormField, useNonEmptyString, useNonZeroBn, useApi } from '@polkadot/react-hooks';
-import keyring from '@polkadot/ui-keyring';
-
-import { ABI, InputMegaGas, InputName, MessageSignature, Params } from './shared';
-import store from './store';
-import { useTranslation } from './translate';
-import useAbi from './useAbi';
-import useWeight from './useWeight';
-import { ENDOWMENT } from './constants';
-
-type CodeOptions = { text: string; value: string }[];
-type ConstructOptions = { key: string; text: React.ReactNode; value: string }[];
-
-interface Props {
-  basePath: string;
-  allCodes: CodeStored[];
-  codeHash: string;
-  constructorIndex?: number;
-  isOpen?: boolean;
-  onClose: VoidFn;
-  setCodeHash: React.Dispatch<string>;
-  setConstructorIndex: React.Dispatch<number>;
-}
-
-function defaultContractName (name: string) {
-  return `${name} (instance)`;
-}
-
-function Deploy ({ allCodes, basePath, codeHash, constructorIndex = 0, isOpen, onClose, setCodeHash, setConstructorIndex }: Props): React.ReactElement<Props> {
-  const { t } = useTranslation();
-  const { api } = useApi();
-  const history = useHistory();
-  const useWeightHook = useWeight();
-  const { isValid: isWeightValid, weight } = useWeightHook;
-
-  const code = useMemo(
-    (): CodeStored => store.getCode(codeHash),
-    [codeHash]
-  );
-  const [accountId, isAccountIdValid, setAccountId] = useFormField<StringOrNull>(null);
-  const [endowment, isEndowmentValid, setEndowment] = useNonZeroBn(new BN(ENDOWMENT));
-  const [name, isNameValid, setName] = useNonEmptyString(t(defaultContractName(code.json.name)));
-  const { abi, contractAbi, errorText, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi([code.json.abi || null, code.contractAbi || null], codeHash, true);
-
-  const isValid = useMemo(
-    (): boolean => isNameValid && isEndowmentValid && isWeightValid && isAccountIdValid,
-    [isAccountIdValid, isEndowmentValid, isNameValid, isWeightValid]
-  );
-  const codeOptions = useMemo(
-    (): CodeOptions => allCodes.map(({ json: { codeHash, name } }): { text: string; value: string } => ({
-      text: `${name} (${codeHash})`,
-      value: codeHash
-    })),
-    [allCodes]
-  );
-
-  const constructOptions = useMemo(
-    (): ConstructOptions => {
-      if (!contractAbi) {
-        return [];
-      }
-
-      return contractAbi.abi.contract.constructors.map((message, index) => ({
-        key: `${index}`,
-        text: (
-          <MessageSignature
-            asConstructor
-            message={message}
-          />
-        ),
-        value: `${index}`
-      }));
-    },
-    [contractAbi]
-  );
-
-  const [params, setParams] = useState<unknown[]>(contractAbi && constructorIndex >= 0 ? contractAbi.abi.contract.constructors[constructorIndex].args : []);
-
-  useEffect(
-    () => setParams(contractAbi ? contractAbi.abi.contract.constructors[constructorIndex].args : []),
-    [constructorIndex, contractAbi]
-  );
-
-  useEffect(
-    () => setName(t(defaultContractName(code.json.name))),
-    [code, setName, t]
-  );
-
-  const _constructCall = useCallback(
-    (): any[] => {
-      if (!contractAbi || constructorIndex < 0) {
-        return [];
-      }
-
-      return [endowment, weight, codeHash, contractAbi.constructors[constructorIndex](...(params as CodecArg[]))];
-    },
-    [codeHash, constructorIndex, contractAbi, endowment, params, weight]
-  );
-
-  const _onSuccess = useCallback(
-    (result: SubmittableResult): void => {
-      const section = api.tx.contracts ? 'contracts' : 'contract';
-      const records = result.filterRecords(section, 'Instantiated');
-
-      if (records.length) {
-        // find the last EventRecord (in the case of multiple contracts deployed - we should really be
-        // more clever here to find the exact contract deployed, this works for eg. Delegator)
-        const address = records[records.length - 1].event.data[1] as unknown as AccountId;
-
-        keyring.saveContract(address.toString(), {
-          contract: {
-            abi,
-            genesisHash: api.genesisHash.toHex()
-          },
-          name,
-          tags: []
-        });
-
-        history.push(basePath);
-
-        onClose && onClose();
-      }
-    },
-    [abi, api, basePath, history, name, onClose]
-  );
-
-  return (
-    <Modal
-      header={t('Add an existing code hash')}
-      onClose={onClose}
-      open={isOpen}
-    >
-      <Modal.Content>
-        <InputAddress
-          help={t('Specify the user account to use for this deployment. Any fees will be deducted from this account.')}
-          isInput={false}
-          label={t('deployment account')}
-          onChange={setAccountId}
-          type='account'
-          value={accountId}
-        />
-        <Dropdown
-          defaultValue={
-            codeOptions.length
-              ? codeOptions[codeOptions.length - 1].value
-              : undefined
-          }
-          help={t('The contract WASM previously deployed. Internally this is identified by the hash of the code, as either created or attached.')}
-          label={t('code for this contract')}
-          onChange={setCodeHash}
-          options={codeOptions}
-          value={codeHash}
-        />
-        <InputName
-          isContract
-          isError={!isNameValid}
-          onChange={setName}
-          value={name || ''}
-        />
-        {
-          isAbiSupplied
-            ? null
-            : (
-              <ABI
-                contractAbi={contractAbi}
-                errorText={errorText}
-                isError={isAbiError}
-                isSupplied={isAbiSupplied}
-                isValid={isAbiValid}
-                onChange={onChangeAbi}
-                onRemove={onRemoveAbi}
-                withLabel
-              />
-            )
-        }
-        {
-          contractAbi
-            ? (
-              <Dropdown
-                help={t<string>('The deployment constructor information for this contract, as provided by the ABI.')}
-                isDisabled={contractAbi.abi.contract.constructors.length <= 1}
-                label={t('deployment constructor')}
-                onChange={setConstructorIndex}
-                options={constructOptions}
-                value={`${constructorIndex}`}
-              />
-            )
-            : null
-        }
-        <Params
-          onChange={setParams}
-          params={
-            contractAbi && constructorIndex >= 0
-              ? contractAbi.abi.contract.constructors[constructorIndex].args
-              : []
-          }
-        />
-        <InputBalance
-          help={t<string>('The allotted endowment for this contract, i.e. the amount transferred to the contract upon instantiation.')}
-          isError={!isEndowmentValid}
-          label={t<string>('endowment')}
-          onChange={setEndowment}
-          value={endowment}
-        />
-        <InputMegaGas
-          help={t<string>('The maximum amount of gas that can be used by this deployment, if the code requires more, the deployment will fail.')}
-          label={t<string>('maximum gas allowed')}
-          {...useWeightHook}
-        />
-      </Modal.Content>
-      <Modal.Actions onCancel={onClose}>
-        <TxButton
-          accountId={accountId}
-          icon='upload'
-          isDisabled={!isValid}
-          label={t('Deploy')}
-          onClick={onClose}
-          onSuccess={_onSuccess}
-          params={_constructCall}
-          tx={
-            api.tx.contracts
-              ? (
-                !api.tx.contracts.instantiate
-                  ? 'contracts.create' // V2 (new)
-                  : 'contracts.instantiate' // V2 (old)
-              )
-              : 'contract.create' // V1
-          }
-          withSpinner
-        />
-      </Modal.Actions>
-    </Modal>
-  );
-}
-
-export default React.memo(Deploy);

+ 0 - 56
pioneer/packages/page-contracts/src/RemoveABI.tsx

@@ -1,56 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-accounts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { CodeStored } from '@polkadot/app-contracts/types';
-
-import React, { useCallback } from 'react';
-import { Button, Modal } from '@polkadot/react-components';
-
-import CodeRow from './shared/CodeRow';
-import { useTranslation } from './translate';
-
-interface Props {
-  code: CodeStored;
-  onClose: () => void;
-  onRemove: () => void;
-}
-
-function RemoveABI ({ code, onClose, onRemove }: Props): React.ReactElement<Props> {
-  const { t } = useTranslation();
-
-  const _onRemove = useCallback(
-    (): void => {
-      onClose && onClose();
-      onRemove();
-    },
-    [onClose, onRemove]
-  );
-
-  return (
-    <Modal
-      className='app--accounts-Modal'
-      header={t<string>('Confirm ABI removal')}
-      onClose={onClose}
-    >
-      <Modal.Content>
-        <CodeRow
-          code={code}
-          isInline
-        >
-          <p>{t<string>('You are about to remove this code\'s ABI. Once completed, should you need to access it again, you will have to manually re-upload it.')}</p>
-          <p>{t<string>('This operation does not impact the associated on-chain code or any of its contracts.')}</p>
-        </CodeRow>
-      </Modal.Content>
-      <Modal.Actions onCancel={onClose}>
-        <Button
-          icon='trash'
-          label={t<string>('Remove')}
-          onClick={_onRemove}
-        />
-      </Modal.Actions>
-    </Modal>
-  );
-}
-
-export default React.memo(RemoveABI);

+ 0 - 10
pioneer/packages/page-contracts/src/constants.ts

@@ -1,10 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-staking authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-export const ENDOWMENT = 1000;
-export const GAS_LIMIT = '100000000000';
-export const CONTRACT_NULL = {
-  abi: null,
-  address: null
-};

+ 0 - 128
pioneer/packages/page-contracts/src/index.tsx

@@ -1,128 +0,0 @@
-// Copyright 2017-2020 @polkadot/app-contracts authors & contributors
-// This software may be modified and distributed under the terms
-// of the Apache-2.0 license. See the LICENSE file for details.
-
-import { AppProps as Props } from '@polkadot/react-components/types';
-import { TabItem } from '@polkadot/react-components/Tabs/types';
-import { ComponentProps } from './types';
-
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { Route, Switch } from 'react-router';
-import { HelpOverlay, Tabs } from '@polkadot/react-components';
-import { useAccounts, useContracts, useToggle } from '@polkadot/react-hooks';
-
-import introMd from './md/intro.md';
-import store from './store';
-import Contracts from './Contracts';
-import Codes from './Codes';
-import Deploy from './Deploy';
-import { useTranslation } from './translate';
-
-function ContractsApp ({ basePath, onStatusChange }: Props): React.ReactElement<Props> {
-  const { t } = useTranslation();
-  const { allAccounts } = useAccounts();
-  const { allContracts } = useContracts();
-  const [codeHash, setCodeHash] = useState<string | undefined>();
-  const [constructorIndex, setConstructorIndex] = useState(0);
-  const [isDeployOpen, toggleIsDeployOpen, setIsDeployOpen] = useToggle();
-  const [updated, setUpdated] = useState(0);
-  const [allCodes, setAllCodes] = useState(store.getAllCode());
-
-  const _triggerUpdate = useCallback(
-    (): void => {
-      setUpdated(Date.now());
-      setAllCodes(store.getAllCode());
-    },
-    []
-  );
-
-  const _onShowDeploy = useCallback(
-    (codeHash?: string, constructorIndex = 0): () => void =>
-      (): void => {
-        setCodeHash(codeHash || (allCodes && allCodes[0] ? allCodes[0].json.codeHash : undefined));
-        setConstructorIndex(constructorIndex);
-        toggleIsDeployOpen();
-      },
-    [allCodes, toggleIsDeployOpen]
-  );
-
-  const _onCloseDeploy = useCallback(
-    () => setIsDeployOpen(false),
-    [setIsDeployOpen]
-  );
-
-  const componentProps = useMemo(
-    (): ComponentProps => ({
-      accounts: allAccounts,
-      basePath,
-      contracts: allContracts,
-      hasCode: store.hasCode,
-      onShowDeploy: _onShowDeploy,
-      onStatusChange,
-      updated
-    }),
-    [allAccounts, allContracts, basePath, _onShowDeploy, onStatusChange, updated]
-  );
-
-  useEffect(
-    (): void => {
-      store.on('new-code', _triggerUpdate);
-      store.on('removed-code', _triggerUpdate);
-
-      store.loadAll()
-        .then((): void => setAllCodes(store.getAllCode()))
-        .catch((): void => {
-          // noop, handled internally
-        });
-    },
-    [_triggerUpdate]
-  );
-
-  const hidden: string[] = [];
-
-  return (
-    <main className='contracts--App'>
-      <HelpOverlay md={introMd as string} />
-      <header>
-        <Tabs
-          basePath={basePath}
-          hidden={hidden}
-          items={[
-            {
-              name: 'code',
-              text: 'Code'
-            },
-            {
-              isRoot: true,
-              name: 'contracts',
-              text: 'Contracts'
-            }
-          ].map((tab): TabItem => ({ ...tab, text: t(tab.text) }))
-          }
-        />
-      </header>
-      <Switch>
-        <Route path={`${basePath}/code`}>
-          <Codes {...componentProps} />
-        </Route>
-        <Route exact>
-          <Contracts {...componentProps} />
-        </Route>
-      </Switch>
-      {codeHash && (
-        <Deploy
-          allCodes={allCodes}
-          basePath={basePath}
-          codeHash={codeHash}
-          constructorIndex={constructorIndex}
-          isOpen={isDeployOpen}
-          onClose={_onCloseDeploy}
-          setCodeHash={setCodeHash}
-          setConstructorIndex={setConstructorIndex}
-        />
-      )}
-    </main>
-  );
-}
-
-export default React.memo(ContractsApp);

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