From 9354ad5afa57ad0f1b521c5e317616d899f38cf7 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 13:12:30 +0100 Subject: [PATCH 01/13] Add packages/faucet --- NOTICE | 3 + packages/faucet/.eslintignore | 1 + packages/faucet/.gitignore | 3 + packages/faucet/bin/cosm-faucet | 6 + packages/faucet/nonces/README.txt | 1 + packages/faucet/package.json | 62 ++ packages/faucet/src/actions/generate.ts | 20 + packages/faucet/src/actions/help.ts | 33 + packages/faucet/src/actions/index.ts | 4 + .../src/actions/start/httperror.spec.ts | 20 + .../faucet/src/actions/start/httperror.ts | 5 + packages/faucet/src/actions/start/index.ts | 1 + .../src/actions/start/requestparser.spec.ts | 48 + .../faucet/src/actions/start/requestparser.ts | 35 + packages/faucet/src/actions/start/start.ts | 157 ++++ packages/faucet/src/actions/version.ts | 15 + packages/faucet/src/cashflow.spec.ts | 163 ++++ packages/faucet/src/cashflow.ts | 95 ++ packages/faucet/src/codec.spec.ts | 16 + packages/faucet/src/codec.ts | 80 ++ packages/faucet/src/constants.ts | 7 + packages/faucet/src/crypto.ts | 15 + packages/faucet/src/debugging.ts | 58 ++ packages/faucet/src/faucet.ts | 38 + packages/faucet/src/hdpaths.spec.ts | 45 + packages/faucet/src/hdpaths.ts | 10 + packages/faucet/src/multichainhelpers.spec.ts | 57 ++ packages/faucet/src/multichainhelpers.ts | 145 +++ packages/faucet/src/profile.ts | 34 + packages/faucet/src/types.ts | 10 + packages/faucet/tsconfig.json | 12 + packages/faucet/tslint.json | 3 + packages/faucet/typedoc.js | 14 + yarn.lock | 833 +++++++++++++++++- 34 files changed, 2006 insertions(+), 43 deletions(-) create mode 120000 packages/faucet/.eslintignore create mode 100644 packages/faucet/.gitignore create mode 100755 packages/faucet/bin/cosm-faucet create mode 100644 packages/faucet/nonces/README.txt create mode 100644 packages/faucet/package.json create mode 100644 packages/faucet/src/actions/generate.ts create mode 100644 packages/faucet/src/actions/help.ts create mode 100644 packages/faucet/src/actions/index.ts create mode 100644 packages/faucet/src/actions/start/httperror.spec.ts create mode 100644 packages/faucet/src/actions/start/httperror.ts create mode 100644 packages/faucet/src/actions/start/index.ts create mode 100644 packages/faucet/src/actions/start/requestparser.spec.ts create mode 100644 packages/faucet/src/actions/start/requestparser.ts create mode 100644 packages/faucet/src/actions/start/start.ts create mode 100644 packages/faucet/src/actions/version.ts create mode 100644 packages/faucet/src/cashflow.spec.ts create mode 100644 packages/faucet/src/cashflow.ts create mode 100644 packages/faucet/src/codec.spec.ts create mode 100644 packages/faucet/src/codec.ts create mode 100644 packages/faucet/src/constants.ts create mode 100644 packages/faucet/src/crypto.ts create mode 100644 packages/faucet/src/debugging.ts create mode 100644 packages/faucet/src/faucet.ts create mode 100644 packages/faucet/src/hdpaths.spec.ts create mode 100644 packages/faucet/src/hdpaths.ts create mode 100644 packages/faucet/src/multichainhelpers.spec.ts create mode 100644 packages/faucet/src/multichainhelpers.ts create mode 100644 packages/faucet/src/profile.ts create mode 100644 packages/faucet/src/types.ts create mode 100644 packages/faucet/tsconfig.json create mode 100644 packages/faucet/tslint.json create mode 100644 packages/faucet/typedoc.js diff --git a/NOTICE b/NOTICE index 24ba00c8..216009de 100644 --- a/NOTICE +++ b/NOTICE @@ -2,6 +2,9 @@ This repository was forked from the folders packages/iov-cosmos and scripts/cosm of https://github.com/iov-one/iov-core at tag v2.0.0-alpha.7. It was repurposed and heavily modified from there on. +The code in packages/faucet was forked from https://github.com/iov-one/iov-faucet on +2020-01-29 at commit 33e2d707e7. + Copyright 2018-2020 IOV SAS Copyright 2020 Confio UO Copyright 2020 Simon Warta diff --git a/packages/faucet/.eslintignore b/packages/faucet/.eslintignore new file mode 120000 index 00000000..86039baf --- /dev/null +++ b/packages/faucet/.eslintignore @@ -0,0 +1 @@ +../../.eslintignore \ No newline at end of file diff --git a/packages/faucet/.gitignore b/packages/faucet/.gitignore new file mode 100644 index 00000000..68bf3735 --- /dev/null +++ b/packages/faucet/.gitignore @@ -0,0 +1,3 @@ +build/ +dist/ +docs/ diff --git a/packages/faucet/bin/cosm-faucet b/packages/faucet/bin/cosm-faucet new file mode 100755 index 00000000..c44ac640 --- /dev/null +++ b/packages/faucet/bin/cosm-faucet @@ -0,0 +1,6 @@ +#!/usr/bin/env node +const path = require("path"); + +// attempt to call in main file.... +const faucet = require(path.join(__dirname, "..", "build", "faucet.js")); +faucet.main(process.argv.slice(2)); diff --git a/packages/faucet/nonces/README.txt b/packages/faucet/nonces/README.txt new file mode 100644 index 00000000..092fe732 --- /dev/null +++ b/packages/faucet/nonces/README.txt @@ -0,0 +1 @@ +Directory used to trigger lerna package updates for all packages diff --git a/packages/faucet/package.json b/packages/faucet/package.json new file mode 100644 index 00000000..4e156995 --- /dev/null +++ b/packages/faucet/package.json @@ -0,0 +1,62 @@ +{ + "name": "@cosmwasm/faucet", + "version": "0.0.1", + "description": "The faucet", + "author": "Ethan Frey ", + "license": "Apache-2.0", + "main": "build/index.js", + "types": "types/index.d.ts", + "files": [ + "build/", + "types/", + "*.md", + "!*.spec.*", + "!**/testdata/" + ], + "repository": { + "type": "git", + "url": "https://github.com/confio/cosm-js/tree/master/packages/faucet" + }, + "publishConfig": { + "access": "public" + }, + "scripts": { + "docs": "shx rm -rf docs && typedoc --options typedoc.js", + "format": "prettier --write --loglevel warn \"./src/**/*.ts\"", + "lint": "eslint --max-warnings 0 \"**/*.{js,ts}\" && tslint -t verbose --project .", + "lint-fix": "eslint --max-warnings 0 \"**/*.{js,ts}\" --fix", + "move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts", + "format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"", + "build": "shx rm -rf ./build && tsc && yarn move-types && yarn format-types", + "build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build", + "test-node": "mocha \"./build/**/*.spec.js\"", + "test": "yarn build-or-skip && yarn test-node" + }, + "dependencies": { + "@iov/bcp": "^2.0.0-alpha.7", + "@iov/bns": "^2.0.0-alpha.7", + "@iov/crypto": "^2.0.0-alpha.7", + "@iov/encoding": "^2.0.0-alpha.7", + "@iov/ethereum": "^2.0.0-alpha.7", + "@iov/lisk": "^2.0.0-alpha.7", + "@iov/multichain": "^2.0.0-alpha.7", + "@koa/cors": "^3.0.0", + "axios": "^0.19.0", + "bn.js": "^5.1.1", + "fast-deep-equal": "^3.1.1", + "koa": "^2.11.0", + "koa-bodyparser": "^4.2.1", + "readonly-date": "^1.0.0", + "xstream": "^11.11.0" + }, + "devDependencies": { + "@types/bn.js": "^4.11.6", + "@types/chai": "^4.2.7", + "@types/koa": "^2.11.0", + "@types/koa-bodyparser": "^4.3.0", + "@types/koa__cors": "^3.0.1", + "@types/mocha": "^5.2.7", + "chai": "^4.2.0", + "mocha": "^7.0.1" + } +} diff --git a/packages/faucet/src/actions/generate.ts b/packages/faucet/src/actions/generate.ts new file mode 100644 index 00000000..3ca673d2 --- /dev/null +++ b/packages/faucet/src/actions/generate.ts @@ -0,0 +1,20 @@ +import { ChainId } from "@iov/bcp"; +import { Bip39, Random } from "@iov/crypto"; +import { UserProfile } from "@iov/keycontrol"; + +import { codecFromString } from "../codec"; +import { setSecretAndCreateIdentities } from "../profile"; + +export async function generate(args: ReadonlyArray): Promise { + if (args.length < 2) { + throw Error(`Not enough arguments for action 'generate'. See 'iov-faucet help' or README for arguments.`); + } + const codecName = codecFromString(args[0]); + const chainId = args[1] as ChainId; + + const mnemonic = Bip39.encode(await Random.getBytes(16)).toString(); + console.info(`FAUCET_MNEMONIC="${mnemonic}"`); + + const profile = new UserProfile(); + await setSecretAndCreateIdentities(profile, mnemonic, chainId, codecName); +} diff --git a/packages/faucet/src/actions/help.ts b/packages/faucet/src/actions/help.ts new file mode 100644 index 00000000..14cfd7ad --- /dev/null +++ b/packages/faucet/src/actions/help.ts @@ -0,0 +1,33 @@ +export function help(): void { + const out = ` +Usage: iov-faucet action [arguments...] + +Positional arguments per action are listed below. Arguments in parentheses are optional. + +help Shows a help text and exits + +version Prints the version and exits + +generate Generates a random mnemonic, shows derived faucet addresses and exits + 1 Codec + 2 Chain ID + +start Starts the faucet + 1 Codec + 2 Node base URL, e.g. wss://bov.friendnet-fast.iov.one + +Environment variables + +FAUCET_CONCURRENCY Number of distributor accounts. Defaults to 5. +FAUCET_PORT Port of the webserver. Defaults to 8000. +FAUCET_MNEMONIC Secret mnemonic that serves as the base secret for the + faucet HD accounts +FAUCET_CREDIT_AMOUNT_TKN Send this amount of TKN to a user requesting TKN. TKN is + a placeholder for the token ticker. Defaults to 10. +FAUCET_REFILL_FACTOR Send factor times credit amount on refilling. Defauls to 8. +FAUCET_REFILL_THRESHOLD Refill when balance gets below factor times credit amount. + Defaults to 20. +`.trim(); + + process.stdout.write(`${out}\n`); +} diff --git a/packages/faucet/src/actions/index.ts b/packages/faucet/src/actions/index.ts new file mode 100644 index 00000000..036bb348 --- /dev/null +++ b/packages/faucet/src/actions/index.ts @@ -0,0 +1,4 @@ +export { generate } from "./generate"; +export { help } from "./help"; +export { start } from "./start"; +export { version } from "./version"; diff --git a/packages/faucet/src/actions/start/httperror.spec.ts b/packages/faucet/src/actions/start/httperror.spec.ts new file mode 100644 index 00000000..9505bce6 --- /dev/null +++ b/packages/faucet/src/actions/start/httperror.spec.ts @@ -0,0 +1,20 @@ +import { expect } from "chai"; + +import { HttpError } from "./httperror"; + +describe("HttpError", () => { + it("can be constructed", () => { + { + const error = new HttpError(400, "Invalid name field"); + expect(error.message).to.eql("Invalid name field"); + expect(error.status).to.eql(400); + expect(error.expose).to.eql(true); + } + { + const error = new HttpError(500, "Out of memory", false); + expect(error.message).to.eql("Out of memory"); + expect(error.status).to.eql(500); + expect(error.expose).to.eql(false); + } + }); +}); diff --git a/packages/faucet/src/actions/start/httperror.ts b/packages/faucet/src/actions/start/httperror.ts new file mode 100644 index 00000000..4bf02237 --- /dev/null +++ b/packages/faucet/src/actions/start/httperror.ts @@ -0,0 +1,5 @@ +export class HttpError extends Error { + constructor(public readonly status: number, text: string, public readonly expose: boolean = true) { + super(text); + } +} diff --git a/packages/faucet/src/actions/start/index.ts b/packages/faucet/src/actions/start/index.ts new file mode 100644 index 00000000..56e0e121 --- /dev/null +++ b/packages/faucet/src/actions/start/index.ts @@ -0,0 +1 @@ +export { start } from "./start"; diff --git a/packages/faucet/src/actions/start/requestparser.spec.ts b/packages/faucet/src/actions/start/requestparser.spec.ts new file mode 100644 index 00000000..c6d68e25 --- /dev/null +++ b/packages/faucet/src/actions/start/requestparser.spec.ts @@ -0,0 +1,48 @@ +import { expect } from "chai"; + +import { RequestParser } from "./requestparser"; + +describe("RequestParser", () => { + it("can process valid credit request", () => { + const body = { address: "abc", ticker: "CASH" }; + expect(RequestParser.parseCreditBody(body)).to.eql({ address: "abc", ticker: "CASH" }); + }); + + it("throws for invalid credit requests", () => { + // address unset + { + const body = { ticker: "CASH" }; + expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'address' must be a string/i); + } + + // address wrong type + { + const body = { address: true, ticker: "CASH" }; + expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'address' must be a string/i); + } + + // address empty + { + const body = { address: "", ticker: "CASH" }; + expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'address' must not be empty/i); + } + + // ticker unset + { + const body = { address: "abc" }; + expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'ticker' must be a string/i); + } + + // ticker wrong type + { + const body = { address: "abc", ticker: true }; + expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'ticker' must be a string/i); + } + + // ticker empty + { + const body = { address: "abc", ticker: "" }; + expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'ticker' must not be empty/i); + } + }); +}); diff --git a/packages/faucet/src/actions/start/requestparser.ts b/packages/faucet/src/actions/start/requestparser.ts new file mode 100644 index 00000000..2c9cfb4a --- /dev/null +++ b/packages/faucet/src/actions/start/requestparser.ts @@ -0,0 +1,35 @@ +import { Address, TokenTicker } from "@iov/bcp"; + +import { HttpError } from "./httperror"; + +export interface CreditRequestBodyData { + readonly ticker: TokenTicker; + readonly address: Address; +} + +export class RequestParser { + public static parseCreditBody(body: any): CreditRequestBodyData { + const { address, ticker } = body; + + if (typeof address !== "string") { + throw new HttpError(400, "Property 'address' must be a string."); + } + + if (address.length === 0) { + throw new HttpError(400, "Property 'address' must not be empty."); + } + + if (typeof ticker !== "string") { + throw new HttpError(400, "Property 'ticker' must be a string"); + } + + if (ticker.length === 0) { + throw new HttpError(400, "Property 'ticker' must not be empty."); + } + + return { + address: address as Address, + ticker: ticker as TokenTicker, + }; + } +} diff --git a/packages/faucet/src/actions/start/start.ts b/packages/faucet/src/actions/start/start.ts new file mode 100644 index 00000000..1cac66f6 --- /dev/null +++ b/packages/faucet/src/actions/start/start.ts @@ -0,0 +1,157 @@ +/* eslint-disable require-atomic-updates */ +import { UserProfile } from "@iov/keycontrol"; +import { MultiChainSigner } from "@iov/multichain"; +import cors = require("@koa/cors"); +import Koa from "koa"; +import bodyParser from "koa-bodyparser"; + +import { creditAmount, gasLimit, gasPrice, setFractionalDigits } from "../../cashflow"; +import { + codecDefaultFractionalDigits, + codecFromString, + codecImplementation, + createChainConnector, +} from "../../codec"; +import * as constants from "../../constants"; +import { logAccountsState, logSendJob } from "../../debugging"; +import { + accountsOfFirstChain, + availableTokensFromHolder, + identitiesOfFirstWallet, + refillFirstChain, + sendOnFirstChain, + tokenTickersOfFirstChain, +} from "../../multichainhelpers"; +import { setSecretAndCreateIdentities } from "../../profile"; +import { SendJob } from "../../types"; +import { HttpError } from "./httperror"; +import { RequestParser } from "./requestparser"; + +let count = 0; + +/** returns an integer >= 0 that increments and is unique in module scope */ +function getCount(): number { + return count++; +} + +export async function start(args: ReadonlyArray): Promise { + if (args.length < 2) { + throw Error(`Not enough arguments for action 'start'. See 'iov-faucet help' or README for arguments.`); + } + const codec = codecFromString(args[0]); + const blockchainBaseUrl: string = args[1]; + + const port = constants.port; + + const profile = new UserProfile(); + if (!constants.mnemonic) { + throw new Error("The FAUCET_MNEMONIC environment variable is not set"); + } + const signer = new MultiChainSigner(profile); + console.info(`Connecting to blockchain ${blockchainBaseUrl} ...`); + const connection = (await signer.addChain(createChainConnector(codec, blockchainBaseUrl))).connection; + + const connectedChainId = connection.chainId(); + console.info(`Connected to network: ${connectedChainId}`); + + setFractionalDigits(codecDefaultFractionalDigits(codec)); + await setSecretAndCreateIdentities(profile, constants.mnemonic, connectedChainId, codec); + + const chainTokens = await tokenTickersOfFirstChain(signer); + console.info("Chain tokens:", chainTokens); + + const accounts = await accountsOfFirstChain(profile, signer); + logAccountsState(accounts); + + let availableTokens = availableTokensFromHolder(accounts[0]); + console.info("Available tokens:", availableTokens); + setInterval(async () => { + const updatedAccounts = await accountsOfFirstChain(profile, signer); + availableTokens = availableTokensFromHolder(updatedAccounts[0]); + console.info("Available tokens:", availableTokens); + }, 60_000); + + const distibutorIdentities = identitiesOfFirstWallet(profile).slice(1); + + await refillFirstChain(profile, signer, codec); + setInterval(async () => refillFirstChain(profile, signer, codec), 60_000); // ever 60 seconds + + console.info("Creating webserver ..."); + const api = new Koa(); + api.use(cors()); + api.use(bodyParser()); + + api.use(async context => { + switch (context.path) { + case "/": + case "/healthz": + context.response.body = + "Welcome to the faucet!\n" + + "\n" + + "Check the full status via the /status endpoint.\n" + + "You can get tokens from here by POSTing to /credit.\n" + + "See https://github.com/iov-one/iov-faucet for all further information.\n"; + break; + case "/status": { + const updatedAccounts = await accountsOfFirstChain(profile, signer); + context.response.body = { + status: "ok", + nodeUrl: blockchainBaseUrl, + chainId: connectedChainId, + chainTokens: chainTokens, + availableTokens: availableTokens, + holder: updatedAccounts[0], + distributors: updatedAccounts.slice(1), + }; + break; + } + case "/credit": { + if (context.request.method !== "POST") { + throw new HttpError(405, "This endpoint requires a POST request"); + } + + if (context.request.type !== "application/json") { + throw new HttpError(415, "Content-type application/json expected"); + } + + // context.request.body is set by the bodyParser() plugin + const requestBody = (context.request as any).body; + const { address, ticker } = RequestParser.parseCreditBody(requestBody); + + if (!codecImplementation(codec).isValidAddress(address)) { + throw new HttpError(400, "Address is not in the expected format for this chain."); + } + + if (availableTokens.indexOf(ticker) === -1) { + const tokens = JSON.stringify(availableTokens); + throw new HttpError(422, `Token is not available. Available tokens are: ${tokens}`); + } + + const sender = distibutorIdentities[getCount() % distibutorIdentities.length]; + + try { + const job: SendJob = { + sender: sender, + recipient: address, + amount: creditAmount(ticker), + tokenTicker: ticker, + gasPrice: gasPrice(codec), + gasLimit: gasLimit(codec), + }; + logSendJob(signer, job); + await sendOnFirstChain(profile, signer, job); + } catch (e) { + console.error(e); + throw new HttpError(500, "Sending tokens failed"); + } + + context.response.body = "ok"; + break; + } + default: + // koa sends 404 by default + } + }); + console.info(`Starting webserver on port ${port} ...`); + api.listen(port); +} diff --git a/packages/faucet/src/actions/version.ts b/packages/faucet/src/actions/version.ts new file mode 100644 index 00000000..2863d786 --- /dev/null +++ b/packages/faucet/src/actions/version.ts @@ -0,0 +1,15 @@ +import fs from "fs"; + +export async function version(): Promise { + return new Promise((resolve, reject) => { + fs.readFile(__dirname + "/../../package.json", { encoding: "utf8" }, (error, data) => { + if (error) { + reject(error); + } else { + const packagejson = JSON.parse(data); + process.stdout.write(`${packagejson.version}\n`); + resolve(); + } + }); + }); +} diff --git a/packages/faucet/src/cashflow.spec.ts b/packages/faucet/src/cashflow.spec.ts new file mode 100644 index 00000000..7fed499e --- /dev/null +++ b/packages/faucet/src/cashflow.spec.ts @@ -0,0 +1,163 @@ +import { TokenTicker } from "@iov/bcp"; +import { expect } from "chai"; + +import { + creditAmount, + gasLimit, + gasPrice, + refillAmount, + refillThreshold, + setFractionalDigits, +} from "./cashflow"; +import { Codec } from "./codec"; + +describe("Cashflow", () => { + before(() => { + setFractionalDigits(3); + }); + + describe("creditAmount", () => { + it("returns '10' + '000' by default", () => { + expect(creditAmount("TOKENZ" as TokenTicker)).to.eql({ + quantity: "10000", + fractionalDigits: 3, + tokenTicker: "TOKENZ", + }); + expect(creditAmount("TRASH" as TokenTicker)).to.eql({ + quantity: "10000", + fractionalDigits: 3, + tokenTicker: "TRASH", + }); + }); + + it("returns value from env variable + '000' when set", () => { + process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; + expect(creditAmount("WTF" as TokenTicker)).to.eql({ + quantity: "22000", + fractionalDigits: 3, + tokenTicker: "WTF", + }); + }); + + it("returns default from env variable + '000' when set to empty", () => { + process.env.FAUCET_CREDIT_AMOUNT_WTF = ""; + expect(creditAmount("WTF" as TokenTicker)).to.eql({ + quantity: "10000", + fractionalDigits: 3, + tokenTicker: "WTF", + }); + }); + }); + + describe("refillAmount", () => { + beforeEach(() => { + process.env.FAUCET_REFILL_FACTOR = ""; + }); + it("returns 20*10 + '000' by default", () => { + expect(refillAmount("TOKENZ" as TokenTicker)).to.eql({ + quantity: "200000", + fractionalDigits: 3, + tokenTicker: "TOKENZ", + }); + }); + + it("returns 20*22 + '000' when credit amount is 22", () => { + process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; + expect(refillAmount("WTF" as TokenTicker)).to.eql({ + quantity: "440000", + fractionalDigits: 3, + tokenTicker: "WTF", + }); + }); + + it("returns 30*10 + '000' when refill factor is 30", () => { + process.env.FAUCET_REFILL_FACTOR = "30"; + expect(refillAmount("TOKENZ" as TokenTicker)).to.eql({ + quantity: "300000", + fractionalDigits: 3, + tokenTicker: "TOKENZ", + }); + }); + + it("returns 30*22 + '000' when refill factor is 30 and credit amount is 22", () => { + process.env.FAUCET_REFILL_FACTOR = "30"; + process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; + expect(refillAmount("WTF" as TokenTicker)).to.eql({ + quantity: "660000", + fractionalDigits: 3, + tokenTicker: "WTF", + }); + }); + }); + + describe("refillThreshold", () => { + beforeEach(() => { + process.env.FAUCET_REFILL_THRESHOLD = ""; + }); + it("returns 8*10 + '000' by default", () => { + expect(refillThreshold("TOKENZ" as TokenTicker)).to.eql({ + quantity: "80000", + fractionalDigits: 3, + tokenTicker: "TOKENZ", + }); + }); + + it("returns 8*22 + '000' when credit amount is 22", () => { + process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; + expect(refillThreshold("WTF" as TokenTicker)).to.eql({ + quantity: "176000", + fractionalDigits: 3, + tokenTicker: "WTF", + }); + }); + + it("returns 5*10 + '000' when refill threshold is 5", () => { + process.env.FAUCET_REFILL_THRESHOLD = "5"; + expect(refillThreshold("TOKENZ" as TokenTicker)).to.eql({ + quantity: "50000", + fractionalDigits: 3, + tokenTicker: "TOKENZ", + }); + }); + + it("returns 5*22 + '000' when refill threshold is 5 and credit amount is 22", () => { + process.env.FAUCET_REFILL_THRESHOLD = "5"; + process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; + expect(refillThreshold("WTF" as TokenTicker)).to.eql({ + quantity: "110000", + fractionalDigits: 3, + tokenTicker: "WTF", + }); + }); + }); + + describe("gasPrice", () => { + it("returns undefined for non-Ethereum codecs", () => { + expect(gasPrice(Codec.Lisk)).to.be.undefined; + expect(gasPrice(Codec.Bns)).to.be.undefined; + }); + + it("returns amount for Ethereum codec", () => { + expect(gasPrice(Codec.Ethereum)).to.be.eql({ + quantity: "20000000000", + fractionalDigits: 18, + tokenTicker: "ETH", + }); + }); + }); + + describe("gasLimit", () => { + it("returns undefined for non-Ethereum codecs", () => { + expect(gasLimit(Codec.Lisk)).to.be.undefined; + expect(gasLimit(Codec.Bns)).to.be.undefined; + }); + + it("returns amount for Ethereum codec", () => { + expect(gasLimit(Codec.Ethereum)).to.be.eql({ + quantity: "2100000", + fractionalDigits: 18, + tokenTicker: "ETH", + }); + }); + }); +}); diff --git a/packages/faucet/src/cashflow.ts b/packages/faucet/src/cashflow.ts new file mode 100644 index 00000000..079a5c37 --- /dev/null +++ b/packages/faucet/src/cashflow.ts @@ -0,0 +1,95 @@ +import BN = require("bn.js"); + +import { Account, Amount, TokenTicker } from "@iov/bcp"; +import { Int53 } from "@iov/encoding"; + +import { Codec } from "./codec"; +import * as constants from "./constants"; + +/** Send `factor` times credit amount on refilling */ +const defaultRefillFactor = 20; + +/** refill when balance gets below `factor` times credit amount */ +const defaultRefillThresholdFactor = 8; + +// Load this from connection? +let globalFractionalDigits: number | undefined; + +export function setFractionalDigits(input: number): void { + globalFractionalDigits = input; +} + +export function getFractionalDigits(): number { + if (globalFractionalDigits === undefined) { + throw new Error("Fractional digits not set"); + } + return globalFractionalDigits; +} + +/** The amount of tokens that will be sent to the user */ +export function creditAmount(token: TokenTicker, factor = 1): Amount { + const amountFromEnv = process.env[`FAUCET_CREDIT_AMOUNT_${token}`]; + const wholeNumber = amountFromEnv ? Int53.fromString(amountFromEnv).toNumber() : 10; + const total = wholeNumber * factor; + const fractionalDigits = getFractionalDigits(); + // replace BN with BigInt with TypeScript 3.2 and node 11 + const quantity = new BN(total).imul(new BN(10).pow(new BN(fractionalDigits))).toString(); + return { + quantity: quantity, + fractionalDigits: fractionalDigits, + tokenTicker: token, + }; +} + +export function refillAmount(token: TokenTicker): Amount { + const factorFromEnv = Number.parseInt(process.env.FAUCET_REFILL_FACTOR || "0", 10) || undefined; + const factor = factorFromEnv || defaultRefillFactor; + return creditAmount(token, factor); +} + +export function refillThreshold(token: TokenTicker): Amount { + const factorFromEnv = Number.parseInt(process.env.FAUCET_REFILL_THRESHOLD || "0", 10) || undefined; + const factor = factorFromEnv || defaultRefillThresholdFactor; + return creditAmount(token, factor); +} + +/** true iff the distributor account needs a refill */ +export function needsRefill(account: Account, token: TokenTicker): boolean { + const coin = account.balance.find(balance => balance.tokenTicker === token); + + const tokenBalance = coin ? coin.quantity : "0"; + const refillQty = new BN(refillThreshold(token).quantity); + return new BN(tokenBalance).lt(refillQty); +} + +export function gasPrice(codec: Codec): Amount | undefined { + switch (codec) { + case Codec.Bns: + case Codec.Lisk: + return undefined; + case Codec.Ethereum: + return { + quantity: constants.ethereum.gasPrice, + fractionalDigits: 18, + tokenTicker: "ETH" as TokenTicker, + }; + default: + throw new Error("No codec imlementation for this codec found"); + } +} + +export function gasLimit(codec: Codec): Amount | undefined { + switch (codec) { + case Codec.Bns: + case Codec.Lisk: + return undefined; + case Codec.Ethereum: + return { + quantity: constants.ethereum.gasLimit, + fractionalDigits: 18, + tokenTicker: "ETH" as TokenTicker, + }; + default: + throw new Error("Codec not supported"); + } +} diff --git a/packages/faucet/src/codec.spec.ts b/packages/faucet/src/codec.spec.ts new file mode 100644 index 00000000..bf5ff998 --- /dev/null +++ b/packages/faucet/src/codec.spec.ts @@ -0,0 +1,16 @@ +import { expect } from "chai"; + +import { Codec, codecFromString } from "./codec"; + +describe("Codec", () => { + it("can convert string to codec", () => { + expect(codecFromString("bns")).to.equal(Codec.Bns); + expect(codecFromString("lisk")).to.equal(Codec.Lisk); + expect(codecFromString("ethereum")).to.equal(Codec.Ethereum); + + expect(() => codecFromString("")).to.throw(/not supported/i); + expect(() => codecFromString("abc")).to.throw(/not supported/i); + expect(() => codecFromString("LISK")).to.throw(/not supported/i); + expect(() => codecFromString("ETHEREUM")).to.throw(/not supported/i); + }); +}); diff --git a/packages/faucet/src/codec.ts b/packages/faucet/src/codec.ts new file mode 100644 index 00000000..1080a85e --- /dev/null +++ b/packages/faucet/src/codec.ts @@ -0,0 +1,80 @@ +import { ChainConnector, TxCodec } from "@iov/bcp"; +import { bnsCodec, createBnsConnector } from "@iov/bns"; +import { Slip10RawIndex } from "@iov/crypto"; +import { createEthereumConnector, ethereumCodec } from "@iov/ethereum"; +import { HdPaths } from "@iov/keycontrol"; +import { createLiskConnector, liskCodec } from "@iov/lisk"; + +export const enum Codec { + Bns, + Lisk, + Ethereum, +} + +export function codecFromString(input: string): Codec { + switch (input) { + case "bns": + return Codec.Bns; + case "lisk": + return Codec.Lisk; + case "ethereum": + return Codec.Ethereum; + default: + throw new Error(`Codec '${input}' not supported`); + } +} + +export function codecImplementation(codec: Codec): TxCodec { + switch (codec) { + case Codec.Bns: + return bnsCodec; + case Codec.Lisk: + return liskCodec; + case Codec.Ethereum: + return ethereumCodec; + default: + throw new Error("No codec implementation for this codec found"); + } +} + +export function createPathBuilderForCodec(codec: Codec): (derivation: number) => readonly Slip10RawIndex[] { + const pathBuilder = (accountIndex: number): readonly Slip10RawIndex[] => { + switch (codec) { + case Codec.Bns: + return HdPaths.iov(accountIndex); + case Codec.Lisk: + return HdPaths.bip44Like(134, accountIndex); + case Codec.Ethereum: + return HdPaths.ethereum(accountIndex); + default: + throw new Error("No path builder for this codec found"); + } + }; + return pathBuilder; +} + +export function createChainConnector(codec: Codec, url: string): ChainConnector { + switch (codec) { + case Codec.Bns: + return createBnsConnector(url); + case Codec.Lisk: + return createLiskConnector(url); + case Codec.Ethereum: + return createEthereumConnector(url, {}); + default: + throw new Error("No connector for this codec found"); + } +} + +export function codecDefaultFractionalDigits(codec: Codec): number { + switch (codec) { + case Codec.Bns: + return 9; // fixed for all weave tokens + case Codec.Lisk: + return 8; + case Codec.Ethereum: + return 18; + default: + throw new Error("Unknown codec"); + } +} diff --git a/packages/faucet/src/constants.ts b/packages/faucet/src/constants.ts new file mode 100644 index 00000000..9ff6e410 --- /dev/null +++ b/packages/faucet/src/constants.ts @@ -0,0 +1,7 @@ +export const concurrency: number = Number.parseInt(process.env.FAUCET_CONCURRENCY || "", 10) || 5; +export const port: number = Number.parseInt(process.env.FAUCET_PORT || "", 10) || 8000; +export const mnemonic: string | undefined = process.env.FAUCET_MNEMONIC; +export const ethereum = { + gasPrice: "20000000000", + gasLimit: "2100000", +}; diff --git a/packages/faucet/src/crypto.ts b/packages/faucet/src/crypto.ts new file mode 100644 index 00000000..59424ef9 --- /dev/null +++ b/packages/faucet/src/crypto.ts @@ -0,0 +1,15 @@ +import { Ed25519HdWallet, Secp256k1HdWallet, Wallet } from "@iov/keycontrol"; + +import { Codec } from "./codec"; + +export function createWalletForCodec(input: Codec, mnemonic: string): Wallet { + switch (input) { + case Codec.Bns: + case Codec.Lisk: + return Ed25519HdWallet.fromMnemonic(mnemonic); + case Codec.Ethereum: + return Secp256k1HdWallet.fromMnemonic(mnemonic); + default: + throw new Error(`Codec '${input}' not supported`); + } +} diff --git a/packages/faucet/src/debugging.ts b/packages/faucet/src/debugging.ts new file mode 100644 index 00000000..5b5adc09 --- /dev/null +++ b/packages/faucet/src/debugging.ts @@ -0,0 +1,58 @@ +import { Account, Amount } from "@iov/bcp"; +import { MultiChainSigner } from "@iov/multichain"; + +import { SendJob } from "./types"; + +export function amountToNumber(amount: Amount): number { + const { quantity, fractionalDigits } = amount; + if (!quantity.match(/^[0-9]+$/)) { + throw new Error(`quantity must be a number, got ${quantity}`); + } + if (fractionalDigits < 0) { + throw new Error(`invalid fractional digits: ${fractionalDigits}`); + } + // let's remove those leading zeros... + const temp = quantity.replace(/^0+/, ""); + // unless we need them to reach a decimal point + const pad = fractionalDigits - temp.length; + const trimmed = pad > 0 ? "0".repeat(pad) + temp : temp; + + const cut = trimmed.length - fractionalDigits; + const whole = cut === 0 ? "0" : trimmed.slice(0, cut); + const decimal = fractionalDigits === 0 ? "" : `.${trimmed.slice(cut)}`; + const value = `${whole}${decimal}`; + + return Number(value); +} + +/** A string representation of a coin in a human-readable format that can change at any time */ +export function debugCoin(coin: Amount): string { + return `${amountToNumber(coin)} ${coin.tokenTicker}`; +} + +/** A string representation of a balance in a human-readable format that can change at any time */ +export function debugBalance(data: ReadonlyArray): string { + return `[${data.map(debugCoin).join(", ")}]`; +} + +/** A string representation of an account in a human-readable format that can change at any time */ +export function debugAccount(account: Account): string { + return `${account.address}: ${debugBalance(account.balance)}`; +} + +export function logAccountsState(accounts: ReadonlyArray): void { + if (accounts.length < 2) { + throw new Error("List of accounts must contain at least one token holder and one distributor"); + } + const holder = accounts[0]; + const distributors = accounts.slice(1); + console.info("Holder:\n" + ` ${debugAccount(holder)}`); + console.info("Distributors:\n" + distributors.map(r => ` ${debugAccount(r)}`).join("\n")); +} + +export function logSendJob(signer: MultiChainSigner, job: SendJob): void { + const from = signer.identityToAddress(job.sender); + const to = job.recipient; + const amount = debugCoin(job.amount); + console.info(`Sending ${amount} from ${from} to ${to} ...`); +} diff --git a/packages/faucet/src/faucet.ts b/packages/faucet/src/faucet.ts new file mode 100644 index 00000000..3587566a --- /dev/null +++ b/packages/faucet/src/faucet.ts @@ -0,0 +1,38 @@ +import { generate, help, start, version } from "./actions"; + +export function main(args: ReadonlyArray): void { + if (args.length < 1) { + help(); + process.exit(1); + return; + } + + const action = args[0]; + const restArgs = args.slice(1); + + switch (action) { + case "generate": + generate(restArgs).catch(error => { + console.error(error); + process.exit(1); + }); + break; + case "help": + help(); + break; + case "version": + version().catch(error => { + console.error(error); + process.exit(1); + }); + break; + case "start": + start(restArgs).catch(error => { + console.error(error); + process.exit(1); + }); + break; + default: + throw new Error("Unexpected action argument"); + } +} diff --git a/packages/faucet/src/hdpaths.spec.ts b/packages/faucet/src/hdpaths.spec.ts new file mode 100644 index 00000000..ff92f9f1 --- /dev/null +++ b/packages/faucet/src/hdpaths.spec.ts @@ -0,0 +1,45 @@ +import { Slip10RawIndex } from "@iov/crypto"; +import { expect } from "chai"; + +import { debugPath } from "./hdpaths"; + +describe("hdpaths", () => { + describe("debugPath", () => { + it("works for no component", () => { + // See https://github.com/bitcoin/bips/blob/master/bip-0032/derivation.png from BIP32 + expect(debugPath([])).to.eql("m"); + }); + + it("works for normal components", () => { + const one = Slip10RawIndex.normal(1); + expect(debugPath([one])).to.eql("m/1"); + expect(debugPath([one, one])).to.eql("m/1/1"); + expect(debugPath([one, one, one])).to.eql("m/1/1/1"); + + const min = Slip10RawIndex.normal(0); + expect(debugPath([min])).to.eql("m/0"); + + const max = Slip10RawIndex.normal(2 ** 31 - 1); + expect(debugPath([max])).to.eql("m/2147483647"); + }); + + it("works for hardened components", () => { + const one = Slip10RawIndex.hardened(1); + expect(debugPath([one])).to.eql("m/1'"); + expect(debugPath([one, one])).to.eql("m/1'/1'"); + expect(debugPath([one, one, one])).to.eql("m/1'/1'/1'"); + + const min = Slip10RawIndex.hardened(0); + expect(debugPath([min])).to.eql("m/0'"); + + const max = Slip10RawIndex.hardened(2 ** 31 - 1); + expect(debugPath([max])).to.eql("m/2147483647'"); + }); + + it("works for mixed components", () => { + const one = Slip10RawIndex.normal(1); + const two = Slip10RawIndex.hardened(2); + expect(debugPath([one, two, two, one])).to.eql("m/1/2'/2'/1"); + }); + }); +}); diff --git a/packages/faucet/src/hdpaths.ts b/packages/faucet/src/hdpaths.ts new file mode 100644 index 00000000..f61e35ba --- /dev/null +++ b/packages/faucet/src/hdpaths.ts @@ -0,0 +1,10 @@ +import { Slip10RawIndex } from "@iov/crypto"; + +export function debugPath(path: readonly Slip10RawIndex[]): string { + return path.reduce((current, component): string => { + const componentString = component.isHardened() + ? `${component.toNumber() - 2 ** 31}'` + : component.toString(); + return current + "/" + componentString; + }, "m"); +} diff --git a/packages/faucet/src/multichainhelpers.spec.ts b/packages/faucet/src/multichainhelpers.spec.ts new file mode 100644 index 00000000..0531c26e --- /dev/null +++ b/packages/faucet/src/multichainhelpers.spec.ts @@ -0,0 +1,57 @@ +import { Address, Algorithm, PubkeyBundle, PubkeyBytes, TokenTicker } from "@iov/bcp"; +import { expect } from "chai"; + +import { availableTokensFromHolder } from "./multichainhelpers"; + +describe("multichainhelpers", () => { + describe("availableTokensFromHolder", () => { + const defaultPubkey: PubkeyBundle = { + algo: Algorithm.Ed25519, + data: new Uint8Array([0, 1, 2, 3]) as PubkeyBytes, + }; + + it("works for an empty account", () => { + const tickers = availableTokensFromHolder({ + address: "aabbccdd" as Address, + pubkey: defaultPubkey, + balance: [], + }); + expect(tickers).to.be.empty; + }); + + it("works for one token", () => { + const tickers = availableTokensFromHolder({ + address: "aabbccdd" as Address, + pubkey: defaultPubkey, + balance: [ + { + quantity: "1", + fractionalDigits: 9, + tokenTicker: "CASH" as TokenTicker, + }, + ], + }); + expect(tickers).to.eql(["CASH"]); + }); + + it("works for two tokens", () => { + const tickers = availableTokensFromHolder({ + address: "aabbccdd" as Address, + pubkey: defaultPubkey, + balance: [ + { + quantity: "1", + fractionalDigits: 9, + tokenTicker: "CASH" as TokenTicker, + }, + { + quantity: "1", + fractionalDigits: 9, + tokenTicker: "TRASH" as TokenTicker, + }, + ], + }); + expect(tickers).to.eql(["CASH", "TRASH"]); + }); + }); +}); diff --git a/packages/faucet/src/multichainhelpers.ts b/packages/faucet/src/multichainhelpers.ts new file mode 100644 index 00000000..6b98d0ab --- /dev/null +++ b/packages/faucet/src/multichainhelpers.ts @@ -0,0 +1,145 @@ +import { + Account, + Identity, + isBlockInfoFailed, + isBlockInfoPending, + SendTransaction, + TokenTicker, + WithCreator, +} from "@iov/bcp"; +import { UserProfile } from "@iov/keycontrol"; +import { MultiChainSigner } from "@iov/multichain"; + +import { gasLimit, gasPrice, needsRefill, refillAmount } from "./cashflow"; +import { Codec } from "./codec"; +import { debugAccount, logAccountsState, logSendJob } from "./debugging"; +import { SendJob } from "./types"; + +async function sleep(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export function identitiesOfFirstWallet(profile: UserProfile): ReadonlyArray { + const wallet = profile.wallets.value[0]; + return profile.getIdentities(wallet.id); +} + +export async function accountsOfFirstChain( + profile: UserProfile, + signer: MultiChainSigner, +): Promise> { + const addresses = identitiesOfFirstWallet(profile).map(identity => signer.identityToAddress(identity)); + const chainId = signer.chainIds()[0]; + + const out: Account[] = []; + for (const address of addresses) { + const response = await signer.connection(chainId).getAccount({ address: address }); + if (response) { + out.push({ + address: response.address, + balance: response.balance, + }); + } else { + out.push({ + address: address, + balance: [], + }); + } + } + + return out; +} + +export async function tokenTickersOfFirstChain( + signer: MultiChainSigner, +): Promise> { + const chainId = signer.chainIds()[0]; + return (await signer.connection(chainId).getAllTokens()).map(token => token.tokenTicker); +} + +/** + * Creates and posts a send transaction. Then waits until the transaction is in a block. + */ +export async function sendOnFirstChain( + profile: UserProfile, + signer: MultiChainSigner, + job: SendJob, +): Promise { + const chainId = signer.chainIds()[0]; + const connection = signer.connection(chainId); + + const sendWithFee = await connection.withDefaultFee({ + kind: "bcp/send", + creator: { + chainId: chainId, + pubkey: job.sender.pubkey, + }, + sender: signer.identityToAddress(job.sender), + recipient: job.recipient, + memo: "We ❤️ developers – iov.one", + amount: job.amount, + }); + + const post = await signer.signAndPost(sendWithFee); + const blockInfo = await post.blockInfo.waitFor(info => !isBlockInfoPending(info)); + if (isBlockInfoFailed(blockInfo)) { + throw new Error(`Sending tokens failed. Code: ${blockInfo.code}, message: ${blockInfo.message}`); + } +} + +export function availableTokensFromHolder(holderAccount: Account): ReadonlyArray { + return holderAccount.balance.map(coin => coin.tokenTicker); +} + +export async function refillFirstChain( + profile: UserProfile, + signer: MultiChainSigner, + codec: Codec, +): Promise { + const chainId = signer.chainIds()[0]; + + console.info(`Connected to network: ${chainId}`); + console.info(`Tokens on network: ${(await tokenTickersOfFirstChain(signer)).join(", ")}`); + + const holderIdentity = identitiesOfFirstWallet(profile)[0]; + + const accounts = await accountsOfFirstChain(profile, signer); + logAccountsState(accounts); + const holderAccount = accounts[0]; + const distributorAccounts = accounts.slice(1); + + const availableTokens = availableTokensFromHolder(holderAccount); + console.info("Available tokens:", availableTokens); + + const jobs: SendJob[] = []; + + for (const token of availableTokens) { + const refillDistibutors = distributorAccounts.filter(account => needsRefill(account, token)); + console.info(`Refilling ${token} of:`); + console.info( + refillDistibutors.length ? refillDistibutors.map(r => ` ${debugAccount(r)}`).join("\n") : " none", + ); + for (const refillDistibutor of refillDistibutors) { + jobs.push({ + sender: holderIdentity, + recipient: refillDistibutor.address, + tokenTicker: token, + amount: refillAmount(token), + gasPrice: gasPrice(codec), + gasLimit: gasLimit(codec), + }); + } + } + if (jobs.length > 0) { + for (const job of jobs) { + logSendJob(signer, job); + await sendOnFirstChain(profile, signer, job); + await sleep(50); + } + + console.info("Done refilling accounts."); + logAccountsState(await accountsOfFirstChain(profile, signer)); + } else { + console.info("Nothing to be done. Anyways, thanks for checking."); + } +} diff --git a/packages/faucet/src/profile.ts b/packages/faucet/src/profile.ts new file mode 100644 index 00000000..36c0352e --- /dev/null +++ b/packages/faucet/src/profile.ts @@ -0,0 +1,34 @@ +import { ChainId } from "@iov/bcp"; +import { UserProfile } from "@iov/keycontrol"; + +import { Codec, codecImplementation, createPathBuilderForCodec } from "./codec"; +import * as constants from "./constants"; +import { createWalletForCodec } from "./crypto"; +import { debugPath } from "./hdpaths"; + +export async function setSecretAndCreateIdentities( + profile: UserProfile, + mnemonic: string, + chainId: ChainId, + codecName: Codec, +): Promise { + if (profile.wallets.value.length !== 0) { + throw new Error("Profile already contains wallets"); + } + const wallet = profile.addWallet(createWalletForCodec(codecName, mnemonic)); + + const pathBuilder = createPathBuilderForCodec(codecName); + + // first account is the token holder + const numberOfIdentities = 1 + constants.concurrency; + for (let i = 0; i < numberOfIdentities; i++) { + // create + const path = pathBuilder(i); + const identity = await profile.createIdentity(wallet.id, chainId, path); + + // log + const role = i === 0 ? "token holder " : `distributor ${i}`; + const address = codecImplementation(codecName).identityToAddress(identity); + console.info(`Created ${role} (${debugPath(path)}): ${address}`); + } +} diff --git a/packages/faucet/src/types.ts b/packages/faucet/src/types.ts new file mode 100644 index 00000000..a4a0cc34 --- /dev/null +++ b/packages/faucet/src/types.ts @@ -0,0 +1,10 @@ +import { Address, Amount, Identity, TokenTicker } from "@iov/bcp"; + +export interface SendJob { + readonly sender: Identity; + readonly recipient: Address; + readonly tokenTicker: TokenTicker; + readonly amount: Amount; + readonly gasPrice?: Amount; + readonly gasLimit?: Amount; +} diff --git a/packages/faucet/tsconfig.json b/packages/faucet/tsconfig.json new file mode 100644 index 00000000..167e8c02 --- /dev/null +++ b/packages/faucet/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": ".", + "outDir": "build", + "declarationDir": "build/types", + "rootDir": "src" + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/faucet/tslint.json b/packages/faucet/tslint.json new file mode 100644 index 00000000..0946f209 --- /dev/null +++ b/packages/faucet/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tslint.json" +} diff --git a/packages/faucet/typedoc.js b/packages/faucet/typedoc.js new file mode 100644 index 00000000..e2387c7d --- /dev/null +++ b/packages/faucet/typedoc.js @@ -0,0 +1,14 @@ +const packageJson = require("./package.json"); + +module.exports = { + src: ["./src"], + out: "docs", + exclude: "**/*.spec.ts", + target: "es6", + name: `${packageJson.name} Documentation`, + readme: "README.md", + mode: "file", + excludeExternals: true, + excludeNotExported: true, + excludePrivate: true, +}; diff --git a/yarn.lock b/yarn.lock index fc1ff754..52522ace 100644 --- a/yarn.lock +++ b/yarn.lock @@ -103,6 +103,25 @@ type-tagger "^1.0.0" xstream "^11.10.0" +"@iov/bns@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/bns/-/bns-2.0.0-alpha.7.tgz#83a9ab0fa97631c7d42f32038b8fb1b86d318405" + integrity sha512-xX/o65HC78SfxJLLZE6pSUcfszwDezXovYBuhoelR0vIHqGbZjetksWwXrBz7zgkyBXQnXcfUDFgyaefFfmJjw== + dependencies: + "@iov/bcp" "^2.0.0-alpha.7" + "@iov/crypto" "^2.0.0-alpha.7" + "@iov/encoding" "^2.0.0-alpha.7" + "@iov/stream" "^2.0.0-alpha.7" + "@iov/tendermint-rpc" "^2.0.0-alpha.7" + "@types/long" "^4.0.0" + "@types/node" "^10.12.18" + bn.js "^4.11.8" + fast-deep-equal "^3.1.1" + long "^4.0.0" + protobufjs "^6.8.6" + type-tagger "^1.0.0" + xstream "^11.10.0" + "@iov/crypto@^2.0.0-alpha.7": version "2.0.0-alpha.7" resolved "https://registry.yarnpkg.com/@iov/crypto/-/crypto-2.0.0-alpha.7.tgz#5cb24dbc3cdd344bf782039f1fe6d55975d171f6" @@ -130,6 +149,37 @@ bn.js "^4.11.8" readonly-date "^1.0.0" +"@iov/ethereum@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/ethereum/-/ethereum-2.0.0-alpha.7.tgz#f1a72947e5ce62a7afc56f0320866f08b2bf01b9" + integrity sha512-q+AJsIuwbBbrEMpztgGQIsApFJQ/n7t9Uq/pi3OGqUdcXCG6JYJH+XjClv0yIVcMB8pxfNwQ9RvYy75Zpn0icw== + dependencies: + "@iov/bcp" "^2.0.0-alpha.7" + "@iov/crypto" "^2.0.0-alpha.7" + "@iov/encoding" "^2.0.0-alpha.7" + "@iov/jsonrpc" "^2.0.0-alpha.7" + "@iov/keycontrol" "^2.0.0-alpha.7" + "@iov/socket" "^2.0.0-alpha.7" + "@iov/stream" "^2.0.0-alpha.7" + "@iov/utils" "^2.0.0-alpha.7" + "@types/long" "^4.0.0" + axios "^0.19.0" + bn.js "^4.11.8" + fast-deep-equal "^3.1.1" + long "^4.0.0" + readonly-date "^1.0.0" + rlp "^2.2.3" + xstream "^11.10.0" + +"@iov/jsonrpc@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/jsonrpc/-/jsonrpc-2.0.0-alpha.7.tgz#7bff8e1f21d52ff07482212ded8cc00e01dda964" + integrity sha512-eVCfNi3Zg4ZUEXOxhzRb3kcoBupBGQWmU4pYu7OYBi3uvuUz8KP6kcIdsy+51+y/nqrnk3H2Ur7MWCzwsu215w== + dependencies: + "@iov/encoding" "^2.0.0-alpha.7" + "@iov/stream" "^2.0.0-alpha.7" + xstream "^11.10.0" + "@iov/keycontrol@^2.0.0-alpha.7": version "2.0.0-alpha.7" resolved "https://registry.yarnpkg.com/@iov/keycontrol/-/keycontrol-2.0.0-alpha.7.tgz#d115a1b536664afb64b40a6db87aaf19f8d07afd" @@ -150,6 +200,45 @@ type-tagger "^1.0.0" xstream "^11.10.0" +"@iov/lisk@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/lisk/-/lisk-2.0.0-alpha.7.tgz#5ff6c617ac00e6be736ada34ad68dce0efd64637" + integrity sha512-m5mr2NDU7pxuS8d6SBXCZ1WBtCSXtV+EWqMEIuPSCJwZxnwmWotowX+WhSYn+dGyuvgTd7DpfQ5C6pliAyhcyQ== + dependencies: + "@iov/bcp" "^2.0.0-alpha.7" + "@iov/crypto" "^2.0.0-alpha.7" + "@iov/encoding" "^2.0.0-alpha.7" + "@iov/keycontrol" "^2.0.0-alpha.7" + "@iov/stream" "^2.0.0-alpha.7" + "@types/long" "^4.0.0" + axios "^0.19.0" + fast-deep-equal "^3.1.1" + long "^4.0.0" + readonly-date "^1.0.0" + xstream "^11.10.0" + +"@iov/multichain@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/multichain/-/multichain-2.0.0-alpha.7.tgz#29ec9f61ec2fa60c17d462c9be48feb7196c28ba" + integrity sha512-hhEyqalADrQa4JS99JqawM7jWLYGqb52Ipq/49Zz5eDG9/nj9QyLn5nayWLTbm60ZXzHvvGr5oJpZx8Xb2PzfA== + dependencies: + "@iov/bcp" "^2.0.0-alpha.7" + "@iov/encoding" "^2.0.0-alpha.7" + "@iov/jsonrpc" "^2.0.0-alpha.7" + "@iov/keycontrol" "^2.0.0-alpha.7" + "@types/long" "^4.0.0" + long "^4.0.0" + +"@iov/socket@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/socket/-/socket-2.0.0-alpha.7.tgz#d88baf91617a91d87b5f5d51a11b2bc0800cf532" + integrity sha512-4c96cvwRJTEuG2vrUM36v3sFq5tkxZ3afn21zqUXIfaAo9VC3wFSpEUXjyx7/j1iwC7SOPOT2ExckiyMWBTa9A== + dependencies: + "@iov/stream" "^2.0.0-alpha.7" + isomorphic-ws "^4.0.1" + ws "^6.2.0" + xstream "^11.10.0" + "@iov/stream@^2.0.0-alpha.7": version "2.0.0-alpha.7" resolved "https://registry.yarnpkg.com/@iov/stream/-/stream-2.0.0-alpha.7.tgz#212c3f684f592ec04ac43e166183d946a49b895c" @@ -157,6 +246,32 @@ dependencies: xstream "^11.10.0" +"@iov/tendermint-rpc@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/tendermint-rpc/-/tendermint-rpc-2.0.0-alpha.7.tgz#5c70bdcb0c2850be4012812116cbe1188bc9bdd6" + integrity sha512-UaMu7wCGiiT5baIDdeTwQ3gCWFd4J1fJDDico/RuAqxbGhtvZSUpzevv+r/xeysydviNLue1J1w2ZdqTS9mJRg== + dependencies: + "@iov/crypto" "^2.0.0-alpha.7" + "@iov/encoding" "^2.0.0-alpha.7" + "@iov/jsonrpc" "^2.0.0-alpha.7" + "@iov/socket" "^2.0.0-alpha.7" + axios "^0.19.0" + readonly-date "^1.0.0" + type-tagger "^1.0.0" + xstream "^11.10.0" + +"@iov/utils@^2.0.0-alpha.7": + version "2.0.0-alpha.7" + resolved "https://registry.yarnpkg.com/@iov/utils/-/utils-2.0.0-alpha.7.tgz#af9aebcb9e221e53cf62c5511f007c65d95f5c0c" + integrity sha512-myWATqmlCFZ/jSrsBQlyn+6D2ViAscZVAqBAw38kbIfv3TiKTjWb2RqhlNDnlVgt3uD0ZtQFyY9hkRMCwfIk+w== + +"@koa/cors@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.0.0.tgz#df021b4df2dadf1e2b04d7c8ddf93ba2d42519cb" + integrity sha512-hDp+cXj6vTYSwHRJfiSpnf5dTMv3FmqNKh1or9BPJk4SHOviHnK9GoL9dT0ypt/E+hlkRkZ9edHylcosW3Ghrw== + dependencies: + vary "^1.1.2" + "@lerna/add@3.20.0": version "3.20.0" resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.20.0.tgz#bea7edf36fc93fb72ec34cb9ba854c48d4abf309" @@ -925,6 +1040,59 @@ dependencies: "@types/node" ">= 8" +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78= + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A= + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= + "@tendermint/amino-js@^0.7.0-alpha.1": version "0.7.0-alpha.1" resolved "https://registry.yarnpkg.com/@tendermint/amino-js/-/amino-js-0.7.0-alpha.1.tgz#5d9f689fb601a0c0a6bb245a16d0b9a197f616e5" @@ -950,6 +1118,50 @@ resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.1.tgz#3c7750d0186b954c7f2d2f6acc8c3c7ba0c3412e" integrity sha512-wYxU3kp5zItbxKmeRYCEplS2MW7DzyBnxPGj+GJVHZEUZiK/nn5Ei1sUFgURDh+X051+zsGe28iud3oHjrYWQQ== +"@types/accepts@*": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" + integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ== + dependencies: + "@types/node" "*" + +"@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/body-parser@*": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.1.tgz#18fcf61768fb5c30ccc508c21d6fd2e8b3bf7897" + integrity sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/chai@^4.2.7": + version "4.2.7" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d" + integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g== + +"@types/connect@*": + version "3.4.33" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" + integrity sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A== + dependencies: + "@types/node" "*" + +"@types/cookies@*": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.4.tgz#26dedf791701abc0e36b5b79a5722f40e455f87b" + integrity sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw== + dependencies: + "@types/connect" "*" + "@types/express" "*" + "@types/keygrip" "*" + "@types/node" "*" + "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" @@ -960,6 +1172,23 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== +"@types/express-serve-static-core@*": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz#f6f41fa35d42e79dbf6610eccbb2637e6008a0cf" + integrity sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg== + dependencies: + "@types/node" "*" + "@types/range-parser" "*" + +"@types/express@*": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.2.tgz#a0fb7a23d8855bac31bc01d5a58cadd9b2173e6c" + integrity sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + "@types/glob@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" @@ -969,6 +1198,11 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/http-assert@*": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.1.tgz#d775e93630c2469c2f980fc27e3143240335db3b" + integrity sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ== + "@types/jasmine@^3.3.7": version "3.5.1" resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.1.tgz#e417aa74738aa9e9285016abbfcae68d5be0f827" @@ -979,6 +1213,44 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/keygrip@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72" + integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw== + +"@types/koa-bodyparser@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz#54ecd662c45f3a4fa9de849528de5fc8ab269ba5" + integrity sha512-aB/vwwq4G9FAtKzqZ2p8UHTscXxZvICFKVjuckqxCtkX1Ro7F5KHkTCUqTRZFBgDoEkmeca+bFLI1bIsdPPZTA== + dependencies: + "@types/koa" "*" + +"@types/koa-compose@*": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.5.tgz#85eb2e80ac50be95f37ccf8c407c09bbe3468e9d" + integrity sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ== + dependencies: + "@types/koa" "*" + +"@types/koa@*", "@types/koa@^2.11.0": + version "2.11.0" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.11.0.tgz#394a3e9ec94f796003a6c8374b4dbc2778746f20" + integrity sha512-Hgx/1/rVlJvqYBrdeCsS7PDiR2qbxlMt1RnmNWD4Uxi5FF9nwkYqIldo7urjc+dfNpk+2NRGcnAYd4L5xEhCcQ== + dependencies: + "@types/accepts" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + +"@types/koa__cors@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-3.0.1.tgz#a8cf8535f0fe682c9421f1b9379837c585f8b66b" + integrity sha512-loqZNXliley8kncc4wrX9KMqLGN6YfiaO3a3VFX+yVkkXJwOrZU4lipdudNjw5mFyC+5hd7h9075hQWcVVpeOg== + dependencies: + "@types/koa" "*" + "@types/levelup@^3.1.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-3.1.1.tgz#f7cc08f248f14cb6c92914e91bceb8761020e8f0" @@ -987,6 +1259,11 @@ "@types/abstract-leveldown" "*" "@types/node" "*" +"@types/long@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" + integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== + "@types/memdown@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/memdown/-/memdown-3.0.0.tgz#2d909cb507afd341e3132d77dafa213347e47455" @@ -994,11 +1271,21 @@ dependencies: "@types/abstract-leveldown" "*" +"@types/mime@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" + integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/mocha@^5.2.7": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + "@types/node@*", "@types/node@>= 8": version "13.5.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.5.0.tgz#4e498dbf355795a611a87ae5ef811a8660d42662" @@ -1009,6 +1296,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== +"@types/node@^10.1.0": + version "10.17.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.14.tgz#b6c60ebf2fb5e4229fdd751ff9ddfae0f5f31541" + integrity sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw== + "@types/node@^10.12.18": version "10.17.13" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c" @@ -1019,6 +1311,19 @@ resolved "https://registry.yarnpkg.com/@types/random-js/-/random-js-1.0.31.tgz#18a8bcc075afa504421e638fcbe021f27e802941" integrity sha512-EAM56DrKw3VhcE4HV0/YlVKeJI07We4Mz1ra6TNtZpaMoiBVMA2bkLEcoFpYOyxoDXfVZWojxkR617LTqtRI0A== +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + +"@types/serve-static@*": + version "1.13.3" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" + integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g== + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + "@typescript-eslint/eslint-plugin@^2.10.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.17.0.tgz#880435a9f9bdd50b45fa286ba63fed723d73c837" @@ -1257,7 +1562,7 @@ abstract-leveldown@~6.2.1: level-supports "~1.0.0" xtend "~4.0.0" -accepts@~1.3.4: +accepts@^1.3.5, accepts@~1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== @@ -1326,6 +1631,11 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -1365,7 +1675,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -any-promise@^1.0.0: +any-promise@^1.0.0, any-promise@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= @@ -1519,6 +1829,11 @@ assert@^1.1.1: object-assign "^4.1.1" util "0.10.3" +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -1682,11 +1997,16 @@ bluebird@^3.3.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.8, bn.js@^4.4.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.1, bn.js@^4.11.8, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== +bn.js@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.1.tgz#48efc4031a9c4041b9c99c6941d903463ab62eb5" + integrity sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA== + body-parser@^1.16.1: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -1739,6 +2059,11 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -1906,6 +2231,14 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cache-content-type@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c" + integrity sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA== + dependencies: + mime-types "^2.1.18" + ylru "^1.2.0" + call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" @@ -1977,7 +2310,19 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.2: +chai@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" + integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.0" + type-detect "^4.0.5" + +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1991,6 +2336,26 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + chokidar@^2.0.2: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -2102,6 +2467,21 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= +co-body@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.0.0.tgz#965b9337d7f5655480787471f4237664820827e3" + integrity sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw== + dependencies: + inflation "^2.0.0" + qs "^6.5.2" + raw-body "^2.3.3" + type-is "^1.6.16" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -2253,7 +2633,14 @@ contains-path@^0.1.0: resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -content-type@~1.0.4: +content-disposition@~0.5.2: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@^1.0.4, content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== @@ -2346,6 +2733,14 @@ cookie@0.3.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= +cookies@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" + integrity sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow== + dependencies: + depd "~2.0.0" + keygrip "~1.1.0" + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -2363,6 +2758,11 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= +copy-to@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5" + integrity sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU= + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2492,7 +2892,7 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: +debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -2534,6 +2934,18 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deep-equal@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -2593,11 +3005,16 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -depd@~1.1.2: +depd@^1.1.2, depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +depd@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + deprecation@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" @@ -2611,6 +3028,11 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" +destroy@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" @@ -2634,6 +3056,11 @@ di@^0.0.1: resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -2760,7 +3187,7 @@ emojis-list@^2.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= -encodeurl@~1.0.2: +encodeurl@^1.0.2, encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= @@ -2871,6 +3298,11 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-inject@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37" + integrity sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc= + es-abstract@^1.17.0, es-abstract@^1.17.0-next.1: version "1.17.4" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" @@ -2914,12 +3346,12 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -3299,6 +3731,13 @@ find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -3314,13 +3753,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - findup-sync@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" @@ -3340,6 +3772,13 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + flatted@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" @@ -3393,6 +3832,11 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +fresh@~0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" @@ -3456,7 +3900,7 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" -fsevents@~2.1.2: +fsevents@~2.1.1, fsevents@~2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== @@ -3495,6 +3939,11 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + get-pkg-repo@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" @@ -3609,6 +4058,18 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -3683,6 +4144,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + handlebars@^4.4.0: version "4.7.2" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.2.tgz#01127b3840156a0927058779482031afe0e730d7" @@ -3788,6 +4254,11 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -3809,6 +4280,14 @@ hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== +http-assert@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.1.tgz#c5f725d677aa7e873ef736199b89686cceb37878" + integrity sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw== + dependencies: + deep-equal "~1.0.1" + http-errors "~1.7.2" + http-cache-semantics@^3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" @@ -3825,6 +4304,17 @@ http-errors@1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http-errors@1.7.3, http-errors@^1.6.3, http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" @@ -3956,6 +4446,11 @@ infer-owner@^1.0.3, infer-owner@^1.0.4: resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== +inflation@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f" + integrity sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8= + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3964,7 +4459,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -4089,6 +4584,11 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + is-callable@^1.1.4, is-callable@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" @@ -4184,6 +4684,11 @@ is-fullwidth-code-point@^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-generator-function@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" + integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -4341,6 +4846,11 @@ isobject@^4.0.0: resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== +isomorphic-ws@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -4376,7 +4886,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: +js-yaml@3.13.1, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -4514,6 +5024,13 @@ karma@^4.1.0: tmp "0.0.33" useragent "2.3.0" +keygrip@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" + integrity sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ== + dependencies: + tsscmp "1.0.6" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -4538,6 +5055,64 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +koa-bodyparser@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/koa-bodyparser/-/koa-bodyparser-4.2.1.tgz#4d7dacb5e6db1106649b595d9e5ccb158b6f3b29" + integrity sha512-UIjPAlMZfNYDDe+4zBaOAUKYqkwAGcIU6r2ARf1UOXPAlfennQys5IiShaVeNf7KkVBlf88f2LeLvBFvKylttw== + dependencies: + co-body "^6.0.0" + copy-to "^2.0.1" + +koa-compose@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-3.2.1.tgz#a85ccb40b7d986d8e5a345b3a1ace8eabcf54de7" + integrity sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec= + dependencies: + any-promise "^1.1.0" + +koa-compose@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/koa-compose/-/koa-compose-4.1.0.tgz#507306b9371901db41121c812e923d0d67d3e877" + integrity sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw== + +koa-convert@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/koa-convert/-/koa-convert-1.2.0.tgz#da40875df49de0539098d1700b50820cebcd21d0" + integrity sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA= + dependencies: + co "^4.6.0" + koa-compose "^3.0.0" + +koa@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.11.0.tgz#fe5a51c46f566d27632dd5dc8fd5d7dd44f935a4" + integrity sha512-EpR9dElBTDlaDgyhDMiLkXrPwp6ZqgAIBvhhmxQ9XN4TFgW+gEz6tkcsNI6BnUbUftrKDjVFj4lW2/J2aNBMMA== + dependencies: + accepts "^1.3.5" + cache-content-type "^1.0.0" + content-disposition "~0.5.2" + content-type "^1.0.4" + cookies "~0.8.0" + debug "~3.1.0" + delegates "^1.0.0" + depd "^1.1.2" + destroy "^1.0.4" + encodeurl "^1.0.2" + error-inject "^1.0.0" + escape-html "^1.0.3" + fresh "~0.5.2" + http-assert "^1.3.0" + http-errors "^1.6.3" + is-generator-function "^1.0.7" + koa-compose "^4.1.0" + koa-convert "^1.2.0" + on-finished "^2.3.0" + only "~0.0.2" + parseurl "^1.3.2" + statuses "^1.5.0" + type-is "^1.6.16" + vary "^1.1.2" + lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -4755,6 +5330,13 @@ lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + log4js@^4.0.0: version "4.5.1" resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5" @@ -5004,7 +5586,7 @@ mime-db@1.43.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== -mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.26" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== @@ -5036,7 +5618,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -5117,13 +5699,43 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== -mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" +mocha@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.0.1.tgz#276186d35a4852f6249808c6dd4a1376cbf6c6ce" + integrity sha512-9eWmWTdHLXh72rGrdZjNbG3aa1/3NRPpul1z0D979QpEnFdCG0Q5tv834N+94QEN2cysfV72YocQ3fn87s70fg== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + chokidar "3.3.0" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.1" + ms "2.1.1" + node-environment-flags "1.0.6" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" + modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -5146,6 +5758,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -5222,6 +5839,14 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-fetch-npm@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" @@ -5439,7 +6064,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@^4.1.0: +object.assign@4.1.0, object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -5479,7 +6104,7 @@ octokit-pagination-methods@^1.1.0: resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== -on-finished@~2.3.0: +on-finished@^2.3.0, on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= @@ -5507,6 +6132,11 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +only@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" + integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= + optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -5746,7 +6376,7 @@ parseuri@0.0.5: dependencies: better-assert "~1.0.0" -parseurl@~1.3.3: +parseurl@^1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== @@ -5816,6 +6446,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +pathval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= + pbkdf2@^3.0.16, pbkdf2@^3.0.3, pbkdf2@^3.0.9: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -5940,6 +6575,25 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= +protobufjs@^6.8.6: + version "6.8.8" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c" + integrity sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.0" + "@types/node" "^10.1.0" + long "^4.0.0" + protocols@^1.1.0, protocols@^1.4.0: version "1.4.7" resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" @@ -6034,6 +6688,11 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@^6.5.2: + version "6.9.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9" + integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA== + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -6089,6 +6748,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^2.3.3: + version "2.4.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" + integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== + dependencies: + bytes "3.1.0" + http-errors "1.7.3" + iconv-lite "0.4.24" + unpipe "1.0.0" + read-cmd-shim@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16" @@ -6216,6 +6885,13 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + readdirp@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" @@ -6422,6 +7098,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: hash-base "^3.0.0" inherits "^2.0.1" +rlp@^2.2.3: + version "2.2.4" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.4.tgz#d6b0e1659e9285fc509a5d169a9bd06f704951c1" + integrity sha512-fdq2yYCWpAQBhwkZv+Z8o/Z4sPmYm1CUq6P7n6lVTOdb949CnqA0sndXal5C1NleSVSZm6q5F3iEbauyVln/iw== + dependencies: + bn.js "^4.11.1" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -6443,16 +7126,16 @@ rxjs@^6.4.0, rxjs@^6.5.3: dependencies: tslib "^1.9.0" +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -6808,7 +7491,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: +"statuses@>= 1.5.0 < 2", statuses@^1.5.0, statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -6978,6 +7661,11 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + strip-json-comments@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" @@ -6992,6 +7680,13 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + supports-color@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" @@ -7251,6 +7946,11 @@ tslint@^5.19.0: tslib "^1.8.0" tsutils "^2.29.0" +tsscmp@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== + "tsutils@^2.28.0 || ^3.0.0", tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -7289,6 +7989,11 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -7299,7 +8004,7 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.17: +type-is@^1.6.16, type-is@~1.6.17: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -7498,6 +8203,11 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" +vary@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -7606,14 +8316,14 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: +which@1.3.1, which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: +wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -7706,6 +8416,13 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +ws@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + ws@~3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -7747,14 +8464,7 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yargs-parser@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" - -yargs-parser@^13.1.0: +yargs-parser@13.1.1, yargs-parser@^13.1.0, yargs-parser@^13.1.1: version "13.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== @@ -7762,6 +8472,13 @@ yargs-parser@^13.1.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" + integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== + dependencies: + camelcase "^4.1.0" + yargs-parser@^15.0.0: version "15.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" @@ -7770,6 +8487,15 @@ yargs-parser@^15.0.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + yargs@13.2.4: version "13.2.4" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" @@ -7787,6 +8513,22 @@ yargs@13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.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 "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + yargs@^14.2.2: version "14.2.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" @@ -7808,3 +8550,8 @@ yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + +ylru@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" + integrity sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ== From 0c39c634e191e7c7d6657f3d3c270dd6b89bcf64 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 13:21:13 +0100 Subject: [PATCH 02/13] Convert mocha+chai tests to Jasmine --- .../faucet/jasmine-spec-reporter.config.json | 12 + packages/faucet/jasmine-testrunner.js | 26 ++ packages/faucet/package.json | 8 +- .../src/actions/start/httperror.spec.ts | 14 +- .../src/actions/start/requestparser.spec.ts | 16 +- packages/faucet/src/cashflow.spec.ts | 40 +-- packages/faucet/src/codec.spec.ts | 16 +- packages/faucet/src/hdpaths.spec.ts | 25 +- packages/faucet/src/multichainhelpers.spec.ts | 7 +- yarn.lock | 262 ++---------------- 10 files changed, 120 insertions(+), 306 deletions(-) create mode 100644 packages/faucet/jasmine-spec-reporter.config.json create mode 100755 packages/faucet/jasmine-testrunner.js diff --git a/packages/faucet/jasmine-spec-reporter.config.json b/packages/faucet/jasmine-spec-reporter.config.json new file mode 100644 index 00000000..3a997556 --- /dev/null +++ b/packages/faucet/jasmine-spec-reporter.config.json @@ -0,0 +1,12 @@ +{ + "suite": { + "displayNumber": true + }, + "spec": { + "displayDuration": true + }, + "summary": { + "displayPending": false, + "displayStacktrace": true + } +} diff --git a/packages/faucet/jasmine-testrunner.js b/packages/faucet/jasmine-testrunner.js new file mode 100755 index 00000000..55b2df29 --- /dev/null +++ b/packages/faucet/jasmine-testrunner.js @@ -0,0 +1,26 @@ +#!/usr/bin/env node + +require("source-map-support").install(); +const defaultSpecReporterConfig = require("./jasmine-spec-reporter.config.json"); + +// setup Jasmine +const Jasmine = require("jasmine"); +const jasmine = new Jasmine(); +jasmine.loadConfig({ + spec_dir: "build", + spec_files: ["**/*.spec.js"], + helpers: [], + random: false, + seed: null, + stopSpecOnExpectationFailure: false, +}); +jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 15 * 1000; + +// setup reporter +const { SpecReporter } = require("jasmine-spec-reporter"); +const reporter = new SpecReporter({ ...defaultSpecReporterConfig }); + +// initialize and execute +jasmine.env.clearReporters(); +jasmine.addReporter(reporter); +jasmine.execute(); diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 4e156995..1af16609 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -29,7 +29,7 @@ "format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"", "build": "shx rm -rf ./build && tsc && yarn move-types && yarn format-types", "build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build", - "test-node": "mocha \"./build/**/*.spec.js\"", + "test-node": "node jasmine-testrunner.js", "test": "yarn build-or-skip && yarn test-node" }, "dependencies": { @@ -51,12 +51,8 @@ }, "devDependencies": { "@types/bn.js": "^4.11.6", - "@types/chai": "^4.2.7", "@types/koa": "^2.11.0", "@types/koa-bodyparser": "^4.3.0", - "@types/koa__cors": "^3.0.1", - "@types/mocha": "^5.2.7", - "chai": "^4.2.0", - "mocha": "^7.0.1" + "@types/koa__cors": "^3.0.1" } } diff --git a/packages/faucet/src/actions/start/httperror.spec.ts b/packages/faucet/src/actions/start/httperror.spec.ts index 9505bce6..fb3e61c6 100644 --- a/packages/faucet/src/actions/start/httperror.spec.ts +++ b/packages/faucet/src/actions/start/httperror.spec.ts @@ -1,20 +1,18 @@ -import { expect } from "chai"; - import { HttpError } from "./httperror"; describe("HttpError", () => { it("can be constructed", () => { { const error = new HttpError(400, "Invalid name field"); - expect(error.message).to.eql("Invalid name field"); - expect(error.status).to.eql(400); - expect(error.expose).to.eql(true); + expect(error.message).toEqual("Invalid name field"); + expect(error.status).toEqual(400); + expect(error.expose).toEqual(true); } { const error = new HttpError(500, "Out of memory", false); - expect(error.message).to.eql("Out of memory"); - expect(error.status).to.eql(500); - expect(error.expose).to.eql(false); + expect(error.message).toEqual("Out of memory"); + expect(error.status).toEqual(500); + expect(error.expose).toEqual(false); } }); }); diff --git a/packages/faucet/src/actions/start/requestparser.spec.ts b/packages/faucet/src/actions/start/requestparser.spec.ts index c6d68e25..84be6d2c 100644 --- a/packages/faucet/src/actions/start/requestparser.spec.ts +++ b/packages/faucet/src/actions/start/requestparser.spec.ts @@ -1,48 +1,46 @@ -import { expect } from "chai"; - import { RequestParser } from "./requestparser"; describe("RequestParser", () => { it("can process valid credit request", () => { const body = { address: "abc", ticker: "CASH" }; - expect(RequestParser.parseCreditBody(body)).to.eql({ address: "abc", ticker: "CASH" }); + expect(RequestParser.parseCreditBody(body)).toEqual({ address: "abc", ticker: "CASH" }); }); it("throws for invalid credit requests", () => { // address unset { const body = { ticker: "CASH" }; - expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'address' must be a string/i); + expect(() => RequestParser.parseCreditBody(body)).toThrowError(/Property 'address' must be a string/i); } // address wrong type { const body = { address: true, ticker: "CASH" }; - expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'address' must be a string/i); + expect(() => RequestParser.parseCreditBody(body)).toThrowError(/Property 'address' must be a string/i); } // address empty { const body = { address: "", ticker: "CASH" }; - expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'address' must not be empty/i); + expect(() => RequestParser.parseCreditBody(body)).toThrowError(/Property 'address' must not be empty/i); } // ticker unset { const body = { address: "abc" }; - expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'ticker' must be a string/i); + expect(() => RequestParser.parseCreditBody(body)).toThrowError(/Property 'ticker' must be a string/i); } // ticker wrong type { const body = { address: "abc", ticker: true }; - expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'ticker' must be a string/i); + expect(() => RequestParser.parseCreditBody(body)).toThrowError(/Property 'ticker' must be a string/i); } // ticker empty { const body = { address: "abc", ticker: "" }; - expect(() => RequestParser.parseCreditBody(body)).to.throw(/Property 'ticker' must not be empty/i); + expect(() => RequestParser.parseCreditBody(body)).toThrowError(/Property 'ticker' must not be empty/i); } }); }); diff --git a/packages/faucet/src/cashflow.spec.ts b/packages/faucet/src/cashflow.spec.ts index 7fed499e..6257254a 100644 --- a/packages/faucet/src/cashflow.spec.ts +++ b/packages/faucet/src/cashflow.spec.ts @@ -1,5 +1,5 @@ +// tslint:disable: no-object-mutation import { TokenTicker } from "@iov/bcp"; -import { expect } from "chai"; import { creditAmount, @@ -12,18 +12,18 @@ import { import { Codec } from "./codec"; describe("Cashflow", () => { - before(() => { + beforeAll(() => { setFractionalDigits(3); }); describe("creditAmount", () => { it("returns '10' + '000' by default", () => { - expect(creditAmount("TOKENZ" as TokenTicker)).to.eql({ + expect(creditAmount("TOKENZ" as TokenTicker)).toEqual({ quantity: "10000", fractionalDigits: 3, tokenTicker: "TOKENZ", }); - expect(creditAmount("TRASH" as TokenTicker)).to.eql({ + expect(creditAmount("TRASH" as TokenTicker)).toEqual({ quantity: "10000", fractionalDigits: 3, tokenTicker: "TRASH", @@ -32,7 +32,7 @@ describe("Cashflow", () => { it("returns value from env variable + '000' when set", () => { process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; - expect(creditAmount("WTF" as TokenTicker)).to.eql({ + expect(creditAmount("WTF" as TokenTicker)).toEqual({ quantity: "22000", fractionalDigits: 3, tokenTicker: "WTF", @@ -41,7 +41,7 @@ describe("Cashflow", () => { it("returns default from env variable + '000' when set to empty", () => { process.env.FAUCET_CREDIT_AMOUNT_WTF = ""; - expect(creditAmount("WTF" as TokenTicker)).to.eql({ + expect(creditAmount("WTF" as TokenTicker)).toEqual({ quantity: "10000", fractionalDigits: 3, tokenTicker: "WTF", @@ -54,7 +54,7 @@ describe("Cashflow", () => { process.env.FAUCET_REFILL_FACTOR = ""; }); it("returns 20*10 + '000' by default", () => { - expect(refillAmount("TOKENZ" as TokenTicker)).to.eql({ + expect(refillAmount("TOKENZ" as TokenTicker)).toEqual({ quantity: "200000", fractionalDigits: 3, tokenTicker: "TOKENZ", @@ -63,7 +63,7 @@ describe("Cashflow", () => { it("returns 20*22 + '000' when credit amount is 22", () => { process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; - expect(refillAmount("WTF" as TokenTicker)).to.eql({ + expect(refillAmount("WTF" as TokenTicker)).toEqual({ quantity: "440000", fractionalDigits: 3, tokenTicker: "WTF", @@ -72,7 +72,7 @@ describe("Cashflow", () => { it("returns 30*10 + '000' when refill factor is 30", () => { process.env.FAUCET_REFILL_FACTOR = "30"; - expect(refillAmount("TOKENZ" as TokenTicker)).to.eql({ + expect(refillAmount("TOKENZ" as TokenTicker)).toEqual({ quantity: "300000", fractionalDigits: 3, tokenTicker: "TOKENZ", @@ -82,7 +82,7 @@ describe("Cashflow", () => { it("returns 30*22 + '000' when refill factor is 30 and credit amount is 22", () => { process.env.FAUCET_REFILL_FACTOR = "30"; process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; - expect(refillAmount("WTF" as TokenTicker)).to.eql({ + expect(refillAmount("WTF" as TokenTicker)).toEqual({ quantity: "660000", fractionalDigits: 3, tokenTicker: "WTF", @@ -95,7 +95,7 @@ describe("Cashflow", () => { process.env.FAUCET_REFILL_THRESHOLD = ""; }); it("returns 8*10 + '000' by default", () => { - expect(refillThreshold("TOKENZ" as TokenTicker)).to.eql({ + expect(refillThreshold("TOKENZ" as TokenTicker)).toEqual({ quantity: "80000", fractionalDigits: 3, tokenTicker: "TOKENZ", @@ -104,7 +104,7 @@ describe("Cashflow", () => { it("returns 8*22 + '000' when credit amount is 22", () => { process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; - expect(refillThreshold("WTF" as TokenTicker)).to.eql({ + expect(refillThreshold("WTF" as TokenTicker)).toEqual({ quantity: "176000", fractionalDigits: 3, tokenTicker: "WTF", @@ -113,7 +113,7 @@ describe("Cashflow", () => { it("returns 5*10 + '000' when refill threshold is 5", () => { process.env.FAUCET_REFILL_THRESHOLD = "5"; - expect(refillThreshold("TOKENZ" as TokenTicker)).to.eql({ + expect(refillThreshold("TOKENZ" as TokenTicker)).toEqual({ quantity: "50000", fractionalDigits: 3, tokenTicker: "TOKENZ", @@ -123,7 +123,7 @@ describe("Cashflow", () => { it("returns 5*22 + '000' when refill threshold is 5 and credit amount is 22", () => { process.env.FAUCET_REFILL_THRESHOLD = "5"; process.env.FAUCET_CREDIT_AMOUNT_WTF = "22"; - expect(refillThreshold("WTF" as TokenTicker)).to.eql({ + expect(refillThreshold("WTF" as TokenTicker)).toEqual({ quantity: "110000", fractionalDigits: 3, tokenTicker: "WTF", @@ -133,12 +133,12 @@ describe("Cashflow", () => { describe("gasPrice", () => { it("returns undefined for non-Ethereum codecs", () => { - expect(gasPrice(Codec.Lisk)).to.be.undefined; - expect(gasPrice(Codec.Bns)).to.be.undefined; + expect(gasPrice(Codec.Lisk)).toBeUndefined(); + expect(gasPrice(Codec.Bns)).toBeUndefined(); }); it("returns amount for Ethereum codec", () => { - expect(gasPrice(Codec.Ethereum)).to.be.eql({ + expect(gasPrice(Codec.Ethereum)).toEqual({ quantity: "20000000000", fractionalDigits: 18, tokenTicker: "ETH", @@ -148,12 +148,12 @@ describe("Cashflow", () => { describe("gasLimit", () => { it("returns undefined for non-Ethereum codecs", () => { - expect(gasLimit(Codec.Lisk)).to.be.undefined; - expect(gasLimit(Codec.Bns)).to.be.undefined; + expect(gasLimit(Codec.Lisk)).toBeUndefined(); + expect(gasLimit(Codec.Bns)).toBeUndefined(); }); it("returns amount for Ethereum codec", () => { - expect(gasLimit(Codec.Ethereum)).to.be.eql({ + expect(gasLimit(Codec.Ethereum)).toEqual({ quantity: "2100000", fractionalDigits: 18, tokenTicker: "ETH", diff --git a/packages/faucet/src/codec.spec.ts b/packages/faucet/src/codec.spec.ts index bf5ff998..3085fe12 100644 --- a/packages/faucet/src/codec.spec.ts +++ b/packages/faucet/src/codec.spec.ts @@ -1,16 +1,14 @@ -import { expect } from "chai"; - import { Codec, codecFromString } from "./codec"; describe("Codec", () => { it("can convert string to codec", () => { - expect(codecFromString("bns")).to.equal(Codec.Bns); - expect(codecFromString("lisk")).to.equal(Codec.Lisk); - expect(codecFromString("ethereum")).to.equal(Codec.Ethereum); + expect(codecFromString("bns")).toEqual(Codec.Bns); + expect(codecFromString("lisk")).toEqual(Codec.Lisk); + expect(codecFromString("ethereum")).toEqual(Codec.Ethereum); - expect(() => codecFromString("")).to.throw(/not supported/i); - expect(() => codecFromString("abc")).to.throw(/not supported/i); - expect(() => codecFromString("LISK")).to.throw(/not supported/i); - expect(() => codecFromString("ETHEREUM")).to.throw(/not supported/i); + expect(() => codecFromString("")).toThrowError(/not supported/i); + expect(() => codecFromString("abc")).toThrowError(/not supported/i); + expect(() => codecFromString("LISK")).toThrowError(/not supported/i); + expect(() => codecFromString("ETHEREUM")).toThrowError(/not supported/i); }); }); diff --git a/packages/faucet/src/hdpaths.spec.ts b/packages/faucet/src/hdpaths.spec.ts index ff92f9f1..fb60694a 100644 --- a/packages/faucet/src/hdpaths.spec.ts +++ b/packages/faucet/src/hdpaths.spec.ts @@ -1,5 +1,4 @@ import { Slip10RawIndex } from "@iov/crypto"; -import { expect } from "chai"; import { debugPath } from "./hdpaths"; @@ -7,39 +6,39 @@ describe("hdpaths", () => { describe("debugPath", () => { it("works for no component", () => { // See https://github.com/bitcoin/bips/blob/master/bip-0032/derivation.png from BIP32 - expect(debugPath([])).to.eql("m"); + expect(debugPath([])).toEqual("m"); }); it("works for normal components", () => { const one = Slip10RawIndex.normal(1); - expect(debugPath([one])).to.eql("m/1"); - expect(debugPath([one, one])).to.eql("m/1/1"); - expect(debugPath([one, one, one])).to.eql("m/1/1/1"); + expect(debugPath([one])).toEqual("m/1"); + expect(debugPath([one, one])).toEqual("m/1/1"); + expect(debugPath([one, one, one])).toEqual("m/1/1/1"); const min = Slip10RawIndex.normal(0); - expect(debugPath([min])).to.eql("m/0"); + expect(debugPath([min])).toEqual("m/0"); const max = Slip10RawIndex.normal(2 ** 31 - 1); - expect(debugPath([max])).to.eql("m/2147483647"); + expect(debugPath([max])).toEqual("m/2147483647"); }); it("works for hardened components", () => { const one = Slip10RawIndex.hardened(1); - expect(debugPath([one])).to.eql("m/1'"); - expect(debugPath([one, one])).to.eql("m/1'/1'"); - expect(debugPath([one, one, one])).to.eql("m/1'/1'/1'"); + expect(debugPath([one])).toEqual("m/1'"); + expect(debugPath([one, one])).toEqual("m/1'/1'"); + expect(debugPath([one, one, one])).toEqual("m/1'/1'/1'"); const min = Slip10RawIndex.hardened(0); - expect(debugPath([min])).to.eql("m/0'"); + expect(debugPath([min])).toEqual("m/0'"); const max = Slip10RawIndex.hardened(2 ** 31 - 1); - expect(debugPath([max])).to.eql("m/2147483647'"); + expect(debugPath([max])).toEqual("m/2147483647'"); }); it("works for mixed components", () => { const one = Slip10RawIndex.normal(1); const two = Slip10RawIndex.hardened(2); - expect(debugPath([one, two, two, one])).to.eql("m/1/2'/2'/1"); + expect(debugPath([one, two, two, one])).toEqual("m/1/2'/2'/1"); }); }); }); diff --git a/packages/faucet/src/multichainhelpers.spec.ts b/packages/faucet/src/multichainhelpers.spec.ts index 0531c26e..b81c8553 100644 --- a/packages/faucet/src/multichainhelpers.spec.ts +++ b/packages/faucet/src/multichainhelpers.spec.ts @@ -1,5 +1,4 @@ import { Address, Algorithm, PubkeyBundle, PubkeyBytes, TokenTicker } from "@iov/bcp"; -import { expect } from "chai"; import { availableTokensFromHolder } from "./multichainhelpers"; @@ -16,7 +15,7 @@ describe("multichainhelpers", () => { pubkey: defaultPubkey, balance: [], }); - expect(tickers).to.be.empty; + expect(tickers).toEqual([]); }); it("works for one token", () => { @@ -31,7 +30,7 @@ describe("multichainhelpers", () => { }, ], }); - expect(tickers).to.eql(["CASH"]); + expect(tickers).toEqual(["CASH"]); }); it("works for two tokens", () => { @@ -51,7 +50,7 @@ describe("multichainhelpers", () => { }, ], }); - expect(tickers).to.eql(["CASH", "TRASH"]); + expect(tickers).toEqual(["CASH", "TRASH"]); }); }); }); diff --git a/yarn.lock b/yarn.lock index 52522ace..a6669a56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1140,11 +1140,6 @@ "@types/connect" "*" "@types/node" "*" -"@types/chai@^4.2.7": - version "4.2.7" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d" - integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g== - "@types/connect@*": version "3.4.33" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.33.tgz#31610c901eca573b8713c3330abc6e6b9f588546" @@ -1281,11 +1276,6 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/mocha@^5.2.7": - version "5.2.7" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" - integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== - "@types/node@*", "@types/node@>= 8": version "13.5.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.5.0.tgz#4e498dbf355795a611a87ae5ef811a8660d42662" @@ -1631,11 +1621,6 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== - ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -1829,11 +1814,6 @@ assert@^1.1.1: object-assign "^4.1.1" util "0.10.3" -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2059,11 +2039,6 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -2310,19 +2285,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - pathval "^1.1.0" - type-detect "^4.0.5" - -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2336,26 +2299,6 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - -chokidar@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" - integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.2.0" - optionalDependencies: - fsevents "~2.1.1" - chokidar@^2.0.2: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -2892,7 +2835,7 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: +debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -2934,13 +2877,6 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== - dependencies: - type-detect "^4.0.0" - deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" @@ -3056,11 +2992,6 @@ di@^0.0.1: resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -3351,7 +3282,7 @@ escape-html@^1.0.3, escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -3731,13 +3662,6 @@ find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@3.0.0, find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -3753,6 +3677,13 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + findup-sync@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" @@ -3772,13 +3703,6 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" -flat@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== - dependencies: - is-buffer "~2.0.3" - flatted@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" @@ -3900,7 +3824,7 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" -fsevents@~2.1.1, fsevents@~2.1.2: +fsevents@~2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== @@ -3939,11 +3863,6 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - get-pkg-repo@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" @@ -4058,18 +3977,6 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^7.0.0, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -4144,11 +4051,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - handlebars@^4.4.0: version "4.7.2" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.2.tgz#01127b3840156a0927058779482031afe0e730d7" @@ -4254,11 +4156,6 @@ hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -4584,11 +4481,6 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== - is-callable@^1.1.4, is-callable@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" @@ -4886,7 +4778,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@^3.13.1: +js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -5330,13 +5222,6 @@ lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -log-symbols@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - log4js@^4.0.0: version "4.5.1" resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5" @@ -5618,7 +5503,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -5699,43 +5584,13 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" -mocha@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.0.1.tgz#276186d35a4852f6249808c6dd4a1376cbf6c6ce" - integrity sha512-9eWmWTdHLXh72rGrdZjNbG3aa1/3NRPpul1z0D979QpEnFdCG0Q5tv834N+94QEN2cysfV72YocQ3fn87s70fg== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - chokidar "3.3.0" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "2.2.0" - minimatch "3.0.4" - mkdirp "0.5.1" - ms "2.1.1" - node-environment-flags "1.0.6" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.3.0" - yargs-parser "13.1.1" - yargs-unparser "1.6.0" - modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -5758,11 +5613,6 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -5839,14 +5689,6 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-environment-flags@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" - integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - node-fetch-npm@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" @@ -6064,7 +5906,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0, object.assign@^4.1.0: +object.assign@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -6446,11 +6288,6 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= - pbkdf2@^3.0.16, pbkdf2@^3.0.3, pbkdf2@^3.0.9: version "3.0.17" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" @@ -6885,13 +6722,6 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" - integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== - dependencies: - picomatch "^2.0.4" - readdirp@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" @@ -7661,11 +7491,6 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= -strip-json-comments@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - strip-json-comments@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" @@ -7680,13 +7505,6 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== - dependencies: - has-flag "^3.0.0" - supports-color@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" @@ -7989,11 +7807,6 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - type-fest@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -8316,14 +8129,14 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1.3.1, which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: +which@^1.2.1, which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -wide-align@1.1.3, wide-align@^1.1.0: +wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -8464,14 +8277,6 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yargs-parser@13.1.1, yargs-parser@^13.1.0, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" @@ -8479,6 +8284,14 @@ yargs-parser@^10.0.0: dependencies: camelcase "^4.1.0" +yargs-parser@^13.1.0: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^15.0.0: version "15.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" @@ -8487,15 +8300,6 @@ yargs-parser@^15.0.0: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== - dependencies: - flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" - yargs@13.2.4: version "13.2.4" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" @@ -8513,22 +8317,6 @@ yargs@13.2.4: y18n "^4.0.0" yargs-parser "^13.1.0" -yargs@13.3.0, yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.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 "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" - yargs@^14.2.2: version "14.2.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" From 670fb11901c99b2bc91af4f39b2bde8883f38cf4 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 13:27:39 +0100 Subject: [PATCH 03/13] Upgrade code to IOV Core 2.0 --- packages/faucet/src/multichainhelpers.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/faucet/src/multichainhelpers.ts b/packages/faucet/src/multichainhelpers.ts index 6b98d0ab..29e9a04b 100644 --- a/packages/faucet/src/multichainhelpers.ts +++ b/packages/faucet/src/multichainhelpers.ts @@ -5,7 +5,6 @@ import { isBlockInfoPending, SendTransaction, TokenTicker, - WithCreator, } from "@iov/bcp"; import { UserProfile } from "@iov/keycontrol"; import { MultiChainSigner } from "@iov/multichain"; @@ -68,19 +67,17 @@ export async function sendOnFirstChain( const chainId = signer.chainIds()[0]; const connection = signer.connection(chainId); - const sendWithFee = await connection.withDefaultFee({ + const sendWithFee = await connection.withDefaultFee({ kind: "bcp/send", - creator: { - chainId: chainId, - pubkey: job.sender.pubkey, - }, + chainId: chainId, sender: signer.identityToAddress(job.sender), + senderPubkey: job.sender.pubkey, recipient: job.recipient, memo: "We ❤️ developers – iov.one", amount: job.amount, }); - const post = await signer.signAndPost(sendWithFee); + const post = await signer.signAndPost(job.sender, sendWithFee); const blockInfo = await post.blockInfo.waitFor(info => !isBlockInfoPending(info)); if (isBlockInfoFailed(blockInfo)) { throw new Error(`Sending tokens failed. Code: ${blockInfo.code}, message: ${blockInfo.message}`); From 006494e441b191d6ddc623acb6bb1991d9083b6a Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 13:29:01 +0100 Subject: [PATCH 04/13] Avoid checking-in types --- packages/faucet/package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 1af16609..3d2833ed 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -25,9 +25,7 @@ "format": "prettier --write --loglevel warn \"./src/**/*.ts\"", "lint": "eslint --max-warnings 0 \"**/*.{js,ts}\" && tslint -t verbose --project .", "lint-fix": "eslint --max-warnings 0 \"**/*.{js,ts}\" --fix", - "move-types": "shx rm -rf ./types/* && shx mv build/types/* ./types && rm -rf ./types/testdata && shx rm -f ./types/*.spec.d.ts", - "format-types": "prettier --write --loglevel warn \"./types/**/*.d.ts\"", - "build": "shx rm -rf ./build && tsc && yarn move-types && yarn format-types", + "build": "shx rm -rf ./build && tsc", "build-or-skip": "[ -n \"$SKIP_BUILD\" ] || yarn build", "test-node": "node jasmine-testrunner.js", "test": "yarn build-or-skip && yarn test-node" From ffda6e2baffa6c6d6a85faf578904a44b856031b Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 13:33:41 +0100 Subject: [PATCH 05/13] Make linter happy --- packages/faucet/src/actions/start/start.ts | 2 +- packages/faucet/src/multichainhelpers.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/faucet/src/actions/start/start.ts b/packages/faucet/src/actions/start/start.ts index 1cac66f6..6d069546 100644 --- a/packages/faucet/src/actions/start/start.ts +++ b/packages/faucet/src/actions/start/start.ts @@ -1,4 +1,4 @@ -/* eslint-disable require-atomic-updates */ +// tslint:disable: no-object-mutation import { UserProfile } from "@iov/keycontrol"; import { MultiChainSigner } from "@iov/multichain"; import cors = require("@koa/cors"); diff --git a/packages/faucet/src/multichainhelpers.ts b/packages/faucet/src/multichainhelpers.ts index 29e9a04b..384bb334 100644 --- a/packages/faucet/src/multichainhelpers.ts +++ b/packages/faucet/src/multichainhelpers.ts @@ -30,6 +30,7 @@ export async function accountsOfFirstChain( const addresses = identitiesOfFirstWallet(profile).map(identity => signer.identityToAddress(identity)); const chainId = signer.chainIds()[0]; + // tslint:disable-next-line: readonly-array const out: Account[] = []; for (const address of addresses) { const response = await signer.connection(chainId).getAccount({ address: address }); @@ -108,6 +109,7 @@ export async function refillFirstChain( const availableTokens = availableTokensFromHolder(holderAccount); console.info("Available tokens:", availableTokens); + // tslint:disable-next-line: readonly-array const jobs: SendJob[] = []; for (const token of availableTokens) { From 7c8ddf801920ed1a400fe961f661be39fe8a40b5 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 13:41:17 +0100 Subject: [PATCH 06/13] Rename cosmos* types to cosmwasm* --- ...moscodec.spec.ts => cosmwasmcodec.spec.ts} | 18 +++++----- .../src/{cosmoscodec.ts => cosmwasmcodec.ts} | 4 +-- ...ion.spec.ts => cosmwasmconnection.spec.ts} | 36 +++++++++---------- ...mosconnection.ts => cosmwasmconnection.ts} | 6 ++-- ...osmosconnector.ts => cosmwasmconnector.ts} | 12 +++---- packages/bcp/src/index.ts | 6 ++-- .../{cosmoscodec.d.ts => cosmwasmcodec.d.ts} | 4 +-- ...onnection.d.ts => cosmwasmconnection.d.ts} | 8 +++-- ...sconnector.d.ts => cosmwasmconnector.d.ts} | 6 ++-- packages/bcp/types/index.d.ts | 6 ++-- 10 files changed, 55 insertions(+), 51 deletions(-) rename packages/bcp/src/{cosmoscodec.spec.ts => cosmwasmcodec.spec.ts} (69%) rename packages/bcp/src/{cosmoscodec.ts => cosmwasmcodec.ts} (96%) rename packages/bcp/src/{cosmosconnection.spec.ts => cosmwasmconnection.spec.ts} (90%) rename packages/bcp/src/{cosmosconnection.ts => cosmwasmconnection.ts} (98%) rename packages/bcp/src/{cosmosconnector.ts => cosmwasmconnector.ts} (54%) rename packages/bcp/types/{cosmoscodec.d.ts => cosmwasmcodec.d.ts} (87%) rename packages/bcp/types/{cosmosconnection.d.ts => cosmwasmconnection.d.ts} (90%) rename packages/bcp/types/{cosmosconnector.d.ts => cosmwasmconnector.d.ts} (67%) diff --git a/packages/bcp/src/cosmoscodec.spec.ts b/packages/bcp/src/cosmwasmcodec.spec.ts similarity index 69% rename from packages/bcp/src/cosmoscodec.spec.ts rename to packages/bcp/src/cosmwasmcodec.spec.ts index a4a046ec..1829b936 100644 --- a/packages/bcp/src/cosmoscodec.spec.ts +++ b/packages/bcp/src/cosmwasmcodec.spec.ts @@ -1,12 +1,12 @@ import { PostableBytes, PrehashType } from "@iov/bcp"; import { Encoding } from "@iov/encoding"; -import { cosmosCodec } from "./cosmoscodec"; +import { cosmWasmCodec } from "./cosmwasmcodec"; import { chainId, nonce, sendTxJson, signedTxBin, signedTxJson, txId } from "./testdata.spec"; const { toUtf8 } = Encoding; -describe("cosmoscodec", () => { +describe("cosmWasmCodec", () => { it("properly generates bytes to sign", () => { const expected = { bytes: toUtf8( @@ -14,36 +14,36 @@ describe("cosmoscodec", () => { ), prehashType: PrehashType.Sha256, }; - const bytesToSign = cosmosCodec.bytesToSign(sendTxJson, nonce); + const bytesToSign = cosmWasmCodec.bytesToSign(sendTxJson, nonce); expect(bytesToSign).toEqual(expected); }); it("properly encodes transactions", () => { - const encoded = cosmosCodec.bytesToPost(signedTxJson); + const encoded = cosmWasmCodec.bytesToPost(signedTxJson); expect(encoded).toEqual(signedTxBin); }); it("throws when trying to decode a transaction without a nonce", () => { - expect(() => cosmosCodec.parseBytes(signedTxBin as PostableBytes, chainId)).toThrowError( + expect(() => cosmWasmCodec.parseBytes(signedTxBin as PostableBytes, chainId)).toThrowError( /nonce is required/i, ); }); it("properly decodes transactions", () => { - const decoded = cosmosCodec.parseBytes(signedTxBin as PostableBytes, chainId, nonce); + const decoded = cosmWasmCodec.parseBytes(signedTxBin as PostableBytes, chainId, nonce); expect(decoded).toEqual(signedTxJson); }); it("generates transaction id", () => { - const id = cosmosCodec.identifier(signedTxJson); + const id = cosmWasmCodec.identifier(signedTxJson); expect(id).toMatch(/^[0-9A-F]{64}$/); expect(id).toEqual(txId); }); it("round trip works", () => { - const encoded = cosmosCodec.bytesToPost(signedTxJson); - const decoded = cosmosCodec.parseBytes(encoded, chainId, nonce); + const encoded = cosmWasmCodec.bytesToPost(signedTxJson); + const decoded = cosmWasmCodec.parseBytes(encoded, chainId, nonce); expect(decoded).toEqual(signedTxJson); }); }); diff --git a/packages/bcp/src/cosmoscodec.ts b/packages/bcp/src/cosmwasmcodec.ts similarity index 96% rename from packages/bcp/src/cosmoscodec.ts rename to packages/bcp/src/cosmwasmcodec.ts index f4b3619d..17e8c70a 100644 --- a/packages/bcp/src/cosmoscodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -44,7 +44,7 @@ function sortJson(json: any): any { return result; } -export class CosmosCodec implements TxCodec { +export class CosmWasmCodec implements TxCodec { private readonly prefix: CosmosBech32Prefix; private readonly tokens: TokenInfos; @@ -113,4 +113,4 @@ const defaultTokens: TokenInfos = [ }, ]; -export const cosmosCodec = new CosmosCodec(defaultPrefix, defaultTokens); +export const cosmWasmCodec = new CosmWasmCodec(defaultPrefix, defaultTokens); diff --git a/packages/bcp/src/cosmosconnection.spec.ts b/packages/bcp/src/cosmwasmconnection.spec.ts similarity index 90% rename from packages/bcp/src/cosmosconnection.spec.ts rename to packages/bcp/src/cosmwasmconnection.spec.ts index fc916c56..3bb665fc 100644 --- a/packages/bcp/src/cosmosconnection.spec.ts +++ b/packages/bcp/src/cosmwasmconnection.spec.ts @@ -15,8 +15,8 @@ import { Encoding } from "@iov/encoding"; import { HdPaths, Secp256k1HdWallet, UserProfile } from "@iov/keycontrol"; import { CosmosBech32Prefix } from "./address"; -import { CosmosCodec, cosmosCodec } from "./cosmoscodec"; -import { CosmosConnection } from "./cosmosconnection"; +import { CosmWasmCodec, cosmWasmCodec } from "./cosmwasmcodec"; +import { CosmWasmConnection } from "./cosmwasmconnection"; import { nonceToSequence, TokenInfos } from "./types"; const { fromBase64, toHex } = Encoding; @@ -27,7 +27,7 @@ function pendingWithoutCosmos(): void { } } -describe("CosmosConnection", () => { +describe("CosmWasmConnection", () => { const cosm = "COSM" as TokenTicker; const httpUrl = "http://localhost:1317"; const defaultChainId = "cosmos:testing" as ChainId; @@ -63,7 +63,7 @@ describe("CosmosConnection", () => { describe("establish", () => { it("can connect to Cosmos via http", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); expect(connection).toBeTruthy(); connection.disconnect(); }); @@ -72,7 +72,7 @@ describe("CosmosConnection", () => { describe("chainId", () => { it("displays the chain ID", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const chainId = connection.chainId(); expect(chainId).toEqual(defaultChainId); connection.disconnect(); @@ -82,7 +82,7 @@ describe("CosmosConnection", () => { describe("height", () => { it("displays the current height", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const height = await connection.height(); expect(height).toBeGreaterThan(0); connection.disconnect(); @@ -92,7 +92,7 @@ describe("CosmosConnection", () => { describe("getToken", () => { it("displays a given token", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const token = await connection.getToken("COSM" as TokenTicker); expect(token).toEqual({ fractionalDigits: 6, @@ -104,7 +104,7 @@ describe("CosmosConnection", () => { it("resolves to undefined if the token is not supported", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const token = await connection.getToken("whatever" as TokenTicker); expect(token).toBeUndefined(); connection.disconnect(); @@ -114,7 +114,7 @@ describe("CosmosConnection", () => { describe("getAllTokens", () => { it("resolves to a list of all supported tokens", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const tokens = await connection.getAllTokens(); // TODO: make this more flexible expect(tokens).toEqual([ @@ -136,7 +136,7 @@ describe("CosmosConnection", () => { describe("getAccount", () => { it("gets an empty account by address", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const account = await connection.getAccount({ address: defaultEmptyAddress }); expect(account).toBeUndefined(); connection.disconnect(); @@ -144,7 +144,7 @@ describe("CosmosConnection", () => { it("gets an account by address", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const account = await connection.getAccount({ address: defaultAddress }); if (account === undefined) { throw new Error("Expected account not to be undefined"); @@ -161,7 +161,7 @@ describe("CosmosConnection", () => { it("gets an account by pubkey", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const account = await connection.getAccount({ pubkey: defaultPubkey }); if (account === undefined) { throw new Error("Expected account not to be undefined"); @@ -180,11 +180,11 @@ describe("CosmosConnection", () => { describe("integration tests", () => { it("can post and get a transaction", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const profile = new UserProfile(); const wallet = profile.addWallet(Secp256k1HdWallet.fromMnemonic(faucetMnemonic)); const faucet = await profile.createIdentity(wallet.id, defaultChainId, faucetPath); - const faucetAddress = cosmosCodec.identityToAddress(faucet); + const faucetAddress = cosmWasmCodec.identityToAddress(faucet); const unsigned = await connection.withDefaultFee({ kind: "bcp/send", @@ -200,7 +200,7 @@ describe("CosmosConnection", () => { }); const nonce = await connection.getNonce({ address: faucetAddress }); // TODO: we need to use custom codecs everywhere - const codec = new CosmosCodec(defaultPrefix, defaultTokens); + const codec = new CosmWasmCodec(defaultPrefix, defaultTokens); const signed = await profile.signTransaction(faucet, unsigned, codec, nonce); const postableBytes = codec.bytesToPost(signed); const response = await connection.postTx(postableBytes); @@ -243,11 +243,11 @@ describe("CosmosConnection", () => { it("can post and search for a transaction", async () => { pendingWithoutCosmos(); - const connection = await CosmosConnection.establish(httpUrl, defaultPrefix, defaultTokens); + const connection = await CosmWasmConnection.establish(httpUrl, defaultPrefix, defaultTokens); const profile = new UserProfile(); const wallet = profile.addWallet(Secp256k1HdWallet.fromMnemonic(faucetMnemonic)); const faucet = await profile.createIdentity(wallet.id, defaultChainId, faucetPath); - const faucetAddress = cosmosCodec.identityToAddress(faucet); + const faucetAddress = cosmWasmCodec.identityToAddress(faucet); const unsigned = await connection.withDefaultFee({ kind: "bcp/send", @@ -263,7 +263,7 @@ describe("CosmosConnection", () => { }); const nonce = await connection.getNonce({ address: faucetAddress }); // TODO: we need to use custom codecs everywhere - const codec = new CosmosCodec(defaultPrefix, defaultTokens); + const codec = new CosmWasmCodec(defaultPrefix, defaultTokens); const signed = await profile.signTransaction(faucet, unsigned, codec, nonce); const postableBytes = codec.bytesToPost(signed); const response = await connection.postTx(postableBytes); diff --git a/packages/bcp/src/cosmosconnection.ts b/packages/bcp/src/cosmwasmconnection.ts similarity index 98% rename from packages/bcp/src/cosmosconnection.ts rename to packages/bcp/src/cosmwasmconnection.ts index 3c10fa6f..c5277212 100644 --- a/packages/bcp/src/cosmosconnection.ts +++ b/packages/bcp/src/cosmwasmconnection.ts @@ -68,16 +68,16 @@ function buildQueryString({ return components.filter(Boolean).join("&"); } -export class CosmosConnection implements BlockchainConnection { +export class CosmWasmConnection implements BlockchainConnection { // we must know prefix and tokens a priori to understand the chain public static async establish( url: string, prefix: CosmosBech32Prefix, tokenInfo: TokenInfos, - ): Promise { + ): Promise { const restClient = new RestClient(url); const chainData = await this.initialize(restClient); - return new CosmosConnection(restClient, chainData, prefix, tokenInfo); + return new CosmWasmConnection(restClient, chainData, prefix, tokenInfo); } private static async initialize(restClient: RestClient): Promise { diff --git a/packages/bcp/src/cosmosconnector.ts b/packages/bcp/src/cosmwasmconnector.ts similarity index 54% rename from packages/bcp/src/cosmosconnector.ts rename to packages/bcp/src/cosmwasmconnector.ts index fd9c82e4..9863aa18 100644 --- a/packages/bcp/src/cosmosconnector.ts +++ b/packages/bcp/src/cosmwasmconnector.ts @@ -1,22 +1,22 @@ import { ChainConnector, ChainId } from "@iov/bcp"; import { CosmosBech32Prefix } from "./address"; -import { cosmosCodec } from "./cosmoscodec"; -import { CosmosConnection } from "./cosmosconnection"; +import { cosmWasmCodec } from "./cosmwasmcodec"; +import { CosmWasmConnection } from "./cosmwasmconnection"; import { TokenInfos } from "./types"; /** * A helper to connect to a cosmos-based chain at a given url */ -export function createCosmosConnector( +export function createCosmWasmConnector( url: string, prefix: CosmosBech32Prefix, tokenInfo: TokenInfos, expectedChainId?: ChainId, -): ChainConnector { +): ChainConnector { return { - establishConnection: async () => CosmosConnection.establish(url, prefix, tokenInfo), - codec: cosmosCodec, + establishConnection: async () => CosmWasmConnection.establish(url, prefix, tokenInfo), + codec: cosmWasmCodec, expectedChainId: expectedChainId, }; } diff --git a/packages/bcp/src/index.ts b/packages/bcp/src/index.ts index 4c607b18..91313392 100644 --- a/packages/bcp/src/index.ts +++ b/packages/bcp/src/index.ts @@ -1,3 +1,3 @@ -export { cosmosCodec, CosmosCodec } from "./cosmoscodec"; -export { CosmosConnection } from "./cosmosconnection"; -export { createCosmosConnector } from "./cosmosconnector"; +export { cosmWasmCodec, CosmWasmCodec } from "./cosmwasmcodec"; +export { CosmWasmConnection } from "./cosmwasmconnection"; +export { createCosmWasmConnector } from "./cosmwasmconnector"; diff --git a/packages/bcp/types/cosmoscodec.d.ts b/packages/bcp/types/cosmwasmcodec.d.ts similarity index 87% rename from packages/bcp/types/cosmoscodec.d.ts rename to packages/bcp/types/cosmwasmcodec.d.ts index 64de7f38..ec1253b0 100644 --- a/packages/bcp/types/cosmoscodec.d.ts +++ b/packages/bcp/types/cosmwasmcodec.d.ts @@ -12,7 +12,7 @@ import { } from "@iov/bcp"; import { CosmosBech32Prefix } from "./address"; import { TokenInfos } from "./types"; -export declare class CosmosCodec implements TxCodec { +export declare class CosmWasmCodec implements TxCodec { private readonly prefix; private readonly tokens; constructor(prefix: CosmosBech32Prefix, tokens: TokenInfos); @@ -23,4 +23,4 @@ export declare class CosmosCodec implements TxCodec { identityToAddress(identity: Identity): Address; isValidAddress(address: string): boolean; } -export declare const cosmosCodec: CosmosCodec; +export declare const cosmWasmCodec: CosmWasmCodec; diff --git a/packages/bcp/types/cosmosconnection.d.ts b/packages/bcp/types/cosmwasmconnection.d.ts similarity index 90% rename from packages/bcp/types/cosmosconnection.d.ts rename to packages/bcp/types/cosmwasmconnection.d.ts index de0cf74a..5144df67 100644 --- a/packages/bcp/types/cosmosconnection.d.ts +++ b/packages/bcp/types/cosmwasmconnection.d.ts @@ -22,8 +22,12 @@ import { import { Stream } from "xstream"; import { CosmosBech32Prefix } from "./address"; import { TokenInfos } from "./types"; -export declare class CosmosConnection implements BlockchainConnection { - static establish(url: string, prefix: CosmosBech32Prefix, tokenInfo: TokenInfos): Promise; +export declare class CosmWasmConnection implements BlockchainConnection { + static establish( + url: string, + prefix: CosmosBech32Prefix, + tokenInfo: TokenInfos, + ): Promise; private static initialize; private readonly restClient; private readonly chainData; diff --git a/packages/bcp/types/cosmosconnector.d.ts b/packages/bcp/types/cosmwasmconnector.d.ts similarity index 67% rename from packages/bcp/types/cosmosconnector.d.ts rename to packages/bcp/types/cosmwasmconnector.d.ts index 05a3d528..9e34e052 100644 --- a/packages/bcp/types/cosmosconnector.d.ts +++ b/packages/bcp/types/cosmwasmconnector.d.ts @@ -1,13 +1,13 @@ import { ChainConnector, ChainId } from "@iov/bcp"; import { CosmosBech32Prefix } from "./address"; -import { CosmosConnection } from "./cosmosconnection"; +import { CosmWasmConnection } from "./cosmwasmconnection"; import { TokenInfos } from "./types"; /** * A helper to connect to a cosmos-based chain at a given url */ -export declare function createCosmosConnector( +export declare function createCosmWasmConnector( url: string, prefix: CosmosBech32Prefix, tokenInfo: TokenInfos, expectedChainId?: ChainId, -): ChainConnector; +): ChainConnector; diff --git a/packages/bcp/types/index.d.ts b/packages/bcp/types/index.d.ts index 4c607b18..91313392 100644 --- a/packages/bcp/types/index.d.ts +++ b/packages/bcp/types/index.d.ts @@ -1,3 +1,3 @@ -export { cosmosCodec, CosmosCodec } from "./cosmoscodec"; -export { CosmosConnection } from "./cosmosconnection"; -export { createCosmosConnector } from "./cosmosconnector"; +export { cosmWasmCodec, CosmWasmCodec } from "./cosmwasmcodec"; +export { CosmWasmConnection } from "./cosmwasmconnection"; +export { createCosmWasmConnector } from "./cosmwasmconnector"; From f01c48b7e10531adb4e0d106b64065e09d02df26 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 14:28:04 +0100 Subject: [PATCH 07/13] Prepare createCosmWasmConnector to be used by faucet --- packages/bcp/src/cosmwasmcodec.ts | 1 + packages/bcp/src/cosmwasmconnector.ts | 9 +++++---- packages/bcp/src/index.ts | 3 ++- packages/bcp/types/cosmwasmcodec.d.ts | 1 + packages/bcp/types/cosmwasmconnector.d.ts | 4 ++-- packages/bcp/types/index.d.ts | 3 ++- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/bcp/src/cosmwasmcodec.ts b/packages/bcp/src/cosmwasmcodec.ts index 17e8c70a..3d89c589 100644 --- a/packages/bcp/src/cosmwasmcodec.ts +++ b/packages/bcp/src/cosmwasmcodec.ts @@ -113,4 +113,5 @@ const defaultTokens: TokenInfos = [ }, ]; +/** Unconfigured codec is useful for testing only */ export const cosmWasmCodec = new CosmWasmCodec(defaultPrefix, defaultTokens); diff --git a/packages/bcp/src/cosmwasmconnector.ts b/packages/bcp/src/cosmwasmconnector.ts index 9863aa18..295aee0a 100644 --- a/packages/bcp/src/cosmwasmconnector.ts +++ b/packages/bcp/src/cosmwasmconnector.ts @@ -1,9 +1,9 @@ import { ChainConnector, ChainId } from "@iov/bcp"; import { CosmosBech32Prefix } from "./address"; -import { cosmWasmCodec } from "./cosmwasmcodec"; +import { CosmWasmCodec } from "./cosmwasmcodec"; import { CosmWasmConnection } from "./cosmwasmconnection"; -import { TokenInfos } from "./types"; +import { TokenInfo } from "./types"; /** * A helper to connect to a cosmos-based chain at a given url @@ -11,12 +11,13 @@ import { TokenInfos } from "./types"; export function createCosmWasmConnector( url: string, prefix: CosmosBech32Prefix, - tokenInfo: TokenInfos, + tokenInfo: readonly TokenInfo[], expectedChainId?: ChainId, ): ChainConnector { + const codec = new CosmWasmCodec(prefix, tokenInfo); return { establishConnection: async () => CosmWasmConnection.establish(url, prefix, tokenInfo), - codec: cosmWasmCodec, + codec: codec, expectedChainId: expectedChainId, }; } diff --git a/packages/bcp/src/index.ts b/packages/bcp/src/index.ts index 91313392..81e10d6e 100644 --- a/packages/bcp/src/index.ts +++ b/packages/bcp/src/index.ts @@ -1,3 +1,4 @@ -export { cosmWasmCodec, CosmWasmCodec } from "./cosmwasmcodec"; +export { CosmWasmCodec } from "./cosmwasmcodec"; export { CosmWasmConnection } from "./cosmwasmconnection"; export { createCosmWasmConnector } from "./cosmwasmconnector"; +export { TokenInfo } from "./types"; diff --git a/packages/bcp/types/cosmwasmcodec.d.ts b/packages/bcp/types/cosmwasmcodec.d.ts index ec1253b0..1373ef99 100644 --- a/packages/bcp/types/cosmwasmcodec.d.ts +++ b/packages/bcp/types/cosmwasmcodec.d.ts @@ -23,4 +23,5 @@ export declare class CosmWasmCodec implements TxCodec { identityToAddress(identity: Identity): Address; isValidAddress(address: string): boolean; } +/** Unconfigured codec is useful for testing only */ export declare const cosmWasmCodec: CosmWasmCodec; diff --git a/packages/bcp/types/cosmwasmconnector.d.ts b/packages/bcp/types/cosmwasmconnector.d.ts index 9e34e052..2a2ba3e7 100644 --- a/packages/bcp/types/cosmwasmconnector.d.ts +++ b/packages/bcp/types/cosmwasmconnector.d.ts @@ -1,13 +1,13 @@ import { ChainConnector, ChainId } from "@iov/bcp"; import { CosmosBech32Prefix } from "./address"; import { CosmWasmConnection } from "./cosmwasmconnection"; -import { TokenInfos } from "./types"; +import { TokenInfo } from "./types"; /** * A helper to connect to a cosmos-based chain at a given url */ export declare function createCosmWasmConnector( url: string, prefix: CosmosBech32Prefix, - tokenInfo: TokenInfos, + tokenInfo: readonly TokenInfo[], expectedChainId?: ChainId, ): ChainConnector; diff --git a/packages/bcp/types/index.d.ts b/packages/bcp/types/index.d.ts index 91313392..81e10d6e 100644 --- a/packages/bcp/types/index.d.ts +++ b/packages/bcp/types/index.d.ts @@ -1,3 +1,4 @@ -export { cosmWasmCodec, CosmWasmCodec } from "./cosmwasmcodec"; +export { CosmWasmCodec } from "./cosmwasmcodec"; export { CosmWasmConnection } from "./cosmwasmconnection"; export { createCosmWasmConnector } from "./cosmwasmconnector"; +export { TokenInfo } from "./types"; From bf22ee313f0e3233b14ae5ef4a3c67544c304504 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 14:37:55 +0100 Subject: [PATCH 08/13] Add support for CosmWasm in faucet --- packages/faucet/README.md | 99 +++++++++++++++++++++++++++++ packages/faucet/package.json | 2 + packages/faucet/src/actions/help.ts | 4 +- packages/faucet/src/cashflow.ts | 6 +- packages/faucet/src/codec.ts | 50 ++++++++++----- packages/faucet/src/crypto.ts | 1 + 6 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 packages/faucet/README.md diff --git a/packages/faucet/README.md b/packages/faucet/README.md new file mode 100644 index 00000000..cc80b739 --- /dev/null +++ b/packages/faucet/README.md @@ -0,0 +1,99 @@ +# @cosmwasm/faucet + +The faucet is built as part of the monorepo. In the repo root do: + +``` +yarn install +yarn build +``` + +Then start it for a Wasmd development blockchain using: + +``` +cd packages/faucet +yarn dev-start +``` + +Advanced users that want to provide their custom config can start as follows: + +``` +FAUCET_CREDIT_AMOUNT_COSM=10 \ + FAUCET_CREDIT_AMOUNT_STAKE=5 \ + FAUCET_CONCURRENCY=3 \ + FAUCET_MNEMONIC="economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone" \ + ./bin/cosm-faucet start cosmwasm "http://localhost:1317" +``` + +## Usage + +``` +sage: cosmwasm-faucet action [arguments...] + +Positional arguments per action are listed below. Arguments in parentheses are optional. + +help Shows a help text and exits + +version Prints the version and exits + +generate Generates a random mnemonic, shows derived faucet addresses and exits + 1 Codec + 2 Chain ID + +start Starts the faucet + 1 Codec + 2 Node base URL, e.g. wss://bov.friendnet-fast.iov.one + +Environment variables + +FAUCET_CONCURRENCY Number of distributor accounts. Defaults to 5. +FAUCET_PORT Port of the webserver. Defaults to 8000. +FAUCET_MNEMONIC Secret mnemonic that serves as the base secret for the + faucet HD accounts +FAUCET_CREDIT_AMOUNT_TKN Send this amount of TKN to a user requesting TKN. TKN is + a placeholder for the token ticker. Defaults to 10. +FAUCET_REFILL_FACTOR Send factor times credit amount on refilling. Defauls to 8. +FAUCET_REFILL_THRESHOLD Refill when balance gets below factor times credit amount. + Defaults to 20. +``` + +### Faucet HD wallet + +The faucet uses standard HD paths for each blockchain, e.g. + +``` +IOV m/44'/234'/a' +Lisk m/44'/134'/a' +Ethereum m/44'/60'/0'/0/a +CosmWasm m/44'/118'/0'/0/a +``` + +where `a` is a 0-based index of the account. Account 0 is the token holder and +account 1...FAUCET_CONCURRENCY are the distributor accounts. + +This means the token holder account can be accessed using the Neuma wallet when +the same mnemonic is used. Accessing the distributor accounts will be possible +as soon as there is +[multi account support](https://github.com/iov-one/ponferrada/milestone/3). + +### Using the faucet + +Now that the faucet has been started up, you can send credit requests to it. +This can be done with a simple http POST request. These commands assume the +faucet is running locally, be sure to change it from `localhost` if your +situation is different. + +``` +curl --header "Content-Type: application/json" \ + --request POST \ + --data '{"ticker":"CASH","address":"tiov1k898u78hgs36uqw68dg7va5nfkgstu5z0fhz3f"}' \ + http://localhost:8000/credit +``` + +### Checking the faucets status + +The faucet provides a simple status check in the form of an http GET request. As +above, make sure to adjust the URL as necessary. + +``` +curl http://localhost:8000/status +``` diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 3d2833ed..9465a1ad 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -21,6 +21,7 @@ "access": "public" }, "scripts": { + "dev-start": "FAUCET_CREDIT_AMOUNT_COSM=10 FAUCET_CREDIT_AMOUNT_STAKE=5 FAUCET_CONCURRENCY=3 FAUCET_MNEMONIC=\"economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone\" ./bin/cosm-faucet start cosmwasm \"http://localhost:1317\"", "docs": "shx rm -rf docs && typedoc --options typedoc.js", "format": "prettier --write --loglevel warn \"./src/**/*.ts\"", "lint": "eslint --max-warnings 0 \"**/*.{js,ts}\" && tslint -t verbose --project .", @@ -31,6 +32,7 @@ "test": "yarn build-or-skip && yarn test-node" }, "dependencies": { + "@cosmwasm/bcp": "^0.0.1", "@iov/bcp": "^2.0.0-alpha.7", "@iov/bns": "^2.0.0-alpha.7", "@iov/crypto": "^2.0.0-alpha.7", diff --git a/packages/faucet/src/actions/help.ts b/packages/faucet/src/actions/help.ts index 14cfd7ad..039655cc 100644 --- a/packages/faucet/src/actions/help.ts +++ b/packages/faucet/src/actions/help.ts @@ -1,6 +1,8 @@ +const binaryName = "cosmwasm-faucet"; + export function help(): void { const out = ` -Usage: iov-faucet action [arguments...] +Usage: ${binaryName} action [arguments...] Positional arguments per action are listed below. Arguments in parentheses are optional. diff --git a/packages/faucet/src/cashflow.ts b/packages/faucet/src/cashflow.ts index 079a5c37..27545ef9 100644 --- a/packages/faucet/src/cashflow.ts +++ b/packages/faucet/src/cashflow.ts @@ -66,6 +66,7 @@ export function gasPrice(codec: Codec): Amount | undefined { switch (codec) { case Codec.Bns: case Codec.Lisk: + case Codec.CosmWasm: return undefined; case Codec.Ethereum: return { @@ -74,7 +75,7 @@ export function gasPrice(codec: Codec): Amount | undefined { tokenTicker: "ETH" as TokenTicker, }; default: - throw new Error("No codec imlementation for this codec found"); + throw new Error("No gasPrice imlementation found for this codec"); } } @@ -82,6 +83,7 @@ export function gasLimit(codec: Codec): Amount | undefined { switch (codec) { case Codec.Bns: case Codec.Lisk: + case Codec.CosmWasm: return undefined; case Codec.Ethereum: return { @@ -90,6 +92,6 @@ export function gasLimit(codec: Codec): Amount | undefined { tokenTicker: "ETH" as TokenTicker, }; default: - throw new Error("Codec not supported"); + throw new Error("No gasLimit imlementation found for this codec"); } } diff --git a/packages/faucet/src/codec.ts b/packages/faucet/src/codec.ts index 1080a85e..b59b75be 100644 --- a/packages/faucet/src/codec.ts +++ b/packages/faucet/src/codec.ts @@ -1,14 +1,16 @@ -import { ChainConnector, TxCodec } from "@iov/bcp"; -import { bnsCodec, createBnsConnector } from "@iov/bns"; +import { createCosmWasmConnector, TokenInfo } from "@cosmwasm/bcp"; +import { ChainConnector, TokenTicker, TxCodec } from "@iov/bcp"; +import { createBnsConnector } from "@iov/bns"; import { Slip10RawIndex } from "@iov/crypto"; -import { createEthereumConnector, ethereumCodec } from "@iov/ethereum"; +import { createEthereumConnector } from "@iov/ethereum"; import { HdPaths } from "@iov/keycontrol"; -import { createLiskConnector, liskCodec } from "@iov/lisk"; +import { createLiskConnector } from "@iov/lisk"; export const enum Codec { Bns, Lisk, Ethereum, + CosmWasm, } export function codecFromString(input: string): Codec { @@ -19,24 +21,13 @@ export function codecFromString(input: string): Codec { return Codec.Lisk; case "ethereum": return Codec.Ethereum; + case "cosmwasm": + return Codec.CosmWasm; default: throw new Error(`Codec '${input}' not supported`); } } -export function codecImplementation(codec: Codec): TxCodec { - switch (codec) { - case Codec.Bns: - return bnsCodec; - case Codec.Lisk: - return liskCodec; - case Codec.Ethereum: - return ethereumCodec; - default: - throw new Error("No codec implementation for this codec found"); - } -} - export function createPathBuilderForCodec(codec: Codec): (derivation: number) => readonly Slip10RawIndex[] { const pathBuilder = (accountIndex: number): readonly Slip10RawIndex[] => { switch (codec) { @@ -46,6 +37,8 @@ export function createPathBuilderForCodec(codec: Codec): (derivation: number) => return HdPaths.bip44Like(134, accountIndex); case Codec.Ethereum: return HdPaths.ethereum(accountIndex); + case Codec.CosmWasm: + return HdPaths.cosmos(accountIndex); default: throw new Error("No path builder for this codec found"); } @@ -61,11 +54,32 @@ export function createChainConnector(codec: Codec, url: string): ChainConnector return createLiskConnector(url); case Codec.Ethereum: return createEthereumConnector(url, {}); + case Codec.CosmWasm: { + const tokens: readonly TokenInfo[] = [ + { + fractionalDigits: 6, + tokenName: "Fee Token", + tokenTicker: "COSM" as TokenTicker, + denom: "cosm", + }, + { + fractionalDigits: 6, + tokenName: "Staking Token", + tokenTicker: "STAKE" as TokenTicker, + denom: "stake", + }, + ]; + return createCosmWasmConnector(url, "cosmos", tokens); + } default: throw new Error("No connector for this codec found"); } } +export function codecImplementation(codec: Codec): TxCodec { + return createChainConnector(codec, "unused dummy url").codec; +} + export function codecDefaultFractionalDigits(codec: Codec): number { switch (codec) { case Codec.Bns: @@ -74,6 +88,8 @@ export function codecDefaultFractionalDigits(codec: Codec): number { return 8; case Codec.Ethereum: return 18; + case Codec.CosmWasm: + return 6; default: throw new Error("Unknown codec"); } diff --git a/packages/faucet/src/crypto.ts b/packages/faucet/src/crypto.ts index 59424ef9..f2103310 100644 --- a/packages/faucet/src/crypto.ts +++ b/packages/faucet/src/crypto.ts @@ -8,6 +8,7 @@ export function createWalletForCodec(input: Codec, mnemonic: string): Wallet { case Codec.Lisk: return Ed25519HdWallet.fromMnemonic(mnemonic); case Codec.Ethereum: + case Codec.CosmWasm: return Secp256k1HdWallet.fromMnemonic(mnemonic); default: throw new Error(`Codec '${input}' not supported`); From 3fbd1288feb8ef325b2a92d0d2dd69249e8cc032 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 14:51:22 +0100 Subject: [PATCH 09/13] Remove unused ethereum support from faucet --- packages/faucet/README.md | 1 - packages/faucet/package.json | 1 - packages/faucet/src/actions/start/start.ts | 8 ++--- packages/faucet/src/cashflow.spec.ts | 40 +--------------------- packages/faucet/src/cashflow.ts | 37 -------------------- packages/faucet/src/codec.spec.ts | 4 +-- packages/faucet/src/codec.ts | 10 ------ packages/faucet/src/constants.ts | 4 --- packages/faucet/src/crypto.ts | 1 - packages/faucet/src/multichainhelpers.ts | 11 ++---- packages/faucet/src/types.ts | 2 -- yarn.lock | 36 +------------------ 12 files changed, 9 insertions(+), 146 deletions(-) diff --git a/packages/faucet/README.md b/packages/faucet/README.md index cc80b739..f5d37074 100644 --- a/packages/faucet/README.md +++ b/packages/faucet/README.md @@ -63,7 +63,6 @@ The faucet uses standard HD paths for each blockchain, e.g. ``` IOV m/44'/234'/a' Lisk m/44'/134'/a' -Ethereum m/44'/60'/0'/0/a CosmWasm m/44'/118'/0'/0/a ``` diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 9465a1ad..9b9ff932 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -37,7 +37,6 @@ "@iov/bns": "^2.0.0-alpha.7", "@iov/crypto": "^2.0.0-alpha.7", "@iov/encoding": "^2.0.0-alpha.7", - "@iov/ethereum": "^2.0.0-alpha.7", "@iov/lisk": "^2.0.0-alpha.7", "@iov/multichain": "^2.0.0-alpha.7", "@koa/cors": "^3.0.0", diff --git a/packages/faucet/src/actions/start/start.ts b/packages/faucet/src/actions/start/start.ts index 6d069546..beb9ea1d 100644 --- a/packages/faucet/src/actions/start/start.ts +++ b/packages/faucet/src/actions/start/start.ts @@ -5,7 +5,7 @@ import cors = require("@koa/cors"); import Koa from "koa"; import bodyParser from "koa-bodyparser"; -import { creditAmount, gasLimit, gasPrice, setFractionalDigits } from "../../cashflow"; +import { creditAmount, setFractionalDigits } from "../../cashflow"; import { codecDefaultFractionalDigits, codecFromString, @@ -73,8 +73,8 @@ export async function start(args: ReadonlyArray): Promise { const distibutorIdentities = identitiesOfFirstWallet(profile).slice(1); - await refillFirstChain(profile, signer, codec); - setInterval(async () => refillFirstChain(profile, signer, codec), 60_000); // ever 60 seconds + await refillFirstChain(profile, signer); + setInterval(async () => refillFirstChain(profile, signer), 60_000); // ever 60 seconds console.info("Creating webserver ..."); const api = new Koa(); @@ -135,8 +135,6 @@ export async function start(args: ReadonlyArray): Promise { recipient: address, amount: creditAmount(ticker), tokenTicker: ticker, - gasPrice: gasPrice(codec), - gasLimit: gasLimit(codec), }; logSendJob(signer, job); await sendOnFirstChain(profile, signer, job); diff --git a/packages/faucet/src/cashflow.spec.ts b/packages/faucet/src/cashflow.spec.ts index 6257254a..6cd56c28 100644 --- a/packages/faucet/src/cashflow.spec.ts +++ b/packages/faucet/src/cashflow.spec.ts @@ -1,15 +1,7 @@ // tslint:disable: no-object-mutation import { TokenTicker } from "@iov/bcp"; -import { - creditAmount, - gasLimit, - gasPrice, - refillAmount, - refillThreshold, - setFractionalDigits, -} from "./cashflow"; -import { Codec } from "./codec"; +import { creditAmount, refillAmount, refillThreshold, setFractionalDigits } from "./cashflow"; describe("Cashflow", () => { beforeAll(() => { @@ -130,34 +122,4 @@ describe("Cashflow", () => { }); }); }); - - describe("gasPrice", () => { - it("returns undefined for non-Ethereum codecs", () => { - expect(gasPrice(Codec.Lisk)).toBeUndefined(); - expect(gasPrice(Codec.Bns)).toBeUndefined(); - }); - - it("returns amount for Ethereum codec", () => { - expect(gasPrice(Codec.Ethereum)).toEqual({ - quantity: "20000000000", - fractionalDigits: 18, - tokenTicker: "ETH", - }); - }); - }); - - describe("gasLimit", () => { - it("returns undefined for non-Ethereum codecs", () => { - expect(gasLimit(Codec.Lisk)).toBeUndefined(); - expect(gasLimit(Codec.Bns)).toBeUndefined(); - }); - - it("returns amount for Ethereum codec", () => { - expect(gasLimit(Codec.Ethereum)).toEqual({ - quantity: "2100000", - fractionalDigits: 18, - tokenTicker: "ETH", - }); - }); - }); }); diff --git a/packages/faucet/src/cashflow.ts b/packages/faucet/src/cashflow.ts index 27545ef9..987b34e1 100644 --- a/packages/faucet/src/cashflow.ts +++ b/packages/faucet/src/cashflow.ts @@ -3,9 +3,6 @@ import BN = require("bn.js"); import { Account, Amount, TokenTicker } from "@iov/bcp"; import { Int53 } from "@iov/encoding"; -import { Codec } from "./codec"; -import * as constants from "./constants"; - /** Send `factor` times credit amount on refilling */ const defaultRefillFactor = 20; @@ -61,37 +58,3 @@ export function needsRefill(account: Account, token: TokenTicker): boolean { const refillQty = new BN(refillThreshold(token).quantity); return new BN(tokenBalance).lt(refillQty); } - -export function gasPrice(codec: Codec): Amount | undefined { - switch (codec) { - case Codec.Bns: - case Codec.Lisk: - case Codec.CosmWasm: - return undefined; - case Codec.Ethereum: - return { - quantity: constants.ethereum.gasPrice, - fractionalDigits: 18, - tokenTicker: "ETH" as TokenTicker, - }; - default: - throw new Error("No gasPrice imlementation found for this codec"); - } -} - -export function gasLimit(codec: Codec): Amount | undefined { - switch (codec) { - case Codec.Bns: - case Codec.Lisk: - case Codec.CosmWasm: - return undefined; - case Codec.Ethereum: - return { - quantity: constants.ethereum.gasLimit, - fractionalDigits: 18, - tokenTicker: "ETH" as TokenTicker, - }; - default: - throw new Error("No gasLimit imlementation found for this codec"); - } -} diff --git a/packages/faucet/src/codec.spec.ts b/packages/faucet/src/codec.spec.ts index 3085fe12..ee3aa586 100644 --- a/packages/faucet/src/codec.spec.ts +++ b/packages/faucet/src/codec.spec.ts @@ -4,11 +4,11 @@ describe("Codec", () => { it("can convert string to codec", () => { expect(codecFromString("bns")).toEqual(Codec.Bns); expect(codecFromString("lisk")).toEqual(Codec.Lisk); - expect(codecFromString("ethereum")).toEqual(Codec.Ethereum); + expect(codecFromString("cosmwasm")).toEqual(Codec.CosmWasm); expect(() => codecFromString("")).toThrowError(/not supported/i); expect(() => codecFromString("abc")).toThrowError(/not supported/i); expect(() => codecFromString("LISK")).toThrowError(/not supported/i); - expect(() => codecFromString("ETHEREUM")).toThrowError(/not supported/i); + expect(() => codecFromString("CosmWasm")).toThrowError(/not supported/i); }); }); diff --git a/packages/faucet/src/codec.ts b/packages/faucet/src/codec.ts index b59b75be..2a5263f3 100644 --- a/packages/faucet/src/codec.ts +++ b/packages/faucet/src/codec.ts @@ -2,14 +2,12 @@ import { createCosmWasmConnector, TokenInfo } from "@cosmwasm/bcp"; import { ChainConnector, TokenTicker, TxCodec } from "@iov/bcp"; import { createBnsConnector } from "@iov/bns"; import { Slip10RawIndex } from "@iov/crypto"; -import { createEthereumConnector } from "@iov/ethereum"; import { HdPaths } from "@iov/keycontrol"; import { createLiskConnector } from "@iov/lisk"; export const enum Codec { Bns, Lisk, - Ethereum, CosmWasm, } @@ -19,8 +17,6 @@ export function codecFromString(input: string): Codec { return Codec.Bns; case "lisk": return Codec.Lisk; - case "ethereum": - return Codec.Ethereum; case "cosmwasm": return Codec.CosmWasm; default: @@ -35,8 +31,6 @@ export function createPathBuilderForCodec(codec: Codec): (derivation: number) => return HdPaths.iov(accountIndex); case Codec.Lisk: return HdPaths.bip44Like(134, accountIndex); - case Codec.Ethereum: - return HdPaths.ethereum(accountIndex); case Codec.CosmWasm: return HdPaths.cosmos(accountIndex); default: @@ -52,8 +46,6 @@ export function createChainConnector(codec: Codec, url: string): ChainConnector return createBnsConnector(url); case Codec.Lisk: return createLiskConnector(url); - case Codec.Ethereum: - return createEthereumConnector(url, {}); case Codec.CosmWasm: { const tokens: readonly TokenInfo[] = [ { @@ -86,8 +78,6 @@ export function codecDefaultFractionalDigits(codec: Codec): number { return 9; // fixed for all weave tokens case Codec.Lisk: return 8; - case Codec.Ethereum: - return 18; case Codec.CosmWasm: return 6; default: diff --git a/packages/faucet/src/constants.ts b/packages/faucet/src/constants.ts index 9ff6e410..a28481d1 100644 --- a/packages/faucet/src/constants.ts +++ b/packages/faucet/src/constants.ts @@ -1,7 +1,3 @@ export const concurrency: number = Number.parseInt(process.env.FAUCET_CONCURRENCY || "", 10) || 5; export const port: number = Number.parseInt(process.env.FAUCET_PORT || "", 10) || 8000; export const mnemonic: string | undefined = process.env.FAUCET_MNEMONIC; -export const ethereum = { - gasPrice: "20000000000", - gasLimit: "2100000", -}; diff --git a/packages/faucet/src/crypto.ts b/packages/faucet/src/crypto.ts index f2103310..6d624a59 100644 --- a/packages/faucet/src/crypto.ts +++ b/packages/faucet/src/crypto.ts @@ -7,7 +7,6 @@ export function createWalletForCodec(input: Codec, mnemonic: string): Wallet { case Codec.Bns: case Codec.Lisk: return Ed25519HdWallet.fromMnemonic(mnemonic); - case Codec.Ethereum: case Codec.CosmWasm: return Secp256k1HdWallet.fromMnemonic(mnemonic); default: diff --git a/packages/faucet/src/multichainhelpers.ts b/packages/faucet/src/multichainhelpers.ts index 384bb334..d54b8891 100644 --- a/packages/faucet/src/multichainhelpers.ts +++ b/packages/faucet/src/multichainhelpers.ts @@ -9,8 +9,7 @@ import { import { UserProfile } from "@iov/keycontrol"; import { MultiChainSigner } from "@iov/multichain"; -import { gasLimit, gasPrice, needsRefill, refillAmount } from "./cashflow"; -import { Codec } from "./codec"; +import { needsRefill, refillAmount } from "./cashflow"; import { debugAccount, logAccountsState, logSendJob } from "./debugging"; import { SendJob } from "./types"; @@ -89,11 +88,7 @@ export function availableTokensFromHolder(holderAccount: Account): ReadonlyArray return holderAccount.balance.map(coin => coin.tokenTicker); } -export async function refillFirstChain( - profile: UserProfile, - signer: MultiChainSigner, - codec: Codec, -): Promise { +export async function refillFirstChain(profile: UserProfile, signer: MultiChainSigner): Promise { const chainId = signer.chainIds()[0]; console.info(`Connected to network: ${chainId}`); @@ -124,8 +119,6 @@ export async function refillFirstChain( recipient: refillDistibutor.address, tokenTicker: token, amount: refillAmount(token), - gasPrice: gasPrice(codec), - gasLimit: gasLimit(codec), }); } } diff --git a/packages/faucet/src/types.ts b/packages/faucet/src/types.ts index a4a0cc34..28186ee9 100644 --- a/packages/faucet/src/types.ts +++ b/packages/faucet/src/types.ts @@ -5,6 +5,4 @@ export interface SendJob { readonly recipient: Address; readonly tokenTicker: TokenTicker; readonly amount: Amount; - readonly gasPrice?: Amount; - readonly gasLimit?: Amount; } diff --git a/yarn.lock b/yarn.lock index a6669a56..dc48d303 100644 --- a/yarn.lock +++ b/yarn.lock @@ -149,28 +149,6 @@ bn.js "^4.11.8" readonly-date "^1.0.0" -"@iov/ethereum@^2.0.0-alpha.7": - version "2.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@iov/ethereum/-/ethereum-2.0.0-alpha.7.tgz#f1a72947e5ce62a7afc56f0320866f08b2bf01b9" - integrity sha512-q+AJsIuwbBbrEMpztgGQIsApFJQ/n7t9Uq/pi3OGqUdcXCG6JYJH+XjClv0yIVcMB8pxfNwQ9RvYy75Zpn0icw== - dependencies: - "@iov/bcp" "^2.0.0-alpha.7" - "@iov/crypto" "^2.0.0-alpha.7" - "@iov/encoding" "^2.0.0-alpha.7" - "@iov/jsonrpc" "^2.0.0-alpha.7" - "@iov/keycontrol" "^2.0.0-alpha.7" - "@iov/socket" "^2.0.0-alpha.7" - "@iov/stream" "^2.0.0-alpha.7" - "@iov/utils" "^2.0.0-alpha.7" - "@types/long" "^4.0.0" - axios "^0.19.0" - bn.js "^4.11.8" - fast-deep-equal "^3.1.1" - long "^4.0.0" - readonly-date "^1.0.0" - rlp "^2.2.3" - xstream "^11.10.0" - "@iov/jsonrpc@^2.0.0-alpha.7": version "2.0.0-alpha.7" resolved "https://registry.yarnpkg.com/@iov/jsonrpc/-/jsonrpc-2.0.0-alpha.7.tgz#7bff8e1f21d52ff07482212ded8cc00e01dda964" @@ -260,11 +238,6 @@ type-tagger "^1.0.0" xstream "^11.10.0" -"@iov/utils@^2.0.0-alpha.7": - version "2.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@iov/utils/-/utils-2.0.0-alpha.7.tgz#af9aebcb9e221e53cf62c5511f007c65d95f5c0c" - integrity sha512-myWATqmlCFZ/jSrsBQlyn+6D2ViAscZVAqBAw38kbIfv3TiKTjWb2RqhlNDnlVgt3uD0ZtQFyY9hkRMCwfIk+w== - "@koa/cors@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.0.0.tgz#df021b4df2dadf1e2b04d7c8ddf93ba2d42519cb" @@ -1977,7 +1950,7 @@ bluebird@^3.3.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.1, bn.js@^4.11.8, bn.js@^4.4.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.8, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== @@ -6928,13 +6901,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.2.3: - version "2.2.4" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.4.tgz#d6b0e1659e9285fc509a5d169a9bd06f704951c1" - integrity sha512-fdq2yYCWpAQBhwkZv+Z8o/Z4sPmYm1CUq6P7n6lVTOdb949CnqA0sndXal5C1NleSVSZm6q5F3iEbauyVln/iw== - dependencies: - bn.js "^4.11.1" - run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" From f692efc9103be500f55a5c0e55ffe90896939048 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 14:52:51 +0100 Subject: [PATCH 10/13] Remove irrelevant override --- .eslintrc.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index cbbaf4b5..738b64b7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -50,12 +50,6 @@ "rules": { "@typescript-eslint/camelcase": ["error", { "properties": "never" }] } - }, - { - "files": "packages/{iov-bns,iov-tendermint-rpc}/**/*.ts", - "rules": { - "@typescript-eslint/camelcase": ["error", { "allow": ["v0_[0-9]+"] }] - } } ] } From 8921b5c20a6b7699ce5947ec2e256b19212cb662 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 14:56:36 +0100 Subject: [PATCH 11/13] Remove bns support from faucet --- packages/faucet/package.json | 1 - packages/faucet/src/codec.spec.ts | 2 +- packages/faucet/src/codec.ts | 10 --- packages/faucet/src/crypto.ts | 1 - yarn.lock | 132 ------------------------------ 5 files changed, 1 insertion(+), 145 deletions(-) diff --git a/packages/faucet/package.json b/packages/faucet/package.json index 9b9ff932..4c234aee 100644 --- a/packages/faucet/package.json +++ b/packages/faucet/package.json @@ -34,7 +34,6 @@ "dependencies": { "@cosmwasm/bcp": "^0.0.1", "@iov/bcp": "^2.0.0-alpha.7", - "@iov/bns": "^2.0.0-alpha.7", "@iov/crypto": "^2.0.0-alpha.7", "@iov/encoding": "^2.0.0-alpha.7", "@iov/lisk": "^2.0.0-alpha.7", diff --git a/packages/faucet/src/codec.spec.ts b/packages/faucet/src/codec.spec.ts index ee3aa586..2176ec63 100644 --- a/packages/faucet/src/codec.spec.ts +++ b/packages/faucet/src/codec.spec.ts @@ -2,11 +2,11 @@ import { Codec, codecFromString } from "./codec"; describe("Codec", () => { it("can convert string to codec", () => { - expect(codecFromString("bns")).toEqual(Codec.Bns); expect(codecFromString("lisk")).toEqual(Codec.Lisk); expect(codecFromString("cosmwasm")).toEqual(Codec.CosmWasm); expect(() => codecFromString("")).toThrowError(/not supported/i); + expect(() => codecFromString("bns")).toThrowError(/not supported/i); expect(() => codecFromString("abc")).toThrowError(/not supported/i); expect(() => codecFromString("LISK")).toThrowError(/not supported/i); expect(() => codecFromString("CosmWasm")).toThrowError(/not supported/i); diff --git a/packages/faucet/src/codec.ts b/packages/faucet/src/codec.ts index 2a5263f3..dab2a092 100644 --- a/packages/faucet/src/codec.ts +++ b/packages/faucet/src/codec.ts @@ -1,20 +1,16 @@ import { createCosmWasmConnector, TokenInfo } from "@cosmwasm/bcp"; import { ChainConnector, TokenTicker, TxCodec } from "@iov/bcp"; -import { createBnsConnector } from "@iov/bns"; import { Slip10RawIndex } from "@iov/crypto"; import { HdPaths } from "@iov/keycontrol"; import { createLiskConnector } from "@iov/lisk"; export const enum Codec { - Bns, Lisk, CosmWasm, } export function codecFromString(input: string): Codec { switch (input) { - case "bns": - return Codec.Bns; case "lisk": return Codec.Lisk; case "cosmwasm": @@ -27,8 +23,6 @@ export function codecFromString(input: string): Codec { export function createPathBuilderForCodec(codec: Codec): (derivation: number) => readonly Slip10RawIndex[] { const pathBuilder = (accountIndex: number): readonly Slip10RawIndex[] => { switch (codec) { - case Codec.Bns: - return HdPaths.iov(accountIndex); case Codec.Lisk: return HdPaths.bip44Like(134, accountIndex); case Codec.CosmWasm: @@ -42,8 +36,6 @@ export function createPathBuilderForCodec(codec: Codec): (derivation: number) => export function createChainConnector(codec: Codec, url: string): ChainConnector { switch (codec) { - case Codec.Bns: - return createBnsConnector(url); case Codec.Lisk: return createLiskConnector(url); case Codec.CosmWasm: { @@ -74,8 +66,6 @@ export function codecImplementation(codec: Codec): TxCodec { export function codecDefaultFractionalDigits(codec: Codec): number { switch (codec) { - case Codec.Bns: - return 9; // fixed for all weave tokens case Codec.Lisk: return 8; case Codec.CosmWasm: diff --git a/packages/faucet/src/crypto.ts b/packages/faucet/src/crypto.ts index 6d624a59..cfa370e4 100644 --- a/packages/faucet/src/crypto.ts +++ b/packages/faucet/src/crypto.ts @@ -4,7 +4,6 @@ import { Codec } from "./codec"; export function createWalletForCodec(input: Codec, mnemonic: string): Wallet { switch (input) { - case Codec.Bns: case Codec.Lisk: return Ed25519HdWallet.fromMnemonic(mnemonic); case Codec.CosmWasm: diff --git a/yarn.lock b/yarn.lock index dc48d303..61271131 100644 --- a/yarn.lock +++ b/yarn.lock @@ -103,25 +103,6 @@ type-tagger "^1.0.0" xstream "^11.10.0" -"@iov/bns@^2.0.0-alpha.7": - version "2.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@iov/bns/-/bns-2.0.0-alpha.7.tgz#83a9ab0fa97631c7d42f32038b8fb1b86d318405" - integrity sha512-xX/o65HC78SfxJLLZE6pSUcfszwDezXovYBuhoelR0vIHqGbZjetksWwXrBz7zgkyBXQnXcfUDFgyaefFfmJjw== - dependencies: - "@iov/bcp" "^2.0.0-alpha.7" - "@iov/crypto" "^2.0.0-alpha.7" - "@iov/encoding" "^2.0.0-alpha.7" - "@iov/stream" "^2.0.0-alpha.7" - "@iov/tendermint-rpc" "^2.0.0-alpha.7" - "@types/long" "^4.0.0" - "@types/node" "^10.12.18" - bn.js "^4.11.8" - fast-deep-equal "^3.1.1" - long "^4.0.0" - protobufjs "^6.8.6" - type-tagger "^1.0.0" - xstream "^11.10.0" - "@iov/crypto@^2.0.0-alpha.7": version "2.0.0-alpha.7" resolved "https://registry.yarnpkg.com/@iov/crypto/-/crypto-2.0.0-alpha.7.tgz#5cb24dbc3cdd344bf782039f1fe6d55975d171f6" @@ -207,16 +188,6 @@ "@types/long" "^4.0.0" long "^4.0.0" -"@iov/socket@^2.0.0-alpha.7": - version "2.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@iov/socket/-/socket-2.0.0-alpha.7.tgz#d88baf91617a91d87b5f5d51a11b2bc0800cf532" - integrity sha512-4c96cvwRJTEuG2vrUM36v3sFq5tkxZ3afn21zqUXIfaAo9VC3wFSpEUXjyx7/j1iwC7SOPOT2ExckiyMWBTa9A== - dependencies: - "@iov/stream" "^2.0.0-alpha.7" - isomorphic-ws "^4.0.1" - ws "^6.2.0" - xstream "^11.10.0" - "@iov/stream@^2.0.0-alpha.7": version "2.0.0-alpha.7" resolved "https://registry.yarnpkg.com/@iov/stream/-/stream-2.0.0-alpha.7.tgz#212c3f684f592ec04ac43e166183d946a49b895c" @@ -224,20 +195,6 @@ dependencies: xstream "^11.10.0" -"@iov/tendermint-rpc@^2.0.0-alpha.7": - version "2.0.0-alpha.7" - resolved "https://registry.yarnpkg.com/@iov/tendermint-rpc/-/tendermint-rpc-2.0.0-alpha.7.tgz#5c70bdcb0c2850be4012812116cbe1188bc9bdd6" - integrity sha512-UaMu7wCGiiT5baIDdeTwQ3gCWFd4J1fJDDico/RuAqxbGhtvZSUpzevv+r/xeysydviNLue1J1w2ZdqTS9mJRg== - dependencies: - "@iov/crypto" "^2.0.0-alpha.7" - "@iov/encoding" "^2.0.0-alpha.7" - "@iov/jsonrpc" "^2.0.0-alpha.7" - "@iov/socket" "^2.0.0-alpha.7" - axios "^0.19.0" - readonly-date "^1.0.0" - type-tagger "^1.0.0" - xstream "^11.10.0" - "@koa/cors@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.0.0.tgz#df021b4df2dadf1e2b04d7c8ddf93ba2d42519cb" @@ -1013,59 +970,6 @@ dependencies: "@types/node" ">= 8" -"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" - integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78= - -"@protobufjs/base64@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" - integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== - -"@protobufjs/codegen@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" - integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== - -"@protobufjs/eventemitter@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" - integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A= - -"@protobufjs/fetch@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" - integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= - dependencies: - "@protobufjs/aspromise" "^1.1.1" - "@protobufjs/inquire" "^1.1.0" - -"@protobufjs/float@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" - integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= - -"@protobufjs/inquire@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" - integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= - -"@protobufjs/path@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" - integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= - -"@protobufjs/pool@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" - integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= - -"@protobufjs/utf8@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" - integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= - "@tendermint/amino-js@^0.7.0-alpha.1": version "0.7.0-alpha.1" resolved "https://registry.yarnpkg.com/@tendermint/amino-js/-/amino-js-0.7.0-alpha.1.tgz#5d9f689fb601a0c0a6bb245a16d0b9a197f616e5" @@ -1259,11 +1163,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== -"@types/node@^10.1.0": - version "10.17.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.14.tgz#b6c60ebf2fb5e4229fdd751ff9ddfae0f5f31541" - integrity sha512-G0UmX5uKEmW+ZAhmZ6PLTQ5eu/VPaT+d/tdLd5IFsKRPcbe6lPxocBtcYBFSaLaCW8O60AX90e91Nsp8lVHCNw== - "@types/node@^10.12.18": version "10.17.13" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.13.tgz#ccebcdb990bd6139cd16e84c39dc2fb1023ca90c" @@ -4711,11 +4610,6 @@ isobject@^4.0.0: resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== -isomorphic-ws@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" - integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -6385,25 +6279,6 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -protobufjs@^6.8.6: - version "6.8.8" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.8.8.tgz#c8b4f1282fd7a90e6f5b109ed11c84af82908e7c" - integrity sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.0" - "@types/node" "^10.1.0" - long "^4.0.0" - protocols@^1.1.0, protocols@^1.4.0: version "1.4.7" resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" @@ -8195,13 +8070,6 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -ws@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - ws@~3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" From c666f30fd237c3eff261ff8d5e566926e9c9f53a Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 14:57:18 +0100 Subject: [PATCH 12/13] Remove obsolete faucet scripts --- scripts/iov_faucet_start.sh | 25 ------------------------- scripts/iov_faucet_stop.sh | 9 --------- 2 files changed, 34 deletions(-) delete mode 100755 scripts/iov_faucet_start.sh delete mode 100755 scripts/iov_faucet_stop.sh diff --git a/scripts/iov_faucet_start.sh b/scripts/iov_faucet_start.sh deleted file mode 100755 index 2c8e7972..00000000 --- a/scripts/iov_faucet_start.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck > /dev/null && shellcheck "$0" - -# Choose from https://hub.docker.com/r/iov1/iov-faucet/tags/ -FAUCET_VERSION="v0.8.1" - -TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/faucet_start.XXXXXXXXX") -LOGFILE="$TMP_DIR/faucet.log" - -DOCKER_HOST_IP=$(docker run --rm alpine ip route | awk 'NR==1 {print $3}') - -BLOCKCHAIN_URL="ws://$DOCKER_HOST_IP:23456" -echo "Connecting to $BLOCKCHAIN_URL" - -docker run --rm \ - --read-only \ - --env "FAUCET_CONCURRENCY=3" \ - --env "FAUCET_MNEMONIC=degree tackle suggest window test behind mesh extra cover prepare oak script" \ - -p 8000:8000 \ - "iov1/iov-faucet:${FAUCET_VERSION}" \ - start bns "$BLOCKCHAIN_URL" \ - > "$LOGFILE" & - -echo "Faucet running and logging into $LOGFILE" diff --git a/scripts/iov_faucet_stop.sh b/scripts/iov_faucet_stop.sh deleted file mode 100755 index af68ceca..00000000 --- a/scripts/iov_faucet_stop.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -o errexit -o nounset -o pipefail -command -v shellcheck > /dev/null && shellcheck "$0" - -LABEL_PART="iov1/iov-faucet" - -CONTAINER_ID=$(docker container ls | grep -F "$LABEL_PART:" | awk '{print $1}') -echo "Killing $LABEL_PART container '$CONTAINER_ID' ..." -docker container kill "$CONTAINER_ID" From 8c3c7778699d8ad2d4ea14a2b9dbe93bad075263 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 29 Jan 2020 15:23:58 +0100 Subject: [PATCH 13/13] Add docker configuration for faucet --- .circleci/config.yml | 16 ++++++++++++++++ faucet.Dockerfile | 23 +++++++++++++++++++++++ packages/faucet/README.md | 28 ++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 faucet.Dockerfile diff --git a/.circleci/config.yml b/.circleci/config.yml index 39168477..28e6a717 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,6 +5,7 @@ workflows: jobs: - build - lint + - faucet_docker jobs: build: @@ -53,3 +54,18 @@ jobs: - ~/.cache/yarn - run: command: yarn lint + faucet_docker: + docker: + - image: circleci/node:10 + steps: + - checkout + - setup_remote_docker: + docker_layer_caching: true + - run: + name: Build docker image + command: docker build -t cosmwasm/faucet:manual --file faucet.Dockerfile . + - run: + name: Test docker image + command: | + docker run --read-only --rm cosmwasm/faucet:manual help + docker run --read-only --rm cosmwasm/faucet:manual version diff --git a/faucet.Dockerfile b/faucet.Dockerfile new file mode 100644 index 00000000..51cbb8d6 --- /dev/null +++ b/faucet.Dockerfile @@ -0,0 +1,23 @@ +# Start the build environment +# https://hub.docker.com/_/node/ +FROM node:12.14-alpine AS build-env + +ADD package.json yarn.lock tsconfig.json lerna.json /build_repo_root/ +ADD packages/bcp /build_repo_root/packages/bcp +ADD packages/faucet /build_repo_root/packages/faucet + +WORKDIR /build_repo_root +RUN yarn install --frozen-lockfile +RUN yarn build + +# Start the runtime environment +FROM node:12.14-alpine +COPY --from=build-env /build_repo_root/package.json /run_repo_root/ +COPY --from=build-env /build_repo_root/yarn.lock /run_repo_root/ +COPY --from=build-env /build_repo_root/packages /run_repo_root/packages +WORKDIR /run_repo_root +RUN yarn install --frozen-lockfile --production + +EXPOSE 8000 +ENTRYPOINT ["/run_repo_root/packages/faucet/bin/cosm-faucet"] +CMD [""] diff --git a/packages/faucet/README.md b/packages/faucet/README.md index f5d37074..63ba5f98 100644 --- a/packages/faucet/README.md +++ b/packages/faucet/README.md @@ -74,6 +74,34 @@ the same mnemonic is used. Accessing the distributor accounts will be possible as soon as there is [multi account support](https://github.com/iov-one/ponferrada/milestone/3). +### Working with docker + +- Build an artifact () + +```sh +docker build -t cosmwasm/faucet:manual --file faucet.Dockerfile . +``` + +- Version and help + +```sh +docker run --read-only --rm cosmwasm/faucet:manual version +docker run --read-only --rm cosmwasm/faucet:manual help +``` + +- Run faucet locally + +```sh +DOCKER_HOST_IP=$(docker run --read-only --rm alpine ip route | awk 'NR==1 {print $3}') \ + FAUCET_CONCURRENCY=3 FAUCET_MNEMONIC="economy stock theory fatal elder harbor betray wasp final emotion task crumble siren bottom lizard educate guess current outdoor pair theory focus wife stone" \ + docker run --read-only --rm \ + -e FAUCET_MNEMONIC \ + -e FAUCET_CONCURRENCY \ + -p 8000:8000 \ + cosmwasm/faucet:manual \ + start cosmwasm "http://$DOCKER_HOST_IP:1317" +``` + ### Using the faucet Now that the faucet has been started up, you can send credit requests to it.