From 3688122b79b38fa9b2b4011a5dd37dda1fa5d945 Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Wed, 1 Sep 2021 10:17:37 +0000 Subject: [PATCH 1/7] feat: setup docker-compose with relay --- docker-compose/goloop2moonbeam/btp.share.env | 8 +- .../goloop2moonbeam/docker-compose.yml | 15 +- .../goloop2moonbeam/moonbeam/Dockerfile | 15 +- .../goloop2moonbeam/moonbeam/launch.ts | 501 ++++++++++++++++++ 4 files changed, 520 insertions(+), 19 deletions(-) create mode 100644 docker-compose/goloop2moonbeam/moonbeam/launch.ts diff --git a/docker-compose/goloop2moonbeam/btp.share.env b/docker-compose/goloop2moonbeam/btp.share.env index 53b0137e..9a58b339 100644 --- a/docker-compose/goloop2moonbeam/btp.share.env +++ b/docker-compose/goloop2moonbeam/btp.share.env @@ -1,5 +1,5 @@ GOLOOPCHAIN=goloop -RELAY_ENDPOINT=wss://kusama-rpc.polkadot.io -PARA_ENDPOINT=ws://moonbeam:9944 -MOONBEAM_RPC_URL=http://moonbeam:9933 -RELAY_CHAIN_OFFSET=8511058 +RELAY_ENDPOINT=wss://moonbeam:34002 +PARA_ENDPOINT=ws://moonbeam:34102 +MOONBEAM_RPC_URL=http://moonbeam:34101 +RELAY_CHAIN_OFFSET=2 diff --git a/docker-compose/goloop2moonbeam/docker-compose.yml b/docker-compose/goloop2moonbeam/docker-compose.yml index 4f51fcb1..e24a1bf6 100644 --- a/docker-compose/goloop2moonbeam/docker-compose.yml +++ b/docker-compose/goloop2moonbeam/docker-compose.yml @@ -19,16 +19,15 @@ services: container_name: g2m_moonbeam build: context: ./moonbeam - args: - MOONBEAM_VERSION: v0.9.6 logging: driver: none volumes: - - ${PWD}/data/moonbase_dev:/data/chains/moonbase_dev + - /var/run/docker.sock:/var/run/docker.sock ports: - - "9933:9933" - - "9944:9944" - command: ['--dev', '--ws-external', '--rpc-external', '--rpc-cors', 'all', '--base-path', '/data', '--ethapi', 'debug', '--sealing', '3000'] + - "34001:34001" # relay rpc + - "34002:34002" # relay ws + - "34101:34101" # para rpc + - "34102:34102" # para ws btp_icon: container_name: g2m_btp_icon build: @@ -50,7 +49,7 @@ services: - BTPSIMPLE_SRC_ADDRESS=/btpsimple/config/btp.icon - BTPSIMPLE_SRC_ENDPOINT=http://goloop:9080/api/v3/icon - BTPSIMPLE_DST_ADDRESS=/btpsimple/config/btp.moonbeam - - BTPSIMPLE_DST_ENDPOINT=http://moonbeam:9933 + - BTPSIMPLE_DST_ENDPOINT=http://moonbeam:34101 - BTPSIMPLE_OFFSET=/btpsimple/config/offset.icon - BTPSIMPLE_KEY_STORE=/btpsimple/config/moonbeam.keystore.json - BTPSIMPLE_KEY_SECRET=/btpsimple/config/moonbeam.keysecret @@ -74,7 +73,7 @@ services: - BTPSIMPLE_BASE_DIR=/btpsimple/data/btpsimple_moonbeam - BTPSIMPLE_CONFIG=/btpsimple/config/config.moonbeam.json - BTPSIMPLE_SRC_ADDRESS=/btpsimple/config/btp.moonbeam - - BTPSIMPLE_SRC_ENDPOINT=http://moonbeam:9933 + - BTPSIMPLE_SRC_ENDPOINT=http://moonbeam:34101 - BTPSIMPLE_DST_ADDRESS=/btpsimple/config/btp.icon - BTPSIMPLE_DST_ENDPOINT=http://goloop:9080/api/v3/icon - BTPSIMPLE_DST_OPTIONS="stepLimit=5000000000" diff --git a/docker-compose/goloop2moonbeam/moonbeam/Dockerfile b/docker-compose/goloop2moonbeam/moonbeam/Dockerfile index ba65c4ee..9c4fad38 100644 --- a/docker-compose/goloop2moonbeam/moonbeam/Dockerfile +++ b/docker-compose/goloop2moonbeam/moonbeam/Dockerfile @@ -1,10 +1,11 @@ -ARG MOONBEAM_VERSION=latest - -FROM debian:buster-slim as base -FROM purestake/moonbeam:${MOONBEAM_VERSION} +FROM node:lts-buster-slim USER root -COPY --from=base /usr/bin /usr/bin -RUN apt-get update && apt-get install -y curl +WORKDIR /root/moonbeam-launch +COPY . /root/moonbeam-launch +RUN apt-get update && apt-get install -y docker.io curl \ + && yarn + +CMD ["yarn", "launch", "--parachain", "moonriver-genesis"] -HEALTHCHECK --interval=3s --timeout=3s --start-period=5s --retries=10 CMD ["curl", "-f", "http://127.0.0.1:9933/health" ] \ No newline at end of file +HEALTHCHECK --interval=3s --timeout=3s --start-period=5s --retries=10 CMD ["curl", "-f", "http://127.0.0.1:34101/health" ] \ No newline at end of file diff --git a/docker-compose/goloop2moonbeam/moonbeam/launch.ts b/docker-compose/goloop2moonbeam/moonbeam/launch.ts new file mode 100644 index 00000000..bcaf02a5 --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/launch.ts @@ -0,0 +1,501 @@ +/** + * All rights reserved to https://github.com/PureStake/moonbeam/tree/v0.11.2/tools + */ + +/** + * Script to launch 2 relay and 2 parachain nodes. + * It contains pre-registered versions to allow easy run using Docker. + * + * ports can be given using --port-prefix xx (default 34) using the following rule: + * - relay 1 - p2p (p2p: XX000, rpcPort: XX001, wsPort: XX002) + * - relay 2 - p2p (p2p: XX010, rpcPort: XX011, wsPort: XX012) + * - para 1 - p2p (p2p: XX100, rpcPort: XX101, wsPort: XX102) + * - para 2 - p2p (p2p: XX110, rpcPort: XX111, wsPort: XX112) + * + */ + +import yargs from "yargs"; +import * as fs from "fs"; +import * as path from "path"; +import * as child_process from "child_process"; +import { killAll, run } from "polkadot-launch"; + +// Description of the network to launch +type NetworkConfig = { + // From which docker to take the binary + docker?: string; + // To use instead of docker to run local binary + binary?: string; + // What chain to run + chain: string; +}; + +// Description of the parachain network +type ParachainConfig = NetworkConfig & { + // Which relay (name) config to use + relay: string; +}; + +const parachains: { [name: string]: ParachainConfig } = { + "moonriver-genesis": { + relay: "kusama-9040", + chain: "moonriver-local", + docker: "purestake/moonbeam:moonriver-genesis", + }, + "moonriver-genesis-fast": { + relay: "rococo-9004", + chain: "moonriver-local", + docker: "purestake/moonbeam:sha-153c4c4a", + }, + "moonbase-0.8.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.2", + }, + "moonbase-0.8.1": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.1", + }, + "moonbase-0.8.0": { + relay: "rococo-9001", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.0", + }, + "moonbase-0.9.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.2", + }, + "moonbase-0.9.4": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.4", + }, + "moonbase-0.9.6": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.6", + }, + "moonbase-0.10.0": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.10.0", + }, + "moonbase-0.11.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.11.2", + }, + local: { + relay: "rococo-9004", + chain: "moonbase-local", + binary: "../target/release/moonbeam", + }, +}; +const parachainNames = Object.keys(parachains); + +const relays: { [name: string]: NetworkConfig } = { + "kusama-9030": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "kusama-local", + }, + "kusama-9040": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "kusama-local", + }, + "kusama-9030-fast": { + docker: "purestake/moonbase-relay-testnet:sha-832cc0af", + chain: "kusama-local", + }, + "kusama-9040-fast": { + docker: "purestake/moonbase-relay-testnet:sha-2239072e", + chain: "kusama-local", + }, + "rococo-9001": { + docker: "purestake/moonbase-relay-testnet:sha-86a45114", + chain: "rococo-local", + }, + "rococo-9003": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "rococo-local", + }, + "rococo-9004": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "rococo-local", + }, + "westend-9030": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "westend-local", + }, + "westend-9040": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "westend-local", + }, + local: { + binary: "../../polkadot/target/release/polkadot", + chain: "rococo-local", + }, +}; +const relayNames = Object.keys(relays); + +// We support 3 parachains for now +const validatorNames = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"]; + +function start() { + const argv = yargs(process.argv.slice(2)) + .usage("Usage: npm run launch [args]") + .version("1.0.0") + .options({ + parachain: { + type: "string", + choices: Object.keys(parachains), + default: "local", + describe: "which parachain configuration to run", + }, + "parachain-chain": { + type: "string", + describe: "overrides parachain chain/runtime", + }, + "parachain-id": { type: "number", default: 1000, describe: "overrides parachain-id" }, + relay: { + type: "string", + choices: Object.keys(relays), + describe: "overrides relay configuration", + }, + "relay-chain": { + type: "string", + choices: [ + "rococo", + "westend", + "kusama", + "polkadot", + "rococo-local", + "westend-local", + "kusama-local", + "polkadot-local", + ], + describe: "overrides relay chain/runtime", + }, + "port-prefix": { + type: "number", + default: 34, + check: (port) => port >= 0 && port <= 64, + describe: "provides port prefix for nodes", + }, + }) + .help().argv; + + const portPrefix = argv["port-prefix"] || 34; + const startingPort = portPrefix * 1000; + let paras = []; + let parasNames = []; + let parachainsChains = []; + let paraIds = []; + + // We start gathering all the information about the parachains + if (Array.isArray(argv["parachain-id"])) { + // We need two validators per parachain, so there is a maximum we can support + if (argv["parachain-id"].length * 2 > validatorNames.length) { + console.error(`Exceeded max number of paras: ${validatorNames.length / 2}`); + return; + } + for (let i = 0; i < argv["parachain-id"].length; i++) { + paraIds.push(argv["parachain-id"][i]); + } + } + + if (Array.isArray(argv.parachain)) { + for (let i = 0; i < argv.parachain.length; i++) { + if (i >= paraIds.length) { + // If no paraId was provided for all of them, we just start assigning defaults + // But if one of the defaults was assigned to a previous para, we error + if (paraIds.includes(1000 + i)) { + console.error(`Para id already included as default: ${1000 + i}`); + return; + } else { + paraIds.push(1000 + i); + } + } + const parachainName = argv.parachain[i].toString(); + parasNames.push(parachainName); + paras.push(parachains[parachainName]); + // If it is an array, push the position at which we are + if (Array.isArray(argv["parachain-chain"])) { + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } + // Else, push the value to the first parachain if it exists, else the default + else { + if (i == 0) { + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } else { + parachainsChains.push(parachains[parachainName].chain); + } + } + } + } + // If it is not an array, we just simply push it + else { + paraIds.push(argv["parachain-id"] || 1000); + const parachainName = argv.parachain.toString(); + parasNames.push(parachainName); + paras.push(parachains[parachainName]); + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } + + const relayName = argv.relay || paras[0].relay; + + if (!relayName || !relayNames.includes(relayName)) { + console.error(`Invalid relay name: ${relayName}`); + console.error(`Expected one of: ${relayNames.join(", ")}`); + return; + } + + const relay = relays[relayName]; + const relayChain = argv["relay-chain"] || relay.chain; + + console.log( + `๐Ÿš€ Relay: ${relayName.padEnd(20)} - ${relay.docker || relay.binary} (${relayChain})` + ); + + let parachainBinaries = []; + let parachainPaths = []; + + // We retrieve the binaries and paths for all parachains + for (let i = 0; i < paras.length; i++) { + if (paras[i].binary) { + parachainBinaries.push(paras[i].binary); + const parachainPath = path.join(__dirname, paras[i].binary); + if (!fs.existsSync(parachainPath)) { + console.log(` Missing ${parachainPath}`); + return; + } + parachainPaths.push(parachainPath); + } else { + if (process.platform != "linux") { + console.log( + `docker binaries are only supported on linux. Use "local" config for compiled binaries` + ); + return; + } + const parachainBinary = `build/${paras[i].parachainName}/moonbeam`; + const parachainPath = path.join(__dirname, `build/${paras[i].parachainName}/moonbeam`); + if (!fs.existsSync(parachainPath)) { + console.log(` Missing ${parachainBinary} locally, downloading it...`); + child_process.execSync(`mkdir -p ${path.dirname(parachainPath)} && \ + docker create --name moonbeam-tmp ${paras[i].docker} && \ + docker cp moonbeam-tmp:/moonbeam/moonbeam ${parachainPath} && \ + docker rm moonbeam-tmp`); + console.log(`${parachainBinary} downloaded !`); + parachainBinaries.push(parachainBinary); + parachainPaths.push(parachainPath); + } + } + console.log( + `๐Ÿš€ Parachain: ${parasNames[i].padEnd(20)} - ${paras[i].docker || paras[i].binary} (${parachainsChains[i] + })` + ); + } + + let relayBinary; + if (relay.binary) { + relayBinary = relay.binary; + const relayPath = path.join(__dirname, relay.binary); + if (!fs.existsSync(relayPath)) { + console.log(` Missing ${relayPath}`); + return; + } + } else { + if (process.platform != "linux") { + console.log( + `docker binaries are only supported on linux. Use "local" config for compiled binaries` + ); + return; + } + relayBinary = `build/${relayName}/polkadot`; + const relayPath = path.join(__dirname, `build/${relayName}/polkadot`); + if (!fs.existsSync(relayPath)) { + console.log(` Missing ${relayBinary} locally, downloading it...`); + child_process.execSync(`mkdir -p ${path.dirname(relayPath)} && \ + docker create --name polkadot-tmp ${relay.docker} && \ + docker cp polkadot-tmp:/usr/local/bin/polkadot ${relayPath} && \ + docker rm polkadot-tmp`); + console.log(` ${relayBinary} downloaded !`); + } + } + console.log(""); + + let launchConfig = launchTemplate; + launchConfig.relaychain.bin = relayBinary; + launchConfig.relaychain.chain = relayChain; + + let relay_nodes = []; + + // We need to build the configuration for each of the paras + for (let i = 0; i < parachainBinaries.length; i++) { + let relayNodeConfig = JSON.parse(JSON.stringify(relayNodeTemplate)); + let parachainConfig = JSON.parse(JSON.stringify(parachainTemplate)); + // HRMP is not configurable in Kusama and Westend thorugh genesis. We should detect this here + // Maybe there is a nicer way of doing this + if (launchConfig.relaychain.chain.startsWith("rococo")) { + // Create HRMP channels + // HRMP channels are uni-directonal, we need to create both ways + for (let j = 0; j < paraIds.length; j++) { + let hrmpConfig = JSON.parse(JSON.stringify(hrmpTemplate)); + if (j != i) { + hrmpConfig.sender = paraIds[i]; + hrmpConfig.recipient = paraIds[j]; + launchConfig.hrmpChannels.push(hrmpConfig); + } + } + } + + parachainConfig.bin = parachainBinaries[i]; + parachainConfig.chain = parachainsChains[i]; + parachainConfig.id = paraIds[i]; + parachainConfig.nodes[0].port = startingPort + 100 + i * 100; + parachainConfig.nodes[0].rpcPort = startingPort + 101 + i * 100; + parachainConfig.nodes[0].wsPort = startingPort + 102 + i * 100; + + parachainConfig.nodes[1].port = startingPort + 110 + i * 100; + parachainConfig.nodes[1].rpcPort = startingPort + 111 + i * 100; + parachainConfig.nodes[1].wsPort = startingPort + 112 + i * 100; + launchConfig.parachains.push(parachainConfig); + + // Two relay nodes per para + relayNodeConfig[0].name = validatorNames[i * 2]; + relayNodeConfig[0].port = startingPort + i * 10; + relayNodeConfig[0].rpcPort = startingPort + 1 + i * 10; + relayNodeConfig[0].wsPort = startingPort + 2 + i * 10; + relayNodeConfig[1].name = validatorNames[i * 2 + 1]; + relayNodeConfig[1].port = startingPort + i * 10; + relayNodeConfig[1].rpcPort = startingPort + 1 + i * 10; + relayNodeConfig[1].wsPort = startingPort + 1 + i * 10; + relay_nodes.push(relayNodeConfig[0]); + relay_nodes.push(relayNodeConfig[1]); + } + + launchConfig.relaychain.nodes = relay_nodes; + + const knownRelayChains = ["kusama", "westend", "rococo", "polkadot"] + .map((network) => [`${network}`, `${network}-local`, `${network}-dev`]) + .flat(); + + // In case the chain is a spec file + if (!knownRelayChains.includes(launchConfig.relaychain.chain)) { + delete launchConfig.relaychain.genesis; + } else if (launchConfig.relaychain.chain.startsWith("rococo")) { + // To support compatibility with rococo + (launchConfig.relaychain.genesis.runtime as any).runtime_genesis_config = { + ...launchConfig.relaychain.genesis.runtime, + }; + for (let key of Object.keys(launchConfig.relaychain.genesis.runtime)) { + if (key != "runtime_genesis_config") { + delete launchConfig.relaychain.genesis.runtime[key]; + } + } + } + + // Kill all processes when exiting. + process.on("exit", function () { + killAll(); + }); + + // Handle ctrl+c to trigger `exit`. + process.on("SIGINT", function () { + process.exit(2); + }); + + run(__dirname, launchConfig); +} + +const launchTemplate = { + relaychain: { + bin: "...", + chain: "...", + nodes: [], + genesis: { + runtime: { + parachainsConfiguration: { + config: { + validation_upgrade_frequency: 1, + validation_upgrade_delay: 1, + }, + }, + }, + }, + }, + parachains: [], + simpleParachains: [], + hrmpChannels: [], + types: { + Address: "MultiAddress", + LookupSource: "MultiAddress", + RoundIndex: "u32", + }, + finalization: true, +}; + +const relayNodeTemplate = [ + { + name: "alice", + port: 0, + rpcPort: 1, + wsPort: 2, + // basePath: "/data/relay1" + }, + { + name: "bob", + port: 10, + rpcPort: 11, + wsPort: 12, + // basePath: "/data/relay1" + }, +]; + +const parachainTemplate = { + bin: "...", + id: 1000, + balance: "1000000000000000000000", + chain: "...", + nodes: [ + { + port: 100, + rpcPort: 101, + wsPort: 102, + name: "alice", + // basePath: "/data/parachain1", + flags: [ + "--log=info,rpc=trace,evm=trace,ethereum=trace", + "--unsafe-rpc-external", + "--unsafe-ws-external", + "--rpc-cors=all", + "--", + "--execution=wasm", + ], + }, + { + port: 110, + rpcPort: 111, + wsPort: 112, + name: "bob", + // basePath: "/data/parachain2", + flags: [ + "--log=info,rpc=trace,evm=trace,ethereum=trace", + "--unsafe-rpc-external", + "--rpc-cors=all", + "--", + "--execution=wasm", + ], + }, + ], +}; + +const hrmpTemplate = { + sender: "200", + recipient: "300", + maxCapacity: 8, + maxMessageSize: 32768, +}; + +start(); \ No newline at end of file From 203e213d240fac0a49892f4349a27c0239d45986 Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Fri, 3 Sep 2021 02:47:28 +0000 Subject: [PATCH 2/7] fix: add missing files to install deps --- docker-compose/goloop2moonbeam/Makefile | 3 +- .../goloop2moonbeam/moonbeam/package.json | 19 + .../goloop2moonbeam/moonbeam/yarn.lock | 930 ++++++++++++++++++ 3 files changed, 950 insertions(+), 2 deletions(-) create mode 100644 docker-compose/goloop2moonbeam/moonbeam/package.json create mode 100644 docker-compose/goloop2moonbeam/moonbeam/yarn.lock diff --git a/docker-compose/goloop2moonbeam/Makefile b/docker-compose/goloop2moonbeam/Makefile index d50e152c..9d7ba359 100644 --- a/docker-compose/goloop2moonbeam/Makefile +++ b/docker-compose/goloop2moonbeam/Makefile @@ -1,7 +1,6 @@ clean: docker-compose down -v --remove-orphans - rm -rf data - rm -rf config + rm -rf data config build: docker-compose build diff --git a/docker-compose/goloop2moonbeam/moonbeam/package.json b/docker-compose/goloop2moonbeam/moonbeam/package.json new file mode 100644 index 00000000..ee14781e --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/package.json @@ -0,0 +1,19 @@ +{ + "name": "moonbeam-launch", + "version": "0.0.0", + "description": "launch moonbeam parachain and relay chain network locally", + "main": "launch.ts", + "dependencies": { + "polkadot-launch": "^1.7.0", + "ts-node": "^8.10.1", + "yargs": "^17.0.1" + }, + "devDependencies": { + "@types/yargs": "^15.0.12" + }, + "scripts": { + "launch": "ts-node launch" + }, + "author": "", + "license": "Apache-2.0" +} diff --git a/docker-compose/goloop2moonbeam/moonbeam/yarn.lock b/docker-compose/goloop2moonbeam/moonbeam/yarn.lock new file mode 100644 index 00000000..7a03f71d --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/yarn.lock @@ -0,0 +1,930 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/runtime@^7.14.6", "@babel/runtime@^7.15.3": + version "7.15.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b" + integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA== + dependencies: + regenerator-runtime "^0.13.4" + +"@polkadot/api-derive@4.17.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-4.17.1.tgz#7902ab73159f89a4f1a896ce856dd7377318d275" + integrity sha512-mgq57F1yAiZjuiA0vrR2zWidyyd+mGe7Kbs4SxVeDWLsNbLc9+eASIfX7Hch2SDHIn3CQpv6DQqJH00uDfw9Lw== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/api" "4.17.1" + "@polkadot/rpc-core" "4.17.1" + "@polkadot/types" "4.17.1" + "@polkadot/util" "^6.11.1" + "@polkadot/util-crypto" "^6.11.1" + "@polkadot/x-rxjs" "^6.11.1" + +"@polkadot/api@4.17.1", "@polkadot/api@^4.15.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-4.17.1.tgz#c9c8e7f5e33122aeb5b1345e43bc9579658720db" + integrity sha512-uuNIKWC+PjM+1AARRu4NLWOEudZE6DW8UOlaubx3uGhPywqPIP+HGWP2I6PqRGYKARBWxxOvca1Q7WoKzpYC8w== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/api-derive" "4.17.1" + "@polkadot/keyring" "^6.11.1" + "@polkadot/metadata" "4.17.1" + "@polkadot/rpc-core" "4.17.1" + "@polkadot/rpc-provider" "4.17.1" + "@polkadot/types" "4.17.1" + "@polkadot/types-known" "4.17.1" + "@polkadot/util" "^6.11.1" + "@polkadot/util-crypto" "^6.11.1" + "@polkadot/x-rxjs" "^6.11.1" + eventemitter3 "^4.0.7" + +"@polkadot/keyring@^6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-6.11.1.tgz#2510c349c965c74cc2f108f114f1048856940604" + integrity sha512-rW8INl7pO6Dmaffd6Df1yAYCRWa2RmWQ0LGfJeA/M6seVIkI6J3opZqAd4q2Op+h9a7z4TESQGk8yggOEL+Csg== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/util" "6.11.1" + "@polkadot/util-crypto" "6.11.1" + +"@polkadot/metadata@4.17.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@polkadot/metadata/-/metadata-4.17.1.tgz#4da9ee5b2b816493910abfd302a50b58141ceca2" + integrity sha512-219isiCWVfbu5JxZnOPj+cV4T+S0XHS4+Jal3t3xz9y4nbgr+25Pa4KInEsJPx0u8EZAxMeiUCX3vd5U7oe72g== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/types" "4.17.1" + "@polkadot/types-known" "4.17.1" + "@polkadot/util" "^6.11.1" + "@polkadot/util-crypto" "^6.11.1" + +"@polkadot/networks@6.11.1", "@polkadot/networks@^6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-6.11.1.tgz#8fd189593f6ee4f8bf64378d0aaae09e39a37d35" + integrity sha512-0C6Ha2kvr42se3Gevx6UhHzv3KnPHML0N73Amjwvdr4y0HLZ1Nfw+vcm5yqpz5gpiehqz97XqFrsPRauYdcksQ== + dependencies: + "@babel/runtime" "^7.14.6" + +"@polkadot/rpc-core@4.17.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-4.17.1.tgz#b9fa739fa98e4355fdc2b8d2b43b3a4b9d32dac4" + integrity sha512-1gqYaYuSSQsRmt3ol55jmjBP/euKyAh4PwSj94I2wu0fngK/FZwVZNDJZn/Ib68X/s38TBIgqJ6+YdUdr3z1xw== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/metadata" "4.17.1" + "@polkadot/rpc-provider" "4.17.1" + "@polkadot/types" "4.17.1" + "@polkadot/util" "^6.11.1" + "@polkadot/x-rxjs" "^6.11.1" + +"@polkadot/rpc-provider@4.17.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-4.17.1.tgz#1f99b8365d0f76f714f613423e6a1832b5d833b3" + integrity sha512-vlU1H5mnfP0Ej8PbjcxwF9ZlT7LtcpekOKI4iYfMnfdelSUKUVyaD5PC8yRGIg9fxkorA6OM5AZs116jAl3TLA== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/types" "4.17.1" + "@polkadot/util" "^6.11.1" + "@polkadot/util-crypto" "^6.11.1" + "@polkadot/x-fetch" "^6.11.1" + "@polkadot/x-global" "^6.11.1" + "@polkadot/x-ws" "^6.11.1" + eventemitter3 "^4.0.7" + +"@polkadot/types-known@4.17.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-4.17.1.tgz#71c18dda4967a13ec34fbbf0c4ef264e882c2688" + integrity sha512-YkOwGrO+k9aVrBR8FgYHnfJKhOfpdgC5ZRYNL/xJ9oa7lBYqPts9ENAxeBmJS/5IGeDF9f32MNyrCP2umeCXWg== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/networks" "^6.11.1" + "@polkadot/types" "4.17.1" + "@polkadot/util" "^6.11.1" + +"@polkadot/types@4.17.1": + version "4.17.1" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-4.17.1.tgz#41d43621d53820ee930ba4036bfa8b16cf98ca6f" + integrity sha512-rjW4OFdwvFekzN3ATLibC2JPSd8AWt5YepJhmuCPdwH26r3zB8bEC6dM7YQExLVUmygVPvgXk5ffHI6RAdXBMg== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/metadata" "4.17.1" + "@polkadot/util" "^6.11.1" + "@polkadot/util-crypto" "^6.11.1" + "@polkadot/x-rxjs" "^6.11.1" + +"@polkadot/util-crypto@6.11.1", "@polkadot/util-crypto@^6.11.1", "@polkadot/util-crypto@^6.9.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-6.11.1.tgz#7a36acf5c8bf52541609ec0b0b2a69af295d652e" + integrity sha512-fWA1Nz17FxWJslweZS4l0Uo30WXb5mYV1KEACVzM+BSZAvG5eoiOAYX6VYZjyw6/7u53XKrWQlD83iPsg3KvZw== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/networks" "6.11.1" + "@polkadot/util" "6.11.1" + "@polkadot/wasm-crypto" "^4.0.2" + "@polkadot/x-randomvalues" "6.11.1" + base-x "^3.0.8" + base64-js "^1.5.1" + blakejs "^1.1.1" + bn.js "^4.11.9" + create-hash "^1.2.0" + elliptic "^6.5.4" + hash.js "^1.1.7" + js-sha3 "^0.8.0" + scryptsy "^2.1.0" + tweetnacl "^1.0.3" + xxhashjs "^0.2.2" + +"@polkadot/util@6.11.1", "@polkadot/util@^6.11.1", "@polkadot/util@^6.9.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-6.11.1.tgz#8950b038ba3e6ebfc0a7ff47feeb972e81b2626c" + integrity sha512-TEdCetr9rsdUfJZqQgX/vxLuV4XU8KMoKBMJdx+JuQ5EWemIdQkEtMBdL8k8udNGbgSNiYFA6rPppATeIxAScg== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/x-textdecoder" "6.11.1" + "@polkadot/x-textencoder" "6.11.1" + "@types/bn.js" "^4.11.6" + bn.js "^4.11.9" + camelcase "^5.3.1" + ip-regex "^4.3.0" + +"@polkadot/wasm-crypto-asmjs@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-4.2.1.tgz#6b7eae1c011709f8042dfd30872a5fc5e9e021c0" + integrity sha512-ON9EBpTNDCI3QRUmuQJIegYoAcwvxDaNNA7uwKTaEEStu8LjCIbQxbt4WbOBYWI0PoUpl4iIluXdT3XZ3V3jXA== + dependencies: + "@babel/runtime" "^7.15.3" + +"@polkadot/wasm-crypto-wasm@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-4.2.1.tgz#2a86f9b405e7195c3f523798c6ce4afffd19737e" + integrity sha512-Rs2CKiR4D+2hKzmKBfPNYxcd2E8NfLWia0av4fgicjT9YsWIWOGQUi9AtSOfazPOR9FrjxKJy+chQxAkcfKMnQ== + dependencies: + "@babel/runtime" "^7.15.3" + +"@polkadot/wasm-crypto@^4.0.2": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-4.2.1.tgz#4d09402f5ac71a90962fb58cbe4b1707772a4fb6" + integrity sha512-C/A/QnemOilRTLnM0LfhPY2N/x3ZFd1ihm9sXYyuh98CxtekSVYI9h4IJ5Jrgz5imSUHgvt9oJLqJ5GbWQV/Zg== + dependencies: + "@babel/runtime" "^7.15.3" + "@polkadot/wasm-crypto-asmjs" "^4.2.1" + "@polkadot/wasm-crypto-wasm" "^4.2.1" + +"@polkadot/x-fetch@^6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-6.11.1.tgz#97d44d78ef0285eec6f6dbc4006302308ec8e24c" + integrity sha512-qJyLLnm+4SQEZ002UDz2wWnXbnnH84rIS0mLKZ5k82H4lMYY+PQflvzv6sbu463e/lgiEao+6zvWS6DSKv1Yog== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/x-global" "6.11.1" + "@types/node-fetch" "^2.5.10" + node-fetch "^2.6.1" + +"@polkadot/x-global@6.11.1", "@polkadot/x-global@^6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-6.11.1.tgz#c292b3825fea60e9b33fff1790323fc57de1ca5d" + integrity sha512-lsBK/e4KbjfieyRmnPs7bTiGbP/6EoCZz7rqD/voNS5qsJAaXgB9LR+ilubun9gK/TDpebyxgO+J19OBiQPIRw== + dependencies: + "@babel/runtime" "^7.14.6" + +"@polkadot/x-randomvalues@6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-6.11.1.tgz#f006fa250c8e82c92ccb769976a45a8e7f3df28b" + integrity sha512-2MfUfGZSOkuPt7GF5OJkPDbl4yORI64SUuKM25EGrJ22o1UyoBnPOClm9eYujLMD6BfDZRM/7bQqqoLW+NuHVw== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/x-global" "6.11.1" + +"@polkadot/x-rxjs@^6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-rxjs/-/x-rxjs-6.11.1.tgz#5454708b61da70eea05708611d9148fce9372498" + integrity sha512-zIciEmij7SUuXXg9g/683Irx6GogxivrQS2pgBir2DI/YZq+um52+Dqg1mqsEZt74N4KMTMnzAZAP6LJOBOMww== + dependencies: + "@babel/runtime" "^7.14.6" + rxjs "^6.6.7" + +"@polkadot/x-textdecoder@6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-6.11.1.tgz#6cc314645681cc4639085c03b65328671c7f182c" + integrity sha512-DI1Ym2lyDSS/UhnTT2e9WutukevFZ0WGpzj4eotuG2BTHN3e21uYtYTt24SlyRNMrWJf5+TkZItmZeqs1nwAfQ== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/x-global" "6.11.1" + +"@polkadot/x-textencoder@6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-6.11.1.tgz#73e89da5b91954ae380042c19314c90472f59d9e" + integrity sha512-8ipjWdEuqFo+R4Nxsc3/WW9CSEiprX4XU91a37ZyRVC4e9R1bmvClrpXmRQLVcAQyhRvG8DKOOtWbz8xM+oXKg== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/x-global" "6.11.1" + +"@polkadot/x-ws@^6.11.1": + version "6.11.1" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-6.11.1.tgz#338adc7309e3a8e660fce8eb42f975426da48d10" + integrity sha512-GNu4ywrMlVi0QF6QSpKwYWMK6JRK+kadgN/zEhMoH1z5h8LwpqDLv128j5WspWbQti2teCQtridjf7t2Lzoe8Q== + dependencies: + "@babel/runtime" "^7.14.6" + "@polkadot/x-global" "6.11.1" + "@types/websocket" "^1.0.3" + websocket "^1.0.34" + +"@types/bn.js@^4.11.6": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/node-fetch@^2.5.10": + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "16.7.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.10.tgz#7aa732cc47341c12a16b7d562f519c2383b6d4fc" + integrity sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA== + +"@types/websocket@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.4.tgz#1dc497280d8049a5450854dd698ee7e6ea9e60b8" + integrity sha512-qn1LkcFEKK8RPp459jkjzsfpbsx36BBt3oC3pITYtkoBw/aVX+EZFa5j3ThCRTNpLFvIMr5dSTD4RaMdilIOpA== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + +"@types/yargs@^15.0.12": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +base-x@^3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" + integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +blakejs@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" + integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== + +bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +bufferutil@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b" + integrity sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw== + dependencies: + node-gyp-build "^4.2.0" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +cipher-base@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +cuint@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" + integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +eventemitter3@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +ext@^1.1.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.5.0.tgz#e93b97ae0cb23f8370380f6107d2d2b7887687ad" + integrity sha512-+ONcYoWj/SoQwUofMr94aGu05Ou4FepKi7N7b+O8T4jVfyIsZQV1/xeS8jpaBzF0csAk0KLXoHCxU7cKYZjo1Q== + dependencies: + type "^2.5.0" + +filter-console@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/filter-console/-/filter-console-0.1.1.tgz#6242be28982bba7415bcc6db74a79f4a294fa67c" + integrity sha512-zrXoV1Uaz52DqPs+qEwNJWJFAWZpYJ47UNmpN9q4j+/EYsz85uV0DC9k8tRND5kYmoVzL0W+Y75q4Rg8sRJCdg== + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ip-regex@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" + integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mime-db@1.49.0: + version "1.49.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" + integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== + +mime-types@^2.1.12: + version "2.1.32" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" + integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== + dependencies: + mime-db "1.49.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-gyp-build@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" + integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +polkadot-launch@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/polkadot-launch/-/polkadot-launch-1.7.0.tgz#cb84d407b459d11f9b73ed5887e8a9bf29ddfd26" + integrity sha512-1zn87/erTmTM1BkS04M845IdBZMbxc5x57NeKFCOYR6geuRjoUpa+l6zDxjbWw4r8p/GR4hGdcpwioQAM0ZokA== + dependencies: + "@polkadot/api" "^4.15.1" + "@polkadot/util" "^6.9.1" + "@polkadot/util-crypto" "^6.9.1" + filter-console "^0.1.1" + typescript "^4.1.5" + yargs "^15.4.1" + yarn "^1.22.10" + +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rxjs@^6.6.7: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +scryptsy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790" + integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +sha.js@^2.4.0: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +source-map-support@^0.5.17: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +ts-node@^8.10.1: + version "8.10.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" + integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@^4.1.5: + version "4.4.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== + +utf-8-validate@^5.0.2: + version "5.0.5" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.5.tgz#dd32c2e82c72002dc9f02eb67ba6761f43456ca1" + integrity sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ== + dependencies: + node-gyp-build "^4.2.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +websocket@^1.0.34: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +xxhashjs@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/xxhashjs/-/xxhashjs-0.2.2.tgz#8a6251567621a1c46a5ae204da0249c7f8caa9d8" + integrity sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw== + dependencies: + cuint "^0.2.2" + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.0.1: + version "17.1.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.1.1.tgz#c2a8091564bdb196f7c0a67c1d12e5b85b8067ba" + integrity sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yarn@^1.22.10: + version "1.22.11" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.11.tgz#d0104043e7349046e0e2aec977c24be106925ed6" + integrity sha512-AWje4bzqO9RUn3sdnM5N8n4ZJ0BqCc/kqFJvpOI5/EVkINXui0yuvU7NDCEF//+WaxHuNay2uOHxA4+tq1P3cg== + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 308d083e68e12d3a681fd94f565799d36ee2c7e8 Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Tue, 7 Sep 2021 12:17:33 +0700 Subject: [PATCH 3/7] feat: use launch script from moonbeam v0.11.3 fix: error on rpcPort not set --- .../goloop2moonbeam/moonbeam/launch.ts | 965 +++++++++--------- 1 file changed, 482 insertions(+), 483 deletions(-) diff --git a/docker-compose/goloop2moonbeam/moonbeam/launch.ts b/docker-compose/goloop2moonbeam/moonbeam/launch.ts index bcaf02a5..111c817b 100644 --- a/docker-compose/goloop2moonbeam/moonbeam/launch.ts +++ b/docker-compose/goloop2moonbeam/moonbeam/launch.ts @@ -1,8 +1,6 @@ /** - * All rights reserved to https://github.com/PureStake/moonbeam/tree/v0.11.2/tools - */ - -/** + * All rights reserved to https://github.com/PureStake/moonbeam/tree/v0.11.3/tools + * * Script to launch 2 relay and 2 parachain nodes. * It contains pre-registered versions to allow easy run using Docker. * @@ -14,488 +12,489 @@ * */ -import yargs from "yargs"; -import * as fs from "fs"; -import * as path from "path"; -import * as child_process from "child_process"; -import { killAll, run } from "polkadot-launch"; - -// Description of the network to launch -type NetworkConfig = { - // From which docker to take the binary - docker?: string; - // To use instead of docker to run local binary - binary?: string; - // What chain to run - chain: string; -}; - -// Description of the parachain network -type ParachainConfig = NetworkConfig & { - // Which relay (name) config to use - relay: string; -}; - -const parachains: { [name: string]: ParachainConfig } = { - "moonriver-genesis": { - relay: "kusama-9040", - chain: "moonriver-local", - docker: "purestake/moonbeam:moonriver-genesis", - }, - "moonriver-genesis-fast": { - relay: "rococo-9004", - chain: "moonriver-local", - docker: "purestake/moonbeam:sha-153c4c4a", - }, - "moonbase-0.8.2": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.8.2", - }, - "moonbase-0.8.1": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.8.1", - }, - "moonbase-0.8.0": { - relay: "rococo-9001", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.8.0", - }, - "moonbase-0.9.2": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.9.2", - }, - "moonbase-0.9.4": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.9.4", - }, - "moonbase-0.9.6": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.9.6", - }, - "moonbase-0.10.0": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.10.0", - }, - "moonbase-0.11.2": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.11.2", - }, - local: { - relay: "rococo-9004", - chain: "moonbase-local", - binary: "../target/release/moonbeam", - }, -}; -const parachainNames = Object.keys(parachains); - -const relays: { [name: string]: NetworkConfig } = { - "kusama-9030": { - docker: "purestake/moonbase-relay-testnet:sha-aa386760", - chain: "kusama-local", - }, - "kusama-9040": { - docker: "purestake/moonbase-relay-testnet:sha-2f28561a", - chain: "kusama-local", - }, - "kusama-9030-fast": { - docker: "purestake/moonbase-relay-testnet:sha-832cc0af", - chain: "kusama-local", - }, - "kusama-9040-fast": { - docker: "purestake/moonbase-relay-testnet:sha-2239072e", - chain: "kusama-local", - }, - "rococo-9001": { - docker: "purestake/moonbase-relay-testnet:sha-86a45114", - chain: "rococo-local", - }, - "rococo-9003": { - docker: "purestake/moonbase-relay-testnet:sha-aa386760", - chain: "rococo-local", - }, - "rococo-9004": { - docker: "purestake/moonbase-relay-testnet:sha-2f28561a", - chain: "rococo-local", - }, - "westend-9030": { - docker: "purestake/moonbase-relay-testnet:sha-aa386760", - chain: "westend-local", - }, - "westend-9040": { - docker: "purestake/moonbase-relay-testnet:sha-2f28561a", - chain: "westend-local", - }, - local: { - binary: "../../polkadot/target/release/polkadot", - chain: "rococo-local", - }, -}; -const relayNames = Object.keys(relays); - -// We support 3 parachains for now -const validatorNames = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"]; - -function start() { - const argv = yargs(process.argv.slice(2)) - .usage("Usage: npm run launch [args]") - .version("1.0.0") - .options({ - parachain: { - type: "string", - choices: Object.keys(parachains), - default: "local", - describe: "which parachain configuration to run", - }, - "parachain-chain": { - type: "string", - describe: "overrides parachain chain/runtime", - }, - "parachain-id": { type: "number", default: 1000, describe: "overrides parachain-id" }, - relay: { - type: "string", - choices: Object.keys(relays), - describe: "overrides relay configuration", - }, - "relay-chain": { - type: "string", - choices: [ - "rococo", - "westend", - "kusama", - "polkadot", - "rococo-local", - "westend-local", - "kusama-local", - "polkadot-local", - ], - describe: "overrides relay chain/runtime", - }, - "port-prefix": { - type: "number", - default: 34, - check: (port) => port >= 0 && port <= 64, - describe: "provides port prefix for nodes", - }, - }) - .help().argv; - - const portPrefix = argv["port-prefix"] || 34; - const startingPort = portPrefix * 1000; - let paras = []; - let parasNames = []; - let parachainsChains = []; - let paraIds = []; - - // We start gathering all the information about the parachains - if (Array.isArray(argv["parachain-id"])) { - // We need two validators per parachain, so there is a maximum we can support - if (argv["parachain-id"].length * 2 > validatorNames.length) { - console.error(`Exceeded max number of paras: ${validatorNames.length / 2}`); - return; - } - for (let i = 0; i < argv["parachain-id"].length; i++) { - paraIds.push(argv["parachain-id"][i]); - } - } - - if (Array.isArray(argv.parachain)) { - for (let i = 0; i < argv.parachain.length; i++) { - if (i >= paraIds.length) { - // If no paraId was provided for all of them, we just start assigning defaults - // But if one of the defaults was assigned to a previous para, we error - if (paraIds.includes(1000 + i)) { - console.error(`Para id already included as default: ${1000 + i}`); - return; - } else { - paraIds.push(1000 + i); - } - } - const parachainName = argv.parachain[i].toString(); - parasNames.push(parachainName); - paras.push(parachains[parachainName]); - // If it is an array, push the position at which we are - if (Array.isArray(argv["parachain-chain"])) { - parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); - } - // Else, push the value to the first parachain if it exists, else the default - else { - if (i == 0) { - parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); - } else { - parachainsChains.push(parachains[parachainName].chain); - } - } - } - } - // If it is not an array, we just simply push it - else { - paraIds.push(argv["parachain-id"] || 1000); - const parachainName = argv.parachain.toString(); - parasNames.push(parachainName); - paras.push(parachains[parachainName]); - parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); - } - - const relayName = argv.relay || paras[0].relay; - - if (!relayName || !relayNames.includes(relayName)) { - console.error(`Invalid relay name: ${relayName}`); - console.error(`Expected one of: ${relayNames.join(", ")}`); - return; - } - - const relay = relays[relayName]; - const relayChain = argv["relay-chain"] || relay.chain; - - console.log( - `๐Ÿš€ Relay: ${relayName.padEnd(20)} - ${relay.docker || relay.binary} (${relayChain})` - ); - - let parachainBinaries = []; - let parachainPaths = []; - - // We retrieve the binaries and paths for all parachains - for (let i = 0; i < paras.length; i++) { - if (paras[i].binary) { - parachainBinaries.push(paras[i].binary); - const parachainPath = path.join(__dirname, paras[i].binary); - if (!fs.existsSync(parachainPath)) { - console.log(` Missing ${parachainPath}`); - return; - } - parachainPaths.push(parachainPath); - } else { - if (process.platform != "linux") { - console.log( - `docker binaries are only supported on linux. Use "local" config for compiled binaries` - ); - return; - } - const parachainBinary = `build/${paras[i].parachainName}/moonbeam`; - const parachainPath = path.join(__dirname, `build/${paras[i].parachainName}/moonbeam`); - if (!fs.existsSync(parachainPath)) { - console.log(` Missing ${parachainBinary} locally, downloading it...`); - child_process.execSync(`mkdir -p ${path.dirname(parachainPath)} && \ + import yargs from "yargs"; + import * as fs from "fs"; + import * as path from "path"; + import * as child_process from "child_process"; + import { killAll, run } from "polkadot-launch"; + + // Description of the network to launch + type NetworkConfig = { + // From which docker to take the binary + docker?: string; + // To use instead of docker to run local binary + binary?: string; + // What chain to run + chain: string; + }; + + // Description of the parachain network + type ParachainConfig = NetworkConfig & { + // Which relay (name) config to use + relay: string; + }; + + const parachains: { [name: string]: ParachainConfig } = { + "moonriver-genesis": { + relay: "kusama-9040", + chain: "moonriver-local", + docker: "purestake/moonbeam:moonriver-genesis", + }, + "moonriver-genesis-fast": { + relay: "rococo-9004", + chain: "moonriver-local", + docker: "purestake/moonbeam:sha-153c4c4a", + }, + "moonbase-0.8.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.2", + }, + "moonbase-0.8.1": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.1", + }, + "moonbase-0.8.0": { + relay: "rococo-9001", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.0", + }, + "moonbase-0.9.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.2", + }, + "moonbase-0.9.4": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.4", + }, + "moonbase-0.9.6": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.6", + }, + "moonbase-0.10.0": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.10.0", + }, + "moonbase-0.11.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.11.2", + }, + local: { + relay: "rococo-9004", + chain: "moonbase-local", + binary: "../target/release/moonbeam", + }, + }; + const parachainNames = Object.keys(parachains); + + const relays: { [name: string]: NetworkConfig } = { + "kusama-9030": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "kusama-local", + }, + "kusama-9040": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "kusama-local", + }, + "kusama-9030-fast": { + docker: "purestake/moonbase-relay-testnet:sha-832cc0af", + chain: "kusama-local", + }, + "kusama-9040-fast": { + docker: "purestake/moonbase-relay-testnet:sha-2239072e", + chain: "kusama-local", + }, + "rococo-9001": { + docker: "purestake/moonbase-relay-testnet:sha-86a45114", + chain: "rococo-local", + }, + "rococo-9003": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "rococo-local", + }, + "rococo-9004": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "rococo-local", + }, + "westend-9030": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "westend-local", + }, + "westend-9040": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "westend-local", + }, + local: { + binary: "../../polkadot/target/release/polkadot", + chain: "rococo-local", + }, + }; + const relayNames = Object.keys(relays); + + // We support 3 parachains for now + const validatorNames = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"]; + + function start() { + const argv = yargs(process.argv.slice(2)) + .usage("Usage: npm run launch [args]") + .version("1.0.0") + .options({ + parachain: { + type: "string", + choices: parachainNames, + default: "local", + describe: "which parachain configuration to run", + }, + "parachain-chain": { + type: "string", + describe: "overrides parachain chain/runtime", + }, + "parachain-id": { type: "number", default: 1000, describe: "overrides parachain-id" }, + relay: { + type: "string", + choices: relayNames, + describe: "overrides relay configuration", + }, + "relay-chain": { + type: "string", + choices: [ + "rococo", + "westend", + "kusama", + "polkadot", + "rococo-local", + "westend-local", + "kusama-local", + "polkadot-local", + ], + describe: "overrides relay chain/runtime", + }, + "port-prefix": { + type: "number", + default: 34, + check: (port) => port >= 0 && port <= 64, + describe: "provides port prefix for nodes", + }, + }) + .help().argv; + + const portPrefix = argv["port-prefix"] || 34; + const startingPort = portPrefix * 1000; + let paras = []; + let parasNames = []; + let parachainsChains = []; + let paraIds = []; + + // We start gathering all the information about the parachains + if (Array.isArray(argv["parachain-id"])) { + // We need two validators per parachain, so there is a maximum we can support + if (argv["parachain-id"].length * 2 > validatorNames.length) { + console.error(`Exceeded max number of paras: ${validatorNames.length / 2}`); + return; + } + for (let i = 0; i < argv["parachain-id"].length; i++) { + paraIds.push(argv["parachain-id"][i]); + } + } + + if (Array.isArray(argv.parachain)) { + for (let i = 0; i < argv.parachain.length; i++) { + if (i >= paraIds.length) { + // If no paraId was provided for all of them, we just start assigning defaults + // But if one of the defaults was assigned to a previous para, we error + if (paraIds.includes(1000 + i)) { + console.error(`Para id already included as default: ${1000 + i}`); + return; + } else { + paraIds.push(1000 + i); + } + } + const parachainName = argv.parachain[i].toString(); + parasNames.push(parachainName); + paras.push(parachains[parachainName]); + // If it is an array, push the position at which we are + if (Array.isArray(argv["parachain-chain"])) { + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } + // Else, push the value to the first parachain if it exists, else the default + else { + if (i == 0) { + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } else { + parachainsChains.push(parachains[parachainName].chain); + } + } + } + } + // If it is not an array, we just simply push it + else { + paraIds.push(argv["parachain-id"] || 1000); + const parachainName = argv.parachain.toString(); + parasNames.push(parachainName); + paras.push(parachains[parachainName]); + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } + + const relayName = argv.relay || paras[0].relay; + + if (!relayName || !relayNames.includes(relayName)) { + console.error(`Invalid relay name: ${relayName}`); + console.error(`Expected one of: ${relayNames.join(", ")}`); + return; + } + + const relay = relays[relayName]; + const relayChain = argv["relay-chain"] || relay.chain; + + console.log( + `๐Ÿš€ Relay: ${relayName.padEnd(20)} - ${relay.docker || relay.binary} (${relayChain})` + ); + + let parachainBinaries = []; + let parachainPaths = []; + + // We retrieve the binaries and paths for all parachains + for (let i = 0; i < paras.length; i++) { + if (paras[i].binary) { + parachainBinaries.push(paras[i].binary); + const parachainPath = path.join(__dirname, paras[i].binary); + if (!fs.existsSync(parachainPath)) { + console.log(` Missing ${parachainPath}`); + return; + } + parachainPaths.push(parachainPath); + } else { + if (process.platform != "linux") { + console.log( + `docker binaries are only supported on linux. Use "local" config for compiled binaries` + ); + return; + } + const parachainBinary = `build/${parasNames[i]}/moonbeam`; + const parachainPath = path.join(__dirname, parachainBinary); + if (!fs.existsSync(parachainPath)) { + console.log(` Missing ${parachainBinary} locally, downloading it...`); + child_process.execSync(`mkdir -p ${path.dirname(parachainPath)} && \ docker create --name moonbeam-tmp ${paras[i].docker} && \ docker cp moonbeam-tmp:/moonbeam/moonbeam ${parachainPath} && \ docker rm moonbeam-tmp`); - console.log(`${parachainBinary} downloaded !`); - parachainBinaries.push(parachainBinary); - parachainPaths.push(parachainPath); - } - } - console.log( - `๐Ÿš€ Parachain: ${parasNames[i].padEnd(20)} - ${paras[i].docker || paras[i].binary} (${parachainsChains[i] - })` - ); - } - - let relayBinary; - if (relay.binary) { - relayBinary = relay.binary; - const relayPath = path.join(__dirname, relay.binary); - if (!fs.existsSync(relayPath)) { - console.log(` Missing ${relayPath}`); - return; - } - } else { - if (process.platform != "linux") { - console.log( - `docker binaries are only supported on linux. Use "local" config for compiled binaries` - ); - return; - } - relayBinary = `build/${relayName}/polkadot`; - const relayPath = path.join(__dirname, `build/${relayName}/polkadot`); - if (!fs.existsSync(relayPath)) { - console.log(` Missing ${relayBinary} locally, downloading it...`); - child_process.execSync(`mkdir -p ${path.dirname(relayPath)} && \ + console.log(`${parachainBinary} downloaded !`); + } + parachainBinaries.push(parachainBinary); + parachainPaths.push(parachainPath); + } + console.log( + `๐Ÿš€ Parachain: ${parasNames[i].padEnd(20)} - ${paras[i].docker || paras[i].binary} (${ + parachainsChains[i] + })` + ); + } + + let relayBinary; + if (relay.binary) { + relayBinary = relay.binary; + const relayPath = path.join(__dirname, relay.binary); + if (!fs.existsSync(relayPath)) { + console.log(` Missing ${relayPath}`); + return; + } + } else { + if (process.platform != "linux") { + console.log( + `docker binaries are only supported on linux. Use "local" config for compiled binaries` + ); + return; + } + relayBinary = `build/${relayName}/polkadot`; + const relayPath = path.join(__dirname, `build/${relayName}/polkadot`); + if (!fs.existsSync(relayPath)) { + console.log(` Missing ${relayBinary} locally, downloading it...`); + child_process.execSync(`mkdir -p ${path.dirname(relayPath)} && \ docker create --name polkadot-tmp ${relay.docker} && \ docker cp polkadot-tmp:/usr/local/bin/polkadot ${relayPath} && \ docker rm polkadot-tmp`); - console.log(` ${relayBinary} downloaded !`); - } - } - console.log(""); - - let launchConfig = launchTemplate; - launchConfig.relaychain.bin = relayBinary; - launchConfig.relaychain.chain = relayChain; - - let relay_nodes = []; - - // We need to build the configuration for each of the paras - for (let i = 0; i < parachainBinaries.length; i++) { - let relayNodeConfig = JSON.parse(JSON.stringify(relayNodeTemplate)); - let parachainConfig = JSON.parse(JSON.stringify(parachainTemplate)); - // HRMP is not configurable in Kusama and Westend thorugh genesis. We should detect this here - // Maybe there is a nicer way of doing this - if (launchConfig.relaychain.chain.startsWith("rococo")) { - // Create HRMP channels - // HRMP channels are uni-directonal, we need to create both ways - for (let j = 0; j < paraIds.length; j++) { - let hrmpConfig = JSON.parse(JSON.stringify(hrmpTemplate)); - if (j != i) { - hrmpConfig.sender = paraIds[i]; - hrmpConfig.recipient = paraIds[j]; - launchConfig.hrmpChannels.push(hrmpConfig); - } - } - } - - parachainConfig.bin = parachainBinaries[i]; - parachainConfig.chain = parachainsChains[i]; - parachainConfig.id = paraIds[i]; - parachainConfig.nodes[0].port = startingPort + 100 + i * 100; - parachainConfig.nodes[0].rpcPort = startingPort + 101 + i * 100; - parachainConfig.nodes[0].wsPort = startingPort + 102 + i * 100; - - parachainConfig.nodes[1].port = startingPort + 110 + i * 100; - parachainConfig.nodes[1].rpcPort = startingPort + 111 + i * 100; - parachainConfig.nodes[1].wsPort = startingPort + 112 + i * 100; - launchConfig.parachains.push(parachainConfig); - - // Two relay nodes per para - relayNodeConfig[0].name = validatorNames[i * 2]; - relayNodeConfig[0].port = startingPort + i * 10; - relayNodeConfig[0].rpcPort = startingPort + 1 + i * 10; - relayNodeConfig[0].wsPort = startingPort + 2 + i * 10; - relayNodeConfig[1].name = validatorNames[i * 2 + 1]; - relayNodeConfig[1].port = startingPort + i * 10; - relayNodeConfig[1].rpcPort = startingPort + 1 + i * 10; - relayNodeConfig[1].wsPort = startingPort + 1 + i * 10; - relay_nodes.push(relayNodeConfig[0]); - relay_nodes.push(relayNodeConfig[1]); - } - - launchConfig.relaychain.nodes = relay_nodes; - - const knownRelayChains = ["kusama", "westend", "rococo", "polkadot"] - .map((network) => [`${network}`, `${network}-local`, `${network}-dev`]) - .flat(); - - // In case the chain is a spec file - if (!knownRelayChains.includes(launchConfig.relaychain.chain)) { - delete launchConfig.relaychain.genesis; - } else if (launchConfig.relaychain.chain.startsWith("rococo")) { - // To support compatibility with rococo - (launchConfig.relaychain.genesis.runtime as any).runtime_genesis_config = { - ...launchConfig.relaychain.genesis.runtime, - }; - for (let key of Object.keys(launchConfig.relaychain.genesis.runtime)) { - if (key != "runtime_genesis_config") { - delete launchConfig.relaychain.genesis.runtime[key]; - } - } - } - - // Kill all processes when exiting. - process.on("exit", function () { - killAll(); - }); - - // Handle ctrl+c to trigger `exit`. - process.on("SIGINT", function () { - process.exit(2); - }); - - run(__dirname, launchConfig); -} - -const launchTemplate = { - relaychain: { - bin: "...", - chain: "...", - nodes: [], - genesis: { - runtime: { - parachainsConfiguration: { - config: { - validation_upgrade_frequency: 1, - validation_upgrade_delay: 1, - }, - }, - }, - }, - }, - parachains: [], - simpleParachains: [], - hrmpChannels: [], - types: { - Address: "MultiAddress", - LookupSource: "MultiAddress", - RoundIndex: "u32", - }, - finalization: true, -}; - -const relayNodeTemplate = [ - { - name: "alice", - port: 0, - rpcPort: 1, - wsPort: 2, - // basePath: "/data/relay1" - }, - { - name: "bob", - port: 10, - rpcPort: 11, - wsPort: 12, - // basePath: "/data/relay1" - }, -]; - -const parachainTemplate = { - bin: "...", - id: 1000, - balance: "1000000000000000000000", - chain: "...", - nodes: [ - { - port: 100, - rpcPort: 101, - wsPort: 102, - name: "alice", - // basePath: "/data/parachain1", - flags: [ - "--log=info,rpc=trace,evm=trace,ethereum=trace", - "--unsafe-rpc-external", - "--unsafe-ws-external", - "--rpc-cors=all", - "--", - "--execution=wasm", - ], - }, - { - port: 110, - rpcPort: 111, - wsPort: 112, - name: "bob", - // basePath: "/data/parachain2", - flags: [ - "--log=info,rpc=trace,evm=trace,ethereum=trace", - "--unsafe-rpc-external", - "--rpc-cors=all", - "--", - "--execution=wasm", - ], - }, - ], -}; - -const hrmpTemplate = { - sender: "200", - recipient: "300", - maxCapacity: 8, - maxMessageSize: 32768, -}; - -start(); \ No newline at end of file + console.log(` ${relayBinary} downloaded !`); + } + } + console.log(""); + + let launchConfig = launchTemplate; + launchConfig.relaychain.bin = relayBinary; + launchConfig.relaychain.chain = relayChain; + + let relay_nodes = []; + // We need to build the configuration for each of the paras + for (let i = 0; i < parachainBinaries.length; i++) { + let relayNodeConfig = JSON.parse(JSON.stringify(relayNodeTemplate)); + let parachainConfig = JSON.parse(JSON.stringify(parachainTemplate)); + // HRMP is not configurable in Kusama and Westend thorugh genesis. We should detect this here + // Maybe there is a nicer way of doing this + if (launchConfig.relaychain.chain.startsWith("rococo")) { + // Create HRMP channels + // HRMP channels are uni-directonal, we need to create both ways + for (let j = 0; j < paraIds.length; j++) { + let hrmpConfig = JSON.parse(JSON.stringify(hrmpTemplate)); + if (j != i) { + hrmpConfig.sender = paraIds[i]; + hrmpConfig.recipient = paraIds[j]; + launchConfig.hrmpChannels.push(hrmpConfig); + } + } + } + + parachainConfig.bin = parachainBinaries[i]; + parachainConfig.chain = parachainsChains[i]; + parachainConfig.id = paraIds[i]; + parachainConfig.nodes[0].port = startingPort + 100 + i * 100; + parachainConfig.nodes[0].rpcPort = startingPort + 101 + i * 100; + parachainConfig.nodes[0].wsPort = startingPort + 102 + i * 100; + parachainConfig.nodes[0].flags.unshift(`--rpc-port=${parachainConfig.nodes[0].rpcPort}`) + + parachainConfig.nodes[1].port = startingPort + 110 + i * 100; + parachainConfig.nodes[1].rpcPort = startingPort + 111 + i * 100; + parachainConfig.nodes[1].wsPort = startingPort + 112 + i * 100; + parachainConfig.nodes[1].flags.unshift(`--rpc-port=${parachainConfig.nodes[1].rpcPort}`) + launchConfig.parachains.push(parachainConfig); + + // Two relay nodes per para + relayNodeConfig[0].name = validatorNames[i * 2]; + relayNodeConfig[0].port = startingPort + i * 10; + relayNodeConfig[0].rpcPort = startingPort + 1 + i * 10; + relayNodeConfig[0].wsPort = startingPort + 2 + i * 10; + relayNodeConfig[1].name = validatorNames[i * 2 + 1]; + relayNodeConfig[1].port = startingPort + i * 10; + relayNodeConfig[1].rpcPort = startingPort + 1 + i * 10; + relayNodeConfig[1].wsPort = startingPort + 1 + i * 10; + relayNodeConfig[0].flags.push(`--rpc-port=${relayNodeConfig[0].rpcPort}`) + relayNodeConfig[1].flags.push(`--rpc-port=${relayNodeConfig[1].rpcPort}`) + relay_nodes.push(relayNodeConfig[0]); + relay_nodes.push(relayNodeConfig[1]); + } + + launchConfig.relaychain.nodes = relay_nodes; + + const knownRelayChains = ["kusama", "westend", "rococo", "polkadot"] + .map((network) => [`${network}`, `${network}-local`, `${network}-dev`]) + .flat(); + + // In case the chain is a spec file + if (!knownRelayChains.includes(launchConfig.relaychain.chain)) { + delete launchConfig.relaychain.genesis; + } else if (launchConfig.relaychain.chain.startsWith("rococo")) { + // To support compatibility with rococo + (launchConfig.relaychain.genesis.runtime as any).runtime_genesis_config = { + ...launchConfig.relaychain.genesis.runtime, + }; + for (let key of Object.keys(launchConfig.relaychain.genesis.runtime)) { + if (key != "runtime_genesis_config") { + delete launchConfig.relaychain.genesis.runtime[key]; + } + } + } + + // Kill all processes when exiting. + process.on("exit", function () { + killAll(); + }); + + // Handle ctrl+c to trigger `exit`. + process.on("SIGINT", function () { + process.exit(2); + }); + + run(__dirname, launchConfig); + } + + const launchTemplate = { + relaychain: { + bin: "...", + chain: "...", + nodes: [], + genesis: { + runtime: { + parachainsConfiguration: { + config: { + validation_upgrade_frequency: 1, + validation_upgrade_delay: 1, + }, + }, + }, + }, + }, + parachains: [], + simpleParachains: [], + hrmpChannels: [], + types: { + Address: "MultiAddress", + LookupSource: "MultiAddress", + RoundIndex: "u32", + }, + finalization: true, + }; + + const relayNodeTemplate = [ + { + name: "alice", + port: 0, + rpcPort: 1, + wsPort: 2, + flags: [], + }, + { + name: "bob", + port: 10, + rpcPort: 11, + wsPort: 12, + flags: [], + }, + ]; + + const parachainTemplate = { + bin: "...", + id: 1000, + balance: "1000000000000000000000", + chain: "...", + nodes: [ + { + port: 100, + rpcPort: 101, + wsPort: 102, + name: "alice", + flags: [ + "--log=info,rpc=trace,evm=trace,ethereum=trace", + "--unsafe-rpc-external", + "--rpc-cors=all", + "--", + "--execution=wasm", + ], + }, + { + port: 110, + rpcPort: 111, + wsPort: 112, + name: "bob", + flags: [ + "--log=info,rpc=trace,evm=trace,ethereum=trace", + "--unsafe-rpc-external", + "--rpc-cors=all", + "--", + "--execution=wasm", + ], + }, + ], + }; + + const hrmpTemplate = { + sender: "200", + recipient: "300", + maxCapacity: 8, + maxMessageSize: 32768, + }; + + start(); \ No newline at end of file From a0669c082a71163bef8e570a82f201fd7cf60b1f Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Tue, 7 Sep 2021 14:11:36 +0700 Subject: [PATCH 4/7] fmt --- .../goloop2moonbeam/moonbeam/launch.ts | 959 +++++++++--------- 1 file changed, 479 insertions(+), 480 deletions(-) diff --git a/docker-compose/goloop2moonbeam/moonbeam/launch.ts b/docker-compose/goloop2moonbeam/moonbeam/launch.ts index 111c817b..bb7fd77b 100644 --- a/docker-compose/goloop2moonbeam/moonbeam/launch.ts +++ b/docker-compose/goloop2moonbeam/moonbeam/launch.ts @@ -12,489 +12,488 @@ * */ - import yargs from "yargs"; - import * as fs from "fs"; - import * as path from "path"; - import * as child_process from "child_process"; - import { killAll, run } from "polkadot-launch"; - - // Description of the network to launch - type NetworkConfig = { - // From which docker to take the binary - docker?: string; - // To use instead of docker to run local binary - binary?: string; - // What chain to run - chain: string; - }; - - // Description of the parachain network - type ParachainConfig = NetworkConfig & { - // Which relay (name) config to use - relay: string; - }; - - const parachains: { [name: string]: ParachainConfig } = { - "moonriver-genesis": { - relay: "kusama-9040", - chain: "moonriver-local", - docker: "purestake/moonbeam:moonriver-genesis", - }, - "moonriver-genesis-fast": { - relay: "rococo-9004", - chain: "moonriver-local", - docker: "purestake/moonbeam:sha-153c4c4a", - }, - "moonbase-0.8.2": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.8.2", - }, - "moonbase-0.8.1": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.8.1", - }, - "moonbase-0.8.0": { - relay: "rococo-9001", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.8.0", - }, - "moonbase-0.9.2": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.9.2", - }, - "moonbase-0.9.4": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.9.4", - }, - "moonbase-0.9.6": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.9.6", - }, - "moonbase-0.10.0": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.10.0", - }, - "moonbase-0.11.2": { - relay: "rococo-9004", - chain: "moonbase-local", - docker: "purestake/moonbeam:v0.11.2", - }, - local: { - relay: "rococo-9004", - chain: "moonbase-local", - binary: "../target/release/moonbeam", - }, - }; - const parachainNames = Object.keys(parachains); - - const relays: { [name: string]: NetworkConfig } = { - "kusama-9030": { - docker: "purestake/moonbase-relay-testnet:sha-aa386760", - chain: "kusama-local", - }, - "kusama-9040": { - docker: "purestake/moonbase-relay-testnet:sha-2f28561a", - chain: "kusama-local", - }, - "kusama-9030-fast": { - docker: "purestake/moonbase-relay-testnet:sha-832cc0af", - chain: "kusama-local", - }, - "kusama-9040-fast": { - docker: "purestake/moonbase-relay-testnet:sha-2239072e", - chain: "kusama-local", - }, - "rococo-9001": { - docker: "purestake/moonbase-relay-testnet:sha-86a45114", - chain: "rococo-local", - }, - "rococo-9003": { - docker: "purestake/moonbase-relay-testnet:sha-aa386760", - chain: "rococo-local", - }, - "rococo-9004": { - docker: "purestake/moonbase-relay-testnet:sha-2f28561a", - chain: "rococo-local", - }, - "westend-9030": { - docker: "purestake/moonbase-relay-testnet:sha-aa386760", - chain: "westend-local", - }, - "westend-9040": { - docker: "purestake/moonbase-relay-testnet:sha-2f28561a", - chain: "westend-local", - }, - local: { - binary: "../../polkadot/target/release/polkadot", - chain: "rococo-local", - }, - }; - const relayNames = Object.keys(relays); - - // We support 3 parachains for now - const validatorNames = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"]; - - function start() { - const argv = yargs(process.argv.slice(2)) - .usage("Usage: npm run launch [args]") - .version("1.0.0") - .options({ - parachain: { - type: "string", - choices: parachainNames, - default: "local", - describe: "which parachain configuration to run", - }, - "parachain-chain": { - type: "string", - describe: "overrides parachain chain/runtime", - }, - "parachain-id": { type: "number", default: 1000, describe: "overrides parachain-id" }, - relay: { - type: "string", - choices: relayNames, - describe: "overrides relay configuration", - }, - "relay-chain": { - type: "string", - choices: [ - "rococo", - "westend", - "kusama", - "polkadot", - "rococo-local", - "westend-local", - "kusama-local", - "polkadot-local", - ], - describe: "overrides relay chain/runtime", - }, - "port-prefix": { - type: "number", - default: 34, - check: (port) => port >= 0 && port <= 64, - describe: "provides port prefix for nodes", - }, - }) - .help().argv; - - const portPrefix = argv["port-prefix"] || 34; - const startingPort = portPrefix * 1000; - let paras = []; - let parasNames = []; - let parachainsChains = []; - let paraIds = []; - - // We start gathering all the information about the parachains - if (Array.isArray(argv["parachain-id"])) { - // We need two validators per parachain, so there is a maximum we can support - if (argv["parachain-id"].length * 2 > validatorNames.length) { - console.error(`Exceeded max number of paras: ${validatorNames.length / 2}`); - return; - } - for (let i = 0; i < argv["parachain-id"].length; i++) { - paraIds.push(argv["parachain-id"][i]); - } - } - - if (Array.isArray(argv.parachain)) { - for (let i = 0; i < argv.parachain.length; i++) { - if (i >= paraIds.length) { - // If no paraId was provided for all of them, we just start assigning defaults - // But if one of the defaults was assigned to a previous para, we error - if (paraIds.includes(1000 + i)) { - console.error(`Para id already included as default: ${1000 + i}`); - return; - } else { - paraIds.push(1000 + i); - } - } - const parachainName = argv.parachain[i].toString(); - parasNames.push(parachainName); - paras.push(parachains[parachainName]); - // If it is an array, push the position at which we are - if (Array.isArray(argv["parachain-chain"])) { - parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); - } - // Else, push the value to the first parachain if it exists, else the default - else { - if (i == 0) { - parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); - } else { - parachainsChains.push(parachains[parachainName].chain); - } - } - } - } - // If it is not an array, we just simply push it - else { - paraIds.push(argv["parachain-id"] || 1000); - const parachainName = argv.parachain.toString(); - parasNames.push(parachainName); - paras.push(parachains[parachainName]); - parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); - } - - const relayName = argv.relay || paras[0].relay; - - if (!relayName || !relayNames.includes(relayName)) { - console.error(`Invalid relay name: ${relayName}`); - console.error(`Expected one of: ${relayNames.join(", ")}`); - return; - } - - const relay = relays[relayName]; - const relayChain = argv["relay-chain"] || relay.chain; - - console.log( - `๐Ÿš€ Relay: ${relayName.padEnd(20)} - ${relay.docker || relay.binary} (${relayChain})` - ); - - let parachainBinaries = []; - let parachainPaths = []; - - // We retrieve the binaries and paths for all parachains - for (let i = 0; i < paras.length; i++) { - if (paras[i].binary) { - parachainBinaries.push(paras[i].binary); - const parachainPath = path.join(__dirname, paras[i].binary); - if (!fs.existsSync(parachainPath)) { - console.log(` Missing ${parachainPath}`); - return; - } - parachainPaths.push(parachainPath); - } else { - if (process.platform != "linux") { - console.log( - `docker binaries are only supported on linux. Use "local" config for compiled binaries` - ); - return; - } - const parachainBinary = `build/${parasNames[i]}/moonbeam`; - const parachainPath = path.join(__dirname, parachainBinary); - if (!fs.existsSync(parachainPath)) { - console.log(` Missing ${parachainBinary} locally, downloading it...`); - child_process.execSync(`mkdir -p ${path.dirname(parachainPath)} && \ +import yargs from "yargs"; +import * as fs from "fs"; +import * as path from "path"; +import * as child_process from "child_process"; +import { killAll, run } from "polkadot-launch"; + +// Description of the network to launch +type NetworkConfig = { + // From which docker to take the binary + docker?: string; + // To use instead of docker to run local binary + binary?: string; + // What chain to run + chain: string; +}; + +// Description of the parachain network +type ParachainConfig = NetworkConfig & { + // Which relay (name) config to use + relay: string; +}; + +const parachains: { [name: string]: ParachainConfig } = { + "moonriver-genesis": { + relay: "kusama-9040", + chain: "moonriver-local", + docker: "purestake/moonbeam:moonriver-genesis", + }, + "moonriver-genesis-fast": { + relay: "rococo-9004", + chain: "moonriver-local", + docker: "purestake/moonbeam:sha-153c4c4a", + }, + "moonbase-0.8.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.2", + }, + "moonbase-0.8.1": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.1", + }, + "moonbase-0.8.0": { + relay: "rococo-9001", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.8.0", + }, + "moonbase-0.9.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.2", + }, + "moonbase-0.9.4": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.4", + }, + "moonbase-0.9.6": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.9.6", + }, + "moonbase-0.10.0": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.10.0", + }, + "moonbase-0.11.2": { + relay: "rococo-9004", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.11.2", + }, + local: { + relay: "rococo-9004", + chain: "moonbase-local", + binary: "../target/release/moonbeam", + }, +}; +const parachainNames = Object.keys(parachains); + +const relays: { [name: string]: NetworkConfig } = { + "kusama-9030": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "kusama-local", + }, + "kusama-9040": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "kusama-local", + }, + "kusama-9030-fast": { + docker: "purestake/moonbase-relay-testnet:sha-832cc0af", + chain: "kusama-local", + }, + "kusama-9040-fast": { + docker: "purestake/moonbase-relay-testnet:sha-2239072e", + chain: "kusama-local", + }, + "rococo-9001": { + docker: "purestake/moonbase-relay-testnet:sha-86a45114", + chain: "rococo-local", + }, + "rococo-9003": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "rococo-local", + }, + "rococo-9004": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "rococo-local", + }, + "westend-9030": { + docker: "purestake/moonbase-relay-testnet:sha-aa386760", + chain: "westend-local", + }, + "westend-9040": { + docker: "purestake/moonbase-relay-testnet:sha-2f28561a", + chain: "westend-local", + }, + local: { + binary: "../../polkadot/target/release/polkadot", + chain: "rococo-local", + }, +}; +const relayNames = Object.keys(relays); + +// We support 3 parachains for now +const validatorNames = ["Alice", "Bob", "Charlie", "Dave", "Eve", "Ferdie"]; + +function start() { + const argv = yargs(process.argv.slice(2)) + .usage("Usage: npm run launch [args]") + .version("1.0.0") + .options({ + parachain: { + type: "string", + choices: parachainNames, + default: "local", + describe: "which parachain configuration to run", + }, + "parachain-chain": { + type: "string", + describe: "overrides parachain chain/runtime", + }, + "parachain-id": { type: "number", default: 1000, describe: "overrides parachain-id" }, + relay: { + type: "string", + choices: relayNames, + describe: "overrides relay configuration", + }, + "relay-chain": { + type: "string", + choices: [ + "rococo", + "westend", + "kusama", + "polkadot", + "rococo-local", + "westend-local", + "kusama-local", + "polkadot-local", + ], + describe: "overrides relay chain/runtime", + }, + "port-prefix": { + type: "number", + default: 34, + check: (port) => port >= 0 && port <= 64, + describe: "provides port prefix for nodes", + }, + }) + .help().argv; + + const portPrefix = argv["port-prefix"] || 34; + const startingPort = portPrefix * 1000; + let paras = []; + let parasNames = []; + let parachainsChains = []; + let paraIds = []; + + // We start gathering all the information about the parachains + if (Array.isArray(argv["parachain-id"])) { + // We need two validators per parachain, so there is a maximum we can support + if (argv["parachain-id"].length * 2 > validatorNames.length) { + console.error(`Exceeded max number of paras: ${validatorNames.length / 2}`); + return; + } + for (let i = 0; i < argv["parachain-id"].length; i++) { + paraIds.push(argv["parachain-id"][i]); + } + } + + if (Array.isArray(argv.parachain)) { + for (let i = 0; i < argv.parachain.length; i++) { + if (i >= paraIds.length) { + // If no paraId was provided for all of them, we just start assigning defaults + // But if one of the defaults was assigned to a previous para, we error + if (paraIds.includes(1000 + i)) { + console.error(`Para id already included as default: ${1000 + i}`); + return; + } else { + paraIds.push(1000 + i); + } + } + const parachainName = argv.parachain[i].toString(); + parasNames.push(parachainName); + paras.push(parachains[parachainName]); + // If it is an array, push the position at which we are + if (Array.isArray(argv["parachain-chain"])) { + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } + // Else, push the value to the first parachain if it exists, else the default + else { + if (i == 0) { + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } else { + parachainsChains.push(parachains[parachainName].chain); + } + } + } + } + // If it is not an array, we just simply push it + else { + paraIds.push(argv["parachain-id"] || 1000); + const parachainName = argv.parachain.toString(); + parasNames.push(parachainName); + paras.push(parachains[parachainName]); + parachainsChains.push(argv["parachain-chain"] || parachains[parachainName].chain); + } + + const relayName = argv.relay || paras[0].relay; + + if (!relayName || !relayNames.includes(relayName)) { + console.error(`Invalid relay name: ${relayName}`); + console.error(`Expected one of: ${relayNames.join(", ")}`); + return; + } + + const relay = relays[relayName]; + const relayChain = argv["relay-chain"] || relay.chain; + + console.log( + `๐Ÿš€ Relay: ${relayName.padEnd(20)} - ${relay.docker || relay.binary} (${relayChain})` + ); + + let parachainBinaries = []; + let parachainPaths = []; + + // We retrieve the binaries and paths for all parachains + for (let i = 0; i < paras.length; i++) { + if (paras[i].binary) { + parachainBinaries.push(paras[i].binary); + const parachainPath = path.join(__dirname, paras[i].binary); + if (!fs.existsSync(parachainPath)) { + console.log(` Missing ${parachainPath}`); + return; + } + parachainPaths.push(parachainPath); + } else { + if (process.platform != "linux") { + console.log( + `docker binaries are only supported on linux. Use "local" config for compiled binaries` + ); + return; + } + const parachainBinary = `build/${parasNames[i]}/moonbeam`; + const parachainPath = path.join(__dirname, parachainBinary); + if (!fs.existsSync(parachainPath)) { + console.log(` Missing ${parachainBinary} locally, downloading it...`); + child_process.execSync(`mkdir -p ${path.dirname(parachainPath)} && \ docker create --name moonbeam-tmp ${paras[i].docker} && \ docker cp moonbeam-tmp:/moonbeam/moonbeam ${parachainPath} && \ docker rm moonbeam-tmp`); - console.log(`${parachainBinary} downloaded !`); - } - parachainBinaries.push(parachainBinary); - parachainPaths.push(parachainPath); - } - console.log( - `๐Ÿš€ Parachain: ${parasNames[i].padEnd(20)} - ${paras[i].docker || paras[i].binary} (${ - parachainsChains[i] - })` - ); - } - - let relayBinary; - if (relay.binary) { - relayBinary = relay.binary; - const relayPath = path.join(__dirname, relay.binary); - if (!fs.existsSync(relayPath)) { - console.log(` Missing ${relayPath}`); - return; - } - } else { - if (process.platform != "linux") { - console.log( - `docker binaries are only supported on linux. Use "local" config for compiled binaries` - ); - return; - } - relayBinary = `build/${relayName}/polkadot`; - const relayPath = path.join(__dirname, `build/${relayName}/polkadot`); - if (!fs.existsSync(relayPath)) { - console.log(` Missing ${relayBinary} locally, downloading it...`); - child_process.execSync(`mkdir -p ${path.dirname(relayPath)} && \ + console.log(`${parachainBinary} downloaded !`); + } + parachainBinaries.push(parachainBinary); + parachainPaths.push(parachainPath); + } + console.log( + `๐Ÿš€ Parachain: ${parasNames[i].padEnd(20)} - ${paras[i].docker || paras[i].binary} (${parachainsChains[i] + })` + ); + } + + let relayBinary; + if (relay.binary) { + relayBinary = relay.binary; + const relayPath = path.join(__dirname, relay.binary); + if (!fs.existsSync(relayPath)) { + console.log(` Missing ${relayPath}`); + return; + } + } else { + if (process.platform != "linux") { + console.log( + `docker binaries are only supported on linux. Use "local" config for compiled binaries` + ); + return; + } + relayBinary = `build/${relayName}/polkadot`; + const relayPath = path.join(__dirname, `build/${relayName}/polkadot`); + if (!fs.existsSync(relayPath)) { + console.log(` Missing ${relayBinary} locally, downloading it...`); + child_process.execSync(`mkdir -p ${path.dirname(relayPath)} && \ docker create --name polkadot-tmp ${relay.docker} && \ docker cp polkadot-tmp:/usr/local/bin/polkadot ${relayPath} && \ docker rm polkadot-tmp`); - console.log(` ${relayBinary} downloaded !`); - } - } - console.log(""); - - let launchConfig = launchTemplate; - launchConfig.relaychain.bin = relayBinary; - launchConfig.relaychain.chain = relayChain; - - let relay_nodes = []; - // We need to build the configuration for each of the paras - for (let i = 0; i < parachainBinaries.length; i++) { - let relayNodeConfig = JSON.parse(JSON.stringify(relayNodeTemplate)); - let parachainConfig = JSON.parse(JSON.stringify(parachainTemplate)); - // HRMP is not configurable in Kusama and Westend thorugh genesis. We should detect this here - // Maybe there is a nicer way of doing this - if (launchConfig.relaychain.chain.startsWith("rococo")) { - // Create HRMP channels - // HRMP channels are uni-directonal, we need to create both ways - for (let j = 0; j < paraIds.length; j++) { - let hrmpConfig = JSON.parse(JSON.stringify(hrmpTemplate)); - if (j != i) { - hrmpConfig.sender = paraIds[i]; - hrmpConfig.recipient = paraIds[j]; - launchConfig.hrmpChannels.push(hrmpConfig); - } - } - } - - parachainConfig.bin = parachainBinaries[i]; - parachainConfig.chain = parachainsChains[i]; - parachainConfig.id = paraIds[i]; - parachainConfig.nodes[0].port = startingPort + 100 + i * 100; - parachainConfig.nodes[0].rpcPort = startingPort + 101 + i * 100; - parachainConfig.nodes[0].wsPort = startingPort + 102 + i * 100; - parachainConfig.nodes[0].flags.unshift(`--rpc-port=${parachainConfig.nodes[0].rpcPort}`) - - parachainConfig.nodes[1].port = startingPort + 110 + i * 100; - parachainConfig.nodes[1].rpcPort = startingPort + 111 + i * 100; - parachainConfig.nodes[1].wsPort = startingPort + 112 + i * 100; - parachainConfig.nodes[1].flags.unshift(`--rpc-port=${parachainConfig.nodes[1].rpcPort}`) - launchConfig.parachains.push(parachainConfig); - - // Two relay nodes per para - relayNodeConfig[0].name = validatorNames[i * 2]; - relayNodeConfig[0].port = startingPort + i * 10; - relayNodeConfig[0].rpcPort = startingPort + 1 + i * 10; - relayNodeConfig[0].wsPort = startingPort + 2 + i * 10; - relayNodeConfig[1].name = validatorNames[i * 2 + 1]; - relayNodeConfig[1].port = startingPort + i * 10; - relayNodeConfig[1].rpcPort = startingPort + 1 + i * 10; - relayNodeConfig[1].wsPort = startingPort + 1 + i * 10; - relayNodeConfig[0].flags.push(`--rpc-port=${relayNodeConfig[0].rpcPort}`) - relayNodeConfig[1].flags.push(`--rpc-port=${relayNodeConfig[1].rpcPort}`) - relay_nodes.push(relayNodeConfig[0]); - relay_nodes.push(relayNodeConfig[1]); - } - - launchConfig.relaychain.nodes = relay_nodes; - - const knownRelayChains = ["kusama", "westend", "rococo", "polkadot"] - .map((network) => [`${network}`, `${network}-local`, `${network}-dev`]) - .flat(); - - // In case the chain is a spec file - if (!knownRelayChains.includes(launchConfig.relaychain.chain)) { - delete launchConfig.relaychain.genesis; - } else if (launchConfig.relaychain.chain.startsWith("rococo")) { - // To support compatibility with rococo - (launchConfig.relaychain.genesis.runtime as any).runtime_genesis_config = { - ...launchConfig.relaychain.genesis.runtime, - }; - for (let key of Object.keys(launchConfig.relaychain.genesis.runtime)) { - if (key != "runtime_genesis_config") { - delete launchConfig.relaychain.genesis.runtime[key]; - } - } - } - - // Kill all processes when exiting. - process.on("exit", function () { - killAll(); - }); - - // Handle ctrl+c to trigger `exit`. - process.on("SIGINT", function () { - process.exit(2); - }); - - run(__dirname, launchConfig); - } - - const launchTemplate = { - relaychain: { - bin: "...", - chain: "...", - nodes: [], - genesis: { - runtime: { - parachainsConfiguration: { - config: { - validation_upgrade_frequency: 1, - validation_upgrade_delay: 1, - }, - }, - }, - }, - }, - parachains: [], - simpleParachains: [], - hrmpChannels: [], - types: { - Address: "MultiAddress", - LookupSource: "MultiAddress", - RoundIndex: "u32", - }, - finalization: true, - }; - - const relayNodeTemplate = [ - { - name: "alice", - port: 0, - rpcPort: 1, - wsPort: 2, - flags: [], - }, - { - name: "bob", - port: 10, - rpcPort: 11, - wsPort: 12, - flags: [], - }, - ]; - - const parachainTemplate = { - bin: "...", - id: 1000, - balance: "1000000000000000000000", - chain: "...", - nodes: [ - { - port: 100, - rpcPort: 101, - wsPort: 102, - name: "alice", - flags: [ - "--log=info,rpc=trace,evm=trace,ethereum=trace", - "--unsafe-rpc-external", - "--rpc-cors=all", - "--", - "--execution=wasm", - ], - }, - { - port: 110, - rpcPort: 111, - wsPort: 112, - name: "bob", - flags: [ - "--log=info,rpc=trace,evm=trace,ethereum=trace", - "--unsafe-rpc-external", - "--rpc-cors=all", - "--", - "--execution=wasm", - ], - }, - ], - }; - - const hrmpTemplate = { - sender: "200", - recipient: "300", - maxCapacity: 8, - maxMessageSize: 32768, - }; - - start(); \ No newline at end of file + console.log(` ${relayBinary} downloaded !`); + } + } + console.log(""); + + let launchConfig = launchTemplate; + launchConfig.relaychain.bin = relayBinary; + launchConfig.relaychain.chain = relayChain; + + let relay_nodes = []; + // We need to build the configuration for each of the paras + for (let i = 0; i < parachainBinaries.length; i++) { + let relayNodeConfig = JSON.parse(JSON.stringify(relayNodeTemplate)); + let parachainConfig = JSON.parse(JSON.stringify(parachainTemplate)); + // HRMP is not configurable in Kusama and Westend thorugh genesis. We should detect this here + // Maybe there is a nicer way of doing this + if (launchConfig.relaychain.chain.startsWith("rococo")) { + // Create HRMP channels + // HRMP channels are uni-directonal, we need to create both ways + for (let j = 0; j < paraIds.length; j++) { + let hrmpConfig = JSON.parse(JSON.stringify(hrmpTemplate)); + if (j != i) { + hrmpConfig.sender = paraIds[i]; + hrmpConfig.recipient = paraIds[j]; + launchConfig.hrmpChannels.push(hrmpConfig); + } + } + } + + parachainConfig.bin = parachainBinaries[i]; + parachainConfig.chain = parachainsChains[i]; + parachainConfig.id = paraIds[i]; + parachainConfig.nodes[0].port = startingPort + 100 + i * 100; + parachainConfig.nodes[0].rpcPort = startingPort + 101 + i * 100; + parachainConfig.nodes[0].wsPort = startingPort + 102 + i * 100; + parachainConfig.nodes[0].flags.unshift(`--rpc-port=${parachainConfig.nodes[0].rpcPort}`) + + parachainConfig.nodes[1].port = startingPort + 110 + i * 100; + parachainConfig.nodes[1].rpcPort = startingPort + 111 + i * 100; + parachainConfig.nodes[1].wsPort = startingPort + 112 + i * 100; + parachainConfig.nodes[1].flags.unshift(`--rpc-port=${parachainConfig.nodes[1].rpcPort}`) + launchConfig.parachains.push(parachainConfig); + + // Two relay nodes per para + relayNodeConfig[0].name = validatorNames[i * 2]; + relayNodeConfig[0].port = startingPort + i * 10; + relayNodeConfig[0].rpcPort = startingPort + 1 + i * 10; + relayNodeConfig[0].wsPort = startingPort + 2 + i * 10; + relayNodeConfig[1].name = validatorNames[i * 2 + 1]; + relayNodeConfig[1].port = startingPort + i * 10; + relayNodeConfig[1].rpcPort = startingPort + 1 + i * 10; + relayNodeConfig[1].wsPort = startingPort + 1 + i * 10; + relayNodeConfig[0].flags.push(`--rpc-port=${relayNodeConfig[0].rpcPort}`) + relayNodeConfig[1].flags.push(`--rpc-port=${relayNodeConfig[1].rpcPort}`) + relay_nodes.push(relayNodeConfig[0]); + relay_nodes.push(relayNodeConfig[1]); + } + + launchConfig.relaychain.nodes = relay_nodes; + + const knownRelayChains = ["kusama", "westend", "rococo", "polkadot"] + .map((network) => [`${network}`, `${network}-local`, `${network}-dev`]) + .flat(); + + // In case the chain is a spec file + if (!knownRelayChains.includes(launchConfig.relaychain.chain)) { + delete launchConfig.relaychain.genesis; + } else if (launchConfig.relaychain.chain.startsWith("rococo")) { + // To support compatibility with rococo + (launchConfig.relaychain.genesis.runtime as any).runtime_genesis_config = { + ...launchConfig.relaychain.genesis.runtime, + }; + for (let key of Object.keys(launchConfig.relaychain.genesis.runtime)) { + if (key != "runtime_genesis_config") { + delete launchConfig.relaychain.genesis.runtime[key]; + } + } + } + + // Kill all processes when exiting. + process.on("exit", function () { + killAll(); + }); + + // Handle ctrl+c to trigger `exit`. + process.on("SIGINT", function () { + process.exit(2); + }); + + run(__dirname, launchConfig); +} + +const launchTemplate = { + relaychain: { + bin: "...", + chain: "...", + nodes: [], + genesis: { + runtime: { + parachainsConfiguration: { + config: { + validation_upgrade_frequency: 1, + validation_upgrade_delay: 1, + }, + }, + }, + }, + }, + parachains: [], + simpleParachains: [], + hrmpChannels: [], + types: { + Address: "MultiAddress", + LookupSource: "MultiAddress", + RoundIndex: "u32", + }, + finalization: true, +}; + +const relayNodeTemplate = [ + { + name: "alice", + port: 0, + rpcPort: 1, + wsPort: 2, + flags: [], + }, + { + name: "bob", + port: 10, + rpcPort: 11, + wsPort: 12, + flags: [], + }, +]; + +const parachainTemplate = { + bin: "...", + id: 1000, + balance: "1000000000000000000000", + chain: "...", + nodes: [ + { + port: 100, + rpcPort: 101, + wsPort: 102, + name: "alice", + flags: [ + "--log=info,rpc=trace,evm=trace,ethereum=trace", + "--unsafe-rpc-external", + "--rpc-cors=all", + "--", + "--execution=wasm", + ], + }, + { + port: 110, + rpcPort: 111, + wsPort: 112, + name: "bob", + flags: [ + "--log=info,rpc=trace,evm=trace,ethereum=trace", + "--unsafe-rpc-external", + "--rpc-cors=all", + "--", + "--execution=wasm", + ], + }, + ], +}; + +const hrmpTemplate = { + sender: "200", + recipient: "300", + maxCapacity: 8, + maxMessageSize: 32768, +}; + +start(); \ No newline at end of file From 898456222d55fbca445c8090ab1082ca0c244340 Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Mon, 13 Sep 2021 11:03:52 +0700 Subject: [PATCH 5/7] fix: launch with moonbase and westend nodes --- .../goloop2moonbeam/moonbeam/Dockerfile | 2 +- .../goloop2moonbeam/moonbeam/launch.ts | 28 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/docker-compose/goloop2moonbeam/moonbeam/Dockerfile b/docker-compose/goloop2moonbeam/moonbeam/Dockerfile index 9c4fad38..7c655fcc 100644 --- a/docker-compose/goloop2moonbeam/moonbeam/Dockerfile +++ b/docker-compose/goloop2moonbeam/moonbeam/Dockerfile @@ -6,6 +6,6 @@ COPY . /root/moonbeam-launch RUN apt-get update && apt-get install -y docker.io curl \ && yarn -CMD ["yarn", "launch", "--parachain", "moonriver-genesis"] +CMD ["yarn", "launch", "--parachain", "moonbase-0.12.1", "--relay", "westend-9040"] HEALTHCHECK --interval=3s --timeout=3s --start-period=5s --retries=10 CMD ["curl", "-f", "http://127.0.0.1:34101/health" ] \ No newline at end of file diff --git a/docker-compose/goloop2moonbeam/moonbeam/launch.ts b/docker-compose/goloop2moonbeam/moonbeam/launch.ts index bb7fd77b..6e87a6ba 100644 --- a/docker-compose/goloop2moonbeam/moonbeam/launch.ts +++ b/docker-compose/goloop2moonbeam/moonbeam/launch.ts @@ -80,10 +80,15 @@ const parachains: { [name: string]: ParachainConfig } = { chain: "moonbase-local", docker: "purestake/moonbeam:v0.10.0", }, - "moonbase-0.11.2": { + "moonbase-0.11.3": { relay: "rococo-9004", chain: "moonbase-local", - docker: "purestake/moonbeam:v0.11.2", + docker: "purestake/moonbeam:v0.11.3", + }, + "moonbase-0.12.1": { + relay: "rococo-9102", + chain: "moonbase-local", + docker: "purestake/moonbeam:v0.12.1", }, local: { relay: "rococo-9004", @@ -118,6 +123,10 @@ const relays: { [name: string]: NetworkConfig } = { docker: "purestake/moonbase-relay-testnet:sha-aa386760", chain: "rococo-local", }, + "rococo-9102": { + docker: "purestake/moonbase-relay-testnet:sha-43d9b899", + chain: "rococo-local", + }, "rococo-9004": { docker: "purestake/moonbase-relay-testnet:sha-2f28561a", chain: "rococo-local", @@ -281,16 +290,17 @@ function start() { if (!fs.existsSync(parachainPath)) { console.log(` Missing ${parachainBinary} locally, downloading it...`); child_process.execSync(`mkdir -p ${path.dirname(parachainPath)} && \ - docker create --name moonbeam-tmp ${paras[i].docker} && \ - docker cp moonbeam-tmp:/moonbeam/moonbeam ${parachainPath} && \ - docker rm moonbeam-tmp`); + docker create --name moonbeam-tmp ${paras[i].docker} && \ + docker cp moonbeam-tmp:/moonbeam/moonbeam ${parachainPath} && \ + docker rm moonbeam-tmp`); console.log(`${parachainBinary} downloaded !`); } parachainBinaries.push(parachainBinary); parachainPaths.push(parachainPath); } console.log( - `๐Ÿš€ Parachain: ${parasNames[i].padEnd(20)} - ${paras[i].docker || paras[i].binary} (${parachainsChains[i] + `๐Ÿš€ Parachain: ${parasNames[i].padEnd(20)} - ${paras[i].docker || paras[i].binary} (${ + parachainsChains[i] })` ); } @@ -315,9 +325,9 @@ function start() { if (!fs.existsSync(relayPath)) { console.log(` Missing ${relayBinary} locally, downloading it...`); child_process.execSync(`mkdir -p ${path.dirname(relayPath)} && \ - docker create --name polkadot-tmp ${relay.docker} && \ - docker cp polkadot-tmp:/usr/local/bin/polkadot ${relayPath} && \ - docker rm polkadot-tmp`); + docker create --name polkadot-tmp ${relay.docker} && \ + docker cp polkadot-tmp:/usr/local/bin/polkadot ${relayPath} && \ + docker rm polkadot-tmp`); console.log(` ${relayBinary} downloaded !`); } } From 7d43be50822729f9756e207e1701fe78cc92aa0a Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Mon, 13 Sep 2021 11:37:15 +0700 Subject: [PATCH 6/7] fix: change network to moonbase local --- .../scripts/deploy_solidity.sh | 20 +++++++++---------- solidity/bmc/truffle-config.js | 7 +++++++ solidity/bmv/truffle-config.js | 6 +++--- solidity/bsh/truffle-config.js | 7 +++++++ 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/docker-compose/goloop2moonbeam/scripts/deploy_solidity.sh b/docker-compose/goloop2moonbeam/scripts/deploy_solidity.sh index fbc2a6e3..7d023ad5 100644 --- a/docker-compose/goloop2moonbeam/scripts/deploy_solidity.sh +++ b/docker-compose/goloop2moonbeam/scripts/deploy_solidity.sh @@ -13,8 +13,8 @@ deploy_solidity_bmc() { cat ./build/contracts/BMCManagement.json | jq -r .abi > $CONFIG_DIR/abi.bmc_management.json BMC_PRA_NET=$(cat $CONFIG_DIR/net.btp.moonbeam) \ - truffle migrate --network moonbeamlocal - truffle exec $SCRIPT_DIR/mb_extract_bmc.js --network moonbeamlocal + truffle migrate --network moonbaselocal + truffle exec $SCRIPT_DIR/mb_extract_bmc.js --network moonbaselocal wait_file_created $CONFIG_DIR bmc.moonbeam echo "btp://$(cat $CONFIG_DIR/net.btp.moonbeam)/$(cat $CONFIG_DIR/bmc.moonbeam)" > $CONFIG_DIR/btp.moonbeam @@ -36,9 +36,9 @@ deploy_solidity_bsh() { BSH_FIXED_FEE=50000 \ BMC_PERIPHERY_ADDRESS=$(cat $CONFIG_DIR/bmc.moonbeam) \ BSH_SERVICE=nativecoin \ - truffle migrate --network moonbeamlocal + truffle migrate --network moonbaselocal - truffle exec $SCRIPT_DIR/mb_extract_bsh.js --network moonbeamlocal + truffle exec $SCRIPT_DIR/mb_extract_bsh.js --network moonbaselocal wait_file_created $CONFIG_DIR bsh.moonbeam } @@ -77,9 +77,9 @@ deploy_solidity_bmv() { BMV_ICON_INIT_ROOTSSIZE=8 \ BMV_ICON_INIT_CACHESIZE=8 \ BMV_ICON_LASTBLOCK_HASH=$LAST_HASH \ - truffle migrate --network moonbeamlocal + truffle migrate --network moonbaselocal - truffle exec $SCRIPT_DIR/mb_extract_bmv.js --network moonbeamlocal + truffle exec $SCRIPT_DIR/mb_extract_bmv.js --network moonbaselocal wait_file_created $CONFIG_DIR bmv.moonbeam } @@ -92,7 +92,7 @@ moonbeam_bmc_addVerifier() { ICON_NET=$(cat $CONFIG_DIR/net.btp.icon) \ BMV_MOONBEAM=$(cat $CONFIG_DIR/bmv.moonbeam) \ - truffle exec mb_bmc_add_verifier.js --network moonbeamlocal + truffle exec mb_bmc_add_verifier.js --network moonbaselocal } moonbeam_bmc_addLink() { @@ -102,7 +102,7 @@ moonbeam_bmc_addLink() { cp $SCRIPT_DIR/mb_bmc_add_link.js . ICON_BTP_ADDRESS=$(cat $CONFIG_DIR/btp.icon) \ - truffle exec mb_bmc_add_link.js --network moonbeamlocal + truffle exec mb_bmc_add_link.js --network moonbaselocal } moonbeam_bmc_addService() { @@ -114,14 +114,14 @@ moonbeam_bmc_addService() { BSH_MOONBEAM=$(cat $CONFIG_DIR/bsh.moonbeam) \ ICON_BTP_ADDRESS=$(cat $CONFIG_DIR/btp.icon) \ RELAY_ADDRESS=0x$(cat $CONFIG_DIR/moonbeam.keystore.json | jq -r .address) \ - truffle exec mb_bmc_add_service.js --network moonbeamlocal + truffle exec mb_bmc_add_service.js --network moonbaselocal } moonbeam_bsh_registerCoin() { echo "moonbeam_bsh_registerCoin" cd $SOLIDITY_DIST_DIR/bsh cp $SCRIPT_DIR/mb_bsh_register_coin.js . - truffle exec mb_bsh_register_coin.js --network moonbeamlocal + truffle exec mb_bsh_register_coin.js --network moonbaselocal } clean_solidity_build() { diff --git a/solidity/bmc/truffle-config.js b/solidity/bmc/truffle-config.js index 1368d9ef..a5036ca0 100644 --- a/solidity/bmc/truffle-config.js +++ b/solidity/bmc/truffle-config.js @@ -30,6 +30,13 @@ module.exports = { }), network_id: 1281 }, + moonbaselocal: { + provider: () => new HDWalletProvider({ + privateKeys: privKeys, + providerOrUrl: "http://localhost:34101", + }), + network_id: 1287 + }, moonbase: { provider: () => new HDWalletProvider({ privateKeys: privKeys, diff --git a/solidity/bmv/truffle-config.js b/solidity/bmv/truffle-config.js index 1368d9ef..07aca485 100644 --- a/solidity/bmv/truffle-config.js +++ b/solidity/bmv/truffle-config.js @@ -23,12 +23,12 @@ module.exports = { }), network_id: 1281 }, - moonbeamlocal: { + moonbaselocal: { provider: () => new HDWalletProvider({ privateKeys: privKeys, - providerOrUrl: "http://localhost:9933", + providerOrUrl: "http://localhost:34101", }), - network_id: 1281 + network_id: 1287 }, moonbase: { provider: () => new HDWalletProvider({ diff --git a/solidity/bsh/truffle-config.js b/solidity/bsh/truffle-config.js index 1368d9ef..a5036ca0 100644 --- a/solidity/bsh/truffle-config.js +++ b/solidity/bsh/truffle-config.js @@ -30,6 +30,13 @@ module.exports = { }), network_id: 1281 }, + moonbaselocal: { + provider: () => new HDWalletProvider({ + privateKeys: privKeys, + providerOrUrl: "http://localhost:34101", + }), + network_id: 1287 + }, moonbase: { provider: () => new HDWalletProvider({ privateKeys: privKeys, From ef83faffff58808a64f7b06221d537beedc1b2c4 Mon Sep 17 00:00:00 2001 From: Truong Ma Phi Date: Wed, 15 Sep 2021 12:38:50 +0700 Subject: [PATCH 7/7] WIP --- .../goloop2moonbeam/moonbeam/package.json | 2 +- .../goloop2moonbeam/moonbeam/src/check.ts | 66 ++++ .../moonbeam/{ => src}/launch.ts | 4 +- .../goloop2moonbeam/moonbeam/src/parachain.ts | 11 + .../goloop2moonbeam/moonbeam/src/rpc.ts | 190 ++++++++++ .../goloop2moonbeam/moonbeam/src/runner.ts | 260 ++++++++++++++ .../goloop2moonbeam/moonbeam/src/spawn.ts | 328 ++++++++++++++++++ .../goloop2moonbeam/moonbeam/src/spec.ts | 219 ++++++++++++ .../goloop2moonbeam/moonbeam/src/types.d.ts | 80 +++++ 9 files changed, 1158 insertions(+), 2 deletions(-) create mode 100644 docker-compose/goloop2moonbeam/moonbeam/src/check.ts rename docker-compose/goloop2moonbeam/moonbeam/{ => src}/launch.ts (99%) create mode 100644 docker-compose/goloop2moonbeam/moonbeam/src/parachain.ts create mode 100644 docker-compose/goloop2moonbeam/moonbeam/src/rpc.ts create mode 100644 docker-compose/goloop2moonbeam/moonbeam/src/runner.ts create mode 100644 docker-compose/goloop2moonbeam/moonbeam/src/spawn.ts create mode 100644 docker-compose/goloop2moonbeam/moonbeam/src/spec.ts create mode 100644 docker-compose/goloop2moonbeam/moonbeam/src/types.d.ts diff --git a/docker-compose/goloop2moonbeam/moonbeam/package.json b/docker-compose/goloop2moonbeam/moonbeam/package.json index ee14781e..4a6d3c60 100644 --- a/docker-compose/goloop2moonbeam/moonbeam/package.json +++ b/docker-compose/goloop2moonbeam/moonbeam/package.json @@ -12,7 +12,7 @@ "@types/yargs": "^15.0.12" }, "scripts": { - "launch": "ts-node launch" + "launch": "ts-node src/launch" }, "author": "", "license": "Apache-2.0" diff --git a/docker-compose/goloop2moonbeam/moonbeam/src/check.ts b/docker-compose/goloop2moonbeam/moonbeam/src/check.ts new file mode 100644 index 00000000..d9aa468d --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/src/check.ts @@ -0,0 +1,66 @@ +// This function checks that the `config.json` file has all the expected properties. +// It displays a unique error message and returns `false` for any detected issues. +import { LaunchConfig } from "./types"; +export function checkConfig(config: LaunchConfig) { + if (!config) { + console.error("โš  Missing config"); + return false; + } + + if (!config.relaychain) { + console.error("โš  Missing `relaychain` object"); + return false; + } + + if (!config.relaychain.bin) { + console.error("โš  Missing `relaychain.bin`"); + return false; + } + + if (!config.relaychain.chain) { + console.error("โš  Missing `relaychain.chain`"); + return false; + } + + if (config.relaychain.nodes.length == 0) { + console.error("โš  No relaychain nodes defined"); + return false; + } + + for (const node of config.relaychain.nodes) { + if (node.flags && node.flags.constructor !== Array) { + console.error("โš  Relay chain flags should be an array."); + return false; + } + } + + if (!config.parachains) { + console.error("โš  Missing `parachains` object"); + return false; + } + + if (config.parachains.length >= config.relaychain.nodes.length) { + console.error( + "โš  Must have the same or greater number of relaychain nodes than parachains." + ); + return false; + } + + for (let parachain of config.parachains) { + if (!parachain.nodes) { + console.error("โš  Missing parachain nodes"); + return false; + } + } + + for (let parachain of config.parachains) { + for (let node of parachain.nodes) { + if (node.flags && node.flags.constructor !== Array) { + console.error("โš  Parachain flags should be an array."); + return false; + } + } + } + + return true; +} diff --git a/docker-compose/goloop2moonbeam/moonbeam/launch.ts b/docker-compose/goloop2moonbeam/moonbeam/src/launch.ts similarity index 99% rename from docker-compose/goloop2moonbeam/moonbeam/launch.ts rename to docker-compose/goloop2moonbeam/moonbeam/src/launch.ts index 6e87a6ba..eea31998 100644 --- a/docker-compose/goloop2moonbeam/moonbeam/launch.ts +++ b/docker-compose/goloop2moonbeam/moonbeam/src/launch.ts @@ -16,7 +16,8 @@ import yargs from "yargs"; import * as fs from "fs"; import * as path from "path"; import * as child_process from "child_process"; -import { killAll, run } from "polkadot-launch"; +import { killAll } from "./spawn"; +import { run } from "./runner"; // Description of the network to launch type NetworkConfig = { @@ -417,6 +418,7 @@ function start() { process.exit(2); }); + // @ts-expect-error run(__dirname, launchConfig); } diff --git a/docker-compose/goloop2moonbeam/moonbeam/src/parachain.ts b/docker-compose/goloop2moonbeam/moonbeam/src/parachain.ts new file mode 100644 index 00000000..2aae1bcb --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/src/parachain.ts @@ -0,0 +1,11 @@ +import { bnToHex, stringToHex, hexStripPrefix } from "@polkadot/util"; +import { encodeAddress } from "@polkadot/util-crypto"; + +export function parachainAccount(id: string) { + let prefix = stringToHex("para"); + let encoded_id = bnToHex(parseInt(id), { isLe: true }); + let address_bytes = (prefix + hexStripPrefix(encoded_id)).padEnd(64 + 2, "0"); + let address = encodeAddress(address_bytes); + + return address; +} diff --git a/docker-compose/goloop2moonbeam/moonbeam/src/rpc.ts b/docker-compose/goloop2moonbeam/moonbeam/src/rpc.ts new file mode 100644 index 00000000..82318b94 --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/src/rpc.ts @@ -0,0 +1,190 @@ +import { ApiPromise, WsProvider } from "@polkadot/api"; +import { Keyring } from "@polkadot/api"; +import { cryptoWaitReady } from "@polkadot/util-crypto"; + +let nonce = 0; + +const filterConsole = require("filter-console"); + +// Hide some warning messages that are coming from Polkadot JS API. +// TODO: Make configurable. +filterConsole([ + `code: '1006' reason: 'connection failed'`, + `Unhandled promise rejections`, + `UnhandledPromiseRejectionWarning:`, + `Unknown types found`, +]); + +// Connect to a local Substrate node. This function wont resolve until connected. +// TODO: Add a timeout where we know something went wrong so we don't wait forever. +export async function connect(port: number, types: any) { + const provider = new WsProvider("ws://127.0.0.1:" + port); + const api = await ApiPromise.create({ + provider, + types, + throwOnConnect: false, + }); + return api; +} + +// Get the genesis header of a node. Used for registering a parachain on the relay chain. +export async function getHeader(api: ApiPromise) { + let genesis_hash = await api.rpc.chain.getBlockHash(0); + let genesis_header = await api.rpc.chain.getHeader(genesis_hash); + return genesis_header.toHex(); +} + +// Submit an extrinsic to the relay chain to register a parachain. +// Uses the Alice account which is known to be Sudo for the relay chain. +export async function registerParachain( + api: ApiPromise, + id: string, + wasm: string, + header: string, + finalization: boolean = false +) { + return new Promise(async (resolvePromise, reject) => { + await cryptoWaitReady(); + + const keyring = new Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice"); + + let paraGenesisArgs = { + genesis_head: header, + validation_code: wasm, + parachain: true, + }; + let genesis = api.createType("ParaGenesisArgs", paraGenesisArgs); + + console.log( + `--- Submitting extrinsic to register parachain ${id}. (nonce: ${nonce}) ---` + ); + const unsub = await api.tx.sudo + .sudo(api.tx.parasSudoWrapper.sudoScheduleParaInitialize(id, genesis)) + .signAndSend(alice, { nonce: nonce, era: 0 }, (result) => { + console.log(`Current status is ${result.status}`); + if (result.status.isInBlock) { + console.log( + `Transaction included at blockHash ${result.status.asInBlock}` + ); + if (finalization) { + console.log("Waiting for finalization..."); + } else { + unsub(); + resolvePromise(); + } + } else if (result.status.isFinalized) { + console.log( + `Transaction finalized at blockHash ${result.status.asFinalized}` + ); + unsub(); + resolvePromise(); + } else if (result.isError) { + console.log(`Transaction Error`); + reject(`Transaction Error`); + } + }); + nonce += 1; + }); +} + +// Set the balance of an account on the relay chain. +export async function setBalance( + api: ApiPromise, + who: string, + value: string, + finalization: boolean = false +) { + return new Promise(async (resolvePromise, reject) => { + await cryptoWaitReady(); + + const keyring = new Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice"); + + if (!nonce) { + nonce = Number((await api.query.system.account(alice.address)).nonce); + } + + console.log( + `--- Submitting extrinsic to set balance of ${who} to ${value}. (nonce: ${nonce}) ---` + ); + const unsub = await api.tx.sudo + .sudo(api.tx.balances.setBalance(who, value, 0)) + .signAndSend(alice, { nonce: nonce, era: 0 }, (result) => { + console.log(`Current status is ${result.status}`); + if (result.status.isInBlock) { + console.log( + `Transaction included at blockHash ${result.status.asInBlock}` + ); + if (finalization) { + console.log("Waiting for finalization..."); + } else { + unsub(); + resolvePromise(); + } + } else if (result.status.isFinalized) { + console.log( + `Transaction finalized at blockHash ${result.status.asFinalized}` + ); + unsub(); + resolvePromise(); + } else if (result.isError) { + console.log(`Transaction Error`); + reject(`Transaction Error`); + } + }); + nonce += 1; + }); +} + +export async function sendHrmpMessage( + api: ApiPromise, + recipient: string, + data: string, + finalization: boolean = false +) { + return new Promise(async (resolvePromise, reject) => { + await cryptoWaitReady(); + + const keyring = new Keyring({ type: "sr25519" }); + const alice = keyring.addFromUri("//Alice"); + + if (!nonce) { + nonce = Number((await api.query.system.account(alice.address)).nonce); + } + + let hrmpMessage = { + recipient: recipient, + data: data, + }; + let message = api.createType("OutboundHrmpMessage", hrmpMessage); + + console.log(`--- Sending a message to ${recipient}. (nonce: ${nonce}) ---`); + const unsub = await api.tx.sudo + .sudo(api.tx.messageBroker.sudoSendHrmpMessage(message)) + .signAndSend(alice, { nonce: nonce, era: 0 }, (result) => { + console.log(`Current status is ${result.status}`); + if (result.status.isInBlock) { + console.log( + `Transaction included at blockHash ${result.status.asInBlock}` + ); + if (finalization) { + console.log("Waiting for finalization..."); + } else { + unsub(); + resolvePromise(); + } + } else if (result.status.isFinalized) { + console.log( + `Transaction finalized at blockHash ${result.status.asFinalized}` + ); + unsub(); + resolvePromise(); + } else if (result.isError) { + console.log(`Transaction Error`); + reject(`Transaction Error`); + } + }); + nonce += 1; + }); +} diff --git a/docker-compose/goloop2moonbeam/moonbeam/src/runner.ts b/docker-compose/goloop2moonbeam/moonbeam/src/runner.ts new file mode 100644 index 00000000..81bc3161 --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/src/runner.ts @@ -0,0 +1,260 @@ +#!/usr/bin/env node + +import { + startNode, + startCollator, + generateChainSpec, + generateChainSpecRaw, + exportGenesisWasm, + exportGenesisState, + startSimpleCollator, + getParachainIdFromSpec, +} from "./spawn"; +import { connect, registerParachain, setBalance } from "./rpc"; +import { checkConfig } from "./check"; +import { + clearAuthorities, + addAuthority, + changeGenesisConfig, + addGenesisParachain, + addGenesisHrmpChannel, +} from "./spec"; +import { parachainAccount } from "./parachain"; +import { ApiPromise } from "@polkadot/api"; + +import { resolve } from "path"; +import fs from "fs"; +import type { + LaunchConfig, + ResolvedParachainConfig, + ResolvedSimpleParachainConfig, + HrmpChannelsConfig, + ResolvedLaunchConfig, +} from "./types"; +import { type } from "os"; + +function loadTypeDef(types: string | object): object { + if (typeof types === "string") { + // Treat types as a json file path + try { + const rawdata = fs.readFileSync(types, { encoding: "utf-8" }); + return JSON.parse(rawdata); + } catch { + console.error("failed to load parachain typedef file"); + process.exit(1); + } + } else { + return types; + } +} + +// keep track of registered parachains +let registeredParachains: { [key: string]: boolean } = {}; + +export async function run(config_dir: string, rawConfig: LaunchConfig) { + // Verify that the `config.json` has all the expected properties. + if (!checkConfig(rawConfig)) { + return; + } + const config = await resolveParachainId(config_dir, rawConfig); + + const relay_chain_bin = resolve(config_dir, config.relaychain.bin); + if (!fs.existsSync(relay_chain_bin)) { + console.error("Relay chain binary does not exist: ", relay_chain_bin); + process.exit(); + } + const chain = config.relaychain.chain; + await generateChainSpec(relay_chain_bin, chain); + // -- Start Chain Spec Modify -- + clearAuthorities(`${chain}.json`); + for (const node of config.relaychain.nodes) { + await addAuthority(`${chain}.json`, node.name); + } + if (config.relaychain.genesis) { + await changeGenesisConfig(`${chain}.json`, config.relaychain.genesis); + } + await addParachainsToGenesis(config_dir, `${chain}.json`, config.parachains, config.simpleParachains); + if (config.hrmpChannels) { + await addHrmpChannelsToGenesis(`${chain}.json`, config.hrmpChannels); + } + // -- End Chain Spec Modify -- + await generateChainSpecRaw(relay_chain_bin, chain); + const spec = resolve(`${chain}-raw.json`); + + // First we launch each of the validators for the relay chain. + for (const node of config.relaychain.nodes) { + const { name, wsPort, port, flags, basePath } = node; + console.log(`Starting ${name}...`); + // We spawn a `child_process` starting a node, and then wait until we + // able to connect to it using PolkadotJS in order to know its running. + startNode(relay_chain_bin, name, wsPort, port, spec, flags, basePath); + } + + // Connect to the first relay chain node to submit the extrinsic. + let relayChainApi: ApiPromise = await connect( + config.relaychain.nodes[0].wsPort, + loadTypeDef(config.types) + ); + + // Then launch each parachain + for (const parachain of config.parachains) { + const { id, resolvedId, balance, chain } = parachain; + const bin = resolve(config_dir, parachain.bin); + if (!fs.existsSync(bin)) { + console.error("Parachain binary does not exist: ", bin); + process.exit(); + } + let account = parachainAccount(resolvedId); + + for (const node of parachain.nodes) { + const { wsPort, port, flags, name, basePath } = node; + console.log( + `Starting a Collator for parachain ${resolvedId}: ${account}, Collator port : ${port} wsPort : ${wsPort}` + ); + const skipIdArg = !id; + await startCollator( + bin, + resolvedId, + wsPort, + port, + name, + chain, + spec, + flags, + basePath, + skipIdArg + ); + } + + // Allow time for the TX to complete, avoiding nonce issues. + // TODO: Handle nonce directly instead of this. + if (balance) { + await setBalance(relayChainApi, account, balance, config.finalization); + } + } + + // Then launch each simple parachain (e.g. an adder-collator) + if (config.simpleParachains) { + for (const simpleParachain of config.simpleParachains) { + const { id, resolvedId, port, balance } = simpleParachain; + const bin = resolve(config_dir, simpleParachain.bin); + if (!fs.existsSync(bin)) { + console.error("Simple parachain binary does not exist: ", bin); + process.exit(); + } + + let account = parachainAccount(resolvedId); + console.log(`Starting Parachain ${resolvedId}: ${account}`); + const skipIdArg = !id; + await startSimpleCollator(bin, resolvedId, spec, port, skipIdArg); + + // Allow time for the TX to complete, avoiding nonce issues. + // TODO: Handle nonce directly instead of this. + if (balance) { + await setBalance(relayChainApi, account, balance, config.finalization); + } + } + } + + // We don't need the PolkadotJs API anymore + await relayChainApi.disconnect(); + + console.log("๐Ÿš€ POLKADOT LAUNCH COMPLETE ๐Ÿš€"); +} + +interface GenesisParachain { + isSimple: boolean, + id?: string + resolvedId: string, + chain?: string, + bin: string +} + +async function addParachainsToGenesis( + config_dir: string, + spec: string, + parachains: ResolvedParachainConfig[], + simpleParachains: ResolvedSimpleParachainConfig[] +) { + console.log("\nโ›“ Adding Genesis Parachains"); + + // Collect all paras into a single list + let x: GenesisParachain[] = parachains.map((p) => { + return { isSimple: false, ...p } + }) + let y: GenesisParachain[] = simpleParachains.map((p) => { + return { isSimple: true, ...p } + }) + let paras = x.concat(y) + + for (const parachain of paras) { + const { isSimple, id, resolvedId, chain } = parachain; + const bin = resolve(config_dir, parachain.bin); + if (!fs.existsSync(bin)) { + console.error("Parachain binary does not exist: ", bin); + process.exit(); + } + // If it isn't registered yet, register the parachain in genesis + if (!registeredParachains[resolvedId]) { + // Get the information required to register the parachain in genesis. + let genesisState; + let genesisWasm; + try { + if (isSimple) { + // adder-collator does not support `--parachain-id` for export-genesis-state (and it is + // not necessary for it anyway), so we don't pass it here. + genesisState = await exportGenesisState(bin); + genesisWasm = await exportGenesisWasm(bin); + } else { + genesisState = await exportGenesisState(bin, id, chain); + genesisWasm = await exportGenesisWasm(bin, chain); + } + } catch (err) { + console.error(err); + process.exit(1); + } + + await addGenesisParachain( + spec, + resolvedId, + genesisState, + genesisWasm, + true + ); + registeredParachains[resolvedId] = true; + } + } +} + +async function addHrmpChannelsToGenesis( + spec: string, + hrmpChannels: HrmpChannelsConfig[] +) { + console.log("โ›“ Adding Genesis HRMP Channels"); + for (const hrmpChannel of hrmpChannels) { + await addGenesisHrmpChannel(spec, hrmpChannel); + } +} + +// Resolves parachain id from chain spec if not specified +async function resolveParachainId( + config_dir: string, + config: LaunchConfig +): Promise { + console.log(`\n๐Ÿงน Resolving parachain id...`); + const resolvedConfig = config as ResolvedLaunchConfig; + for (const parachain of resolvedConfig.parachains) { + if (parachain.id) { + parachain.resolvedId = parachain.id; + } else { + const bin = resolve(config_dir, parachain.bin); + const paraId = await getParachainIdFromSpec(bin, parachain.chain); + console.log(` โœ“ Read parachain id for ${parachain.bin}: ${paraId}`); + parachain.resolvedId = paraId.toString(); + } + } + for (const parachain of resolvedConfig.simpleParachains) { + parachain.resolvedId = parachain.id; + } + return resolvedConfig; +} diff --git a/docker-compose/goloop2moonbeam/moonbeam/src/spawn.ts b/docker-compose/goloop2moonbeam/moonbeam/src/spawn.ts new file mode 100644 index 00000000..50d5ee20 --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/src/spawn.ts @@ -0,0 +1,328 @@ +import { + spawn, + ChildProcessWithoutNullStreams, + execFile as ex, +} from "child_process"; +import util from "util"; +import fs from "fs"; + +// This tracks all the processes that we spawn from this file. +// Used to clean up processes when exiting this program. +const p: { [key: string]: ChildProcessWithoutNullStreams } = {}; + +const execFile = util.promisify(ex); + +// Output the chainspec of a node. +export async function generateChainSpec(bin: string, chain: string) { + return new Promise(function (resolve, reject) { + let args = ["build-spec", "--chain=" + chain, "--disable-default-bootnode"]; + + p["spec"] = spawn(bin, args); + let spec = fs.createWriteStream(`${chain}.json`); + + // `pipe` since it deals with flushing and we need to guarantee that the data is flushed + // before we resolve the promise. + p["spec"].stdout.pipe(spec); + + p["spec"].stderr.pipe(process.stderr); + + p["spec"].on("close", () => { + resolve(); + }); + + p["spec"].on("error", (err) => { + reject(err); + }); + }); +} + +// Output the chainspec of a node using `--raw` from a JSON file. +export async function generateChainSpecRaw(bin: string, chain: string) { + console.log(); // Add a newline in output + return new Promise(function (resolve, reject) { + let args = ["build-spec", "--chain=" + chain + ".json", "--raw"]; + + p["spec"] = spawn(bin, args); + let spec = fs.createWriteStream(`${chain}-raw.json`); + + // `pipe` since it deals with flushing and we need to guarantee that the data is flushed + // before we resolve the promise. + p["spec"].stdout.pipe(spec); + p["spec"].stderr.pipe(process.stderr); + + p["spec"].on("close", () => { + resolve(); + }); + + p["spec"].on("error", (err) => { + reject(err); + }); + }); +} + +export async function getParachainIdFromSpec( + bin: string, + chain?: string +): Promise { + const data = await new Promise(function (resolve, reject) { + let args = ["build-spec"]; + if (chain) { + args.push("--chain=" + chain); + } + + let data = ""; + + p["spec"] = spawn(bin, args); + p["spec"].stdout.on("data", (chunk) => { + data += chunk; + }); + + p["spec"].stderr.pipe(process.stderr); + + p["spec"].on("close", () => { + resolve(data); + }); + + p["spec"].on("error", (err) => { + reject(err); + }); + }); + + const spec = JSON.parse(data); + return spec.para_id; +} + +// Spawn a new relay chain node. +// `name` must be `alice`, `bob`, `charlie`, etc... (hardcoded in Substrate). +export function startNode( + bin: string, + name: string, + wsPort: number, + port: number, + spec: string, + flags?: string[], + basePath?: string +) { + // TODO: Make DB directory configurable rather than just `tmp` + let args = [ + "--chain=" + spec, + "--ws-port=" + wsPort, + "--port=" + port, + "--" + name.toLowerCase(), + ]; + + if (basePath) { + args.push("--base-path=" + basePath); + } else { + args.push("--tmp"); + } + + if (flags) { + // Add any additional flags to the CLI + args = args.concat(flags); + console.log(`Added ${flags}`); + } + + p[name] = spawn(bin, args); + + let log = fs.createWriteStream(`${name}.log`); + + p[name].stdout.pipe(log); + p[name].stderr.pipe(log); +} + +// Export the genesis wasm for a parachain and return it as a hex encoded string starting with 0x. +// Used for registering the parachain on the relay chain. +export async function exportGenesisWasm( + bin: string, + chain?: string +): Promise { + let args = ["export-genesis-wasm"]; + if (chain) { + args.push("--chain=" + chain); + } + + // wasm files are typically large and `exec` requires us to supply the maximum buffer size in + // advance. Hopefully, this generous limit will be enough. + let opts = { maxBuffer: 10 * 1024 * 1024 }; + let { stdout, stderr } = await execFile(bin, args, opts); + if (stderr) { + console.error(stderr); + } + return stdout.trim(); +} + +/// Export the genesis state aka genesis head. +export async function exportGenesisState( + bin: string, + id?: string, + chain?: string +): Promise { + let args = ["export-genesis-state"]; + if (id) { + args.push("--parachain-id=" + id); + } + if (chain) { + args.push("--chain=" + chain); + } + + // wasm files are typically large and `exec` requires us to supply the maximum buffer size in + // advance. Hopefully, this generous limit will be enough. + let opts = { maxBuffer: 5 * 1024 * 1024 }; + let { stdout, stderr } = await execFile(bin, args, opts); + if (stderr) { + console.error(stderr); + } + return stdout.trim(); +} + +// Start a collator node for a parachain. +export function startCollator( + bin: string, + id: string, + wsPort: number, + port: number, + name?: string, + chain?: string, + spec?: string, + flags?: string[], + basePath?: string, + skip_id_arg?: boolean +) { + return new Promise(function (resolve) { + // TODO: Make DB directory configurable rather than just `tmp` + let args = [ + "--ws-port=" + wsPort, + "--port=" + port, + "--collator", + ]; + + if (basePath) { + args.push("--base-path=" + basePath); + } else { + args.push("--tmp"); + } + + if (name) { + args.push(`--${name.toLowerCase()}`); + console.log(`Added --${name.toLowerCase()}`); + } + if (!skip_id_arg) { + args.push("--parachain-id=" + id); + console.log(`Added --parachain-id=${id}`); + } + if (chain) { + args.push("--chain=" + chain); + console.log(`Added --chain=${chain}`); + } + + let flags_collator = null; + let flags_parachain = null; + let split_index = flags ? flags.findIndex((value) => value == "--") : -1; + + if (split_index < 0) { + flags_parachain = flags; + } else { + flags_parachain = flags ? flags.slice(0, split_index) : null; + flags_collator = flags ? flags.slice(split_index + 1) : null; + } + + if (flags_parachain) { + // Add any additional flags to the CLI + args = args.concat(flags_parachain); + console.log(`Added ${flags_parachain} to parachain`); + } + + // Arguments for the relay chain node part of the collator binary. + args = args.concat(["--", "--chain=" + spec]); + + if (flags_collator) { + // Add any additional flags to the CLI + args = args.concat(flags_collator); + console.log(`Added ${flags_collator} to collator`); + } + + p[wsPort] = spawn(bin, args); + + let log = fs.createWriteStream(`${wsPort}.log`); + + p[wsPort].stdout.pipe(log); + p[wsPort].stderr.on("data", function (chunk) { + let message = chunk.toString(); + if (message.includes("Listening for new connections")) { + resolve(); + } + log.write(message); + }); + }); +} + +export function startSimpleCollator( + bin: string, + id: string, + spec: string, + port: string, + skip_id_arg?: boolean +) { + return new Promise(function (resolve) { + let args = [ + "--tmp", + "--port=" + port, + "--chain=" + spec, + "--execution=wasm", + ]; + + if (!skip_id_arg) { + args.push("--parachain-id=" + id); + console.log(`Added --parachain-id=${id}`); + } + + p[port] = spawn(bin, args); + + let log = fs.createWriteStream(`${port}.log`); + + p[port].stdout.pipe(log); + p[port].stderr.on("data", function (chunk) { + let message = chunk.toString(); + if (message.includes("Listening for new connections")) { + resolve(); + } + log.write(message); + }); + }); +} + +// Purge the chain for any node. +// You shouldn't need to use this function since every node starts with `--tmp` +// TODO: Make DB directory configurable rather than just `tmp` +export function purgeChain(bin: string, spec: string) { + console.log("Purging Chain..."); + let args = ["purge-chain"]; + + if (spec) { + args.push("--chain=" + spec); + } + + // Avoid prompt to confirm. + args.push("-y"); + + p["purge"] = spawn(bin, args); + + p["purge"].stdout.on("data", function (chunk) { + let message = chunk.toString(); + console.log(message); + }); + + p["purge"].stderr.on("data", function (chunk) { + let message = chunk.toString(); + console.log(message); + }); +} + +// Kill all processes spawned and tracked by this file. +export function killAll() { + console.log("\nKilling all processes..."); + for (const key of Object.keys(p)) { + p[key].kill(); + } +} diff --git a/docker-compose/goloop2moonbeam/moonbeam/src/spec.ts b/docker-compose/goloop2moonbeam/moonbeam/src/spec.ts new file mode 100644 index 00000000..a32a2e27 --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/src/spec.ts @@ -0,0 +1,219 @@ +import { Keyring } from "@polkadot/api"; +import { cryptoWaitReady } from "@polkadot/util-crypto"; +import { encodeAddress } from "@polkadot/util-crypto"; +import { ChainSpec, HrmpChannelsConfig } from "./types"; +const fs = require("fs"); + +function nameCase(string: string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +// Get authority keys from within chainSpec data +function getAuthorityKeys(chainSpec: ChainSpec) { + // Check runtime_genesis_config key for rococo compatibility. + const runtimeConfig = + chainSpec.genesis.runtime.runtime_genesis_config || + chainSpec.genesis.runtime; + if (runtimeConfig && runtimeConfig.session) { + return runtimeConfig.session.keys; + } + + // For retro-compatibility with substrate pre Polkadot 0.9.5 + if (runtimeConfig && runtimeConfig.palletSession) { + return runtimeConfig.palletSession.keys; + } + + console.error(" โš  session not found in runtimeConfig"); + process.exit(1); +} + +// Remove all existing keys from `session.keys` +export function clearAuthorities(spec: string) { + let rawdata = fs.readFileSync(spec); + let chainSpec; + try { + chainSpec = JSON.parse(rawdata); + } catch { + console.error(" โš  failed to parse the chain spec"); + process.exit(1); + } + + let keys = getAuthorityKeys(chainSpec); + keys.length = 0; + + let data = JSON.stringify(chainSpec, null, 2); + fs.writeFileSync(spec, data); + console.log(`\n๐Ÿงน Starting with a fresh authority set...`); +} + +// Add additional authorities to chain spec in `session.keys` +export async function addAuthority(spec: string, name: string) { + await cryptoWaitReady(); + + const sr_keyring = new Keyring({ type: "sr25519" }); + const sr_account = sr_keyring.createFromUri(`//${nameCase(name)}`); + const sr_stash = sr_keyring.createFromUri(`//${nameCase(name)}//stash`); + + const ed_keyring = new Keyring({ type: "ed25519" }); + const ed_account = ed_keyring.createFromUri(`//${nameCase(name)}`); + + const ec_keyring = new Keyring({ type: "ecdsa" }); + const ec_account = ec_keyring.createFromUri(`//${nameCase(name)}`); + + let key = [ + sr_stash.address, + sr_stash.address, + { + grandpa: ed_account.address, + babe: sr_account.address, + im_online: sr_account.address, + parachain_validator: sr_account.address, + authority_discovery: sr_account.address, + para_validator: sr_account.address, + para_assignment: sr_account.address, + beefy: encodeAddress(ec_account.publicKey), + }, + ]; + + let rawdata = fs.readFileSync(spec); + let chainSpec = JSON.parse(rawdata); + + let keys = getAuthorityKeys(chainSpec); + keys.push(key); + + let data = JSON.stringify(chainSpec, null, 2); + fs.writeFileSync(spec, data); + console.log(` ๐Ÿ‘ค Added Genesis Authority ${name}`); +} + +// Add parachains to the chain spec at genesis. +export async function addGenesisParachain( + spec: string, + para_id: string, + head: string, + wasm: string, + parachain: boolean +) { + let rawdata = fs.readFileSync(spec); + let chainSpec = JSON.parse(rawdata); + + // Check runtime_genesis_config key for rococo compatibility. + const runtimeConfig = + chainSpec.genesis.runtime.runtime_genesis_config || + chainSpec.genesis.runtime; + let paras = undefined; + if (runtimeConfig.paras) { + paras = runtimeConfig.paras.paras; + } + // For retro-compatibility with substrate pre Polkadot 0.9.5 + else if (runtimeConfig.parachainsParas) { + paras = runtimeConfig.parachainsParas.paras; + } + if (paras) { + let new_para = [ + parseInt(para_id), + { + genesis_head: head, + validation_code: wasm, + parachain: parachain, + }, + ]; + + paras.push(new_para); + + let data = JSON.stringify(chainSpec, null, 2); + fs.writeFileSync(spec, data); + console.log(` โœ“ Added Genesis Parachain ${para_id}`); + } else { + console.error(" โš  paras not found in runtimeConfig"); + process.exit(1); + } +} + +// Update the `genesis` object in the chain specification. +export async function addGenesisHrmpChannel( + spec: string, + hrmpChannel: HrmpChannelsConfig +) { + let rawdata = fs.readFileSync(spec); + let chainSpec = JSON.parse(rawdata); + + let newHrmpChannel = [ + hrmpChannel.sender, + hrmpChannel.recipient, + hrmpChannel.maxCapacity, + hrmpChannel.maxMessageSize, + ]; + + // Check runtime_genesis_config key for rococo compatibility. + const runtimeConfig = + chainSpec.genesis.runtime.runtime_genesis_config || + chainSpec.genesis.runtime; + + let hrmp = undefined; + + if (runtimeConfig.hrmp) { + hrmp = runtimeConfig.hrmp; + } + // For retro-compatibility with substrate pre Polkadot 0.9.5 + else if (runtimeConfig.parachainsHrmp) { + hrmp = runtimeConfig.parachainsHrmp; + } + + if ( + hrmp && hrmp.preopenHrmpChannels + ) { + hrmp.preopenHrmpChannels.push(newHrmpChannel); + + let data = JSON.stringify(chainSpec, null, 2); + fs.writeFileSync(spec, data); + console.log( + ` โœ“ Added HRMP channel ${hrmpChannel.sender} -> ${hrmpChannel.recipient}` + ); + } else { + console.error(" โš  hrmp not found in runtimeConfig"); + process.exit(1); + } +} + +// Update the runtime config in the genesis. +// It will try to match keys which exist within the configuration and update the value. +export async function changeGenesisConfig(spec: string, updates: any) { + let rawdata = fs.readFileSync(spec); + let chainSpec = JSON.parse(rawdata); + + console.log(`\nโš™ Updating Relay Chain Genesis Configuration`); + + if (chainSpec.genesis) { + let config = chainSpec.genesis; + findAndReplaceConfig(updates, config); + + let data = JSON.stringify(chainSpec, null, 2); + fs.writeFileSync(spec, data); + } +} + +// Look at the key + values from `obj1` and try to replace them in `obj2`. +function findAndReplaceConfig(obj1: any, obj2: any) { + // Look at keys of obj1 + Object.keys(obj1).forEach((key) => { + // See if obj2 also has this key + if (obj2.hasOwnProperty(key)) { + // If it goes deeper, recurse... + if ( + obj1[key] !== null && + obj1[key] !== undefined && + obj1[key].constructor === Object + ) { + findAndReplaceConfig(obj1[key], obj2[key]); + } else { + obj2[key] = obj1[key]; + console.log( + ` โœ“ Updated Genesis Configuration [ ${key}: ${obj2[key]} ]` + ); + } + } else { + console.error(` โš  Bad Genesis Configuration [ ${key}: ${obj1[key]} ]`); + } + }); +} diff --git a/docker-compose/goloop2moonbeam/moonbeam/src/types.d.ts b/docker-compose/goloop2moonbeam/moonbeam/src/types.d.ts new file mode 100644 index 00000000..d7625e46 --- /dev/null +++ b/docker-compose/goloop2moonbeam/moonbeam/src/types.d.ts @@ -0,0 +1,80 @@ +export interface LaunchConfig { + relaychain: RelayChainConfig; + parachains: ParachainConfig[]; + simpleParachains: SimpleParachainConfig[]; + hrmpChannels: HrmpChannelsConfig[]; + types: any; + finalization: boolean; +} +export interface ParachainNodeConfig { + rpcPort: number; + wsPort: number; + port: number; + basePath?: string; + name?: string; + flags: string[]; +} +export interface ParachainConfig { + bin: string; + id?: string; + balance: string; + chain?: string; + nodes: ParachainNodeConfig[]; +} +export interface SimpleParachainConfig { + bin: string; + id: string; + port: string; + balance: string; +} +export interface HrmpChannelsConfig { + sender: number; + recipient: number; + maxCapacity: number; + maxMessageSize: number; +} +export interface RelayChainConfig { + bin: string; + chain: string; + nodes: { + name: string; + basePath?: string; + wsPort: number; + port: number; + flags?: string[]; + }[]; + genesis?: JSON; +} + +export interface ChainSpec { + name: string; + id: string; + chainType: string; + bootNodes: string[]; + telemetryEndpoints: null; + protocolId: string; + properties: null; + forkBlocks: null; + badBlocks: null; + consensusEngine: null; + lightSyncState: null; + genesis: { + runtime: any; // this can change depending on the versions + raw: { + top: { + [key: string]: string; + }; + }; + }; +} + +export interface ResolvedParachainConfig extends ParachainConfig { + resolvedId: string; +} +export interface ResolvedSimpleParachainConfig extends SimpleParachainConfig { + resolvedId: string; +} +export interface ResolvedLaunchConfig extends LaunchConfig { + parachains: ResolvedParachainConfig[]; + simpleParachains: ResolvedSimpleParachainConfig[]; +}