From b590c5e1425609211e85121e8a1286056c70a21a Mon Sep 17 00:00:00 2001 From: ilyasridhuan Date: Mon, 22 Nov 2021 09:19:41 +0800 Subject: [PATCH 1/4] refactor: remove timber settings --- config/default.js | 3 - docker-compose.host.docker.internal.yml | 12 --- docker-compose.images.example.yml | 109 ------------------------ docker-compose.testnet.yml | 14 --- docker-compose.yml | 109 ------------------------ 5 files changed, 247 deletions(-) diff --git a/config/default.js b/config/default.js index 7b50191d2..f55c14946 100644 --- a/config/default.js +++ b/config/default.js @@ -30,8 +30,6 @@ module.exports = { `ws://${process.env.BLOCKCHAIN_WS_HOST}:${process.env.BLOCKCHAIN_PORT}`, USE_INFURA: process.env.USE_INFURA === 'true', ETH_PRIVATE_KEY: process.env.ETH_PRIVATE_KEY, - TIMBER_HOST: process.env.TIMBER_HOST || 'timber', - TIMBER_PORT: process.env.TIMBER_PORT || 80, OPTIMIST_HOST: process.env.OPTIMIST_HOST || 'optimist', OPTIMIST_PORT: process.env.OPTIMIST_PORT || 80, WEB3_OPTIONS: { @@ -60,7 +58,6 @@ module.exports = { BN128_GROUP_ORDER: 21888242871839275222246405745257275088548364400416034343698204186575808495617n, BN128_PRIME_FIELD: 21888242871839275222246405745257275088696311157297823662689037894645226208583n, TRANSACTIONS_PER_BLOCK: Number(process.env.TRANSACTIONS_PER_BLOCK) || 2, - TIMBER_SYNC_RETRIES: 5, // Sets amount of exponential backoff attempts to sync with timber. PROPOSE_BLOCK_TYPES: [ '(uint48,address,bytes32,uint256,bytes32)', '(uint64,uint64[2],uint8,uint8,bytes32,bytes32,bytes32,bytes32,bytes32[2],bytes32[2],bytes32[8],uint[4])[]', diff --git a/docker-compose.host.docker.internal.yml b/docker-compose.host.docker.internal.yml index 6e134f457..b68a1d9a3 100644 --- a/docker-compose.host.docker.internal.yml +++ b/docker-compose.host.docker.internal.yml @@ -23,23 +23,11 @@ services: ETH_NETWORK: development BLOCKCHAIN_WS_HOST: host.docker.internal - # Timber service, configured for nightfall - timber1: - environment: - BLOCKCHAIN_WS_HOST: host.docker.internal - AUTOSTART_RETRIES: 100 - optimist1: environment: BLOCKCHAIN_WS_HOST: host.docker.internal AUTOSTART_RETRIES: 100 - timber2: - environment: - BLOCKCHAIN_WS_HOST: host.docker.internal - AUTOSTART_RETRIES: 100 - # LOG_LEVEL: debug - optimist2: environment: BLOCKCHAIN_WS_HOST: host.docker.internal diff --git a/docker-compose.images.example.yml b/docker-compose.images.example.yml index c051232db..59fbe1f47 100644 --- a/docker-compose.images.example.yml +++ b/docker-compose.images.example.yml @@ -19,7 +19,6 @@ services: depends_on: - deployer - worker - - timber1 - rabbitmq1 environment: MONGO_INITDB_ROOT_USERNAME: admin @@ -30,8 +29,6 @@ services: ZOKRATES_WORKER_HOST: worker RABBITMQ_HOST: amqp://rabbitmq1 RABBITMQ_PORT: 5672 - TIMBER_HOST: timber1 - TIMBER_PORT: 80 ENABLE_QUEUE: 1 OPTIMIST_HOST: optimist1 OPTIMIST_PORT: 80 @@ -52,7 +49,6 @@ services: depends_on: - deployer - worker - - timber2 - rabbitmq2 environment: MONGO_INITDB_ROOT_USERNAME: admin @@ -63,8 +59,6 @@ services: ZOKRATES_WORKER_HOST: worker RABBITMQ_HOST: amqp://rabbitmq2 RABBITMQ_PORT: 5672 - TIMBER_HOST: timber2 - TIMBER_PORT: 80 ENABLE_QUEUE: 1 OPTIMIST_HOST: optimist2 OPTIMIST_PORT: 80 @@ -104,103 +98,8 @@ services: BLOCKCHAIN_WS_HOST: blockchain1 BLOCKCHAIN_PORT: 8546 ZOKRATES_WORKER_HOST: worker - # TIMBER_HOST: timber1 - # TIMBER_PORT: 80 USE_STUBS: 'false' - # Timber service, configured for nightfall - timber1: - build: - dockerfile: Dockerfile - context: ./timber - restart: on-failure - depends_on: - - deployer - - timber-database1 - networks: - - nightfall_network - ports: - - 8083:80 - volumes: - - type: volume - source: build - target: /app/build/ - - type: bind - source: ./timber/src - target: /app/src/ - - type: bind - source: ./config/timber.js - target: /app/config/default.js - - type: bind - source: ./timber/entrypoint.sh - target: /app/entrypoint.sh - environment: - BLOCKCHAIN_WS_HOST: blockchain1 - BLOCKCHAIN_PORT: 8546 - MONGO_HOST: timber-database1 - MONGO_PORT: 27017 - MONGO_NAME: merkle_tree - HASH_TYPE: mimc - LOG_LEVEL: info - AUTOSTART: enabled - - # Timber service, configured for nightfall - timber2: - build: - dockerfile: Dockerfile - context: ./timber - restart: on-failure - depends_on: - - deployer - - timber-database2 - networks: - - nightfall_network - ports: - - 8087:80 - volumes: - - type: volume - source: build - target: /app/build/ - - type: bind - source: ./timber/src - target: /app/src/ - - type: bind - source: ./config/timber.js - target: /app/config/default.js - environment: - BLOCKCHAIN_WS_HOST: blockchain1 - BLOCKCHAIN_PORT: 8546 - MONGO_HOST: timber-database2 - MONGO_PORT: 27017 - MONGO_NAME: merkle_tree - HASH_TYPE: mimc - LOG_LEVEL: error - AUTOSTART: enabled - - #The database storing the merkle tree - timber-database1: - image: mongo - environment: - - MONGO_INITDB_DATABASE=merkle_tree - volumes: - - type: volume - source: timber-database-volume1 - target: /data/db - networks: - - nightfall_network - - #The database storing the merkle tree - timber-database2: - image: mongo - environment: - - MONGO_INITDB_DATABASE=merkle_tree - volumes: - - type: volume - source: timber-database-volume2 - target: /data/db - networks: - - nightfall_network - rabbitmq1: image: rabbitmq ports: @@ -220,7 +119,6 @@ services: optimist1: image: ghcr.io/eyblockchain/nightfall3-optimist:latest depends_on: - - timber1 - deployer networks: - nightfall_network @@ -240,14 +138,11 @@ services: LOG_LEVEL: debug IS_CHALLENGER: 'true' TRANSACTIONS_PER_BLOCK: ${TRANSACTIONS_PER_BLOCK:-2} - TIMBER_HOST: timber1 - TIMBER_PORT: 80 command: ['npm', 'run', 'dev'] optimist2: image: ghcr.io/eyblockchain/nightfall3-optimist:latest depends_on: - - timber2 - deployer networks: - nightfall_network @@ -268,8 +163,6 @@ services: LOG_LEVEL: error IS_CHALLENGER: 'true' TRANSACTIONS_PER_BLOCK: ${TRANSACTIONS_PER_BLOCK:-2} - TIMBER_HOST: timber2 - TIMBER_PORT: 80 command: ['npm', 'run', 'dev'] volumes: @@ -277,8 +170,6 @@ volumes: mongodb2: proving_files: build: - timber-database-volume1: - timber-database-volume2: networks: nightfall_network: diff --git a/docker-compose.testnet.yml b/docker-compose.testnet.yml index dcd21ca17..c973a444d 100644 --- a/docker-compose.testnet.yml +++ b/docker-compose.testnet.yml @@ -28,20 +28,6 @@ services: ETH_PRIVATE_KEY: $ETH_PRIVATE_KEY INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET - timber1: - environment: - BLOCKCHAIN_URL: 'wss://ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' - USE_INFURA: 'true' - AUTOSTART_RETRIES: 500 - INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET - - timber2: - environment: - BLOCKCHAIN_URL: 'wss://ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' - USE_INFURA: 'true' - AUTOSTART_RETRIES: 500 - INFURA_PROJECT_SECRET: $INFURA_PROJECT_SECRET - optimist1: environment: BLOCKCHAIN_URL: 'wss://ropsten.infura.io/ws/v3/${INFURA_PROJECT_ID}' diff --git a/docker-compose.yml b/docker-compose.yml index 24f3bd194..0c9204bbd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,7 +30,6 @@ services: depends_on: - deployer - worker - - timber1 - rabbitmq1 environment: MONGO_INITDB_ROOT_USERNAME: admin @@ -41,8 +40,6 @@ services: ZOKRATES_WORKER_HOST: worker RABBITMQ_HOST: amqp://rabbitmq1 RABBITMQ_PORT: 5672 - TIMBER_HOST: timber1 - TIMBER_PORT: 80 ENABLE_QUEUE: 1 OPTIMIST_HOST: optimist1 OPTIMIST_PORT: 80 @@ -77,7 +74,6 @@ services: depends_on: - deployer - worker - - timber2 - rabbitmq2 environment: MONGO_INITDB_ROOT_USERNAME: admin @@ -88,8 +84,6 @@ services: ZOKRATES_WORKER_HOST: worker RABBITMQ_HOST: amqp://rabbitmq2 RABBITMQ_PORT: 5672 - TIMBER_HOST: timber2 - TIMBER_PORT: 80 ENABLE_QUEUE: 1 OPTIMIST_HOST: optimist2 OPTIMIST_PORT: 80 @@ -165,103 +159,8 @@ services: BLOCKCHAIN_WS_HOST: blockchain1 BLOCKCHAIN_PORT: 8546 ZOKRATES_WORKER_HOST: worker - # TIMBER_HOST: timber1 - # TIMBER_PORT: 80 USE_STUBS: 'false' - # Timber service, configured for nightfall - timber1: - build: - dockerfile: Dockerfile - context: ./timber - restart: on-failure - depends_on: - - deployer - - timber-database1 - networks: - - nightfall_network - ports: - - 8083:80 - volumes: - - type: volume - source: build - target: /app/build/ - - type: bind - source: ./timber/src - target: /app/src/ - - type: bind - source: ./config/timber.js - target: /app/config/default.js - - type: bind - source: ./timber/entrypoint.sh - target: /app/entrypoint.sh - environment: - BLOCKCHAIN_WS_HOST: blockchain1 - BLOCKCHAIN_PORT: 8546 - MONGO_HOST: timber-database1 - MONGO_PORT: 27017 - MONGO_NAME: merkle_tree - HASH_TYPE: mimc - LOG_LEVEL: info - AUTOSTART: enabled - - # Timber service, configured for nightfall - timber2: - build: - dockerfile: Dockerfile - context: ./timber - restart: on-failure - depends_on: - - deployer - - timber-database2 - networks: - - nightfall_network - ports: - - 8087:80 - volumes: - - type: volume - source: build - target: /app/build/ - - type: bind - source: ./timber/src - target: /app/src/ - - type: bind - source: ./config/timber.js - target: /app/config/default.js - environment: - BLOCKCHAIN_WS_HOST: blockchain1 - BLOCKCHAIN_PORT: 8546 - MONGO_HOST: timber-database2 - MONGO_PORT: 27017 - MONGO_NAME: merkle_tree - HASH_TYPE: mimc - LOG_LEVEL: error - AUTOSTART: enabled - - #The database storing the merkle tree - timber-database1: - image: mongo - environment: - - MONGO_INITDB_DATABASE=merkle_tree - volumes: - - type: volume - source: timber-database-volume1 - target: /data/db - networks: - - nightfall_network - - #The database storing the merkle tree - timber-database2: - image: mongo - environment: - - MONGO_INITDB_DATABASE=merkle_tree - volumes: - - type: volume - source: timber-database-volume2 - target: /data/db - networks: - - nightfall_network - rabbitmq1: image: rabbitmq ports: @@ -282,7 +181,6 @@ services: build: context: ./nightfall-optimist depends_on: - - timber1 - deployer networks: - nightfall_network @@ -311,15 +209,12 @@ services: LOG_LEVEL: debug IS_CHALLENGER: 'true' TRANSACTIONS_PER_BLOCK: ${TRANSACTIONS_PER_BLOCK:-2} - TIMBER_HOST: timber1 - TIMBER_PORT: 80 command: ['npm', 'run', 'dev'] optimist2: build: context: ./nightfall-optimist depends_on: - - timber2 - deployer networks: - nightfall_network @@ -348,8 +243,6 @@ services: LOG_LEVEL: error IS_CHALLENGER: 'true' TRANSACTIONS_PER_BLOCK: ${TRANSACTIONS_PER_BLOCK:-2} - TIMBER_HOST: timber2 - TIMBER_PORT: 80 command: ['npm', 'run', 'dev'] volumes: @@ -357,8 +250,6 @@ volumes: mongodb2: proving_files: build: - timber-database-volume1: - timber-database-volume2: networks: nightfall_network: From dc533b4979174bf412c6d5fc8ece386e2368e4df Mon Sep 17 00:00:00 2001 From: ilyasridhuan Date: Mon, 22 Nov 2021 09:20:22 +0800 Subject: [PATCH 2/4] refactor: remove from other applications --- nightfall-client/dropAll.sh | 7 ---- nightfall-client/src/app.mjs | 2 - nightfall-client/src/routes/check-message.mjs | 23 ------------ nightfall-client/src/routes/index.mjs | 2 - .../src/services/check-message.mjs | 37 ------------------- .../src/services/state-sync.mjs | 5 --- nightfall-optimist/src/utils/timber.mjs | 27 -------------- test/utils.mjs | 7 +--- 8 files changed, 1 insertion(+), 109 deletions(-) delete mode 100644 nightfall-client/src/routes/check-message.mjs delete mode 100644 nightfall-client/src/services/check-message.mjs delete mode 100644 nightfall-optimist/src/utils/timber.mjs diff --git a/nightfall-client/dropAll.sh b/nightfall-client/dropAll.sh index 54fac837e..a83234b79 100755 --- a/nightfall-client/dropAll.sh +++ b/nightfall-client/dropAll.sh @@ -1,12 +1,5 @@ #! /bin/bash -docker exec -t nightfall_3_timber-database1_1 bash -c \ - 'mongo --quiet --eval "db = db.getSiblingDB(\"merkle_tree\"); - db.admin_state_nodes.drop( { writeConcern: { w: \"majority\" } } ); - db.admin_state_histories.drop( { writeConcern: { w: \"majority\" } } ); - db.admin_state_metadatas.drop( { writeConcern: { w: \"majority\" } } ); - db.admin_state_metadatas.insert( { \"_id\" : 1, \"__v\" : 0, \"contractAddress\" : \"0x9b1f7F645351AF3631a656421eD2e40f2802E6c0\", \"created_at\" : ISODate(\"2021-05-03T08:18:08.739Z\"), \"updated_at\" : ISODate(\"2021-05-03T08:18:08.739Z\") })"' - docker exec -t nightfall_3_optimist1_1 bash -c \ 'mongo --quiet --eval "db = db.getSiblingDB(\"optimist_data\"); db.blocks.drop( { writeConcern: { w: \"majority\" } } ); diff --git a/nightfall-client/src/app.mjs b/nightfall-client/src/app.mjs index 69a0bdeeb..18041e261 100644 --- a/nightfall-client/src/app.mjs +++ b/nightfall-client/src/app.mjs @@ -6,7 +6,6 @@ import { getContractAddress, transfer, withdraw, - isMessageValid, finaliseWithdrawal, isValidWithdrawal, peers, @@ -27,7 +26,6 @@ app.use('/deposit', deposit); app.use('/contract-address', getContractAddress); app.use('/transfer', transfer); app.use('/withdraw', withdraw); -app.use('/check-message', isMessageValid); app.use('/finalise-withdrawal', finaliseWithdrawal); app.use('/valid-withdrawal', isValidWithdrawal); app.use('/peers', peers); diff --git a/nightfall-client/src/routes/check-message.mjs b/nightfall-client/src/routes/check-message.mjs deleted file mode 100644 index 0e916e1bb..000000000 --- a/nightfall-client/src/routes/check-message.mjs +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Route to allow a transfer message (which may have been received by a system - * external to Nightfall, to be check for validity by Nightfall. - */ -import express from 'express'; -import logger from 'common-files/utils/logger.mjs'; -import isMessageValid from '../services/check-message.mjs'; - -const router = express.Router(); - -router.get('/', async (req, res, next) => { - logger.debug(`check-message endpoint received GET ${JSON.stringify(req.query, null, 2)}`); - try { - const result = await isMessageValid(req.query.message, req.query.compressedPkd); - logger.debug(`returning result ${result}`); - res.json({ valid: result }); - } catch (err) { - logger.error(err); - next(err); - } -}); - -export default router; diff --git a/nightfall-client/src/routes/index.mjs b/nightfall-client/src/routes/index.mjs index 0f30b2244..ee8f07436 100644 --- a/nightfall-client/src/routes/index.mjs +++ b/nightfall-client/src/routes/index.mjs @@ -2,7 +2,6 @@ import deposit from './deposit.mjs'; import getContractAddress from './contract-address.mjs'; import transfer from './transfer.mjs'; import withdraw from './withdraw.mjs'; -import isMessageValid from './check-message.mjs'; import finaliseWithdrawal from './finalise-withdrawal.mjs'; import isValidWithdrawal from './valid-withdrawal.mjs'; import peers from './peers.mjs'; @@ -16,7 +15,6 @@ export { deposit, withdraw, getContractAddress, - isMessageValid, finaliseWithdrawal, isValidWithdrawal, peers, diff --git a/nightfall-client/src/services/check-message.mjs b/nightfall-client/src/services/check-message.mjs deleted file mode 100644 index 12e4931fe..000000000 --- a/nightfall-client/src/services/check-message.mjs +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Function for checking that a commitment that has been transferred to a - * receiving party is valid. For off-chain messaging, or on-chain messaging - * that does not enforce a proof of correctness, we need to check that the - * commitment that is re-created from the message exists 'on-chain'. - * Note that the commitment may not actually still be saved on-chain and so we - * will, in fact, refer to our Timber instance for confirmation (this is much - * faster than searching all historical NewLeaf or NewLeaves events). - * One thing to watch is that Timber may not yet have updated with the latest - * event data, if the transaction was very recent, and so we need to make sure - * we have waited long enough before we call foul. This function does not - * address that problem; it's up to the caller to solve (e.g. by retrying). - * Likewise, this function makes no assumptions about how we got the message, - * because that is implementation dependent. It does however enforce the - * message object's structure, as defined in the message param below. Thus any - * preprossesing of the message (decryption, header and metadata removal) must - * be done by the message-receiving infrastructure. - * - * This function is NOT required for on-chain messaging methods, that enforce a - * proof of correctness on the message, because the message is provably correct. - * @param {object} message - {ercAddress, tokenId, value, salt } - * @param {general-number} compressedPkd - public key of receiving party - * @return {boolean} - */ - -import { Commitment } from '../classes/index.mjs'; - -async function isMessageValid(message, compressedPkd) { - const commitment = new Commitment({ - compressedPkd, - ...message, - }); - if ((await commitment.index) === null) return false; - return true; -} - -export default isMessageValid; diff --git a/nightfall-optimist/src/services/state-sync.mjs b/nightfall-optimist/src/services/state-sync.mjs index 579250357..ab4b6566a 100644 --- a/nightfall-optimist/src/services/state-sync.mjs +++ b/nightfall-optimist/src/services/state-sync.mjs @@ -7,7 +7,6 @@ import transactionSubmittedEventHandler from '../event-handlers/transaction-subm import newCurrentProposerEventHandler from '../event-handlers/new-current-proposer.mjs'; import committedToChallengeEventHandler from '../event-handlers/challenge-commit.mjs'; import rollbackEventHandler from '../event-handlers/rollback.mjs'; -import { callTimberHandler } from '../utils/timber.mjs'; import { getBlockByBlockNumberL2, getBlocks } from './database.mjs'; import { stopMakingChallenges, startMakingChallenges } from './challenges.mjs'; import { waitForContract } from '../event-handlers/subscribe.mjs'; @@ -52,13 +51,9 @@ const syncState = async ( await newCurrentProposerEventHandler(pastEvent, [proposer]); break; case 'Rollback': - // eslint-disable-next-line no-await-in-loop - await callTimberHandler(pastEvent); await rollbackEventHandler(pastEvent); break; case 'BlockProposed': - // eslint-disable-next-line no-await-in-loop - await callTimberHandler(pastEvent); // eslint-disable-next-line no-await-in-loop await blockProposedEventHandler(pastEvent); break; diff --git a/nightfall-optimist/src/utils/timber.mjs b/nightfall-optimist/src/utils/timber.mjs deleted file mode 100644 index 7f49302e7..000000000 --- a/nightfall-optimist/src/utils/timber.mjs +++ /dev/null @@ -1,27 +0,0 @@ -import axios from 'axios'; -import config from 'config'; -import logger from 'common-files/utils/logger.mjs'; - -const url = `http://${config.TIMBER_HOST}:${config.TIMBER_PORT}`; -const contractName = config.STATE_CONTRACT_NAME; - -// eslint-disable-next-line import/prefer-default-export -export const callTimberHandler = async data => { - try { - logger.http(`Calling /replayEvent for Timber`); - const response = await axios.post( - `${url}/replayEvent`, - { - contractName, - eventData: data, - }, - { - timeout: 3600000, - }, - ); - logger.http('Timber Response:', response.data.data); - return response.data.data; - } catch (error) { - throw new Error(error); - } -}; diff --git a/test/utils.mjs b/test/utils.mjs index e2341bb0d..8b6cc22a2 100644 --- a/test/utils.mjs +++ b/test/utils.mjs @@ -131,16 +131,11 @@ export async function timeJump(secs) { } export async function createBadBlock(badBlockType, block, transactions, args) { - let res; const badBlock = block; const badTransactions = transactions; switch (badBlockType) { case 'IncorrectRoot': { - res = await chai - .request('http://localhost:8083') - .get(`/path/${args.leafIndex}`) - .send({ contractName: 'State' }); - badBlock.root = res.body.data[0].value; + badBlock.root = (await rand(32)).hex(); break; } case 'DuplicateTransaction': { From dfa05a19bada81b648d4a972ec7d2ca6337813a4 Mon Sep 17 00:00:00 2001 From: ilyasridhuan Date: Mon, 22 Nov 2021 09:20:43 +0800 Subject: [PATCH 3/4] refactor: remove timber folder --- config/timber.js | 108 - timber/.dockerignore | 91 - timber/.gitignore | 91 - timber/Dockerfile | 13 - timber/dev.Dockerfile | 12 - timber/entrypoint.sh | 13 - timber/package-lock.json | 5080 ----------------- timber/package.json | 42 - timber/src/auto-start.mjs | 52 - timber/src/compile.mjs | 117 - timber/src/console-testing.mjs | 24 - timber/src/contract-controller.mjs | 184 - timber/src/db/common/adminDbConnection.mjs | 16 - timber/src/db/common/constants.mjs | 7 - timber/src/db/mappers/history.mjs | 18 - timber/src/db/mappers/index.mjs | 4 - timber/src/db/mappers/leaf.mjs | 24 - timber/src/db/mappers/metadata.mjs | 15 - timber/src/db/mappers/node.mjs | 7 - timber/src/db/models/history.model.mjs | 30 - timber/src/db/models/index.mjs | 3 - timber/src/db/models/metadata.model.mjs | 53 - timber/src/db/models/node.model.mjs | 40 - timber/src/db/mongodb/db.mjs | 259 - timber/src/db/service/history.service.mjs | 81 - timber/src/db/service/index.mjs | 4 - timber/src/db/service/leaf.service.mjs | 293 - timber/src/db/service/metadata.service.mjs | 232 - timber/src/db/service/node.service.mjs | 226 - timber/src/filter-controller.mjs | 452 -- timber/src/index.mjs | 67 - timber/src/logger.mjs | 11 - timber/src/merkle-tree-controller.mjs | 455 -- .../src/middleware/assign-db-connection.mjs | 40 - timber/src/middleware/index.mjs | 2 - timber/src/middleware/response.mjs | 43 - timber/src/optimistic/process-calldata.mjs | 59 - timber/src/rest/deployer.mjs | 83 - timber/src/routes/index.mjs | 4 - timber/src/routes/leaf.routes.mjs | 264 - timber/src/routes/merkle-tree.routes.mjs | 239 - timber/src/routes/metadata.routes.mjs | 233 - timber/src/routes/node.routes.mjs | 234 - timber/src/solc-versions-list.mjs | 1000 ---- timber/src/utils-merkle-tree.mjs | 380 -- timber/src/utils-poll.mjs | 81 - timber/src/utils-web3.mjs | 281 - timber/src/utils.mjs | 288 - timber/src/web3.mjs | 60 - timber/src/web3.notes | 132 - 50 files changed, 11547 deletions(-) delete mode 100644 config/timber.js delete mode 100644 timber/.dockerignore delete mode 100644 timber/.gitignore delete mode 100644 timber/Dockerfile delete mode 100644 timber/dev.Dockerfile delete mode 100755 timber/entrypoint.sh delete mode 100644 timber/package-lock.json delete mode 100644 timber/package.json delete mode 100644 timber/src/auto-start.mjs delete mode 100644 timber/src/compile.mjs delete mode 100644 timber/src/console-testing.mjs delete mode 100644 timber/src/contract-controller.mjs delete mode 100644 timber/src/db/common/adminDbConnection.mjs delete mode 100644 timber/src/db/common/constants.mjs delete mode 100644 timber/src/db/mappers/history.mjs delete mode 100644 timber/src/db/mappers/index.mjs delete mode 100644 timber/src/db/mappers/leaf.mjs delete mode 100644 timber/src/db/mappers/metadata.mjs delete mode 100644 timber/src/db/mappers/node.mjs delete mode 100644 timber/src/db/models/history.model.mjs delete mode 100644 timber/src/db/models/index.mjs delete mode 100644 timber/src/db/models/metadata.model.mjs delete mode 100644 timber/src/db/models/node.model.mjs delete mode 100644 timber/src/db/mongodb/db.mjs delete mode 100644 timber/src/db/service/history.service.mjs delete mode 100644 timber/src/db/service/index.mjs delete mode 100644 timber/src/db/service/leaf.service.mjs delete mode 100644 timber/src/db/service/metadata.service.mjs delete mode 100644 timber/src/db/service/node.service.mjs delete mode 100644 timber/src/filter-controller.mjs delete mode 100644 timber/src/index.mjs delete mode 100644 timber/src/logger.mjs delete mode 100644 timber/src/merkle-tree-controller.mjs delete mode 100644 timber/src/middleware/assign-db-connection.mjs delete mode 100644 timber/src/middleware/index.mjs delete mode 100644 timber/src/middleware/response.mjs delete mode 100644 timber/src/optimistic/process-calldata.mjs delete mode 100644 timber/src/rest/deployer.mjs delete mode 100644 timber/src/routes/index.mjs delete mode 100644 timber/src/routes/leaf.routes.mjs delete mode 100644 timber/src/routes/merkle-tree.routes.mjs delete mode 100644 timber/src/routes/metadata.routes.mjs delete mode 100644 timber/src/routes/node.routes.mjs delete mode 100644 timber/src/solc-versions-list.mjs delete mode 100644 timber/src/utils-merkle-tree.mjs delete mode 100644 timber/src/utils-poll.mjs delete mode 100644 timber/src/utils-web3.mjs delete mode 100644 timber/src/utils.mjs delete mode 100644 timber/src/web3.mjs delete mode 100644 timber/src/web3.notes diff --git a/config/timber.js b/config/timber.js deleted file mode 100644 index e640ca9e0..000000000 --- a/config/timber.js +++ /dev/null @@ -1,108 +0,0 @@ -/** -@module default.js -@author iAmMichaelConnor -@desc constants used by a nubmer of other modules -*/ -const nodeHashLength = process.env.HASH_TYPE === 'mimc' ? 32 : 27; -const zeroHex = - process.env.HASH_TYPE === 'mimc' - ? '0x0000000000000000000000000000000000000000000000000000000000000000' - : '0x000000000000000000000000000000000000000000000000000000'; - -module.exports = { - // general: - ZERO: zeroHex, // 27-byte hex string representing zero, for hashing with '0' up the tree. Byte length must match that of NODE_HASHLENGTH - - // Tree parameters. You also need to set these in the MerkleTree.sol contract. - HASH_TYPE: process.env.HASH_TYPE, - LEAF_HASHLENGTH: 32, // expected length of leaves' values in bytes - NODE_HASHLENGTH: nodeHashLength, // expected length of nodes' values up the merkle tree, in bytes - TREE_HEIGHT: 32, // the hieght of the Merkle tree - ZOKRATES_PACKING_SIZE: '128', // ZOKRATES_PRIME is approx 253-254bits (just shy of 256), so we pack field elements into blocks of 128 bits. - ZOKRATES_PRIME: '21888242871839275222246405745257275088548364400416034343698204186575808495617', // decimal representation of the prime p of GaloisField(p) - - POLLING_FREQUENCY: 6000, // milliseconds - FILTER_GENESIS_BLOCK_NUMBER: 0, // blockNumber - - tolerances: { - LAG_BEHIND_CURRENT_BLOCK: 5, // add warnings for use of tree data which lags further behind the current block (e.g. due to anonymity concerns) - }, - - UPDATE_FREQUENCY: 100, // TODO: recalculate the tree every 'x' leaves - NOT USED YET - BULK_WRITE_BUFFER_SIZE: 1000, // number of documents to add to a buffer before bulk-writing them to the db - USE_INFURA: process.env.USE_INFURA === 'true', - - // contracts to filter: - contracts: { - State: { - events: { - BlockProposed: { - parameters: [], - }, - Rollback: { - parameters: ['root', 'leafCount'], - }, - }, - }, - }, - - /* - # Where to find the contractInstances? - # Specify one of: - # - 'remote' (to GET them from a remote microservice); or - # - 'mongodb' (to get them from mongodb); or - # - 'default' (to get them from the app/build/contracts folder) - */ - contractLocation: process.env.CONTRACT_LOCATION, - - // external contract deployment microservice (which deploys the MerkleTree.sol contract): - deployer: { - host: process.env.DEPLOYER_HOST, - port: process.env.DEPLOYER_PORT, - }, - - // mongodb: - mongo: { - host: process.env.MONGO_HOST || 'client', - port: process.env.MONGO_PORT || '27017', - databaseName: process.env.MONGO_DB || 'merkle_tree', - admin: process.env.MONGO_USERNAME || 'admin', - adminPassword: process.env.MONGO_PASSWORD || 'admin', - }, - isLoggerEnabled: true, - - // web3: - web3: { - url: - process.env.BLOCKCHAIN_URL || - `ws://${process.env.BLOCKCHAIN_WS_HOST}:${process.env.BLOCKCHAIN_PORT}`, - options: { - // some of options are not in use - remove after testing shows it's not needed: - defaultAccount: '0x0', - defaultBlock: '0', // e.g. the genesis block our blockchain - defaultGas: 100000, - defaultGasPrice: 20000000000, - transactionBlockTimeout: 50, - transactionConfirmationBlocks: 15, - transactionPollingTimeout: 480, - // transactionSigner: new CustomTransactionSigner() - clientConfig: { - // Useful to keep a connection alive - keepalive: true, - keepaliveInterval: 60000, - }, - timeout: 3600000, - reconnect: { - auto: true, - delay: 5000, // ms - maxAttempts: 120, - onTimeout: false, - }, - }, - }, - LOG_LEVEL: process.env.LOG_LEVEL || 'info', - PROPOSE_BLOCK_TYPES: [ - '(uint48,address,bytes32,uint256,bytes32)', - '(uint64,uint64[2],uint8,uint8,bytes32,bytes32,bytes32,bytes32,bytes32[2],bytes32[2],bytes32[8],uint[4])[]', - ], -}; diff --git a/timber/.dockerignore b/timber/.dockerignore deleted file mode 100644 index e43a7268e..000000000 --- a/timber/.dockerignore +++ /dev/null @@ -1,91 +0,0 @@ - -# Created by https://www.gitignore.io/api/node -# Edit at https://www.gitignore.io/?templates=node - -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# End of https://www.gitignore.io/api/node diff --git a/timber/.gitignore b/timber/.gitignore deleted file mode 100644 index e43a7268e..000000000 --- a/timber/.gitignore +++ /dev/null @@ -1,91 +0,0 @@ - -# Created by https://www.gitignore.io/api/node -# Edit at https://www.gitignore.io/?templates=node - -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# End of https://www.gitignore.io/api/node diff --git a/timber/Dockerfile b/timber/Dockerfile deleted file mode 100644 index f9c25ebc7..000000000 --- a/timber/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM node:14.17 - -WORKDIR /app -RUN apt-get update -y -RUN apt-get install -y netcat-openbsd -COPY ./package.json ./package-lock.json ./ -COPY ./src ./src -COPY entrypoint.sh entrypoint.sh - -RUN npm ci - -EXPOSE 80 -ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file diff --git a/timber/dev.Dockerfile b/timber/dev.Dockerfile deleted file mode 100644 index f29b8eaab..000000000 --- a/timber/dev.Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:14.17 - -WORKDIR /app - -COPY ./package.json ./package-lock.json ./.npmrc ./ -COPY ./src ./src -# ARG GPR_TOKEN -RUN npm ci -RUN rm -f .npmrc - -EXPOSE 80 -CMD npm run dev diff --git a/timber/entrypoint.sh b/timber/entrypoint.sh deleted file mode 100755 index aa4ddfaf8..000000000 --- a/timber/entrypoint.sh +++ /dev/null @@ -1,13 +0,0 @@ -#! /bin/bash -set -o errexit -set -o pipefail - -if [ -z "${USE_INFURA}" ] -then - # wait until there's a blockchain client up - while ! nc -z ${BLOCKCHAIN_WS_HOST} ${BLOCKCHAIN_PORT}; do sleep 3; done -fi - -#sleep 10 - -npm start diff --git a/timber/package-lock.json b/timber/package-lock.json deleted file mode 100644 index e74d698e9..000000000 --- a/timber/package-lock.json +++ /dev/null @@ -1,5080 +0,0 @@ -{ - "name": "timber", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", - "requires": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "@ethersproject/abi": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.7.tgz", - "integrity": "sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw==", - "requires": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/hash": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/strings": "^5.0.4" - } - }, - "@ethersproject/abstract-provider": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.3.0.tgz", - "integrity": "sha512-1+MLhGP1GwxBDBNwMWVmhCsvKwh4gK7oIfOrmlmePNeskg1NhIrYssraJBieaFNHUYfKEd/1DjiVZMw8Qu5Cxw==", - "requires": { - "@ethersproject/bignumber": "^5.3.0", - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/networks": "^5.3.0", - "@ethersproject/properties": "^5.3.0", - "@ethersproject/transactions": "^5.3.0", - "@ethersproject/web": "^5.3.0" - } - }, - "@ethersproject/abstract-signer": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.3.0.tgz", - "integrity": "sha512-w8IFwOYqiPrtvosPuArZ3+QPR2nmdVTRrVY8uJYL3NNfMmQfTy3V3l2wbzX47UUlNbPJY+gKvzJAyvK1onZxJg==", - "requires": { - "@ethersproject/abstract-provider": "^5.3.0", - "@ethersproject/bignumber": "^5.3.0", - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/properties": "^5.3.0" - } - }, - "@ethersproject/address": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.3.0.tgz", - "integrity": "sha512-29TgjzEBK+gUEUAOfWCG7s9IxLNLCqvr+oDSk6L9TXD0VLvZJKhJV479tKQqheVA81OeGxfpdxYtUVH8hqlCvA==", - "requires": { - "@ethersproject/bignumber": "^5.3.0", - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/keccak256": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/rlp": "^5.3.0" - } - }, - "@ethersproject/base64": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.3.0.tgz", - "integrity": "sha512-JIqgtOmgKcbc2sjGWTXyXktqUhvFUDte8fPVsAaOrcPiJf6YotNF+nsrOYGC9pbHBEGSuSBp3QR0varkO8JHEw==", - "requires": { - "@ethersproject/bytes": "^5.3.0" - } - }, - "@ethersproject/bignumber": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.3.0.tgz", - "integrity": "sha512-5xguJ+Q1/zRMgHgDCaqAexx/8DwDVLRemw2i6uR8KyGjwGdXI8f32QZZ1cKGucBN6ekJvpUpHy6XAuQnTv0mPA==", - "requires": { - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "bn.js": "^4.11.9" - } - }, - "@ethersproject/bytes": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.3.0.tgz", - "integrity": "sha512-rqLJjdVqCcn7glPer7Fxh87PRqlnRScVAoxcIP3PmOUNApMWJ6yRdOFfo2KvPAdO7Le3yEI1o0YW+Yvr7XCYvw==", - "requires": { - "@ethersproject/logger": "^5.3.0" - } - }, - "@ethersproject/constants": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.3.0.tgz", - "integrity": "sha512-4y1feNOwEpgjAfiCFWOHznvv6qUF/H6uI0UKp8xdhftb+H+FbKflXg1pOgH5qs4Sr7EYBL+zPyPb+YD5g1aEyw==", - "requires": { - "@ethersproject/bignumber": "^5.3.0" - } - }, - "@ethersproject/hash": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.3.0.tgz", - "integrity": "sha512-gAFZSjUPQ32CIfoKSMtMEQ+IO0kQxqhwz9fCIFt2DtAq2u4pWt8mL9Z5P0r6KkLcQU8LE9FmuPPyd+JvBzmr1w==", - "requires": { - "@ethersproject/abstract-signer": "^5.3.0", - "@ethersproject/address": "^5.3.0", - "@ethersproject/bignumber": "^5.3.0", - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/keccak256": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/properties": "^5.3.0", - "@ethersproject/strings": "^5.3.0" - } - }, - "@ethersproject/keccak256": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.3.0.tgz", - "integrity": "sha512-Gv2YqgIUmRbYVNIibafT0qGaeGYLIA/EdWHJ7JcVxVSs2vyxafGxOJ5VpSBHWeOIsE6OOaCelYowhuuTicgdFQ==", - "requires": { - "@ethersproject/bytes": "^5.3.0", - "js-sha3": "0.5.7" - }, - "dependencies": { - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" - } - } - }, - "@ethersproject/logger": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.3.0.tgz", - "integrity": "sha512-8bwJ2gxJGkZZnpQSq5uSiZSJjyVTWmlGft4oH8vxHdvO1Asy4TwVepAhPgxIQIMxXZFUNMych1YjIV4oQ4I7dA==" - }, - "@ethersproject/networks": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.3.1.tgz", - "integrity": "sha512-6uQKHkYChlsfeiZhQ8IHIqGE/sQsf25o9ZxAYpMxi15dLPzz3IxOEF5KiSD32aHwsjXVBKBSlo+teAXLlYJybw==", - "requires": { - "@ethersproject/logger": "^5.3.0" - } - }, - "@ethersproject/properties": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.3.0.tgz", - "integrity": "sha512-PaHxJyM5/bfusk6vr3yP//JMnm4UEojpzuWGTmtL5X4uNhNnFNvlYilZLyDr4I9cTkIbipCMsAuIcXWsmdRnEw==", - "requires": { - "@ethersproject/logger": "^5.3.0" - } - }, - "@ethersproject/rlp": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.3.0.tgz", - "integrity": "sha512-oI0joYpsRanl9guDubaW+1NbcpK0vJ3F/6Wpcanzcnqq+oaW9O5E98liwkEDPcb16BUTLIJ+ZF8GPIHYxJ/5Pw==", - "requires": { - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/logger": "^5.3.0" - } - }, - "@ethersproject/signing-key": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.3.0.tgz", - "integrity": "sha512-+DX/GwHAd0ok1bgedV1cKO0zfK7P/9aEyNoaYiRsGHpCecN7mhLqcdoUiUzE7Uz86LBsxm5ssK0qA1kBB47fbQ==", - "requires": { - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/properties": "^5.3.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "@ethersproject/strings": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.3.0.tgz", - "integrity": "sha512-j/AzIGZ503cvhuF2ldRSjB0BrKzpsBMtCieDtn4TYMMZMQ9zScJn9wLzTQl/bRNvJbBE6TOspK0r8/Ngae/f2Q==", - "requires": { - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/constants": "^5.3.0", - "@ethersproject/logger": "^5.3.0" - } - }, - "@ethersproject/transactions": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.3.0.tgz", - "integrity": "sha512-cdfK8VVyW2oEBCXhURG0WQ6AICL/r6Gmjh0e4Bvbv6MCn/GBd8FeBH3rtl7ho+AW50csMKeGv3m3K1HSHB2jMQ==", - "requires": { - "@ethersproject/address": "^5.3.0", - "@ethersproject/bignumber": "^5.3.0", - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/constants": "^5.3.0", - "@ethersproject/keccak256": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/properties": "^5.3.0", - "@ethersproject/rlp": "^5.3.0", - "@ethersproject/signing-key": "^5.3.0" - } - }, - "@ethersproject/web": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.3.0.tgz", - "integrity": "sha512-Ni6/DHnY6k/TD41LEkv0RQDx4jqWz5e/RZvrSecsxGYycF+MFy2z++T/yGc2peRunLOTIFwEksgEGGlbwfYmhQ==", - "requires": { - "@ethersproject/base64": "^5.3.0", - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/properties": "^5.3.0", - "@ethersproject/strings": "^5.3.0" - } - }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "requires": { - "@types/node": "*" - } - }, - "@types/bson": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz", - "integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==", - "requires": { - "@types/node": "*" - } - }, - "@types/mongodb": { - "version": "3.6.18", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.18.tgz", - "integrity": "sha512-JSVFt9p0rTfZ4EgzXmVHUB3ue00xe3CRbQho8nXfImzEDDM4O7I3po1bwbWl/EIbLENxUreZxqLOc8lvcnLVPA==", - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "15.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", - "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==" - }, - "@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==", - "requires": { - "@types/node": "*" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, - "requires": { - "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "available-typed-arrays": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", - "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", - "requires": { - "follow-redirects": "^1.10.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base-x": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", - "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" - }, - "bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - } - } - }, - "blakejs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.1.tgz", - "integrity": "sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg==" - }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "dev": true, - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" - } - } - }, - "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "requires": { - "base-x": "^3.0.2" - } - }, - "bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "requires": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "bson": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", - "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "bufferutil": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", - "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", - "requires": { - "node-gyp-build": "^4.2.0" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - } - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "cids": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", - "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "requires": { - "buffer": "^5.5.0", - "class-is": "^1.1.0", - "multibase": "~0.6.0", - "multicodec": "^1.0.0", - "multihashes": "~0.4.15" - }, - "dependencies": { - "multicodec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", - "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "requires": { - "buffer": "^5.6.0", - "varint": "^5.0.0" - } - } - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-is": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" - }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "color-string": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", - "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", - "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "commander": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "config": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/config/-/config-3.3.6.tgz", - "integrity": "sha512-Hj5916C5HFawjYJat1epbyY2PlAgLpBtDUlr0MxGLgo3p5+7kylyvnRY18PqJHgnNWXcdd0eWDemT7eYWuFgwg==", - "requires": { - "json5": "^2.1.1" - } - }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "content-hash": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", - "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "requires": { - "cids": "^0.7.1", - "multicodec": "^0.5.5", - "multihashes": "^0.4.15" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true - }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "denque": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", - "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", - "object-inspect": "^1.10.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "eth-ens-namehash": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", - "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", - "requires": { - "idna-uts46-hx": "^2.3.1", - "js-sha3": "^0.5.7" - }, - "dependencies": { - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" - } - } - }, - "eth-lib": { - "version": "0.1.29", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", - "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "nano-json-stream-parser": "^0.1.2", - "servify": "^0.1.12", - "ws": "^3.0.0", - "xhr-request-promise": "^0.1.2" - } - }, - "ethereum-bloom-filters": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", - "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", - "requires": { - "js-sha3": "^0.8.0" - } - }, - "ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "requires": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - }, - "dependencies": { - "keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - } - } - }, - "ethereumjs-common": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", - "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==" - }, - "ethereumjs-tx": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", - "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "requires": { - "ethereumjs-common": "^1.5.0", - "ethereumjs-util": "^6.0.0" - } - }, - "ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "requires": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, - "ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "requires": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" - } - } - }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } - }, - "eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "express-promise-router": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/express-promise-router/-/express-promise-router-3.0.3.tgz", - "integrity": "sha1-Xm0ipaPwE9cYMxcv6NereAw/a3A=", - "requires": { - "is-promise": "^2.1.0", - "lodash.flattendeep": "^4.0.0", - "methods": "^1.0.0" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", - "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" - }, - "fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" - }, - "file-stream-rotator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.4.1.tgz", - "integrity": "sha512-W3aa3QJEc8BS2MmdVpQiYLKHj3ijpto1gMDlsgCRSKfIUe6MwkcpODGPQ3vZfb0XvCeCqlu9CBQTN7oQri2TZQ==", - "requires": { - "moment": "^2.11.2" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } - }, - "fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" - }, - "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "dependencies": { - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - } - } - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "general-number": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/general-number/-/general-number-1.0.1.tgz", - "integrity": "sha512-yyOHIFhkOQXSwV3eCvimN0sXUj/qc1dQjd5p0mqfk2S1ZJn5il2R+OaPQLk/WH4lHwKZ/GvreJtoSs9+jIUX7Q==", - "requires": { - "winston": "^3.3.3", - "zkp-utils": "^1.0.7" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "requires": { - "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-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "requires": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", - "dev": true, - "requires": { - "ini": "1.3.7" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbol-support-x": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", - "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "has-to-string-tag-x": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", - "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", - "requires": { - "has-symbol-support-x": "^1.4.1" - } - }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hex-to-binary": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hex-to-binary/-/hex-to-binary-1.0.1.tgz", - "integrity": "sha1-YcevAW/CK86pcE2fLpo46MfbuFQ=" - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "http-https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", - "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "idna-uts46-hx": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", - "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", - "requires": { - "punycode": "2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" - } - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", - "dev": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" - }, - "is-generator-function": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", - "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" - }, - "is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", - "dev": true, - "requires": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - } - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" - }, - "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==" - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==" - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - } - }, - "is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" - }, - "is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==" - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", - "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", - "requires": { - "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.0-next.2", - "foreach": "^2.0.5", - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "isurl": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", - "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", - "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" - } - }, - "js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "requires": { - "minimist": "^1.2.5" - } - }, - "jsonfile": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", - "integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^0.1.2" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "kareem": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", - "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" - }, - "keccak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", - "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", - "requires": { - "bindings": "^1.5.0", - "inherits": "^2.0.4", - "nan": "^2.14.0", - "safe-buffer": "^5.2.0" - } - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "requires": { - "json-buffer": "3.0.0" - } - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" - }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "requires": { - "package-json": "^6.3.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "logform": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", - "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", - "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "triple-beam": "^1.3.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", - "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" - }, - "mime-types": { - "version": "2.1.31", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", - "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", - "requires": { - "mime-db": "1.48.0" - } - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "requires": { - "dom-walk": "^0.1.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mkdirp-promise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", - "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", - "requires": { - "mkdirp": "*" - } - }, - "mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "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.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "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.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "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" - } - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - } - } - }, - "mock-fs": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz", - "integrity": "sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==" - }, - "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" - }, - "mongodb": { - "version": "3.6.8", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.8.tgz", - "integrity": "sha512-sDjJvI73WjON1vapcbyBD3Ao9/VN3TKYY8/QX9EPbs22KaCSrQ5rXo5ZZd44tWJ3wl3FlnrFZ+KyUtNH6+1ZPQ==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, - "mongoose": { - "version": "5.12.14", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.12.14.tgz", - "integrity": "sha512-1lMRY8cfGYFWHqe5DLnVgNQDyD0fEbSoWIQe9Mllt/ZtayZ5XUFQt+o5VKrB44vsT5cLNzgwEFO0NvwTwqLluQ==", - "requires": { - "@types/mongodb": "^3.5.27", - "bson": "^1.1.4", - "kareem": "2.3.2", - "mongodb": "3.6.8", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.8.3", - "mquery": "3.2.5", - "ms": "2.1.2", - "regexp-clone": "1.0.0", - "safe-buffer": "5.2.1", - "sift": "13.5.2", - "sliced": "1.0.1" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" - }, - "mpath": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz", - "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==" - }, - "mquery": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", - "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", - "requires": { - "bluebird": "3.5.1", - "debug": "3.1.0", - "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", - "sliced": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "multibase": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", - "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", - "requires": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - }, - "multicodec": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", - "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "requires": { - "varint": "^5.0.0" - } - }, - "multihashes": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", - "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "requires": { - "buffer": "^5.5.0", - "multibase": "^0.7.0", - "varint": "^5.0.0" - }, - "dependencies": { - "multibase": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", - "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", - "requires": { - "base-x": "^3.0.8", - "buffer": "^5.5.0" - } - } - } - }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" - }, - "nano-json-stream-parser": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", - "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" - }, - "nodemon": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz", - "integrity": "sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA==", - "dev": true, - "requires": { - "chokidar": "^3.2.2", - "debug": "^3.2.6", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.7", - "semver": "^5.7.1", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.3", - "update-notifier": "^4.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - }, - "number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA=", - "requires": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" - } - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-hash": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", - "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==" - }, - "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", - "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" - } - }, - "oboe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz", - "integrity": "sha1-VVQoTFQ6ImbXo48X4HOCH73jk80=", - "requires": { - "http-https": "^1.0.0" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "requires": { - "fn.name": "1.x.x" - } - }, - "optional-require": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", - "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-headers": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", - "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "requires": { - "escape-goat": "^2.0.0" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "query-string": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", - "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", - "requires": { - "decode-uri-component": "^0.2.0", - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "requires": { - "inherits": "~2.0.3" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "regexp-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", - "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" - }, - "registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "requires": { - "rc": "^1.2.8" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "rlp": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", - "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", - "requires": { - "bn.js": "^4.11.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" - }, - "secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "requires": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "servify": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", - "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", - "requires": { - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "request": "^2.79.0", - "xhr": "^2.3.3" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "sift": { - "version": "13.5.2", - "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", - "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" - }, - "simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", - "requires": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "requires": { - "is-arrayish": "^0.3.1" - } - }, - "sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" - }, - "solc": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.4.tgz", - "integrity": "sha512-krEdbucX9yY362l79gXTK2UHhsZ02aQjQOYTzcgTd/waApueo3yWGzjX0CDJ1ByOuW46WuKAyzfbRWdFNr6OYQ==", - "requires": { - "command-exists": "^1.2.8", - "commander": "3.0.2", - "follow-redirects": "^1.12.1", - "fs-extra": "^0.30.0", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "require-from-string": "^2.0.0", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "dependencies": { - "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "requires": { - "graceful-fs": "^4.1.6" - } - } - } - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "requires": { - "is-hex-prefixed": "1.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "swarm-js": { - "version": "0.1.40", - "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", - "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", - "requires": { - "bluebird": "^3.5.0", - "buffer": "^5.0.5", - "eth-lib": "^0.1.26", - "fs-extra": "^4.0.2", - "got": "^7.1.0", - "mime-types": "^2.1.16", - "mkdirp-promise": "^5.0.1", - "mock-fs": "^4.1.0", - "setimmediate": "^1.0.5", - "tar": "^4.0.2", - "xhr-request": "^1.0.1" - }, - "dependencies": { - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "requires": { - "decompress-response": "^3.2.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-plain-obj": "^1.1.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "isurl": "^1.0.0-alpha5", - "lowercase-keys": "^1.0.0", - "p-cancelable": "^0.3.0", - "p-timeout": "^1.1.1", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "url-parse-lax": "^1.0.0", - "url-to-options": "^1.0.1" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "p-cancelable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "requires": { - "prepend-http": "^1.0.1" - } - } - } - }, - "tar": { - "version": "4.4.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.15.tgz", - "integrity": "sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - } - } - }, - "term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true - }, - "text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "undefsafe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", - "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", - "dev": true, - "requires": { - "debug": "^2.2.0" - } - }, - "underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", - "dev": true, - "requires": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "requires": { - "prepend-http": "^2.0.0" - } - }, - "url-set-query": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", - "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" - }, - "url-to-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", - "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" - }, - "utf-8-validate": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz", - "integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==", - "requires": { - "node-gyp-build": "^4.2.0" - } - }, - "utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==" - }, - "util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - }, - "varint": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "web3": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.3.6.tgz", - "integrity": "sha512-jEpPhnL6GDteifdVh7ulzlPrtVQeA30V9vnki9liYlUvLV82ZM7BNOQJiuzlDePuE+jZETZSP/0G/JlUVt6pOA==", - "requires": { - "web3-bzz": "1.3.6", - "web3-core": "1.3.6", - "web3-eth": "1.3.6", - "web3-eth-personal": "1.3.6", - "web3-net": "1.3.6", - "web3-shh": "1.3.6", - "web3-utils": "1.3.6" - } - }, - "web3-bzz": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.3.6.tgz", - "integrity": "sha512-ibHdx1wkseujFejrtY7ZyC0QxQ4ATXjzcNUpaLrvM6AEae8prUiyT/OloG9FWDgFD2CPLwzKwfSQezYQlANNlw==", - "requires": { - "@types/node": "^12.12.6", - "got": "9.6.0", - "swarm-js": "^0.1.40", - "underscore": "1.12.1" - }, - "dependencies": { - "@types/node": { - "version": "12.20.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.15.tgz", - "integrity": "sha512-F6S4Chv4JicJmyrwlDkxUdGNSplsQdGwp1A0AJloEVDirWdZOAiRHhovDlsFkKUrquUXhz1imJhXHsf59auyAg==" - } - } - }, - "web3-core": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.3.6.tgz", - "integrity": "sha512-gkLDM4T1Sc0T+HZIwxrNrwPg0IfWI0oABSglP2X5ZbBAYVUeEATA0o92LWV8BeF+okvKXLK1Fek/p6axwM/h3Q==", - "requires": { - "@types/bn.js": "^4.11.5", - "@types/node": "^12.12.6", - "bignumber.js": "^9.0.0", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-requestmanager": "1.3.6", - "web3-utils": "1.3.6" - }, - "dependencies": { - "@types/node": { - "version": "12.20.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.15.tgz", - "integrity": "sha512-F6S4Chv4JicJmyrwlDkxUdGNSplsQdGwp1A0AJloEVDirWdZOAiRHhovDlsFkKUrquUXhz1imJhXHsf59auyAg==" - } - } - }, - "web3-core-helpers": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.3.6.tgz", - "integrity": "sha512-nhtjA2ZbkppjlxTSwG0Ttu6FcPkVu1rCN5IFAOVpF/L0SEt+jy+O5l90+cjDq0jAYvlBwUwnbh2mR9hwDEJCNA==", - "requires": { - "underscore": "1.12.1", - "web3-eth-iban": "1.3.6", - "web3-utils": "1.3.6" - } - }, - "web3-core-method": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.3.6.tgz", - "integrity": "sha512-RyegqVGxn0cyYW5yzAwkPlsSEynkdPiegd7RxgB4ak1eKk2Cv1q2x4C7D2sZjeeCEF+q6fOkVmo2OZNqS2iQxg==", - "requires": { - "@ethersproject/transactions": "^5.0.0-beta.135", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6", - "web3-core-promievent": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-utils": "1.3.6" - } - }, - "web3-core-promievent": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.3.6.tgz", - "integrity": "sha512-Z+QzfyYDTXD5wJmZO5wwnRO8bAAHEItT1XNSPVb4J1CToV/I/SbF7CuF8Uzh2jns0Cm1109o666H7StFFvzVKw==", - "requires": { - "eventemitter3": "4.0.4" - } - }, - "web3-core-requestmanager": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.3.6.tgz", - "integrity": "sha512-2rIaeuqeo7QN1Eex7aXP0ZqeteJEPWXYFS/M3r3LXMiV8R4STQBKE+//dnHJXoo2ctzEB5cgd+7NaJM8S3gPyA==", - "requires": { - "underscore": "1.12.1", - "util": "^0.12.0", - "web3-core-helpers": "1.3.6", - "web3-providers-http": "1.3.6", - "web3-providers-ipc": "1.3.6", - "web3-providers-ws": "1.3.6" - } - }, - "web3-core-subscriptions": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.3.6.tgz", - "integrity": "sha512-wi9Z9X5X75OKvxAg42GGIf81ttbNR2TxzkAsp1g+nnp5K8mBwgZvXrIsDuj7Z7gx72Y45mWJADCWjk/2vqNu8g==", - "requires": { - "eventemitter3": "4.0.4", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6" - } - }, - "web3-eth": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.3.6.tgz", - "integrity": "sha512-9+rnywRRpyX3C4hfsAQXPQh6vHh9XzQkgLxo3gyeXfbhbShUoq2gFVuy42vsRs//6JlsKdyZS7Z3hHPHz2wreA==", - "requires": { - "underscore": "1.12.1", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-eth-abi": "1.3.6", - "web3-eth-accounts": "1.3.6", - "web3-eth-contract": "1.3.6", - "web3-eth-ens": "1.3.6", - "web3-eth-iban": "1.3.6", - "web3-eth-personal": "1.3.6", - "web3-net": "1.3.6", - "web3-utils": "1.3.6" - } - }, - "web3-eth-abi": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.3.6.tgz", - "integrity": "sha512-Or5cRnZu6WzgScpmbkvC6bfNxR26hqiKK4i8sMPFeTUABQcb/FU3pBj7huBLYbp9dH+P5W79D2MqwbWwjj9DoQ==", - "requires": { - "@ethersproject/abi": "5.0.7", - "underscore": "1.12.1", - "web3-utils": "1.3.6" - } - }, - "web3-eth-accounts": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.3.6.tgz", - "integrity": "sha512-Ilr0hG6ONbCdSlVKffasCmNwftD5HsNpwyQASevocIQwHdTlvlwO0tb3oGYuajbKOaDzNTwXfz25bttAEoFCGA==", - "requires": { - "crypto-browserify": "3.12.0", - "eth-lib": "0.2.8", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "scrypt-js": "^3.0.1", - "underscore": "1.12.1", - "uuid": "3.3.2", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-utils": "1.3.6" - }, - "dependencies": { - "eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - } - } - }, - "web3-eth-contract": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.3.6.tgz", - "integrity": "sha512-8gDaRrLF2HCg+YEZN1ov0zN35vmtPnGf3h1DxmJQK5Wm2lRMLomz9rsWsuvig3UJMHqZAQKD7tOl3ocJocQsmA==", - "requires": { - "@types/bn.js": "^4.11.5", - "underscore": "1.12.1", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-promievent": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-eth-abi": "1.3.6", - "web3-utils": "1.3.6" - } - }, - "web3-eth-ens": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.3.6.tgz", - "integrity": "sha512-n27HNj7lpSkRxTgSx+Zo7cmKAgyg2ElFilaFlUu/X2CNH23lXfcPm2bWssivH9z0ndhg0OyR4AYFZqPaqDHkJA==", - "requires": { - "content-hash": "^2.5.2", - "eth-ens-namehash": "2.0.8", - "underscore": "1.12.1", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-promievent": "1.3.6", - "web3-eth-abi": "1.3.6", - "web3-eth-contract": "1.3.6", - "web3-utils": "1.3.6" - } - }, - "web3-eth-iban": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.3.6.tgz", - "integrity": "sha512-nfMQaaLA/zsg5W4Oy/EJQbs8rSs1vBAX6b/35xzjYoutXlpHMQadujDx2RerTKhSHqFXSJeQAfE+2f6mdhYkRQ==", - "requires": { - "bn.js": "^4.11.9", - "web3-utils": "1.3.6" - } - }, - "web3-eth-personal": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.3.6.tgz", - "integrity": "sha512-pOHU0+/h1RFRYoh1ehYBehRbcKWP4OSzd4F7mDljhHngv6W8ewMHrAN8O1ol9uysN2MuCdRE19qkRg5eNgvzFQ==", - "requires": { - "@types/node": "^12.12.6", - "web3-core": "1.3.6", - "web3-core-helpers": "1.3.6", - "web3-core-method": "1.3.6", - "web3-net": "1.3.6", - "web3-utils": "1.3.6" - }, - "dependencies": { - "@types/node": { - "version": "12.20.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.15.tgz", - "integrity": "sha512-F6S4Chv4JicJmyrwlDkxUdGNSplsQdGwp1A0AJloEVDirWdZOAiRHhovDlsFkKUrquUXhz1imJhXHsf59auyAg==" - } - } - }, - "web3-net": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.3.6.tgz", - "integrity": "sha512-KhzU3wMQY/YYjyMiQzbaLPt2kut88Ncx2iqjy3nw28vRux3gVX0WOCk9EL/KVJBiAA/fK7VklTXvgy9dZnnipw==", - "requires": { - "web3-core": "1.3.6", - "web3-core-method": "1.3.6", - "web3-utils": "1.3.6" - } - }, - "web3-providers-http": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.3.6.tgz", - "integrity": "sha512-OQkT32O1A06dISIdazpGLveZcOXhEo5cEX6QyiSQkiPk/cjzDrXMw4SKZOGQbbS1+0Vjizm1Hrp7O8Vp2D1M5Q==", - "requires": { - "web3-core-helpers": "1.3.6", - "xhr2-cookies": "1.1.0" - } - }, - "web3-providers-ipc": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.3.6.tgz", - "integrity": "sha512-+TVsSd2sSVvVgHG4s6FXwwYPPT91boKKcRuEFXqEfAbUC5t52XOgmyc2LNiD9LzPhed65FbV4LqICpeYGUvSwA==", - "requires": { - "oboe": "2.1.5", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6" - } - }, - "web3-providers-ws": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.3.6.tgz", - "integrity": "sha512-bk7MnJf5or0Re2zKyhR3L3CjGululLCHXx4vlbc/drnaTARUVvi559OI5uLytc/1k5HKUUyENAxLvetz2G1dnQ==", - "requires": { - "eventemitter3": "4.0.4", - "underscore": "1.12.1", - "web3-core-helpers": "1.3.6", - "websocket": "^1.0.32" - } - }, - "web3-shh": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.3.6.tgz", - "integrity": "sha512-9zRo415O0iBslxBnmu9OzYjNErzLnzOsy+IOvSpIreLYbbAw0XkDWxv3SfcpKnTIWIACBR4AYMIxmmyi5iB3jw==", - "requires": { - "web3-core": "1.3.6", - "web3-core-method": "1.3.6", - "web3-core-subscriptions": "1.3.6", - "web3-net": "1.3.6" - } - }, - "web3-utils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.6.tgz", - "integrity": "sha512-hHatFaQpkQgjGVER17gNx8u1qMyaXFZtM0y0XLGH1bzsjMPlkMPLRcYOrZ00rOPfTEuYFOdrpGOqZXVmGrMZRg==", - "requires": { - "bn.js": "^4.11.9", - "eth-lib": "0.2.8", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.12.1", - "utf8": "3.0.0" - }, - "dependencies": { - "eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - } - } - }, - "websocket": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", - "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", - "requires": { - "bufferutil": "^4.0.1", - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "typedarray-to-buffer": "^3.1.5", - "utf-8-validate": "^5.0.2", - "yaeti": "^0.0.6" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "which-typed-array": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", - "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", - "requires": { - "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.0", - "es-abstract": "^1.18.0-next.1", - "foreach": "^2.0.5", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.1", - "is-typed-array": "^1.1.3" - } - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "winston": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", - "requires": { - "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", - "is-stream": "^2.0.0", - "logform": "^2.2.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - } - }, - "winston-compat": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/winston-compat/-/winston-compat-0.1.5.tgz", - "integrity": "sha512-EPvPcHT604AV3Ji6d3+vX8ENKIml9VSxMRnPQ+cuK/FX6f3hvPP2hxyoeeCOCFvDrJEujalfcKWlWPvAnFyS9g==", - "requires": { - "cycle": "~1.0.3", - "logform": "^1.6.0", - "triple-beam": "^1.2.0" - }, - "dependencies": { - "fecha": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", - "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" - }, - "logform": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", - "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", - "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", - "ms": "^2.1.1", - "triple-beam": "^1.2.0" - } - } - } - }, - "winston-daily-rotate-file": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-3.10.0.tgz", - "integrity": "sha512-KO8CfbI2CvdR3PaFApEH02GPXiwJ+vbkF1mCkTlvRIoXFI8EFlf1ACcuaahXTEiDEKCii6cNe95gsL4ZkbnphA==", - "requires": { - "file-stream-rotator": "^0.4.1", - "object-hash": "^1.3.0", - "semver": "^6.2.0", - "triple-beam": "^1.3.0", - "winston-compat": "^0.1.4", - "winston-transport": "^4.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "winston-transport": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", - "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", - "requires": { - "readable-stream": "^2.3.7", - "triple-beam": "^1.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, - "xhr": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", - "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", - "requires": { - "global": "~4.4.0", - "is-function": "^1.0.1", - "parse-headers": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "xhr-request": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", - "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", - "requires": { - "buffer-to-arraybuffer": "^0.0.5", - "object-assign": "^4.1.1", - "query-string": "^5.0.1", - "simple-get": "^2.7.0", - "timed-out": "^4.0.1", - "url-set-query": "^1.0.0", - "xhr": "^2.0.4" - } - }, - "xhr-request-promise": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", - "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", - "requires": { - "xhr-request": "^1.1.0" - } - }, - "xhr2-cookies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz", - "integrity": "sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg=", - "requires": { - "cookiejar": "^2.1.1" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "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.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - } - }, - "zkp-utils": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/zkp-utils/-/zkp-utils-1.0.8.tgz", - "integrity": "sha512-F4PM4bfg8AHs4zZ4RGWjSo7De0Ek85H2XOMRsCbXrCbbkxiKeTJ8Er8ykiIEjvWii92S523wfCf+kjD7aMqJ1g==", - "requires": { - "big-integer": "^1.6.48", - "keccak": "^3.0.1", - "winston": "^3.3.3" - }, - "dependencies": { - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" - }, - "keccak": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", - "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - }, - "winston": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", - "requires": { - "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", - "is-stream": "^2.0.0", - "logform": "^2.2.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" - } - } - } - } - } -} diff --git a/timber/package.json b/timber/package.json deleted file mode 100644 index 0ff7a5fcf..000000000 --- a/timber/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "timber", - "version": "1.0.0", - "description": "construct and store a merkle tree from its leaves", - "main": "index.js", - "scripts": { - "start": "node ./src/index.mjs", - "dev": "nodemon --ignore /app/build/ --exec babel-node ./src/index.js", - "test": "truffle test" - }, - "author": "iAmMichaelConnor", - "license": "CC0-1.0", - "contributors": [ - "Michael Connor " - ], - "dependencies": { - "general-number": "^1.0.1", - "axios": "^0.21.1", - "big-integer": "^1.6.48", - "body-parser": "^1.19.0", - "config": "^3.2.2", - "cors": "^2.8.5", - "express": "^4.16.4", - "express-promise-router": "^3.0.3", - "fs-extra": "^8.1.0", - "hex-to-binary": "^1.0.1", - "jsonfile": "^5.0.0", - "keccak": "^2.1.0", - "mongoose": "^5.7.5", - "queue": "^6.0.2", - "request": "^2.88.0", - "safe-buffer": "^5.1.2", - "solc": "0.8.4", - "web3": "^1.3.0", - "winston": "^3.1.0", - "winston-daily-rotate-file": "^3.4.1" - }, - "devDependencies": { - "mocha": "^6.2.2", - "nodemon": "^2.0.12" - } -} diff --git a/timber/src/auto-start.mjs b/timber/src/auto-start.mjs deleted file mode 100644 index b77c4ab21..000000000 --- a/timber/src/auto-start.mjs +++ /dev/null @@ -1,52 +0,0 @@ -import axios from 'axios'; -import config from 'config'; -import logger from './logger.mjs'; -import uw from './utils-web3.mjs'; -/** -function to automatically start the Timber instance. This is useful if you are -starting it up in an already-established blockchain environment. -Currently it only supports a single shield contract. -*/ -const autoStart = async () => { - const contractNames = Object.keys(config.contracts); - for (const contractName of contractNames) { - const data = { - contractName, - contractAddress: config.contracts[contractName].address, - treeId: config.contracts[contractName].treeId, - }; - // if we haven't been given a contractAddress, it's best to make sure that - // Timber has the ability to infer one. Otherwise Timber will fall over. If - // the build artefacts don't exist yet then we need to wait. - // Stop eslint complaining because we DO want delays in this loop - let retries = Number(process.env.AUTOSTART_RETRIES) || 50; - while (!data.contractAddress) { - try { - // eslint-disable-next-line no-await-in-loop - data.contractAddress = await uw.getContractAddress(contractName); - // we want to catch if the above function throws OR returns undefined - if (data.contractAddress === undefined) throw new Error('undefined contract address'); - logger.info(`Contract address for contract ${contractName} is ${data.contractAddress}`); - } catch (err) { - if (retries === 0) throw new Error(err); - retries--; - logger.warn('Unable to find a contract address. Retrying in 3 seconds.'); - // eslint-disable-next-line no-await-in-loop - await new Promise(resolve => setTimeout(resolve, 3000)); - } - } - // Now that we are fairly sure calling start will work, we can go ahead. - try { - logger.debug( - `Calling /start for Timber, with contractName '${contractName}' and url localhost`, - ); - axios.post('http://localhost/start', data, { - timeout: 3600000, - }); - } catch (error) { - throw new Error(error); - } - } -}; - -export default autoStart; diff --git a/timber/src/compile.mjs b/timber/src/compile.mjs deleted file mode 100644 index 5ea5dec0a..000000000 --- a/timber/src/compile.mjs +++ /dev/null @@ -1,117 +0,0 @@ -/** -If CONTRACT_ORIGIN = 'compile', we need to compile the contracts from source, in order to obtain a contract interface json. -*/ -import path from 'path'; -import fs from 'fs-extra'; -import solc from 'solc'; -import config from 'config'; -import versionList from './solc-versions-list.mjs'; -import logger from './logger.mjs'; - -const { contractsPath } = config; -const { buildPath } = config; - -const getSolcVersion = contractName => { - logger.debug('getSolcVersion...'); - const contractsFiles = fs.readdirSync(contractsPath); - const source = {}; - logger.debug(`CONTRACTSFILES: ${JSON.stringify(contractsFiles)}`); - - contractsFiles.forEach(fileName => { - if (contractName === path.basename(fileName, '.sol')) { - // filename without '.sol' - const contractFullPath = path.resolve(contractsPath, fileName); - source[fileName] = { - content: fs.readFileSync(contractFullPath, 'utf8'), - }; - } - }); - - if (Object.keys(source).length === 0 && source.constructor === Object) - throw new Error(`Contract ${contractName} not found in ${contractsPath}.`); - - const sourceCodeString = JSON.stringify(source); - const regex = new RegExp(/(?<=pragma solidity .)(0).*?(?=;)/g); - const solcVersion = sourceCodeString.match(regex); - logger.info(`solcVersion for ${contractName} is ${solcVersion}`); - return solcVersion; -}; - -const buildSources = () => { - logger.info('buildSources...'); - const sources = {}; - const contractsFiles = fs.readdirSync(contractsPath); - - logger.info(`CONTRACTSFILES: ${JSON.stringify(contractsFiles)}`); - - contractsFiles.forEach(file => { - if (path.extname(file) === '.sol') { - const contractFullPath = path.resolve(contractsPath, file); - sources[file] = { - content: fs.readFileSync(contractFullPath, 'utf8'), - }; - } - }); - - return sources; -}; - -const createSolcInput = sources => { - const input = { - language: 'Solidity', - sources, - settings: { - outputSelection: { - '*': { - '*': ['abi', 'evm.bytecode'], - }, - }, - }, - }; - return input; -}; - -const compile = (solcInstance, input) => { - const compiledOutput = solcInstance.compile(JSON.stringify(input)); - logger.info(`COMPILED OUTPUT: ${JSON.parse(compiledOutput).errors || 'no errors'}`); - - const compiledContracts = JSON.parse(compiledOutput).contracts; - - logger.info(`COMPILED CONTRACTS: ${JSON.stringify(compiledContracts)}`); - // eslint-disable-next-line no-restricted-syntax - for (const contract of Object.keys(compiledContracts)) { - // eslint-disable-next-line no-restricted-syntax - for (const contractName of Object.keys(compiledContracts[contract])) { - fs.outputJsonSync( - path.resolve(buildPath, `${contractName}.json`), - compiledContracts[contract][contractName], - { spaces: 2 }, - ); - } - } -}; - -const loadRemoteVersionAsync = async solcVersionRelease => { - return new Promise((resolve, reject) => { - solc.loadRemoteVersion(solcVersionRelease, (err, solcInstance) => { - if (err) { - reject(err); - } else resolve(solcInstance); - }); - }); -}; - -export default async contractName => { - try { - const solcVersion = getSolcVersion(contractName); - const sources = buildSources(); - const input = createSolcInput(sources); - - const solcInstance = await loadRemoteVersionAsync( - versionList.releases[solcVersion].slice(8, -3), - ); - compile(solcInstance, input); - } catch (err) { - throw new Error(err); - } -}; diff --git a/timber/src/console-testing.mjs b/timber/src/console-testing.mjs deleted file mode 100644 index b7ec2e1aa..000000000 --- a/timber/src/console-testing.mjs +++ /dev/null @@ -1,24 +0,0 @@ -/** -This is just a scrapbook for quick debugging of utility functions -*/ - -/* -Execute this from the command line: -cd path/to/src -npx babel-node console-testing -*/ - -import utilsMT from './utils-merkle-tree'; -import logger from './logger'; - -// logger.debug(utilsMT.rightChildBinaryIndex(0b11).toString(2)); - -// logger.debug(utilsMT.getSiblingPathIndices('50')); - -// logger.debug(utilsMT.testMerkleRecursion(0)); - -async function main() { - logger.debug(utilsMT.numberOfHashes(2 ** 31, 5, 32)); -} - -main(); diff --git a/timber/src/contract-controller.mjs b/timber/src/contract-controller.mjs deleted file mode 100644 index d07f1df8e..000000000 --- a/timber/src/contract-controller.mjs +++ /dev/null @@ -1,184 +0,0 @@ -/** -@module contract-controller.js -@desc -@author iAmMichaelConnor -*/ - -import config from 'config'; - -import { MetadataService } from './db/service/index.mjs'; -import deployerRest from './rest/deployer.mjs'; -import compileContract from './compile.mjs'; -import utilsWeb3 from './utils-web3.mjs'; -import utilsPoll from './utils-poll.mjs'; -import Web3 from './web3.mjs'; -import logger from './logger.mjs'; - -const web3 = Web3.connect(); - -/** -Gets a web3 instance of a contract from some external contract deployment microservice (a.k.a. 'deployer') and assembles a contract instance -@returns {false | object} Polling functions MUST return FALSE if the poll is unsuccessful. Otherwise we return the MerkleTree.sol contract instance. -*/ -const getContractInstancePollingFunction = async args => { - try { - const { contractName } = args; - const contractInstance = await deployerRest.getContractInstance(contractName); - return contractInstance; - } catch (err) { - logger.warn( - `Got a polling error "${err}", but that might be because the external server missed our call - we'll poll again...`, - ); - return false; - } -}; - -async function getContractInstanceFromRemote(db, contractName) { - const metadataService = new MetadataService(db); - - // retrieve the contract abi data necessary to generate a web3 instance of the contract, and create that contractInstance: - // we need to poll, in case the service isn't 'up' yet: - const contractInstance = await utilsPoll.poll( - getContractInstancePollingFunction, - config.POLLING_FREQUENCY, - { contractName }, - ); - - // retrieve the address of the contract we wish to filter events for: - let { contractAddress } = (await metadataService.getContractAddress()) || {}; - - if (contractAddress === undefined) { - // if no contractAddress in the mongodb, add it to the db: - contractAddress = contractInstance._address; // eslint-disable-line no-underscore-dangle - logger.info( - `contractAddress ${contractAddress} not yet added to the merkle-tree's metadata db. Adding it now...`, - ); - await metadataService.insertContractAddress({ contractAddress }); - } else if (contractAddress !== contractInstance._address) { - // eslint-disable-line no-underscore-dangle, prettier/prettier - // here, we've noticed that the stored mongodb contractAddress !== the address retrieved from the external microservice. - throw new Error( - `Unexpected mismatch between the stored mongodb contractAddress (${contractAddress}), and the address retrieved from the external microservice (${contractInstance._address}).`, // eslint-disable-line no-underscore-dangle, prettier/prettier - ); - } - - return contractInstance; -} - -/** -Gets a web3 contract instance a contract, and checks its consistency with the merkle tree's existing metadata db. -@param {object} db - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy). This contains permissions to access the merkle tree's databases. -*/ -async function getContractInstanceFromMongoDB(db, contractName) { - logger.debug( - `src/contract-controller getContractInstanceFromMongoDB(db, contractName=${contractName})`, - ); - - const metadataService = new MetadataService(db); - - // retrieve the address of the contract we wish to filter events for: - const { contractAddress } = (await metadataService.getContractAddress()) || {}; - - const { contractInterface } = (await metadataService.getContractInterface()) || {}; - - const contractInstance = await new web3.eth.Contract(contractInterface.abi, contractAddress); - - return contractInstance; -} - -async function getContractInstanceFromContractsFolder(db, contractName, contractAddress) { - logger.debug( - `src/contract-controller getContractInstanceFromContractsFolder(db, contractName=${contractName}, contractAddress=${contractAddress})`, - ); - - const metadataService = new MetadataService(db); - - // compile the contracts in /app/contracts, and save the compiled contract interface json's in /app/build. - await compileContract(contractName); - - // retrieve the contract from the 'build' folder: - const contractInstance = await utilsWeb3.getContractInstance(contractName, contractAddress); - - // Then add its address to the db: - logger.info(`Adding contractAddress ${contractAddress} to the merkle-tree's metadata db...`); - await metadataService.insertContractAddress({ contractAddress }); - - return contractInstance; -} - -async function getContractInstanceFromBuildFolder(db, contractName, contractAddress) { - logger.debug( - `\nsrc/contract-controller getContractInstanceFromBuildFolder(db, contractName=${contractName})`, - ); - - const metadataService = new MetadataService(db); - - // if no address specified in the API call, then let's try to get one from the contract's json interface in the build folder" - if (contractAddress === undefined) - contractAddress = await utilsWeb3.getContractAddress(contractName); // eslint-disable-line no-param-reassign - - if (contractAddress === undefined) - throw new Error( - `No deployed contract address found in the contract interface json for ${contractName}`, - ); - - // retrieve the contract from the 'build' folder, and create a web3 contract instance: - const contractInstance = await utilsWeb3.getContractInstance(contractName, contractAddress); - - // Then add its address to the db: - logger.info(`Adding contractAddress ${contractAddress} to the merkle-tree's metadata db...`); - await metadataService.insertContractAddress({ contractAddress }); - - return contractInstance; -} - -/** -Gets a web3 contract instance a contract, and checks its consistency with the merkle tree's existing metadata db. -@param {object} db - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy). This contains permissions to access the merkle tree's databases. -*/ -async function instantiateContract(db, contractName, contractAddress) { - logger.debug( - `src/contract-controller instantiateContract(db, contractName=${contractName}, contractAddress=${contractAddress})`, - ); - let contractInstance; - // different logic is needed depending on where the contract's interface json is stored: - switch (config.contractOrigin) { - case 'remote': - // 'remote' - get a (truffle-compiled) contract interface json, and the deployed contract address, from an external deployment microservice. A web3 contract instance is created from these components and assigned to contractInstance: - logger.info(`\nGetting contract from contractOrigin 'remote'...`); - contractInstance = await getContractInstanceFromRemote(db, contractName); - break; - - case 'mongodb': - // 'mongodb' - get a (truffle-comiled) contract interface json, and the deployed contract address, from mongodb (e.g. if the info had been POSTed there by some external microservice). A web3 contract instance is created from these components and assigned to contractInstance: - logger.info(`\nGetting contract from contractOrigin 'mongodb'...`); - contractInstance = await getContractInstanceFromMongoDB(db, contractName); - break; - - case 'compile': - // 'compile' - Useful if the application using Timber doesn't use truffle to generate contract interface json's. Get solidity contracts from the /app/contracts/ folder, and compile them (using truffle) at startup. A web3 contract instance is created from the compiled contract interface & deployed address and assigned to contractInstance: - logger.info( - `Compiling the contracts from '/app/contracts/' and then getting contract from contractOrigin '/app/build/'...`, - ); - contractInstance = await getContractInstanceFromContractsFolder( - db, - contractName, - contractAddress, - ); - break; - - default: - // 'default' - get the (truffle-compiled) contract interface json from the /app/build folder. Infer the contract's address from this json file. A web3 contract instance is created from these components and assigned to contractInstance: - logger.info(`Getting contract from contractOrigin '/app/build/'...`); - contractInstance = await getContractInstanceFromBuildFolder( - db, - contractName, - contractAddress, - ); - } - return contractInstance; -} - -export default { - instantiateContract, -}; diff --git a/timber/src/db/common/adminDbConnection.mjs b/timber/src/db/common/adminDbConnection.mjs deleted file mode 100644 index 9c56fb1e7..000000000 --- a/timber/src/db/common/adminDbConnection.mjs +++ /dev/null @@ -1,16 +0,0 @@ -import mongoose from 'mongoose'; -import config from 'config'; - -const { host, port, databaseName } = config.get('mongo'); -const dbConnections = {}; - -dbConnections.admin = mongoose.createConnection(`mongodb://${host}:${port}/${databaseName}`, { - useNewUrlParser: true, - useCreateIndex: true, - reconnectTries: 3, - connectTimeoutMS: 120000, -}); - -const adminDbConnection = dbConnections.admin; - -export default adminDbConnection; diff --git a/timber/src/db/common/constants.mjs b/timber/src/db/common/constants.mjs deleted file mode 100644 index 2e1feebea..000000000 --- a/timber/src/db/common/constants.mjs +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-disable import/prefer-default-export */ - -export const COLLECTIONS = { - NODE: 'node', - METADATA: 'metadata', - HISTORY: 'history', -}; diff --git a/timber/src/db/mappers/history.mjs b/timber/src/db/mappers/history.mjs deleted file mode 100644 index d20cc933d..000000000 --- a/timber/src/db/mappers/history.mjs +++ /dev/null @@ -1,18 +0,0 @@ -import config from 'config'; - -const { ZERO } = config; - -export default history => { - if (!history) return null; - const { root, oldRoot, frontier, leafIndex, currentLeafCount, blockNumber, transactionHash } = - history; - return { - root, - oldRoot: oldRoot || ZERO, - frontier: frontier.map(f => f || ZERO), - leafIndex, - currentLeafCount, - blockNumber, - transactionHash, - }; -}; diff --git a/timber/src/db/mappers/index.mjs b/timber/src/db/mappers/index.mjs deleted file mode 100644 index c5deced29..000000000 --- a/timber/src/db/mappers/index.mjs +++ /dev/null @@ -1,4 +0,0 @@ -export { default as leafMapper } from './leaf.mjs'; -export { default as nodeMapper } from './node.mjs'; -export { default as metadataMapper } from './metadata.mjs'; -export { default as historyMapper } from './history.mjs'; diff --git a/timber/src/db/mappers/leaf.mjs b/timber/src/db/mappers/leaf.mjs deleted file mode 100644 index fca154e1b..000000000 --- a/timber/src/db/mappers/leaf.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import utilsMT from '../../utils-merkle-tree.mjs'; -import logger from '../../logger.mjs'; - -// This 'leaf' mapper differs from the 'node' mapper. -export default (treeHeight, { value, nodeIndex, leafIndex, blockNumber, transactionHash }) => { - // to prevent incorrect leaf data from being stored, we ensure the nodeIndex is calculated correctly from the leafIndex: - const checkNodeIndex = utilsMT.leafIndexToNodeIndex(leafIndex, treeHeight); - if (!nodeIndex) { - nodeIndex = checkNodeIndex; // eslint-disable-line no-param-reassign - logger.debug(`Inserting a nodeIndex of ${nodeIndex} for leafIndex ${leafIndex}`); - } else if (nodeIndex !== checkNodeIndex) { - throw new Error( - `Intercepted an incorrect nodeIndex of ${nodeIndex} for leafIndex ${leafIndex}. The nodeIndex should have been ${checkNodeIndex}`, - ); - } - - return { - value, - nodeIndex, - leafIndex, - blockNumber, - transactionHash, - }; -}; diff --git a/timber/src/db/mappers/metadata.mjs b/timber/src/db/mappers/metadata.mjs deleted file mode 100644 index 51e873538..000000000 --- a/timber/src/db/mappers/metadata.mjs +++ /dev/null @@ -1,15 +0,0 @@ -export default ({ - contractAddress, - contractInterface, - treeHeight, - latestRecalculation, - latestLeaf, -}) => { - return { - ...(contractAddress && { contractAddress }), - ...(contractInterface && { contractInterface }), - ...(treeHeight && { treeHeight }), - ...(latestRecalculation && { latestRecalculation }), - ...(latestLeaf && { latestLeaf }), - }; -}; diff --git a/timber/src/db/mappers/node.mjs b/timber/src/db/mappers/node.mjs deleted file mode 100644 index f1a18c4e9..000000000 --- a/timber/src/db/mappers/node.mjs +++ /dev/null @@ -1,7 +0,0 @@ -// This 'node' mapper differs from the 'leaf' mapper. -export default ({ value, nodeIndex }) => { - return { - value, - nodeIndex, - }; -}; diff --git a/timber/src/db/models/history.model.mjs b/timber/src/db/models/history.model.mjs deleted file mode 100644 index 7b123ff30..000000000 --- a/timber/src/db/models/history.model.mjs +++ /dev/null @@ -1,30 +0,0 @@ -import mongoose from 'mongoose'; - -// This schema stores historic information relating to the whole tree. -// It's basically the latest recalculation that existed before the root -// was updated to 'root' - -export default new mongoose.Schema( - { - root: { - type: String, - required: true, - unique: true, - }, - oldRoot: { - type: String, - default: null, - unique: true, - }, - frontier: { - type: Array, - default: new Array(33), - }, - leafIndex: Number, - currentLeafCount: Number, - blockNumber: Number, - transactionHash: String, - }, - - { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } }, -); diff --git a/timber/src/db/models/index.mjs b/timber/src/db/models/index.mjs deleted file mode 100644 index ae012b7de..000000000 --- a/timber/src/db/models/index.mjs +++ /dev/null @@ -1,3 +0,0 @@ -export { default as nodeSchema } from './node.model.mjs'; -export { default as metadataSchema } from './metadata.model.mjs'; -export { default as historySchema } from './history.model.mjs'; diff --git a/timber/src/db/models/metadata.model.mjs b/timber/src/db/models/metadata.model.mjs deleted file mode 100644 index 2887b9e8b..000000000 --- a/timber/src/db/models/metadata.model.mjs +++ /dev/null @@ -1,53 +0,0 @@ -import mongoose from 'mongoose'; - -// This schema stores information relating to the whole tree. - -export default new mongoose.Schema( - { - _id: { - type: Number, - default: 1, - }, // force only one of these documents to ever exist, with _id = 1 - - treeHeight: { - type: Number, - default: 32, - }, - contractAddress: { - type: String, - default: '0', // '0' can be interpreted as 'no known contract' - }, - contractInterface: { - type: String, // a jsonified object - default: '0', // '0' can be interpreted as 'no known contract' - }, - - latestRecalculation: { - blockNumber: Number, - transactionHash: String, - leafIndex: Number, - root: String, - frontier: { - type: Array, - default: new Array(33), - }, - /* - The frontier contains one value from each level of the tree. - By 'level' (as opposed to 'row') we mean: the leaves are at level '0' and the root is at level 'H = config.TREE_HEIGHT'. - frontier: [ - leafValue, // level_0 corresponds to frontier[0] - level1NodeValue, // level_1 corresponds to frontier[1] - ... - rootValue, // level_H corresponds to frontier[H] - ] - */ - }, - - latestLeaf: { - blockNumber: Number, - transactionHash: String, - leafIndex: Number, - }, - }, - { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } }, -); diff --git a/timber/src/db/models/node.model.mjs b/timber/src/db/models/node.model.mjs deleted file mode 100644 index 345099f1f..000000000 --- a/timber/src/db/models/node.model.mjs +++ /dev/null @@ -1,40 +0,0 @@ -import mongoose from 'mongoose'; - -// This schema stores information relating to each node of the tree. Note that a leaf shares this same schema. - -export default new mongoose.Schema( - { - value: { - // The value at this node of the tree. - // For non-leaves, this will be the hash of its two children. - // For leaves this is some string of information. - type: String, - required: true, - unique: process.env.UNIQUE_LEAVES === 'true', // if the leaves are unique, then all nodes are unique, and so we can index node values for faster lookup. - }, - nodeIndex: { - type: Number, - required: true, - unique: true, - // index: true, // not sure if this is necessary, if we're using 'unique', because I think 'unique' gives us indexing. - }, - leafIndex: { - type: Number, - unique: true, // establish this as a unique index - sparse: true, // the index is 'sparse' (not all documents in the collection will have a leafIndex, so we can skip them) - }, - /** - TODO: make blockNumber 'required' if a leaf? - */ - blockNumber: { - // the blockNumber during which this leaf was emitted - type: Number, - }, - transactionHash: { - // the (layer 1) transactionHash for the transaction that created this leaf - type: String, - }, - }, - - // { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } }, -); diff --git a/timber/src/db/mongodb/db.mjs b/timber/src/db/mongodb/db.mjs deleted file mode 100644 index 27519655f..000000000 --- a/timber/src/db/mongodb/db.mjs +++ /dev/null @@ -1,259 +0,0 @@ -/** - * @module db.js - * @author iAmMichaelConnor - * @desc js wrappers for mongoose & mongodb functions - */ - -import { COLLECTIONS } from '../common/constants.mjs'; -import { nodeSchema, metadataSchema, historySchema } from '../models/index.mjs'; -import logger from '../../logger.mjs'; -/** -Class created from within src/middleware/assign-db-connection -@param {object} connection - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy) -@param {string} username - username -@param {string} contractName - contractName of the contract which relates to this db -*/ -export default class DB { - constructor(connection, username, contractName, treeId) { - this.connection = connection; - this.username = username; - if (!username) return; - this.createModelsForUser(contractName, treeId); - } - - /** - A model is a class with which we construct documents - */ - createModelsForUser(contractName, treeId) { - if (treeId === undefined || treeId === '') { - this.Models = { - node: this.connection.model( - `${this.username}_${contractName}_${COLLECTIONS.NODE}`, - nodeSchema, - ), - metadata: this.connection.model( - `${this.username}_${contractName}_${COLLECTIONS.METADATA}`, - metadataSchema, - ), - history: this.connection.model( - `${this.username}_${contractName}_${COLLECTIONS.HISTORY}`, - historySchema, - ), - }; - } else { - this.Models = { - node: this.connection.model( - `${this.username}_${contractName}_${treeId}_${COLLECTIONS.NODE}`, - nodeSchema, - ), - metadata: this.connection.model( - `${this.username}_${contractName}_${treeId}_${COLLECTIONS.METADATA}`, - metadataSchema, - ), - history: this.connection.model( - `${this.username}_${contractName}_${treeId}_${COLLECTIONS.HISTORY}`, - historySchema, - ), - }; - } - } - - /** - Save data as a document (an instance of a particular Model) in a collection. - @param {string} modelName - the name of the Model class. - @param {object} data - the data to be stored as a document (an instance of a Model) in the collection. - */ - async save(modelName, data) { - try { - // A Model is a class with which we construct documents: - const Model = this.Models[modelName]; - // Construct a document from the Model: - const doc = new Model(data); - // Save the document to the db: - const dbResponse = await doc.save(); - - logger.debug('src/db/mongodb/db save()'); - - return Promise.resolve(dbResponse); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } - - /** - Save data as a document (an instance of a particular Model) in a collection. - @param {string} modelName - the name of the Model class. - @param {array} docs - an array of many documents to store at once in the collection. - */ - async insertMany(modelName, docs) { - try { - // A Model is a class with which we construct documents: - const Model = this.Models[modelName]; - - // insert the documents into the db: - const dbResponse = await Model.insertMany(docs); // insertMany uses a single write operation, rather than iterating through. - - logger.debug('src/db/mongodb/db insertMany()'); - logger.silly(`dbResponse ${JSON.stringify(dbResponse, null, 2)}`); - - return Promise.resolve(dbResponse); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } - - /** - Retrieve a single document (an instance of a particular Model) from a collection. - @param {string} modelName - the name of the Model class. - @param {object} query - query parameters. Default is empty. - */ - async getDoc(modelName, query = {}, projections = null) { - try { - // A Model is a class with which we construct documents. We can also access any document constructed from a particular Model class through that Model class: - const Model = this.Models[modelName]; - const doc = await Model.findOne(query, projections); - - logger.debug('src/db/mongodb/db getDoc()'); - logger.silly(`doc ${JSON.stringify(doc, null, 2)}`); - - return Promise.resolve(doc); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } - - /** - Retrieve documents (instances of a particular Model) from a collection. - @param {string} modelName - the name of the Model class. - @param {object} query - query parameters. Default is empty. - @param {array} projections - to filter for particular keys, include the key as a string in an array, e.g. projections = ['field1', 'field2'] will output only these two fields of the document. - @param {object} sort - specify fields by which to sort and whether ascending or descending. E.g. {field1: 1} will sort in ascending order (-1 for descending) - */ - async getDocs(modelName, query = {}, projections = null, sort = {}, limit) { - try { - // A Model is a class with which we construct documents. We can also access all documents constructed from a particular Model class through that Model class: - const Model = this.Models[modelName]; - const docs = await Model.find(query, projections) - .sort(sort) // sort the output results - .limit(limit) // output only the 'top' n results - .exec(); - - logger.debug('src/db/mongodb/db getDocs()'); - logger.silly(`docs ${JSON.stringify(docs, null, 2)}`); - - return Promise.resolve(docs); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } - - /** - Update a single document (an instance of a particular Model) in a collection. - @param {string} modelName - the name of the Model class. - @param {object} query - the query conditions which filter to the document we want to update. - @param {object} updateData - the data with which to update the document. - @param {object} options - extra mongoose options. E.g. the upsert = true option inserts a new document (from the modelName Model class) containing the updateData, if no existing document matches the conditions. - */ - async updateDoc(modelName, query, updateData, options = {}) { - try { - // A Model is a class with which we construct documents. We can also access any document constructed from a particular Model class through that Model class: - const Model = this.Models[modelName]; - const doc = await Model.updateOne(query, updateData, options); - - logger.debug('src/db/mongodb/db updateDoc()'); - logger.silly(`doc ${JSON.stringify(doc, null, 2)}`); - - return Promise.resolve(doc); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } - - /** - Update many documents (instances of a particular Model) in a collection. - @param {string} modelName - the name of the Model class. - @param {object} query - the query conditions which filter to the document we want to update. - @param {object} updateData - the data with which to update the document. - @param {object} options - extra mongoose options. E.g. the upsert = true option inserts a new document (from the modelName Model class) containing the updateData, if no existing document matches the conditions. - */ - async bulkWrite(modelName, bulkUpdates) { - try { - // A Model is a class with which we construct documents. We can also access any document constructed from a particular Model class through that Model class: - const Model = this.Models[modelName]; - const dbResponse = await Model.collection.bulkWrite(bulkUpdates); // CAUTION: we've used 'Model.collection...' rather than mongoose's built-in 'Model.' '' functions, and so validation might be being skipped! - - logger.debug('src/db/mongodb/db bulkWrite()'); - logger.silly(`dbResponse ${JSON.stringify(dbResponse, null, 2)}`); - - return Promise.resolve(dbResponse); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } - - /** - Aggregation operations process data records and return computed results. Aggregation operations group values from multiple documents together, and can perform a variety of operations on the grouped data to RETURN A SINGLE RESULT. - @param {string} modelName - the name of the Model class. - @param {object} query - the query conditions which filter to the document we want to update. - @param {array} stages - an array containing additional 'stage' objects. See https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/ - @param {object} projections - Specifies the fields to return in the documents that match the query filter. To return all fields in the matching documents, omit this parameter. - @param {object} options - extra mongoose options. - */ - async aggregate(modelName, query, stages, projections, options) { - try { - const Model = this.Models[modelName]; - - const pipeline = [{ $match: query }]; - - if (stages) pipeline.push(...stages); - - if (projections) pipeline.push(projections); - - if (options) pipeline.push(options); - - const data = await Model.aggregate(pipeline); - - return Promise.resolve(data); - } catch (e) { - return Promise.reject(e); - } - } - - /** - Count the number of documents (instances of a particular Model) in a collection. - We can use 'countDocuments' for fast counting of indexed documents. - @param {string} modelName - the name of the Model class. - @param {object} query - query parameters. Default is empty. - */ - async countDocuments(modelName, query = {}) { - try { - // A Model is a class with which we construct documents. We can also access all documents constructed from a particular Model class through that Model class: - const Model = this.Models[modelName]; - const count = await Model.countDocuments(query); - - logger.debug('src/db/mongodb/db countDocuments()'); - logger.silly(`count ${JSON.stringify(count, null, 2)}`); - - return Promise.resolve(count); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } - - async deleteMany(modelName, query = {}) { - try { - const Model = this.Models[modelName]; - return Model.deleteMany(query); - } catch (e) { - logger.error(e); - return Promise.reject(e); - } - } -} diff --git a/timber/src/db/service/history.service.mjs b/timber/src/db/service/history.service.mjs deleted file mode 100644 index 2ffb75eed..000000000 --- a/timber/src/db/service/history.service.mjs +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @module history.service.js - * @author westlad - * @desc orchestrates inserts to and gets from the mongodb related to history - */ - -import { COLLECTIONS } from '../common/constants.mjs'; -import logger from '../../logger.mjs'; -import { historyMapper } from '../mappers/index.mjs'; - -export default class HistoryService { - constructor(_db) { - this.db = _db; - } - - /** - Saves the given root and associated frontier, leafIndex and block - Added by Westlad - */ - async saveTreeHistory({ - root, - oldRoot, - frontier, - leafIndex, - currentLeafCount, - blockNumber, - transactionHash, - }) { - logger.debug('src/db/service/history.service saveTreeHistory()'); - // insert the leaf into the 'nodes' collection: - try { - const dbResponse = await this.db.save(COLLECTIONS.HISTORY, { - root, - oldRoot, - frontier, - leafIndex, - currentLeafCount, - blockNumber, - transactionHash, - }); - return dbResponse; - } catch (err) { - logger.error(err); - return Promise.reject(err); - } - } - - async getTreeHistory(root) { - logger.debug('src/db/service/metadata.service getTreeHistory()'); - const docs = await this.db.getDoc(COLLECTIONS.HISTORY, { - root, - }); - return historyMapper(docs); - } - - async getTreeHistoryByCurrentLeafCount(currentLeafCount) { - logger.debug( - `src/db/service/history.service getTreeHistoryByCurrentLeafCount(${currentLeafCount})`, - ); - const docs = await this.db.getDoc(COLLECTIONS.HISTORY, { - currentLeafCount, - }); - return historyMapper(docs); - } - - async getTreeHistoryByTransactionHash(transactionHash) { - logger.debug( - `src/db/service/history.service getTreeHistoryByTransactionHash(${transactionHash})`, - ); - const docs = await this.db.getDoc(COLLECTIONS.HISTORY, { - transactionHash, - }); - return historyMapper(docs); - } - - async deleteTreeHistory(_leafCount) { - logger.debug('deleting alternative timeline'); - const leafCount = Number(_leafCount); - return this.db.deleteMany(COLLECTIONS.HISTORY, { currentLeafCount: { $gte: leafCount } }); - } -} diff --git a/timber/src/db/service/index.mjs b/timber/src/db/service/index.mjs deleted file mode 100644 index 7debd4eb7..000000000 --- a/timber/src/db/service/index.mjs +++ /dev/null @@ -1,4 +0,0 @@ -export { default as LeafService } from './leaf.service.mjs'; -export { default as NodeService } from './node.service.mjs'; -export { default as MetadataService } from './metadata.service.mjs'; -export { default as HistoryService } from './history.service.mjs'; diff --git a/timber/src/db/service/leaf.service.mjs b/timber/src/db/service/leaf.service.mjs deleted file mode 100644 index 78b8183e2..000000000 --- a/timber/src/db/service/leaf.service.mjs +++ /dev/null @@ -1,293 +0,0 @@ -/** - * @module leaf.service.js - * @author iAmMichaelConnor - * @desc orchestrates inserts to and gets from the mongodb - */ - -import { COLLECTIONS } from '../common/constants.mjs'; -import { leafMapper } from '../mappers/index.mjs'; -import logger from '../../logger.mjs'; - -export default class LeafService { - constructor(_db) { - this.db = _db; - } - - // INSERTS - - /** - Insert a new leaf into the merkle tree - @param {number} treeHeight - @param {object} leaf - */ - async insertLeaf(treeHeight, leaf) { - logger.silly(`data before mapping: ${JSON.stringify(leaf, null, 2)}`); - logger.debug('src/db/service/leaf.service insertLeaf()'); - const mappedData = leafMapper(treeHeight, leaf); - logger.silly(`data after mapping: ${JSON.stringify(mappedData, null, 2)}`); - - // insert the leaf into the 'nodes' collection: - try { - const dbResponse = await this.db.save(COLLECTIONS.NODE, mappedData); - return dbResponse; - } catch (err) { - if (err.code === 11000) { - logger.warn( - 'You may wish to ignore the above "DB Error" message. The record already exists. No overwrite has happened. This is acceptable.', - ); - return false; - } - return Promise.reject(err); - } - } - - /** - Insert many leaves into the merkle tree - @param {number} treeHeight - @param {array} leaves - an array of leaf objects ('documents') - */ - async insertLeaves(treeHeight, leaves) { - logger.debug('src/db/service/leaf.service insertLeaves()'); - logger.silly(`data before mapping: ${JSON.stringify(leaves, null, 2)}`); - const mappedData = leaves.map(leaf => leafMapper(treeHeight, leaf)); - logger.silly(`data after mapping: ${JSON.stringify(mappedData, null, 2)}`); - - // insert the leaves into the 'nodes' collection: - try { - const dbResponse = await this.db.insertMany(COLLECTIONS.NODE, mappedData); - return dbResponse; - } catch (err) { - if (err.code === 11000) { - logger.warn( - 'You may wish to ignore the above "DB Error" message. The record already exists. No overwrite has happened. This is acceptable.', - ); - return false; - } - return Promise.reject(err); - } - } - - // UPDATES - - // nothing here - leaves never change - - // GETTERS - - /** - Get a single leaf by its leafIndex - @param {number} leafIndex - @returns {object} the leaf object - */ - async getLeafByLeafIndex(leafIndex) { - logger.debug('src/db/service/leaf.service getLeafByLeafIndex()'); - - const doc = await this.db.getDoc(COLLECTIONS.NODE, { - leafIndex, - }); - - return doc; - } - - /** - Get many leaves by their leafIndices - @param {array} leafIndices - @returns {array} an array of leaf objects - */ - async getLeavesByLeafIndices(leafIndices) { - logger.debug('src/db/service/leaf.service getLeavesByLeafIndices()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { leafIndex: { $in: leafIndices } }, - null, // don't filter the output - { leafIndex: 1 }, // sort by leafIndex in ascending order - ); - - return docs; - } - - /** - Get all leaves within a range determined by their leafIndices - @param {number} minIndex - @param {number} maxIndex - @returns {array} an array of leaf objects - */ - async getLeavesByLeafIndexRange(minIndex, maxIndex) { - logger.debug('src/db/service/leaf.service getLeavesByLeafIndexRange()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { leafIndex: { $gte: minIndex, $lte: maxIndex } }, - null, // don't filter the output - { leafIndex: 1 }, // sort by leafIndex in ascending order - ); - - return docs; - } - - /** - Get a single leaf (or a set of leaves with duplicate values) by its value - @param {string} value - @returns {object} the leaf object(s) - */ - async getLeafByValue(value) { - logger.debug('src/db/service/leaf.service getLeafByValue()'); - - const docs = await this.db.getDoc(COLLECTIONS.NODE, { - value, - }); - - return docs; - } - - /** - Get many leaves by their values - @param {array} values - @returns {array} an array of leaf objects - */ - async getLeavesByValues(values) { - logger.debug('src/db/service/leaf.service getLeavesByValues()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { value: { $in: values } }, - null, // don't filter the output - { leafIndex: 1 }, // sort by leafIndex in ascending order - ); - - return docs; - } - - /** - Get all leaves. - @returns {array} an array of leaf objects - */ - async getLeaves() { - logger.debug('src/db/service/leaf.service getLeaves()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { leafIndex: { $exists: true } }, - null, // don't filter the output - { leafIndex: 1 }, // sort by leafIndex in ascending order - ); - - return docs; - } - - /** - Get all leaf values. Exclude extra data. - TODO: THIS MIGHT BE COMPUTATIONALLY IMPRACTICAL!!! - @returns {array} an array of leaf values, in ascending order (by leafIndex) - */ - async getLeafValues() { - logger.debug('src/db/service/leaf.service getLeafValues()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { leafIndex: { $exists: true } }, // query - ['leafIndex', 'value'], // output only these keys - { leafIndex: 1 }, // sort by leafIndex in ascending order - ); - - return docs; - } - - /** - Get the leaf document for the latest leaf (i.e. the one with the max index) - */ - async getLatestLeaf() { - logger.debug('src/db/service/leaf.service getLatestLeaf()'); - - // insert the leaf into the 'nodes' collection: - const doc = await this.db.getDocs( - COLLECTIONS.NODE, - { leafIndex: { $exists: true } }, // query - null, // projection (output only these keys) - { leafIndex: -1 }, // sort by leafIndex in descending order (we'll then grab the top one), - 1, // limit to the 'top' (latest) result - ); - - return doc[0]; - } - - // OTHER - - /** - Count the number of leaves stored in the merkle tree - */ - async countLeaves() { - logger.debug('src/db/service/leaf.service countLeaves()'); - - const leafCount = await this.db.countDocuments(COLLECTIONS.NODE, { - leafIndex: { $exists: true }, - }); - - return leafCount; - } - - /** - Get the maximum leafIndex stored in the db - */ - async maxLeafIndex() { - logger.debug('src/db/service/leaf.service maxLeafIndex()'); - - const doc = await this.db.getDocs( - COLLECTIONS.NODE, - { leafIndex: { $exists: true } }, // query - { leafIndex: 1, _id: 0 }, // projection (output only these keys) - { leafIndex: -1 }, // sort by leafIndex in descending order (we'll then grab the top one) - 1, // limit output to the 'top' (max) result - ); - - const { leafIndex } = doc[0] || {}; - - return leafIndex; - } - - async findMissingLeaves(startLeafIndex, endLeafIndex) { - logger.debug('src/db/service/leaf.service findMissingLeaves()'); - - const missingLeaves = await this.db.aggregate( - COLLECTIONS.NODE, - { - leafIndex: { $exists: true }, - }, // query - // stages: - [ - { - $sort: { - leafIndex: 1, // sort by leafIndex in ascending order - }, - }, - { - $group: { - _id: null, // group all documents into the same bucket - leafIndices: { $push: '$leafIndex' }, // create an array of all "leafIndex" fields - }, - }, - ], - - // Find any expected values that are missing from the existing data - { - $project: { - _id: 0, // remove the '_id' field - missing: { - $setDifference: [ - { - $range: [startLeafIndex, endLeafIndex], - }, // create an array of all numbers in this range - '$leafIndices', - ], - }, - }, - }, - ); - - // format of missingLeaves = [ { missing: [ 1, 4, 5, 6 ] } ] - - const { missing } = missingLeaves[0] || {}; - - return missing; - } -} diff --git a/timber/src/db/service/metadata.service.mjs b/timber/src/db/service/metadata.service.mjs deleted file mode 100644 index dea4e096b..000000000 --- a/timber/src/db/service/metadata.service.mjs +++ /dev/null @@ -1,232 +0,0 @@ -/** - * @module metadata.service.js - * @author iAmMichaelConnor - * @desc orchestrates inserts to and gets from the mongodb - */ - -import { COLLECTIONS } from '../common/constants.mjs'; -import { metadataMapper } from '../mappers/index.mjs'; -import logger from '../../logger.mjs'; - -export default class MetadataService { - constructor(_db) { - this.db = _db; - } - - // INSERTS - - /** - Insert a contractAddress into the tree's metadata - @param {object} data - */ - async insertContractAddress(data) { - logger.debug('src/db/service/metadata.service insertContractAddress()'); - const { contractAddress } = metadataMapper(data); - if (contractAddress === undefined) return null; - - const dbResponse = await this.db.updateDoc( - COLLECTIONS.METADATA, - { _id: 1 }, - { $set: { contractAddress } }, - { upsert: true }, - ); - - return dbResponse; - } - - /** - Insert a contractInterface into the tree's metadata - @param {object} data - */ - async insertContractInterface(data) { - logger.debug('src/db/service/metadata.service insertContractInterface()'); - const { contractInterface } = metadataMapper(data); - if (contractInterface === undefined) return null; - - const dbResponse = await this.db.updateDoc( - COLLECTIONS.METADATA, - { _id: 1 }, - { $set: { contractInterface } }, - { upsert: true }, - ); - - return dbResponse; - } - - /** - Get the treeHeight relating to the MerkleTree contract & treeId - @returns {object} the { treeHeight } - */ - async getTreeHeight() { - logger.debug('src/db/service/metadata.service getTreeHeight()'); - - let doc = await this.db.getDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document) - ['treeHeight', '-_id'], // return only the 'treeHeight' key (and exclude the _id key) - ); - doc = doc || {}; - return doc; - } - - /** - Insert a tree height into the tree's metadata - @param {object} data - */ - async insertTreeHeight(data) { - logger.debug('src/db/service/metadata.service insertTreeHeight()'); - - // TODO: although a check is done within the filter-controller to prevent treeHeight overwrites, users who call the API endpoint aren't protected unless we have code here. Unfortunately, this strong error-throwing code is too disruptive. Handle more intelligently, like the filter does. - // const { treeHeight: checkTreeHeight } = await this.getTreeHeight(); - // if (checkTreeHeight) - // throw new Error(`treeHeight already set at ${checkTreeHeight}. This cannot be edited.`); - - const { treeHeight } = metadataMapper(data); - if (treeHeight === undefined) return null; - logger.debug(`treeHeight: ${treeHeight}`); - - const dbResponse = await this.db.updateDoc( - COLLECTIONS.METADATA, - { _id: 1 }, - { $set: { treeHeight } }, - { upsert: true }, - ); - - return dbResponse; - } - - // UPDATES - - /** - Update the latestLeaf object in the tree's metadata - @param {object} data - */ - async updateLatestLeaf(data) { - logger.debug('src/db/service/metadata.service updateLatestLeaf()'); - logger.silly(`data before mapping: ${JSON.stringify(data, null, 2)}`); - const mappedData = metadataMapper(data); - logger.silly(`data after mapping: ${JSON.stringify(mappedData, null, 2)}`); - - const { latestLeaf } = mappedData; - logger.debug('latestLeaf:', latestLeaf); - if (latestLeaf === undefined) return null; - - const doc = await this.db.updateDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document) - { $set: { latestLeaf } }, - // { upsert: false }, // we only ever want 1 'tree' document, so don't want to upsert - ); - - return doc; - } - - /** - Update the latestRecalculation object in the tree's metadata - @param {object} data - */ - async updateLatestRecalculation(data) { - logger.debug('src/db/service/metadata.service updateLatestRecalculation()'); - logger.silly(`data before mapping: ${JSON.stringify(data, null, 2)}`); - const mappedData = metadataMapper(data); - logger.silly(`data after mapping: ${JSON.stringify(mappedData, null, 2)}`); - - const { latestRecalculation } = mappedData; - logger.silly(`latestRecalculation: ${JSON.stringify(latestRecalculation, null, 2)}`); - if (latestRecalculation === undefined) return null; - - const doc = await this.db.updateDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document) - { $set: { latestRecalculation } }, - ); - - return doc; - } - - /** - Get all metadata for the tree - @returns {object} the tree metadata object - */ - async getMetadata() { - logger.debug('src/db/service/metadata.service getMetadata()'); - - const doc = await this.db.getDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document) - ); - - return doc; - } - - /** - Get the contractAddress relating to MerkleTree contract - @returns {object} the { contractAddress } - */ - async getContractAddress() { - logger.debug('src/db/service/metadata.service getContractAddress()'); - - const doc = await this.db.getDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document) - ['contractAddress', '-_id'], // return only the 'contractAddress' key (and exclude the _id key) - ); - - return doc; - } - - /** - Get the contractInterface relating to the MerkleTree contract - @returns {object} the { contractInterface } - */ - async getContractInterface() { - logger.debug('src/db/service/metadata.service getContractInterface()'); - - const doc = await this.db.getDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document) - ['contractInterface', '-_id'], // return only the 'contractInterface' key (and exclude the _id key) - ); - - let { contractInterface } = doc; - - contractInterface = { - contractInterface: JSON.parse(contractInterface), - }; - - return contractInterface; - } - - /** - Get the latestRecalculation metadata for the tree - @returns {object} the latestRecalculation object - */ - async getLatestRecalculation() { - logger.debug('src/db/service/metadata.service getLatestRecalculation()'); - - let doc = await this.db.getDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document) - ['latestRecalculation', '-_id'], // return only the 'latestRecalculation' key (and exclude the _id key) - ); - doc = doc || {}; - - return doc; - } - - /** - Get the latestLeaf metadata for the tree - @returns {object} the latestLeaf object - */ - async getLatestLeaf() { - logger.debug('src/db/service/metadata.service getLatestLeaf()'); - - const doc = await this.db.getDoc( - COLLECTIONS.METADATA, - { _id: 1 }, // 'match all' (within our one document), - ['latestLeaf', '-_id'], // return only the 'latestLeaf' key (and exclude the _id key) - ); - - return doc; - } -} diff --git a/timber/src/db/service/node.service.mjs b/timber/src/db/service/node.service.mjs deleted file mode 100644 index 586a609fd..000000000 --- a/timber/src/db/service/node.service.mjs +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @module node.service.js - * @author iAmMichaelConnor - * @desc orchestrates inserts to and gets from the mongodb - */ - -import { COLLECTIONS } from '../common/constants.mjs'; -import { nodeMapper } from '../mappers/index.mjs'; -import logger from '../../logger.mjs'; - -export default class NodeService { - constructor(_db) { - this.db = _db; - } - - // INSERTS - - /** - Insert a new node (not a leaf) into the merkle tree - @param {object} node - */ - async insertNode(node) { - logger.debug('src/db/service/node.service insertNode()'); - logger.silly(`data before mapping: ${JSON.stringify(node, null, 2)}`); - const mappedData = nodeMapper(node); - logger.silly(`data after mapping: ${JSON.stringify(mappedData, null, 2)}`); - - // insert the node into the 'nodes' collection: - const dbResponse = await this.db.save(COLLECTIONS.NODE, mappedData); - - return dbResponse; - } - - // UPDATES - - /** - Update a node (not a leaf) searching by its nodeIndex - @param {integer} nodeIndex - @param {object} data - */ - async updateNodeByNodeIndex(nodeIndex, data) { - logger.debug('src/db/service/node.service updateNodeByNodeIndex()'); - logger.silly(`data before mapping: ${JSON.stringfy(data, null, 2)}`); - const mappedData = nodeMapper(data); - logger.silly(`data after mapping: ${JSON.stringify(mappedData, null, 2)}`); - - const doc = await this.db.updateDoc( - COLLECTIONS.NODE, - { - nodeIndex, - }, // query - { $set: mappedData }, // update - ); - - return doc; - } - - /** - Update many nodes (not leaves). We implicitly update based on nodeIndex (by finding that index within the 'data') - @param {array} nodes an array of node objects - */ - async updateNodes(nodes) { - logger.debug('src/db/service/node.service updateNodes()'); - logger.silly(`data before mapping: ${JSON.stringify(nodes, null, 2)}`); - const mappedData = nodes.map(nodeMapper); - logger.silly(`data after mapping: ${JSON.stringify(mappedData, null, 2)}`); - - const bulkUpdates = mappedData.map(item => ({ - updateOne: { - filter: { - nodeIndex: item.nodeIndex, - }, - update: { $set: { value: item.value } }, - upsert: true, // create a new entry if the item ('node') doesn't yet exist in the db - }, - })); - - const dbResponse = await this.db.bulkWrite(COLLECTIONS.NODE, bulkUpdates); - - return dbResponse; - } - - // GETTERS - - // GETTERS FOR NODES - - /** - Get a single node by its nodeIndex - @param {number} nodeIndex - @returns {object} the node object - */ - async getNodeByNodeIndex(nodeIndex) { - logger.debug('src/db/service/node.service getNodeByNodeIndex()'); - - const doc = await this.db.getDoc( - COLLECTIONS.NODE, - { nodeIndex }, // query - null, // don't filter the output - { nodeIndex: 1 }, // sort by nodeIndex in ascending order - ); - - return doc; - } - - /** - Get many nodes by their nodeIndices - @param {array} nodeIndices - @returns {array} an array of node objects - */ - async getNodesByNodeIndices(nodeIndices) { - logger.debug('src/db/service/node.service getNodesByNodeIndices()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { nodeIndex: { $in: nodeIndices } }, // query - null, // don't filter the output - { nodeIndex: 1 }, // sort by nodeIndex in ascending order - ); - - return docs; - } - - /** - Get all nodes within a range determined by their nodeIndices (inclusive) - @param {number} minIndex - @param {number} maxIndex - @returns {array} an array of node objects - */ - async getNodesByNodeIndexRange(minIndex, maxIndex) { - logger.debug('src/db/service/node.service getNodesByNodeIndexRange()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { nodeIndex: { $gte: minIndex, $lte: maxIndex } }, // query - null, // don't filter the output - { nodeIndex: 1 }, // sort by nodeIndex in ascending order - ); - - return docs; - } - - /** - Get a single node (or a set of nodes with duplicate values) by its value - @param {string} value - @returns {object} the node object(s) - */ - async getNodeByValue(value) { - logger.debug('src/db/service/node.service getNodeByValue()'); - - const docs = await this.db.getDoc(COLLECTIONS.NODE, { - value, - }); - - return docs; - } - - /** - Get many nodes by their values - @param {array} values - @returns {array} an array of node objects - */ - async getNodesByValues(values) { - logger.debug('src/db/service/node.service getNodesByValues()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { value: { $in: values } }, // query - null, // don't filter the output - { nodeIndex: 1 }, // sort by nodeIndex in ascending order - ); - - return docs; - } - - /** - Get all nodes. - @returns {array} an array of node objects - */ - async getNodes() { - logger.debug('src/db/service/node.service getNodes()'); - - const docs = await this.db.getDocs( - COLLECTIONS.NODE, - { nodeIndex: { $exists: true } }, // query - null, // don't filter the output - { nodeIndex: 1 }, // sort by nodeIndex in ascending order - ); - - return docs; - } - - /** - Get the root (i.e. the node at nodeIndex = 0) - @returns {object} the root's node object - */ - async getRoot() { - logger.debug('src/db/service/node.service getRoot()'); - - const doc = await this.db.getDoc(COLLECTIONS.NODE, { - nodeIndex: { $eq: 0 }, - }); - - return doc; - } - - // OTHER - - /** - Count the number of nodes stored in the merkle tree - */ - async countNodes() { - logger.debug('src/db/service/node.service countNodes()'); - - const nodeCount = await this.db.countDocuments(COLLECTIONS.NODE, { - nodeIndex: { $exists: true }, - }); - - return nodeCount; - } - - async deleteNodes(indices) { - logger.debug('deleting nodes'); - const dbResponse = this.db.deleteMany(COLLECTIONS.NODE, { nodeIndex: { $in: indices } }); - return dbResponse; - } -} diff --git a/timber/src/filter-controller.mjs b/timber/src/filter-controller.mjs deleted file mode 100644 index 06f00f2f5..000000000 --- a/timber/src/filter-controller.mjs +++ /dev/null @@ -1,452 +0,0 @@ -/** -@module filter-controller.js -@desc file that starts up the filter -@author iAmMichaelConnor -*/ - -import config from 'config'; -import Queue from 'queue'; -import utilsWeb3 from './utils-web3.mjs'; - -import { LeafService, MetadataService, HistoryService } from './db/service/index.mjs'; -import logger from './logger.mjs'; -import mtc from './merkle-tree-controller.mjs'; // eslint-disable-line import/no-cycle -import getProposeBlockCalldata from './optimistic/process-calldata.mjs'; - -// const ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000'; -// global subscriptions object: -const subscriptions = {}; -// this queue controls event concurrency to be 1. This means that event -// event responders cannot attempt parallel writes to the db. Instead, such -// requests are queued and handled in order -const queue = new Queue({ autostart: true, concurrency: 1 }); - -/** -@author westlad -This is a response function that is able to filter data from an optimistic block -proposal and extract data that Timber's NewLeaf(s) response functions understand. It then call them. Doing it that way means that the smart contract -Timber is listening to does not have to emit all the commitment data in a -NewLeaf(s) event and that saves considerable gas (event emitting is not free). -*/ -const blockProposedResponseFunction = async (eventObject, args) => { - // NEW - function remains the same, for detecting single leaves, but can now specify the event name - // NOTE - events must have same parameters as newLeaf / newLeaves - // We make some hardcoded presumptions about what's contained in the 'args': - logger.debug('processing BlockProposed event'); - const { db, contractName, treeId } = args; - - const eventName = args.eventName === undefined ? 'BlockProposed' : args.eventName; // hardcoded, as inextricably linked to the name of this function. - - let eventParams; - logger.debug(`eventname: ${eventName}`); - - if (treeId === undefined || treeId === '') { - eventParams = config.contracts[contractName].events[eventName].parameters; - } else { - eventParams = config.contracts[contractName].treeId[treeId].events[eventName].parameters; - } - - // Now some generic eventObject handling code: - const { eventData } = eventObject; - /* - extract each relevent event parameter from the eventData and create an eventInstance: { - eventParamName_0: eventParamValue_0, - eventParamName_1: eventParamValue_1, - ... - } - */ - const eventInstance = {}; - eventParams.forEach(param => { - eventInstance[param] = eventData.returnValues[param]; - }); - - const metadataService = new MetadataService(db); - const { treeHeight } = await metadataService.getTreeHeight(); - // Now some more bespoke code; specific to how our application needs to deal with this eventObject: - // construct an array of 'leaf' documents to store in the db: - const { blockNumber, transactionHash } = eventData; - // first, we need to extract the commitment values from the calldata because - // it's not in the emitted event. We don't care about the Block object - const { transactions } = await getProposeBlockCalldata(eventData); - logger.debug(`recovered transactions ${JSON.stringify(transactions, null, 2)}`); - // note that the block chain does not hold a leaf count that we can assume is correct - // that's because it's not calculated on-chain but instead is posted optimistically - // thus, we're better off relying on Timber's own record. - const { latestRecalculation } = await metadataService.getLatestRecalculation(); - const { leafIndex: storedLeafIndex } = latestRecalculation; - /* - const currentLeafCount = - Number(block.leafCount) + - transactions.map(t => t.commitments.filter(c => c !== ZERO)).flat(Infinity).length; - */ - const leafValues = transactions - .map(transaction => transaction.commitments.filter(c => c !== config.ZERO)) - .flat(Infinity); - // Timber works on the leafIndex BEFORE the new leafValues are added but the - // BlockProposed event broadcasts the AFTER value: - // const minLeafIndex = currentLeafCount - leafValues.length; - const minLeafIndex = storedLeafIndex === undefined ? 0 : storedLeafIndex + 1; - - logger.debug( - `minLeafIndex was ${minLeafIndex}, leafValues.length ${leafValues.length}, eventInstance, ${eventInstance}`, - ); - logger.debug(`leafValues were ${JSON.stringify(leafValues, null, 2)}`); - // now we have the relevant data, update the Merkle tree: - if (leafValues.length === 0) return Promise.resolve(); - if (leafValues.length === 1) { - const leaf = { - value: leafValues[0], - leafIndex: minLeafIndex, - blockNumber, - transactionHash, - }; - const leafService = new LeafService(db); - await leafService.insertLeaf(treeHeight, leaf); - return mtc.update(db); // update the database to ensure we have a historic root - } - const leaves = []; - let leafIndex; - leafValues.forEach((leafValue, index) => { - leafIndex = Number(minLeafIndex) + Number(index); - const leaf = { - value: leafValue, - leafIndex, - blockNumber, - transactionHash, - }; - leaves.push(leaf); - }); - const leafService = new LeafService(db); - await leafService.insertLeaves(treeHeight, leaves); - return mtc.update(db); // update the database to ensure we have a historic root}; -}; - -/** -@author westlad -This is a response function specific for a rollback. -*/ -const rollbackResponseFunction = async (eventObject, args) => { - // NEW - function remains the same, for detecting single leaves, but can now specify the event name - // NOTE - events must have same parameters as newLeaf / newLeaves - // We make some hardcoded presumptions about what's contained in the 'args': - - const { db, contractName, treeId } = args; - - const eventName = args.eventName === undefined ? 'Rollback' : args.eventName; // hardcoded, as inextricably linked to the name of this function. - - let eventParams; - logger.debug(`eventname: ${eventName}`); - - if (treeId === undefined || treeId === '') { - eventParams = config.contracts[contractName].events[eventName].parameters; - } else { - eventParams = config.contracts[contractName].treeId[treeId].events[eventName].parameters; - } - - // Now some generic eventObject handling code: - const { eventData } = eventObject; - - /* - extract each relevent event parameter from the eventData and create an eventInstance: { - eventParamName_0: eventParamValue_0, - eventParamName_1: eventParamValue_1, - ... - } - */ - const eventInstance = {}; - eventParams.forEach(param => { - eventInstance[param] = eventData.returnValues[param]; - }); - logger.silly(`eventInstance: ${JSON.stringify(eventInstance, null, 2)}`); - - const metadataService = new MetadataService(db); - const { treeHeight } = await metadataService.getTreeHeight(); - - // Now some bespoke code; specific to how our application needs to deal with this eventObject: - // const { blockNumber } = eventData; - const { leafCount } = eventInstance; - return mtc.rollback(db, treeHeight, Number(leafCount)); -}; - -/** -This function replays events from blockNumber to the latest block. This is to -rebuild state that was removed when an event was removed by a layer 1 chain -reoganisation -*/ -async function resync(fromblockNumberL1, args) { - // get all the events and sort them into causal order by block and transaction - const { contractName } = args; - const events = await ( - await utilsWeb3.getContractInstance(contractName) - ).methods.events - .allEvents({ - fromBlock: fromblockNumberL1, - toBlock: 'latest', - }) - .flat() - .sort((a, b) => a.blockNumber - b.blockNumber || a.transactionIndex - b.transactionIndex); - // now replay them in order - for (let i = 0; i < events.length; i++) { - switch (events[i].event) { - case 'BlockProposed': - queue.push(() => blockProposedResponseFunction(events[i], args)); - break; - case 'Rollback': - queue.push(() => rollbackResponseFunction(events[i], args)); - break; - default: - } - } -} - -/** -@author westlad -This function is called whenever a BlockProposed event is removed by a layer 1 chain reorg. -When that happens, we need to roll back the database to the point just before the -event happened, and then rebuild the state. -*/ -async function removeBlockProposedFunction(eventObject, args) { - // Generic Timber event processing preamble... - const { db, contractName, treeId } = args; - const eventName = args.eventName === undefined ? 'Rollback' : args.eventName; - let eventParams; - logger.debug(`eventname: ${eventName} removal`); - if (treeId === undefined || treeId === '') { - eventParams = config.contracts[contractName].events[eventName].parameters; - } else { - eventParams = config.contracts[contractName].treeId[treeId].events[eventName].parameters; - } - const { eventData } = eventObject; - const eventInstance = {}; - eventParams.forEach(param => { - eventInstance[param] = eventData.returnValues[param]; - }); - const metadataService = new MetadataService(db); - const { treeHeight } = await metadataService.getTreeHeight(); - - // Now some bespoke code; specific to how our application needs to deal with this eventObject: - const { transactionHash } = eventData; - // we now know the (layer 1) transaction in which the original event took place, - // we can search for the event in Timber's history and extract the leafCount - const historyService = new HistoryService(db); - const history = await historyService.getTreeHistoryByTransactionHash(transactionHash); - // check we do actually have such a history. We could get multiple removals of - // block proposed events coming together in undefined order. It's possible that - // an earlier rollback has already removed the tree history. That's fine, our - // work is already done. - if (!history) return true; - // Now, the leafCount just before this block was added was history.currentLeafCount. - // That's where we need to roll back to. - return mtc.rollback(db, treeHeight, Number(history.currentLeafCount)); -} - -/** -@author westlad -This function is called whenever a Rollback event is removed by a layer 1 chain reorg. -When that happens, we need to roll back the database to the point just before the -event happened, and then rebuild the state. -*/ -async function removeRollbackFunction(eventObject, args) { - // Generic Timber event processing preamble... - const { db, contractName, treeId } = args; - const eventName = args.eventName === undefined ? 'Rollback' : args.eventName; - let eventParams; - logger.debug(`eventname: ${eventName}`); - if (treeId === undefined || treeId === '') { - eventParams = config.contracts[contractName].events[eventName].parameters; - } else { - eventParams = config.contracts[contractName].treeId[treeId].events[eventName].parameters; - } - const { eventData } = eventObject; - const eventInstance = {}; - eventParams.forEach(param => { - eventInstance[param] = eventData.returnValues[param]; - }); - const metadataService = new MetadataService(db); - const { treeHeight } = await metadataService.getTreeHeight(); - - // Now some bespoke code; specific to how our application needs to deal with this eventObject: - const { leafCount } = eventInstance; - // Now,this is the leafCount that we originally rolled back to - // that's where we need to roll back to again to remove any state added after - // the rollback - // before we do that though let's find out the block number that corresponds - // to that leafCount because we'll need to rebuild the state from that block. - const { blockNumber } = await mtc.getTreeHistoryByCurrentLeafCount(db, Number(leafCount)); - await mtc.rollback(db, treeHeight, Number(leafCount)); - // and now we need to roll forwards to the present, along our new timeline - return resync(blockNumber, args); -} - -/** -This function is triggered by the 'event' contract subscription, every time a new event is received via the websocket. -@param {object} eventObject - An event object. -*/ -const newEventResponder = async (eventObject, responseFunction, responseFunctionArgs = {}) => { - logger.debug('Responding to New Event...'); - - // we can push to a queue here to buffer the events during a rollback - // the items in the queue will execute until it's empty or we stop it - queue.push(cb => { - responseFunction(eventObject, responseFunctionArgs).then(() => cb()); - }); // we don't need to await this -}; - -/** -Config object for the above response functions. -Naming convention: -{ - eventName: eventNameResponseFunction -} -*/ -export const responseFunctions = { - Rollback: rollbackResponseFunction, - BlockProposed: blockProposedResponseFunction, -}; -// remover functions are called when an event is removed by a chain reorg. -const removerFunctions = { - Rollback: removeRollbackFunction, - BlockProposed: removeBlockProposedFunction, -}; - -/** -An 'orchestrator' which oversees the various filtering steps of the filter -@param {number} blockNumber -*/ -async function filterBlock(db, contractName, contractInstance, fromBlock, treeId) { - logger.debug( - `src/filter-controller filterBlock(db, contractInstance, fromBlock=${fromBlock}, treeId)`, - ); - const metadataService = new MetadataService(db); - - let eventNames; - - // TODO: if possible, make this easier to read and follow. Fewer 'if' statements. Perhaps use 'switch' statements instead? - if (treeId === undefined || treeId === '') { - eventNames = Object.keys(config.contracts[contractName].events); - if (config.treeHeight !== undefined || config.treeHeight !== '') { - const { treeHeight } = config; - metadataService.insertTreeHeight({ treeHeight }); - } - } else { - const { treeHeightDb } = await metadataService.getTreeHeight(); - const { treeHeight } = config.contracts[contractName].treeId[treeId]; - if (treeHeightDb !== treeHeight && (treeHeight !== undefined || treeHeight !== '')) { - metadataService.insertTreeHeight({ treeHeight }); - } - eventNames = Object.keys(config.contracts[contractName].treeId[treeId].events); - } - - const { treeHeight } = await metadataService.getTreeHeight(); - const { latestRecalculation } = await metadataService.getLatestRecalculation(); - const { frontier } = - latestRecalculation.frontier === undefined ? new Array(treeHeight) : latestRecalculation; - if (frontier.length !== treeHeight + 1 && treeHeight !== 32) { - latestRecalculation.frontier = new Array(treeHeight + 1); - await metadataService.updateLatestRecalculation({ latestRecalculation }); - } - - eventNames.forEach(async eventName => { - const responder = newEventResponder; - const responseFunction = responseFunctions[eventName]; - const responseFunctionArgs = { db, contractName, eventName, treeId }; - const removerFunction = removerFunctions[eventName]; - - const eventSubscription = await utilsWeb3.subscribeToEvent( - contractName, - contractInstance, - null, // if null, the deployedAddress will be gleaned from the contractInstance - eventName, - fromBlock, - responder, - responseFunction, - responseFunctionArgs, - removerFunction, - ); - - subscriptions[eventName] = eventSubscription; // keep the subscription object for this event in global memory; to enable 'unsubscribe' in future. - }); -} - -/** -Check which block was the last to be filtered. -@return {number} the next blockNumber which should be filtered. -*/ -async function getFromBlock(db) { - const metadataService = new MetadataService(db); - - const metadata = await metadataService.getLatestLeaf(); - - let latestLeaf; - let blockNumber; - - switch (metadata) { - case null: // no document exists in the metadata db - throw new Error('Unexpected null response from db: no document found in the metadata db.'); - default: - latestLeaf = metadata.latestLeaf || {}; - blockNumber = latestLeaf.blockNumber || undefined; - break; - } - - logger.info( - `Stats at restart, from the merkle-tree's mongodb: latestLeaf, ${latestLeaf}; blockNumber, ${blockNumber}`, - ); - - if (blockNumber === undefined) { - blockNumber = config.FILTER_GENESIS_BLOCK_NUMBER; - logger.warn( - `No filtering history found in mongodb, so starting filter from the contract's deployment block ${blockNumber}`, - ); - } - - const currentBlockNumber = await utilsWeb3.getBlockNumber(); - logger.info(`Current blockNumber: ${currentBlockNumber}`); - - logger.info(`The filter is ${currentBlockNumber - blockNumber} blocks behind the current block.`); - - return blockNumber; -} - -/** -Commence filtering -*/ -async function start(db, contractName, contractInstance, treeId) { - try { - logger.info('Starting filter...'); - // check the fiddly case of having to re-filter any old blocks due to lost information (e.g. due to a system crash). - const fromBlock = await getFromBlock(db); // the blockNumber we get is the next WHOLE block to start filtering. - - // Now we filter indefinitely: - await filterBlock(db, contractName, contractInstance, fromBlock, treeId); - return true; - } catch (err) { - logger.error(err.stack); - throw new Error(err); - } -} - -/** -Many functions need to be sure that the database is current. If it's -potentially in the process of updating (i.e. an event responder is running) -then these functions will want to hang on for a bit. Hence this function: -*/ -function waitForUpdatesToComplete() { - return new Promise((resolve, reject) => { - // we'll push in this dummy function. This ensures that there is at least - // one function in the queue, when it clear the queue, the 'end' event will - // fire. You'd think you could use queue.length == 0 as a test but that - // doesn't seem to work. - queue.push(cb => { - resolve(); - logger.debug('queued events have run'); - cb(); - }); - setTimeout(() => reject(new Error('Waiting too long for queue to empty')), 1000); - }); -} - -export default { - start, - waitForUpdatesToComplete, -}; diff --git a/timber/src/index.mjs b/timber/src/index.mjs deleted file mode 100644 index b8d35cf89..000000000 --- a/timber/src/index.mjs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @module index.js - * @author iAmMichaelConnor - * @desc index.js gives api endpoints to access the functions of the merkle-tree microservice */ - -import express, { Router } from 'express'; -import bodyParser from 'body-parser'; -import cors from 'cors'; -import logger from './logger.mjs'; -import Web3 from './web3.mjs'; -import autostart from './auto-start.mjs'; - -import { - assignDbConnection, - formatResponse, - formatError, - errorHandler, - logError, -} from './middleware/index.mjs'; - -import { leafRoutes, nodeRoutes, metadataRoutes, merkleTreeRoutes } from './routes/index.mjs'; - -Web3.connect(); -const app = express(); - -// TODO: what is this? : -app.use(function cros(req, res, next) { - res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); - res.header( - 'Access-Control-Allow-Headers', - 'Origin, X-Requested-With, Content-Type, Accept, Authorization', - ); - if (req.method === 'OPTIONS') { - res.end(); - } else { - next(); - } -}); - -// cors & body parser middleware should come before any routes are handled -app.use(cors()); -app.use(bodyParser.json({ limit: '50mb' })); -app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' })); - -app.use(assignDbConnection); - -// Routes -const router = Router(); -app.use(router); - -leafRoutes(router); -nodeRoutes(router); -metadataRoutes(router); -merkleTreeRoutes(router); - -// Response -app.use(formatResponse); -app.use(formatError); -app.use(errorHandler); -app.use(logError); - -const server = app.listen(80, '0.0.0.0', () => { - logger.info('merkle-tree RESTful API server started on ::: 80'); - if (process.env.AUTOSTART) autostart(); -}); -server.timeout = 0; diff --git a/timber/src/logger.mjs b/timber/src/logger.mjs deleted file mode 100644 index c91886d99..000000000 --- a/timber/src/logger.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import logger from 'winston'; -import config from 'config'; - -const { createLogger, format, transports } = logger; -const winstonLogger = createLogger({ - level: config.LOG_LEVEL, - format: format.combine(format.colorize(), format.simple()), - transports: [new transports.Console()], -}); - -export default winstonLogger; diff --git a/timber/src/merkle-tree-controller.mjs b/timber/src/merkle-tree-controller.mjs deleted file mode 100644 index 8f2cd0792..000000000 --- a/timber/src/merkle-tree-controller.mjs +++ /dev/null @@ -1,455 +0,0 @@ -/** -This module reacts to external API calls routed via ./routes/merkle-tree.js. -@module merkle-tree-controller.js -@author iAmMichaelConnor -*/ - -import config from 'config'; -import utilsWeb3 from './utils-web3.mjs'; -import utilsMT from './utils-merkle-tree.mjs'; -import logger from './logger.mjs'; -import { LeafService, NodeService, MetadataService, HistoryService } from './db/service/index.mjs'; -import { responseFunctions } from './filter-controller.mjs'; // eslint-disable-line import/no-cycle -// import { getContractInterface } from '../../../nightfall-optimist/src/utils/contract.mjs' -const { ZERO } = config; - -/** -Check the leaves of the tree are all there. -@param {object} db - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy). This contains permissions to access the merkle tree's databases. -@return {integer} maxReliableLeafIndex - the left-most reliable leafIndex (by 'reliable' we mean that there are no missing leaves in the db from 0 to this maxReliableLeafIndex). Returns -1 if no leaves exist in the tree yet. -*/ -async function checkLeaves(db) { - logger.debug('src/merkle-tree-controller checkLeaves()'); - - const leafService = new LeafService(db); - - // count all the leaves - const leafCount = await leafService.countLeaves(); - // get the max leafIndex of all the leaves - let maxLeafIndex = await leafService.maxLeafIndex(); - if (maxLeafIndex === undefined) maxLeafIndex = -1; - - let maxReliableLeafIndex; - - // then we can quickly see if there are NOT any missing leaves: - if (leafCount < maxLeafIndex + 1) { - // then we are missing values. Let's do a slower search to find the earliest missing value: - logger.warn( - `There are missing leaves in the db. Found ${leafCount} leaves, but expected ${ - maxLeafIndex + 1 - }. Performing a slower check to find the missing leaves...`, - ); - const missingLeaves = await leafService.findMissingLeaves(0, maxLeafIndex); - - logger.warn(`missing leaves: ${JSON.stringify(missingLeaves, null, 2)}`); - - const minMissingLeafIndex = missingLeaves[0]; - const maxMissingLeafIndex = missingLeaves[missingLeaves.length - 1]; - - const leafAfterMissingLeaves = await leafService.getLeafByLeafIndex(maxMissingLeafIndex + 1); - maxReliableLeafIndex = minMissingLeafIndex - 1; - - let fromBlock; - - if (minMissingLeafIndex > 0) { - // get the prior leaf: - const latestConsecutiveLeaf = await leafService.getLeafByLeafIndex(maxReliableLeafIndex); - - fromBlock = latestConsecutiveLeaf.blockNumber; - } else { - // start from scratch: - fromBlock = config.FILTER_GENESIS_BLOCK_NUMBER; - return maxReliableLeafIndex; // the maximum reliable leafIndex is -1; i.e. nothing's reliable. Let's start again. - } - - const currentBlock = await utilsWeb3.getBlockNumber(); - const toBlock = leafAfterMissingLeaves.blockNumber ?? 'latest'; - const lag = currentBlock - fromBlock; - - const lagTolerance = config.tolerances.LAG_BEHIND_CURRENT_BLOCK; - - if (lag <= lagTolerance) { - logger.info( - `Ideally, we would re-filter from block ${fromBlock}, but the filter is only ${lag} blocks behind the current block ${currentBlock}. Since the user's config specifies a 'lag' tolerance of ${lagTolerance} blocks, we will not re-filter.`, - ); - - return maxReliableLeafIndex; // return the latest reliable leaf index up to which we can update the tree - } - const contractName = Object.keys(config.contracts)[0]; - const { treeId } = config.contracts[contractName]; - - const contractAddress = await utilsWeb3.getContractAddress(contractName); - - if (contractAddress === undefined) throw new Error('undefined contract address'); - - const contractInterface = await utilsWeb3.getContractInstance(contractName, contractAddress); - - // fromBlock incremented since we only want the next block after the last one we have saved. - const events = await contractInterface.getPastEvents({ - fromBlock: fromBlock + 1, - toBlock: toBlock - 1, - }); - - const pastTimberEvents = events - .filter(e => ['NewLeaf', 'NewLeaves', 'Rollback', 'BlockProposed'].includes(e.event)) - .sort((a, b) => a.blockNumber - b.blockNumber); - - for (let i = 0; i < pastTimberEvents.length; i++) { - const responseFunction = responseFunctions[pastTimberEvents[i].event]; - const responseFunctionArgs = { - db, - contractName, - event: pastTimberEvents[i], - treeId, - }; - await responseFunction({ eventData: pastTimberEvents[i] }, responseFunctionArgs); // eslint-disable-line no-await-in-loop - } - } - - maxReliableLeafIndex = maxLeafIndex; - - return maxReliableLeafIndex; -} - -/** -Update the latestLeaf metadata with the leaf object of the highest-indexed leaf which has been stored in the db. -@param {object} db - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy). This contains permissions to access the merkle tree's databases. -*/ -async function updateLatestLeaf(db) { - logger.debug('src/merkle-tree-controller updateLatestLeaf()'); - - const leafService = new LeafService(db); - const metadataService = new MetadataService(db); - - const maxReliableLeafIndex = await checkLeaves(db); - - if (maxReliableLeafIndex === -1) return null; - - const maxReliableLeaf = await leafService.getLeafByLeafIndex(maxReliableLeafIndex); - - const { blockNumber, transactionHash, leafIndex } = maxReliableLeaf; - - const latestLeaf = { - blockNumber, - transactionHash, - leafIndex, - }; - - await metadataService.updateLatestLeaf({ latestLeaf }); - - return { latestLeaf }; -} - -/** -Calculate the path (each parent up the tree) from a given leaf to the root. -@param {object} db - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy). This contains permissions to access the merkle tree's databases. -@param {integer} leafIndex - the index of the leaf for which we are computing the path -*/ -async function getPathByLeafIndex(db, leafIndex) { - logger.debug('src/merkle-tree-controller getPathByLeafIndex()'); - const metadataService = new MetadataService(db); - // update the metadata db (based on currently stored leaves): - const { treeHeight } = await metadataService.getTreeHeight(); - - const nodeIndex = utilsMT.leafIndexToNodeIndex(leafIndex, treeHeight); - - // construct an array of indices to query from the db: - const pathIndices = utilsMT.getPathIndices(nodeIndex); - logger.silly(`pathIndices to retreive: ${JSON.stringify(pathIndices, null, 2)}`); - - // get the actual nodes from the db: - const nodeService = new NodeService(db); - const nodes = await nodeService.getNodesByNodeIndices(pathIndices); - - // logger.debug(`${JSON.stringify(nodes, null, 2)}`); - - // Check whether some nodeIndices don't yet exist in the db. If they don't, we'll presume their values are zero, and add these to the 'nodes' before returning them. - // eslint-disable-next-line no-shadow - pathIndices.forEach((nodeIndex, index) => { - if (nodes[index] === undefined || nodes[index].nodeIndex !== pathIndices[index]) { - const node = { - value: config.ZERO, - nodeIndex, - }; - // insert the node into the nodes array: - nodes.splice(index, 0, node); - } - }); - - return nodes; -} - -/** -Calculate the siblingPath or 'witness path' for a given leaf. -@param {object} db - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy). This contains permissions to access the merkle tree's databases. -@param {integer} leafIndex - the index of the leaf for which we are computing the siblingPath -*/ -async function getSiblingPathByLeafIndex(db, leafIndex) { - logger.debug('src/merkle-tree-controller getSiblingPathByLeafIndex()'); - const metadataService = new MetadataService(db); - // update the metadata db (based on currently stored leaves): - const { treeHeight } = await metadataService.getTreeHeight(); - - const nodeIndex = utilsMT.leafIndexToNodeIndex(leafIndex, treeHeight); - - // construct an array of indices to query from the db: - const siblingPathIndices = utilsMT.getSiblingPathIndices(nodeIndex); - logger.silly(`siblingPathIndices to retreive: ${JSON.stringify(siblingPathIndices, null, 2)}`); - - // get the actual nodes from the db: - const nodeService = new NodeService(db); - const nodes = await nodeService.getNodesByNodeIndices(siblingPathIndices); - - // Check whether some nodeIndices don't yet exist in the db. If they don't, we'll presume their values are zero, and add these to the 'nodes' before returning them. - // eslint-disable-next-line no-shadow - siblingPathIndices.forEach((nodeIndex, index) => { - if (nodes[index] === undefined || nodes[index].nodeIndex !== siblingPathIndices[index]) { - const node = { - value: config.ZERO, - nodeIndex, - }; - // insert the node into the nodes array: - nodes.splice(index, 0, node); - } - }); - - return nodes; -} - -async function calculateRootFromFrontier(db, frontier, leafIndex) { - logger.debug('src/merkle-tree-controller calculateRootFromFrontier()'); - const metadataService = new MetadataService(db); - const { treeHeight } = await metadataService.getTreeHeight(); - const root = await utilsMT.calculateRootFromFrontier(frontier, leafIndex, treeHeight); - return root; -} - -const nodes = []; -let hashCount = 0; -async function updateNodes(node) { - logger.silly(`node ${node}`); - nodes.push(node); - hashCount += 1; - logger.silly(`hashCount, ${hashCount}`); - logger.silly(`numberOfHashes, ${this.numberOfHashes}`); - if (nodes.length === config.BULK_WRITE_BUFFER_SIZE) { - await this.nodeService.updateNodes(nodes); - nodes.length = 0; // empty the array to start again - } else if (hashCount === this.numberOfHashes) { - await this.nodeService.updateNodes(nodes); - nodes.length = 0; // empty the array to start again - hashCount = 0; // reset the count - } -} - -/** -Updates the entire tree based on the latest-stored leaves. -@param {object} db - an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy). This contains permissions to access the merkle tree's databases. -*/ -async function update(db) { - logger.debug('src/merkle-tree-controller update()'); - - const leafService = new LeafService(db); - const nodeService = new NodeService(db); - const metadataService = new MetadataService(db); - const historyService = new HistoryService(db); - - // update the metadata db (based on currently stored leaves): - let { latestLeaf } = (await updateLatestLeaf(db)) || {}; - - if (!latestLeaf) { - logger.info('There are no (reliable) leaves in the tree. Nothing to update.'); // this might also be triggered if there are no _reliable_ leaves in the tree; in which case everything should be refiltered: (TODO) - const metadata = await metadataService.getMetadata(); - return metadata; - } - - // get the latest recalculation metadata (to know how up-to-date the nodes of our tree actually are): - let { latestRecalculation } = (await metadataService.getLatestRecalculation()) || {}; - - const latestRecalculationLeafIndex = - latestRecalculation && latestRecalculation.leafIndex - ? Number(latestRecalculation.leafIndex) - : 0; - - const fromLeafIndex = latestRecalculationLeafIndex === 0 ? 0 : latestRecalculationLeafIndex + 1; - - const toLeafIndex = latestLeaf && latestLeaf.leafIndex ? Number(latestLeaf.leafIndex) : 0; - - const { treeHeight } = await metadataService.getTreeHeight(); - - // Check whether we're already up-to-date: - if (latestRecalculationLeafIndex < toLeafIndex || latestRecalculationLeafIndex === 0) { - // We're not up-to-date: - logger.info('The tree needs updating.'); - // Recalculate any nodes along the path from the new leaves to the root: - logger.info(`Updating the tree from leaf ${fromLeafIndex} to leaf ${toLeafIndex}`); - - const numberOfHashes = utilsMT.getNumberOfHashes(toLeafIndex, fromLeafIndex, treeHeight); - logger.debug(`${numberOfHashes} hashes are required to update the tree...`); - - let { frontier } = latestRecalculation; - const { root: oldRoot } = latestRecalculation; // we store the old root in history as well as the new root (the latter being used to look up the history). - frontier = frontier === undefined ? [] : frontier; - const leaves = await leafService.getLeavesByLeafIndexRange(fromLeafIndex, toLeafIndex); - const leafValues = leaves.map(leaf => leaf.value); - const currentLeafCount = fromLeafIndex; - - const historicFrontier = [...frontier]; // avoid mutation of frontier - const [root, newFrontier] = await utilsMT.updateNodes( - leafValues, - currentLeafCount, - frontier, - treeHeight, - updateNodes.bind({ nodeService, numberOfHashes }), - ); - - if (frontier.length !== treeHeight + 1 && treeHeight !== 32) { - newFrontier.length = treeHeight + 1; - } - - latestRecalculation = { - blockNumber: latestLeaf.blockNumber, - transactionHash: latestLeaf.transactionHash, - leafIndex: toLeafIndex, - root, - frontier: newFrontier, - }; - await metadataService.updateLatestRecalculation({ latestRecalculation }); - - // we also need to save the current state of the tree so that Optmistic - // blocks can be checked using Timber data, and optimistic rollbacks of - // the Timber database facilitated. We don't want to remember the new - // forntier, but the one that existed when the block was added. - const history = { - root, - oldRoot, - frontier: historicFrontier, - leafIndex: latestRecalculationLeafIndex, - currentLeafCount, - blockNumber: latestLeaf.blockNumber, - transactionHash: latestLeaf.transactionHash, - }; - await historyService.saveTreeHistory(history); - logger.debug(`Saved new Merkle tree history ${JSON.stringify(history, null, 2)}`); - - // update the metadata db (based on currently stored leaves): - ({ latestLeaf } = await updateLatestLeaf(db)); - } else { - logger.info('The tree is already up to date.'); - } - - const metadata = await metadataService.getMetadata(); - - return metadata; -} - -async function getTreeHistory(db, root) { - const historyService = new HistoryService(db); - return historyService.getTreeHistory(root); -} - -async function getTreeHistoryByCurrentLeafCount(db, currentLeafCount) { - const historyService = new HistoryService(db); - return historyService.getTreeHistoryByCurrentLeafCount(currentLeafCount); -} - -/** -This function rolls back the database to a time when it contained 'leafCount' -leaves and had the root 'root'. -It is triggered by reception of a Rollback event from the blockchain. -*/ -async function rollback(db, treeHeight, leafCount) { - logger.debug(`treeHeight is ${treeHeight}`); - logger.debug(`leafCount to roll back to is ${leafCount}`); - const historyService = new HistoryService(db); - const leafService = new LeafService(db); - const nodeService = new NodeService(db); - const metadataService = new MetadataService(db); - // before we do anything, make sure the DB is up to date - // await update(db); - // let's get the details of where we're going to rollback to - // const history = await historyService.getTreeHistory(root); - const history = await historyService.getTreeHistoryByCurrentLeafCount(leafCount); - logger.debug(`Found history for leafCount ${leafCount}, ${JSON.stringify(history, null, 2)}`); - // We'll actually roll back the metadata so that it's one update behind the - // new max leaf. Then we'll call update (after this function has run) and - // that will recompute the changed hashes in the tree, just as if we'd added - // a new leaf. We'll need the prior history so that we can do that reset of - // the metadata. - const priorHistory = await historyService.getTreeHistory(history.oldRoot); - logger.debug( - `Found priorHistory for leafCount ${leafCount}, ${JSON.stringify(priorHistory, null, 2)}`, - ); - - if (leafCount !== history.currentLeafCount) - throw new Error( - `Rollback event's leaf count (${leafCount}) and the historic record (${history.currentLeafCount}) do not match`, - ); - // Delete all of the nodes between the new highest-index leaf and the old - // highest index leaf (inclusive) up to their common root. This has - // the effect of removing non-zero nodes, which should no longer exist after - // rollback. - const oldMaxLeafIndex = await leafService.maxLeafIndex(); - const newMaxLeafIndex = history.leafIndex; - const newMaxLeaf = await leafService.getLeafByLeafIndex(newMaxLeafIndex); - // we reverse the arrays so that the leaf is element [0] that is similar to - // how the Frontier is arranged and a bit more convenient here. - const oldMaxPath = (await getPathByLeafIndex(db, oldMaxLeafIndex)).reverse(); - const newMaxPath = (await getPathByLeafIndex(db, newMaxLeafIndex)).reverse(); - const indicesOfNodesToDelete = []; - for (let i = 0; i < treeHeight; i++) { - if (newMaxPath[i].value === oldMaxPath[i].value) break; // common root reached - for (let j = newMaxPath[i].nodeIndex; j < oldMaxPath[i].nodeIndex + 1; j++) { - indicesOfNodesToDelete.push(j); - } - } - logger.debug(`Indices of nodes to delete are ${JSON.stringify(indicesOfNodesToDelete, null, 2)}`); - let response = await nodeService.deleteNodes(indicesOfNodesToDelete); - logger.debug(`Mongo response to node deletion ${JSON.stringify(response, null, 2)}`); - // add back the newMaxLeaf (this is the same behaviour as a NewLeaf event) - // because our reset of the Timber database will have deleted it. - // but note the special case of newMaxLeaf index == 0. This could indicate - // that there is one leaf in the tree or no leaves. For this reason we need - // to also check the leafCount. - if (Number(leafCount) !== 0) await leafService.insertLeaf(treeHeight, newMaxLeaf); - // revert the metadata so that it's consistent with the rollback and is in the - // state it would be if we'd just added a new leaf (the newMaxLeaf). - await metadataService.updateLatestLeaf({ - latestLeaf: { - blockNumber: history.blockNumber, - leafIndex: history.leafIndex, - }, - }); - logger.debug(`Reverting metadata to historic values ${JSON.stringify(priorHistory, null, 2)}`); - await metadataService.updateLatestRecalculation({ - latestRecalculation: { - blockNumber: priorHistory.blockNumber, - leafIndex: priorHistory.leafIndex, - root: priorHistory.oldRoot === ZERO ? null : priorHistory.oldRoot, // null is neater - frontier: priorHistory.frontier.map(f => (f === ZERO ? null : f)), - }, - }); - // delete the history which is now in a future that won't happen. The update - // of the db will re-write the priorHistory so we delete that too. In fact we - // need to delete all later histories because they're now causally - // disconnected. - response = await historyService.deleteTreeHistory(priorHistory.currentLeafCount); - logger.debug(`Mongo response to history deletion ${JSON.stringify(response, null, 2)}`); - logger.debug( - `metadata after rollback is ${JSON.stringify(await metadataService.getMetadata(), null, 2)}`, - ); - await update(db); // update to recalculate the hashes that now need to change because of the rollback. - logger.info('Rollback complete'); -} - -export default { - checkLeaves, - updateLatestLeaf, - getPathByLeafIndex, - getSiblingPathByLeafIndex, - calculateRootFromFrontier, - update, - getTreeHistory, - getTreeHistoryByCurrentLeafCount, - rollback, -}; diff --git a/timber/src/middleware/assign-db-connection.mjs b/timber/src/middleware/assign-db-connection.mjs deleted file mode 100644 index 78a9ec350..000000000 --- a/timber/src/middleware/assign-db-connection.mjs +++ /dev/null @@ -1,40 +0,0 @@ -import config from 'config'; -import adminDbConnection from '../db/common/adminDbConnection.mjs'; -import DB from '../db/mongodb/db.mjs'; -import logger from '../logger.mjs'; - -const { admin } = config.get('mongo'); - -export default async (req, res, next) => { - logger.debug('src/middleware/assign-db-connection'); - logger.silly( - `req.query: ${JSON.stringify(req.query, null, 2)}, req.body: ${JSON.stringify( - req.body, - null, - 2, - )}`, - ); - - try { - let contractName = req.body.contractName || req.query.contractName; - if (contractName === undefined) { - const contractNameTest = req.body[0].contractName; - if (contractNameTest === undefined) { - throw new Error('No contractName key provided in req.body.'); - } else { - contractName = contractNameTest; - } - } - const treeId = req.body.treeId || req.query.treeId; - logger.silly(`treeId: ${treeId}`); - req.user = {}; - // give all requesters admin privileges: - req.user.connection = adminDbConnection; - req.user.db = new DB(req.user.connection, admin, contractName, treeId); - - return next(); - } catch (err) { - logger.error(err.stack); - return next(err); - } -}; diff --git a/timber/src/middleware/index.mjs b/timber/src/middleware/index.mjs deleted file mode 100644 index cb7c6fd96..000000000 --- a/timber/src/middleware/index.mjs +++ /dev/null @@ -1,2 +0,0 @@ -export { default as assignDbConnection } from './assign-db-connection.mjs'; -export * from './response.mjs'; diff --git a/timber/src/middleware/response.mjs b/timber/src/middleware/response.mjs deleted file mode 100644 index 1abe085c4..000000000 --- a/timber/src/middleware/response.mjs +++ /dev/null @@ -1,43 +0,0 @@ -import logger from '../logger.mjs'; - -export function formatResponse(req, res, next) { - const { data } = res; - if (data === undefined) { - const err = new Error('Url Not Found'); - err.status = 404; - return next(err); - } - return res.status(200).send({ - error: null, - data, - }); -} - -export function formatError(err, req, res, next) { - logger.debug('src/middleware/response formatError()'); - logger.error(`error: ${JSON.stringify(err, null, 2)}`); - - next({ - code: err.code, - message: err.message, - [process.env.NODE_ENV !== 'production' ? 'errorStack' : undefined]: - process.env.NODE_ENV !== 'production' ? err.stack : undefined, - }); -} - -export function errorHandler(err, req, res, next) { - logger.debug('src/middleware/response errorHandler()'); - logger.error(`error: ${JSON.stringify(err, null, 2)}`); - - res.status(err.status || 500).send({ - error: err, - data: null, - }); - next(err); -} - -export function logError(err, req, res, next) { - logger.debug('src/middleware/response logError()'); - logger.error(`error: ${JSON.stringify(err, null, 2)}`); - next(err); -} diff --git a/timber/src/optimistic/process-calldata.mjs b/timber/src/optimistic/process-calldata.mjs deleted file mode 100644 index 870624484..000000000 --- a/timber/src/optimistic/process-calldata.mjs +++ /dev/null @@ -1,59 +0,0 @@ -/** -Function to retreive calldata associated with a blockchain event. -This is used, rather than re-emmiting the calldata in the event because it's -much cheaper, although the offchain part is more complex. -*/ -import config from 'config'; -import Web3 from '../web3.mjs'; -import logger from '../logger.mjs'; - -async function getProposeBlockCalldata(eventData) { - logger.debug(`Getting calldata, with eventData ${JSON.stringify(eventData, null, 2)}`); - const web3 = Web3.connection(); - const { transactionHash } = eventData; - const tx = await web3.eth.getTransaction(transactionHash); - logger.debug(`found transaction with hash ${transactionHash}`); - // Remove the '0x' and function signature to recove rhte abi bytecode - const abiBytecode = `0x${tx.input.slice(10)}`; - const typesArray = config.PROPOSE_BLOCK_TYPES; - const decoded = web3.eth.abi.decodeParameters(typesArray, abiBytecode); - const blockData = decoded['0']; - const transactionsData = decoded['1']; - const [leafCount, proposer, root, blockNumberL2, previousBlockHash] = blockData; - const block = { proposer, root, leafCount, blockNumberL2, previousBlockHash }; - - const transactions = transactionsData.map(t => { - const [ - value, - historicRootBlockNumberL2, - transactionType, - tokenType, - publicInputHash, - tokenId, - ercAddress, - recipientAddress, - commitments, - nullifiers, - compressedSecrets, - proof, - ] = t; - const transaction = { - value, - historicRootBlockNumberL2, - transactionType, - tokenType, - publicInputHash, - tokenId, - ercAddress, - recipientAddress, - commitments, - nullifiers, - compressedSecrets, - proof, - }; - return transaction; - }); - return { block, transactions }; -} - -export default getProposeBlockCalldata; diff --git a/timber/src/rest/deployer.mjs b/timber/src/rest/deployer.mjs deleted file mode 100644 index 9cd6226d1..000000000 --- a/timber/src/rest/deployer.mjs +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @module node.routes.js - * @author iAmMichaelConnor - * @desc gateway for querying contract details from some external contract deployment microservice. - */ - -import request from 'request'; -import config from 'config'; -import Web3 from '../web3.mjs'; -import logger from '../logger.mjs'; - -const web3 = Web3.connect(); - -/** -Gets an instance of a MerkleTree.sol contract interface from some external contract deployment microservice, a.k.a. 'deployer' -*/ -async function getContractInterface(contractName) { - logger.debug(`Calling getContractInterface(${contractName})`); - const url = `${config.deployer.host}:${config.deployer.port}`; - logger.debug(`url:, ${url}`); - return new Promise((resolve, reject) => { - const options = { - url: `${url}/contract/interface`, - method: 'GET', - json: true, - body: { contractName }, - }; - request(options, (err, res, body) => { - if (err) reject(err); - else resolve(body); - }); - }); -} - -/** -Gets the address of a deployed MerkleTree.sol contract from some external contract deployment microservice, a.k.a. 'deployer' -*/ -async function getContractAddress(contractName) { - logger.debug(`Calling getContractAddress(${contractName})`); - const url = `${config.deployer.host}:${config.deployer.port}`; - logger.debug(`url: ${url}`); - return new Promise((resolve, reject) => { - const options = { - url: `${url}/contract/address`, - method: 'GET', - json: true, - body: { contractName }, - }; - request(options, (err, res, body) => { - if (err) reject(err); - else resolve(body); - }); - }); -} - -/** -Gets MerkleTree.sol contract data from some external contract deployment microservice (a.k.a. 'deployer') and assembles a MerkleTree.sol contract instance -*/ -async function getContractInstance(contractName) { - try { - logger.debug(`Calling getContractInstance(${contractName})`); - const { contractAddress } = await getContractAddress(contractName); - logger.silly(`contractAddress, ${contractAddress}`); - const { contractInterface } = await getContractInterface(contractName); - logger.silly(`contractInterface ${JSON.stringify(contractInterface)}`); - const { abi } = contractInterface; - logger.silly(`abi, ${JSON.stringify(abi, null, 2)}`); - - const contractInstance = await new web3.eth.Contract(abi, contractAddress); - - logger.silly(`MerkleTree.sol contract instance: ${JSON.stringify(contractInstance, null, 2)}`); - if (typeof contractInstance === 'undefined') - throw new Error('Could not retrieve contractInstance'); - - return contractInstance; - } catch (err) { - throw new Error(err); - } -} - -export default { - getContractInstance, -}; diff --git a/timber/src/routes/index.mjs b/timber/src/routes/index.mjs deleted file mode 100644 index e7d2858ec..000000000 --- a/timber/src/routes/index.mjs +++ /dev/null @@ -1,4 +0,0 @@ -export { default as leafRoutes } from './leaf.routes.mjs'; -export { default as nodeRoutes } from './node.routes.mjs'; -export { default as metadataRoutes } from './metadata.routes.mjs'; -export { default as merkleTreeRoutes } from './merkle-tree.routes.mjs'; diff --git a/timber/src/routes/leaf.routes.mjs b/timber/src/routes/leaf.routes.mjs deleted file mode 100644 index 76a6641f6..000000000 --- a/timber/src/routes/leaf.routes.mjs +++ /dev/null @@ -1,264 +0,0 @@ -/** - * @module leaf.routes.js - * @author iAmMichaelConnor - * @desc leaf.routes.js gives api endpoints to access the functions of the merkle-tree microservice - */ - -import config from 'config'; -import { LeafService, MetadataService } from '../db/service/index.mjs'; -import merkleTreeController from '../merkle-tree-controller.mjs'; -import logger from '../logger.mjs'; -import { responseFunctions } from '../filter-controller.mjs'; -import DB from '../db/mongodb/db.mjs'; -import adminDbConnection from '../db/common/adminDbConnection.mjs'; - -const { admin } = config.get('mongo'); -/** - * Add a new leaf to the tree's 'nodes' db. - * req.body { - * contractName: '...', - * leaf: { - * value: '0xabc123..', - * nodeIndex: 12345678, // optional - can be calculated by mapper - * leafIndex: 1234, - * blockNumber: 60000000 - * } - * } - * @param {*} req - * @param {*} res - */ -async function insertLeaf(req, res, next) { - logger.debug('src/routes/leaf.routes insertLeaf()'); - logger.silly(`req.body: ${req.body}`); - try { - const { leaf } = req.body; - const metadataService = new MetadataService(req.user.db); - const leafService = new LeafService(req.user.db); - const { treeHeight } = await metadataService.getTreeHeight(); - - await leafService.insertLeaf(treeHeight, leaf); - - res.data = { message: 'inserted' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Get a leaf from the tree's 'nodes' db. - * req.params { leafIndex: 1234 } - * req.body { contractName: '...', leafIndex: 1234 } - * @param {*} req - * @param {*} res - */ -async function getLeafByLeafIndex(req, res, next) { - logger.debug('src/routes/leaf.routes getLeafByLeafIndex()'); - logger.silly( - `req.params: ${JSON.stringify(req.params, null, 2)}, req.body: ${JSON.stringify( - req.body, - null, - 2, - )}`, - ); - try { - const leafIndex = req.params.leafIndex || req.body.leafIndex || req.body.leafIndex; - const leafService = new LeafService(req.user.db); - res.data = await leafService.getLeafByLeafIndex(leafIndex); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get a leaf from the tree's 'nodes' db. - * req.body { - * contractName: '...', - * value: '0xabc1234' - * } - * @param {*} req - * @param {*} res - */ -async function getLeafByValue(req, res, next) { - logger.debug('src/routes/leaf.routes getLeafByValue()'); - logger.silly( - `req.query: ${JSON.stringify(req.query, null, 2)}, req.body: ${JSON.stringify( - req.body, - null, - 2, - )}`, - ); - try { - const value = req.body.value || req.query.value; - const leafService = new LeafService(req.user.db); - res.data = await leafService.getLeafByValue(value); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get many leaves from the tree's 'nodes' db. - * req.body { contractName: '...', leafIndices: [index0, index1, ..., indexn] } - * or - * req.body { contractName: '...', values: [value0, value1, ..., valuen] } - * or - * req.body { contractName: '...', minIndex: 1234, maxIndex: 5678 } - * @param {*} req - * @param {*} res - */ -async function getLeaves(req, res, next) { - logger.debug('src/routes/leaf.routes getLeaves()'); - logger.silly( - `req.query: ${JSON.stringify(req.query, null, 2)}, req.body: ${JSON.stringify( - req.body, - null, - 2, - )}`, - ); - try { - const leafService = new LeafService(req.user.db); - // some clients call get with data in the body. That's naughty but we handle it anyway - const leafIndices = req.body.leafIndices || req.query.leafIndices; - const values = req.body.values || req.query.values; - const minIndex = req.body.minIndex || req.query.minIndex; - const maxIndex = req.body.maxIndex || req.query.maxIndex; - - // not necessarily, not all of these destructurings will be possible - logger.silly(`leafIndices: ${JSON.stringify(leafIndices, null, 2)}`); - logger.silly(`values: ${JSON.stringify(values, null, 2)}`); - logger.silly(`minIndex: ${minIndex}`); - logger.silly(`maxIndex: ${maxIndex}`); - - if (leafIndices) { - res.data = await leafService.getLeavesByLeafIndices(leafIndices); - } else if (values) { - res.data = await leafService.getLeavesByValues(values); - } else if (minIndex || maxIndex) { - res.data = await leafService.getLeavesByLeafIndexRange(minIndex, maxIndex); - } else { - res.data = await leafService.getLeaves(); - } - - next(); - } catch (err) { - next(err); - } -} - -/** - * Add a new array of leaves to the tree's 'nodes' db. - * req.body { - * contractName: '...', - * leaves: [leafObject1, leafObject2,...] - * }; - * where a leafObject is of the form: - * { - * value: '0xabc123..', - * nodeIndex: 12345678, // optional - can be calculated by mapper - * leafIndex: 1234, - * blockNumber: 60000000, - * } - * @param {*} req - * @param {*} res - */ -async function insertLeaves(req, res, next) { - logger.debug('src/routes/leaf.routes insertLeaves()'); - logger.silly(`req.body: ${JSON.stringify(req.body, null, 2)}`); - try { - const metadataService = new MetadataService(req.user.db); - const leafService = new LeafService(req.user.db); - const { leaves } = req.body; - const { treeHeight } = await metadataService.getTreeHeight(); - - await leafService.insertLeaves(treeHeight, leaves); - - res.data = { message: 'inserted' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Check the leaves of the tree are all there. - * req.user.db (an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy)) is required, to access the user's db from within the merkleTreeController - * @param {*} req - * @param {*} res - { message: true } - */ -async function checkLeaves(req, res, next) { - const { db } = req.user; - - try { - const latestLeafDoc = await merkleTreeController.checkLeaves(db); - - res.data = latestLeafDoc; - next(); - } catch (err) { - next(err); - } -} - -/** - * Count the leaves in the tree's 'nodes' db. - * @param {*} req - * @param {*} res - */ -async function countLeaves(req, res, next) { - logger.debug('src/routes/leaf.routes countLeaves()'); - - try { - const leafService = new LeafService(req.user.db); - const leafCount = await leafService.countLeaves(); - res.data = { leafCount }; - next(); - } catch (err) { - next(err); - } -} - -async function replayEvent(req, res, next) { - logger.debug('src/routes/leaf.routes replayEvent()'); - logger.silly(`req.body: ${req.body}`); - try { - const { eventData, contractName } = req.body; - const { event } = eventData; - // eslint-disable-next-line prefer-destructuring - const treeId = config.contracts[contractName].treeId; - const connection = adminDbConnection; - const db = new DB(connection, admin, contractName, treeId); - const responseFunction = responseFunctions[event]; - const responseFunctionArgs = { db, contractName, event, treeId }; - await responseFunction({ eventData }, responseFunctionArgs); - res.data = { event }; - next(); - } catch (err) { - logger.info(err); - next(err); - } -} - -// initializing routes -export default router => { - // LEAF ROUTES - - router.route('/leaf').post(insertLeaf); - - router.get('/leaf/index/:leafIndex', getLeafByLeafIndex); - - router.route('/leaf/index').get(getLeafByLeafIndex); - router.route('/leaf/value').get(getLeafByValue); - - // LEAVES ROUTES - - router - .route('/leaves') - .get(getLeaves) // will decide within this function whether we're getting leaves by leafIndices or by a leafIndex range, or all leaves. - .post(insertLeaves); - - router.route('/leaves/check').get(checkLeaves); - router.route('/leaves/count').get(countLeaves); - router.route('/replayEvent').post(replayEvent); -}; diff --git a/timber/src/routes/merkle-tree.routes.mjs b/timber/src/routes/merkle-tree.routes.mjs deleted file mode 100644 index e481c3317..000000000 --- a/timber/src/routes/merkle-tree.routes.mjs +++ /dev/null @@ -1,239 +0,0 @@ -/** - * @module node.routes.js - * @author iAmMichaelConnor - * @desc merkle-tree.routes.js gives api endpoints to access the functions of the merkle-tree microservice - */ - -import contractController from '../contract-controller.mjs'; -import filterController from '../filter-controller.mjs'; -import merkleTreeController from '../merkle-tree-controller.mjs'; -import logger from '../logger.mjs'; - -const alreadyStarted = {}; // initialises as false -const alreadyStarting = {}; // initialises as false - -/** - * Updates the entire tree based on the latest-stored leaves. - * req.user.db (an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy)) is required, to access the user's db from within the merkleTreeController - * @param {*} req - * @param {*} res - returns the tree's metadata - */ -async function startEventFilter(req, res, next) { - logger.debug('src/routes/merkle-tree.routes startEventFilter()'); - - const { contractName, treeId, contractAddress } = req.body; // contractAddress & treeId are optional parameters. Address can instead be inferred by Timber in many cases. - const { db } = req.user; - - // TODO: if possible, make this easier to read and follow. Fewer 'if' statements. Perhaps use 'switch' statements instead? - try { - if (alreadyStarted[contractName] && (treeId === undefined || treeId === '')) { - res.data = { message: `filter already started for ${contractName}` }; - } else if (alreadyStarted[(contractName, treeId)]) { - res.data = { message: `filter already started for ${contractName}.${treeId}` }; - } else if (alreadyStarting[contractName] && (treeId === undefined || treeId === '')) { - res.data = { - message: `filter is already in the process of being started for ${contractName}`, - }; - } else if (alreadyStarting[(contractName, treeId)]) { - res.data = { - message: `filter is already in the process of being started for ${contractName}.${treeId}`, - }; - } else { - if (treeId === undefined || treeId === '') { - alreadyStarting[contractName] = true; - logger.info(`starting filter for ${contractName}`); - } else { - alreadyStarting[(contractName, treeId)] = true; - logger.info(`starting filter for ${contractName}.${treeId}`); - } - // get a web3 contractInstance we can work with: - const contractInstance = await contractController.instantiateContract( - db, - contractName, - contractAddress, - ); - - // start an event filter on this contractInstance: - const started = await filterController.start(db, contractName, contractInstance, treeId); - - if (treeId === undefined || treeId === '') { - alreadyStarted[contractName] = started; // true/false - alreadyStarting[contractName] = false; - } else { - alreadyStarted[(contractName, treeId)] = started; // true/false - alreadyStarting[(contractName, treeId)] = false; - } - res.data = { message: 'filter started' }; - } - next(); - } catch (err) { - alreadyStarting[contractName] = false; - next(err); - } -} - -/** - * Get the siblingPath or 'witness path' for a given leaf. - * req.user.db (an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy)) is required, to access the user's db from within the merkleTreeController - * req.params { - * leafIndex: 1234, - * } - * @param {*} req - * @param {*} res - */ -async function getSiblingPathByLeafIndex(req, res, next) { - logger.debug('src/routes/merkle-tree.routes getSiblingPathByLeafIndex()'); - logger.silly(`req.params: ${JSON.stringify(req.params, null, 2)}`); - - const { db } = req.user; - let { leafIndex } = req.params; - leafIndex = Number(leafIndex); // force to number - - try { - // first update all nodes in the DB to be in line with the latest-known leaf: - // await merkleTreeController.update(db); - - // get the sibling path: - const siblingPath = await merkleTreeController.getSiblingPathByLeafIndex(db, leafIndex); - - res.data = siblingPath; - next(); - } catch (err) { - next(err); - } -} - -/** - * Get the path for a given leaf. - * req.user.db (an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy)) is required, to access the user's db from within the merkleTreeController - * req.params { - * leafIndex: 1234, - * } - * @param {*} req - * @param {*} res - */ -async function getPathByLeafIndex(req, res, next) { - logger.debug('src/routes/merkle-tree.routes getPathByLeafIndex()'); - logger.silly(`req.params: ${JSON.stringify(req.params, null, 2)}`); - - const { db } = req.user; - let { leafIndex } = req.params; - leafIndex = Number(leafIndex); // force to number - - try { - // first update all nodes in the DB to be in line with the latest-known leaf: - // await merkleTreeController.update(db); - - // get the path: - const path = await merkleTreeController.getPathByLeafIndex(db, leafIndex); - - res.data = path; - next(); - } catch (err) { - next(err); - } -} - -/** - * Updates the entire tree based on the latest-stored leaves. - * req.user.db (an instance of mongoose.createConnection (a 'Connection' instance in mongoose terminoligy)) is required, to access the user's db from within the merkleTreeController - * @param {*} req - * @param {*} res - returns the tree's metadata - @deprecated There should be no reason to call this as newLea(f|ves) events - cause an update. - */ -async function update(req, res, next) { - logger.debug('src/routes/merkle-tree.routes update()'); - - const { db } = req.user; - - try { - const metadata = await merkleTreeController.update(db); - - res.data = metadata; - next(); - } catch (err) { - next(err); - } -} - -/** - * Special function which calculates the root from a given frontier and the - * corresponding leafIndex of the right-most leaf at the time the frontier was * solidified. - * req.params { - * frontier: [0x123abc, 0x234bcd, ... ], - * leafIndex: 1234, - * } - * @param {*} req - * @param {*} res - returns the root - */ -async function calculateRootFromFrontier(req, res, next) { - logger.debug('src/routes/merkle-tree.routes calculateRootFromFrontier()'); - - const { db } = req.user; - const { frontier } = req.body; - let { leafIndex } = req.body; - leafIndex = Number(leafIndex); // force to number - - try { - const root = await merkleTreeController.calculateRootFromFrontier(db, frontier, leafIndex); - - res.data = { root }; - next(); - } catch (err) { - next(err); - } -} - -async function getTreeHistory(req, res, next) { - const { db } = req.user; - const { root } = req.params; - try { - // see if the historic root is in the dB and return it if it is - await filterController.waitForUpdatesToComplete(); - const history = await merkleTreeController.getTreeHistory(db, root); - // if (history === null) { - // it's possible that an update is running - // await merkleTreeController.update(db); - // history = await merkleTreeController.getTreeHistory(db, root); - // } - logger.debug(`Read history collection and retrieved ${JSON.stringify(history, null, 2)}`); - res.data = history; - next(); - } catch (err) { - next(err); - } -} - -async function getTreeHistoryByCurrentLeafCount(req, res, next) { - const { db } = req.user; - const { currentLeafCount } = req.params; - try { - // see if the historic root is in the dB and return it if it is - let history = await merkleTreeController.getTreeHistoryByCurrentLeafCount(db, currentLeafCount); - if (history === null) { - // if not, update the db with the most recent events and try again - await merkleTreeController.update(db); - history = await merkleTreeController.getTreeHistoryByCurrentLeafCount(db, currentLeafCount); - } - logger.debug(`Read history collection and retrieved ${JSON.stringify(history, null, 2)}`); - res.data = history; - next(); - } catch (err) { - next(err); - } -} - -// initializing routes -export default router => { - router.route('/start').post(startEventFilter); - - router.route('/update').patch(update); - - router.get('/calculate-root-from-frontier', calculateRootFromFrontier); - - router.get('/siblingPath/:leafIndex', getSiblingPathByLeafIndex); - router.get('/path/:leafIndex', getPathByLeafIndex); - router.get('/tree-history/root/:root', getTreeHistory); - router.get('/tree-history/currentLeafCount/:currentLeafCount', getTreeHistoryByCurrentLeafCount); -}; diff --git a/timber/src/routes/metadata.routes.mjs b/timber/src/routes/metadata.routes.mjs deleted file mode 100644 index 208542b86..000000000 --- a/timber/src/routes/metadata.routes.mjs +++ /dev/null @@ -1,233 +0,0 @@ -/** - * @module metadata.routes.js - * @author iAmMichaelConnor - * @desc tree.routes.js gives api endpoints to access the functions of the merkle-tree microservice - */ - -import { MetadataService } from '../db/service/index.mjs'; -import merkleTreeController from '../merkle-tree-controller.mjs'; - -/** - * Add the relevant contract address to the tree's db. - * req.body { - * contractAddress: '0xabc123..', - * } - * @param {*} req - * @param {*} res - */ -async function insertContractAddress(req, res, next) { - try { - const { db } = req.user; - const metadataService = new MetadataService(db); - await metadataService.insertContractAddress(req.body); - res.data = { message: 'inserted' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Add the relevant contract address to the tree's db. - * req.body { - * contractName: '...', - * contractAddress: '0xabc123..', - * } - * @param {*} req - * @param {*} res - */ -async function insertContractInterface(req, res, next) { - try { - const { db } = req.user; - // const contractName = req.body.contractName; - // const { contractInterface } = req.body; - // const path = `../../build/contracts/${contractName}.json`; - - const metadataService = new MetadataService(db); - await metadataService.insertContractInterface(req.body); - res.data = { message: 'inserted' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Add the relevant height to the tree's db. - * req.body { - * contractName: '...', - * treeHeight: 32, - * } - * @param {*} req - * @param {*} res - */ -async function insertTreeHeight(req, res, next) { - try { - const { db } = req.user; - const metadataService = new MetadataService(db); - await metadataService.insertTreeHeight(req.body); - res.data = { message: 'inserted' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Update the latestLeaf metadata in the tree's db. - * req.body { - * contractName: '...', - * latestLeaf: {} // a latestLeaf object - * } - * @param {*} req - * @param {*} res - */ -async function updateLatestLeaf(req, res, next) { - try { - const { db } = req.user; - await merkleTreeController.updateLatestLeaf(db); - res.data = { message: 'updated' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Update the latestRecalculation metadata in the tree's db. - * req.body { - * contractName: '...', - * latestRecalculation: {} // a latestRecalculation object - * } - * @param {*} req - * @param {*} res - */ -async function updateLatestRecalculation(req, res, next) { - const { db } = req.user; - const metadataService = new MetadataService(db); - try { - await metadataService.updateLatestRecalculation(req.body); - res.data = { message: 'updated' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Get all tree metadata from the tree's 'metadata' db. - * @param {*} req - * @param {*} res - */ -async function getMetadata(req, res, next) { - try { - const { db } = req.user; - const metadataService = new MetadataService(db); - res.data = await metadataService.getMetadata(); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get the contract address from the tree's 'metadata' db. - * @param {*} req - * @param {*} res - */ -async function getContractAddress(req, res, next) { - try { - const { db } = req.user; - const metadataService = new MetadataService(db); - res.data = await metadataService.getContractAddress(); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get the contract interface from the tree's 'metadata' db. - * @param {*} req - * @param {*} res - */ -async function getContractInterface(req, res, next) { - try { - const { db } = req.user; - const metadataService = new MetadataService(db); - res.data = await metadataService.getContractInterface(); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get the tree height from the tree's 'metadata' db. - * @param {*} req - * @param {*} res - */ -async function getTreeHeight(req, res, next) { - try { - const { db } = req.user; - const metadataService = new MetadataService(db); - res.data = await metadataService.getTreeHeight(); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get the latestRecalculation tree metadata from the tree's 'metadata' db. - * @param {*} req - * @param {*} res - */ -async function getLatestRecalculation(req, res, next) { - try { - const { db } = req.user; - const metadataService = new MetadataService(db); - res.data = await metadataService.getLatestRecalculation(); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get the latestLeaf tree metadata from the tree's 'tree' db. - * @param {*} req - * @param {*} res - */ -async function getLatestLeaf(req, res, next) { - try { - const { db } = req.user; - res.data = await merkleTreeController.updateLatestLeaf(db); - next(); - } catch (err) { - next(err); - } -} - -// initializing routes -export default router => { - // NODE ROUTES - - router.route('/metadata').get(getMetadata); - - router.route('/metadata/contractAddress').get(getContractAddress).post(insertContractAddress); - - router - .route('/metadata/contractInterface') - .get(getContractInterface) - .post(insertContractInterface); - - router.route('/metadata/treeHeight').get(getTreeHeight).post(insertTreeHeight); - - router.route('/metadata/latestLeaf').get(getLatestLeaf).patch(updateLatestLeaf); - - router - .route('/metadata/latestRecalculation') - .get(getLatestRecalculation) - .patch(updateLatestRecalculation); -}; diff --git a/timber/src/routes/node.routes.mjs b/timber/src/routes/node.routes.mjs deleted file mode 100644 index fcf9e95ec..000000000 --- a/timber/src/routes/node.routes.mjs +++ /dev/null @@ -1,234 +0,0 @@ -/** - * @module node.routes.js - * @author iAmMichaelConnor - * @desc node.routes.js gives api endpoints to access the functions of the merkle-tree microservice - */ - -import { NodeService } from '../db/service/index.mjs'; -import logger from '../logger.mjs'; - -/** - * Add a new node to the tree's 'nodes' db. - * req.body { - * contractName: '...', - * node: { - * value: '0xabc123..', - * nodeIndex: 12345678, - * } - * } - * @param {*} req - * @param {*} res - */ -async function insertNode(req, res, next) { - try { - const { node } = req.body; - const nodeService = new NodeService(req.user.db); - await nodeService.insertNode(node); - res.data = { message: 'inserted' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Get a node from the tree's 'nodes' db. - * req.params { nodeIndex: 1234 } - * req.body { contractName: '...', nodeIndex: 1234 } - * @param {*} req - * @param {*} res - */ -async function getNodeByNodeIndex(req, res, next) { - try { - const nodeIndex = req.params.nodeIndex || req.body.nodeIndex; - const nodeService = new NodeService(req.user.db); - res.data = await nodeService.getNodeByNodeIndex(nodeIndex); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get a node from the tree's 'nodes' db. - * req.body { contractName: '...', value: '0xabc1234' } - * @param {*} req - * @param {*} res - */ -async function getNodeByValue(req, res, next) { - try { - const value = req.body.value || req.query.value; - const nodeService = new NodeService(req.user.db); - res.data = await nodeService.getNodeByValue(value); - next(); - } catch (err) { - next(err); - } -} - -/** - * Get many nodes from the tree's 'nodes' db. - * req.body { - * contractName: '...', - * treeId: '...', // optional - * nodeIndices: [index0, index1, ..., indexn] - * } - * or - * req.body { - * contractName: '...', - * treeId: '...', // optional, - * values: [value0, value1, ..., valuen] - * } - * or - * req.body { - * contractName: '...', - * treeId: '...', // optional - * minIndex: 1234, - * maxIndex: 5678 - * } - * @param {*} req - * @param {*} res - */ -async function getNodes(req, res, next) { - try { - const nodeService = new NodeService(req.user.db); - - const nodeIndices = req.body.nodeIndices || req.query.nodeIndices; - const values = req.body.values || req.query.values; - const minIndex = req.body.minIndex || req.query.minIndex; - const maxIndex = req.body.maxIndex || req.query.maxIndex; - // necessarily, not all of these deconstructions will be possible - - if (nodeIndices) { - res.data = await nodeService.getNodesByNodeIndices(nodeIndices); - } else if (values) { - res.data = await nodeService.getNodesByValues(values); - } else if (minIndex || maxIndex) { - res.data = await nodeService.getNodesByNodeIndexRange(minIndex, maxIndex); - } else { - res.data = await nodeService.getNodes(); - } - - next(); - } catch (err) { - next(err); - } -} - -/** - * Update a node in the db. - * req.params: { nodeIndex } - * req.body: { - * contractName: '...', - * treeId: '...', // optional - * node: { - * value: '0xabc123..', - * nodeIndex: 12345678, - * } - * } - * @param {*} req - * @param {*} res - */ -async function updateNodeByNodeIndex(req, res, next) { - const nodeIndex = req.params.nodeIndex || req.body.node.nodeIndex; - const nodeService = new NodeService(req.user.db); - try { - await nodeService.updateNodeByNodeIndex(nodeIndex, req.body); - res.data = { message: 'updated' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Update many nodes in the db. - * req.body { - * contractName: '...', - * treeId: '...', // optional - * nodes: { - * [ - * { - * value: '0xabc123..', - * nodeIndex: 12345678, - * }, - * { - * value: '0xabc123..', - * nodeIndex: 12345678, - * } - * ] - * } - * } - * @param {*} req - * @param {*} res - */ -async function updateNodes(req, res, next) { - try { - const { nodes } = req.body; - const nodeService = new NodeService(req.user.db); - await nodeService.updateNodes(nodes); - res.data = { message: 'updated' }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Count the nodes in the tree's 'nodes' db. - * @param {*} req - * @param {*} res - */ -async function countNodes(req, res, next) { - logger.debug('src/routes/leaf.routes countLeaves()'); - - try { - const nodeService = new NodeService(req.user.db); - const nodeCount = await nodeService.countNodes(); - res.data = { nodeCount }; - next(); - } catch (err) { - next(err); - } -} - -/** - * Get the root of the tree from the tree's 'nodes' db. - * @param {*} req - * @param {*} res - */ -async function getRoot(req, res, next) { - try { - const nodeService = new NodeService(req.user.db); - res.data = await nodeService.getRoot(); - next(); - } catch (err) { - next(err); - } -} - -// initializing routes -export default router => { - // NODE ROUTES - - router.route('/node').post(insertNode); - - router.route('/node/index/:nodeIndex').get(getNodeByNodeIndex).patch(updateNodeByNodeIndex); - - router.route('/node/index').get(getNodeByNodeIndex).patch(updateNodeByNodeIndex); - - router.route('/node/value').get(getNodeByValue); - - // NODES ROUTES - - router - .route('/nodes') - .get(getNodes) // will decide within this function whether we're getting nodes by nodeIndices or by a nodeIndex range, or all nodes. - .patch(updateNodes); - - router.route('/nodes/count').get(countNodes); - - // ROOT ROUTES - - router.route('/root').get(getRoot); -}; diff --git a/timber/src/solc-versions-list.mjs b/timber/src/solc-versions-list.mjs deleted file mode 100644 index 2c13f93cd..000000000 --- a/timber/src/solc-versions-list.mjs +++ /dev/null @@ -1,1000 +0,0 @@ -// https://github.com/ethereum/solc-bin -// https://github.com/ethereum/solc-bin/blob/gh-pages/bin/list.js - -const soljsonSources = [ - 'soljson-v0.6.2+commit.bacdbe57.js', - 'soljson-v0.6.2-nightly.2020.1.27+commit.1bdb409b.js', - 'soljson-v0.6.2-nightly.2020.1.23+commit.3add37a2.js', - 'soljson-v0.6.2-nightly.2020.1.22+commit.641bb815.js', - 'soljson-v0.6.2-nightly.2020.1.20+commit.470c19eb.js', - 'soljson-v0.6.2-nightly.2020.1.17+commit.92908f52.js', - 'soljson-v0.6.2-nightly.2020.1.16+commit.3d4a2219.js', - 'soljson-v0.6.2-nightly.2020.1.15+commit.9d9a7ebe.js', - 'soljson-v0.6.2-nightly.2020.1.14+commit.6dbadf69.js', - 'soljson-v0.6.2-nightly.2020.1.13+commit.408458b7.js', - 'soljson-v0.6.2-nightly.2020.1.10+commit.d577a768.js', - 'soljson-v0.6.2-nightly.2020.1.9+commit.17158995.js', - 'soljson-v0.6.2-nightly.2020.1.8+commit.12b52ae6.js', - 'soljson-v0.6.1+commit.e6f7d5a4.js', - 'soljson-v0.6.1-nightly.2020.1.7+commit.8385256b.js', - 'soljson-v0.6.1-nightly.2020.1.6+commit.20cf9d9f.js', - 'soljson-v0.6.1-nightly.2020.1.3+commit.943af71d.js', - 'soljson-v0.6.1-nightly.2020.1.2+commit.d082b9b8.js', - 'soljson-v0.6.1-nightly.2019.12.20+commit.ece6463f.js', - 'soljson-v0.6.1-nightly.2019.12.19+commit.d420fe37.js', - 'soljson-v0.6.1-nightly.2019.12.18+commit.9a1cc027.js', - 'soljson-v0.6.0+commit.26b70077.js', - 'soljson-v0.6.0-nightly.2019.12.17+commit.d13438ee.js', - 'soljson-v0.6.0-nightly.2019.12.16+commit.7390b5b5.js', - 'soljson-v0.6.0-nightly.2019.12.14+commit.1c01c69e.js', - 'soljson-v0.6.0-nightly.2019.12.13+commit.9ddd5042.js', - 'soljson-v0.6.0-nightly.2019.12.12+commit.104a8c59.js', - 'soljson-v0.6.0-nightly.2019.12.11+commit.7247e72d.js', - 'soljson-v0.6.0-nightly.2019.12.10+commit.7244aa01.js', - 'soljson-v0.5.16+commit.9c3226ce.js', - 'soljson-v0.5.15+commit.6a57276f.js', - 'soljson-v0.5.14+commit.1f1aaa4.js', - 'soljson-v0.5.14-nightly.2019.12.10+commit.45aa7a88.js', - 'soljson-v0.5.14-nightly.2019.12.9+commit.d6667560.js', - 'soljson-v0.5.14-nightly.2019.12.5+commit.d2e3933d.js', - 'soljson-v0.5.14-nightly.2019.12.4+commit.2a1b6f55.js', - 'soljson-v0.5.14-nightly.2019.11.30+commit.4775af73.js', - 'soljson-v0.5.14-nightly.2019.11.29+commit.7b038dbd.js', - 'soljson-v0.5.14-nightly.2019.11.28+commit.40d9744b.js', - 'soljson-v0.5.14-nightly.2019.11.27+commit.87943bf4.js', - 'soljson-v0.5.14-nightly.2019.11.26+commit.200a92b4.js', - 'soljson-v0.5.14-nightly.2019.11.25+commit.c4622774.js', - 'soljson-v0.5.14-nightly.2019.11.21+commit.9eac460c.js', - 'soljson-v0.5.14-nightly.2019.11.20+commit.7535039f.js', - 'soljson-v0.5.14-nightly.2019.11.19+commit.e383b2bb.js', - 'soljson-v0.5.14-nightly.2019.11.18+commit.79af19db.js', - 'soljson-v0.5.14-nightly.2019.11.15+commit.6a993152.js', - 'soljson-v0.5.14-nightly.2019.11.14+commit.3e04fd6e.js', - 'soljson-v0.5.13+commit.5b0b510c.js', - 'soljson-v0.5.13-nightly.2019.11.14+commit.d1c6ab8a.js', - 'soljson-v0.5.13-nightly.2019.11.13+commit.6bef3071.js', - 'soljson-v0.5.13-nightly.2019.11.12+commit.52a9de83.js', - 'soljson-v0.5.13-nightly.2019.11.11+commit.7c7cca5f.js', - 'soljson-v0.5.13-nightly.2019.11.10+commit.a5f0422d.js', - 'soljson-v0.5.13-nightly.2019.11.8+commit.78be9385.js', - 'soljson-v0.5.13-nightly.2019.11.7+commit.37c6ab4c.js', - 'soljson-v0.5.13-nightly.2019.11.6+commit.56a3abcd.js', - 'soljson-v0.5.13-nightly.2019.11.5+commit.9bec5334.js', - 'soljson-v0.5.13-nightly.2019.11.4+commit.26c6a1fc.js', - 'soljson-v0.5.13-nightly.2019.11.1+commit.73954f16.js', - 'soljson-v0.5.13-nightly.2019.10.31+commit.d932f2d0.js', - 'soljson-v0.5.13-nightly.2019.10.29+commit.5d906cd5.js', - 'soljson-v0.5.13-nightly.2019.10.28+commit.9eb08c0c.js', - 'soljson-v0.5.13-nightly.2019.10.25+commit.302a51a5.js', - 'soljson-v0.5.13-nightly.2019.10.24+commit.15e39f7d.js', - 'soljson-v0.5.13-nightly.2019.10.23+commit.e56d1aa5.js', - 'soljson-v0.5.13-nightly.2019.10.22+commit.eca2b9bd.js', - 'soljson-v0.5.13-nightly.2019.10.18+commit.d5b2f347.js', - 'soljson-v0.5.13-nightly.2019.10.17+commit.5ea1d90f.js', - 'soljson-v0.5.13-nightly.2019.10.16+commit.9ec8bcda.js', - 'soljson-v0.5.13-nightly.2019.10.15+commit.83bb1515.js', - 'soljson-v0.5.13-nightly.2019.10.4+commit.6cbcc379.js', - 'soljson-v0.5.13-nightly.2019.10.2+commit.2d150b65.js', - 'soljson-v0.5.13-nightly.2019.10.1+commit.74d2b228.js', - 'soljson-v0.5.12+commit.7709ece9.js', - 'soljson-v0.5.12-nightly.2019.10.1+commit.cbdc3bc1.js', - 'soljson-v0.5.12-nightly.2019.9.30+commit.88476475.js', - 'soljson-v0.5.12-nightly.2019.9.24+commit.973e4ca9.js', - 'soljson-v0.5.12-nightly.2019.9.23+commit.c4208a6a.js', - 'soljson-v0.5.12-nightly.2019.9.19+commit.478eb1e.js', - 'soljson-v0.5.12-nightly.2019.9.17+commit.58f0f9db.js', - 'soljson-v0.5.12-nightly.2019.9.16+commit.34a84f3a.js', - 'soljson-v0.5.12-nightly.2019.9.13+commit.5d58c43a.js', - 'soljson-v0.5.12-nightly.2019.9.12+commit.b747c267.js', - 'soljson-v0.5.12-nightly.2019.9.11+commit.5063e537.js', - 'soljson-v0.5.12-nightly.2019.9.10+commit.4452a9b6.js', - 'soljson-v0.5.12-nightly.2019.9.9+commit.f5e976ce.js', - 'soljson-v0.5.12-nightly.2019.9.6+commit.7e80fceb.js', - 'soljson-v0.5.12-nightly.2019.9.5+commit.96980d0b.js', - 'soljson-v0.5.12-nightly.2019.9.4+commit.c5fbf23f.js', - 'soljson-v0.5.12-nightly.2019.9.3+commit.d1831b15.js', - 'soljson-v0.5.12-nightly.2019.9.2+commit.3c963eb0.js', - 'soljson-v0.5.12-nightly.2019.8.29+commit.459aed90.js', - 'soljson-v0.5.12-nightly.2019.8.28+commit.e74b63b6.js', - 'soljson-v0.5.12-nightly.2019.8.26+commit.e1bb4b9f.js', - 'soljson-v0.5.12-nightly.2019.8.24+commit.bb104546.js', - 'soljson-v0.5.12-nightly.2019.8.23+commit.b5048bd6.js', - 'soljson-v0.5.12-nightly.2019.8.19+commit.a39d26f3.js', - 'soljson-v0.5.12-nightly.2019.8.16+commit.58bbd39.js', - 'soljson-v0.5.12-nightly.2019.8.15+commit.2508cbc1.js', - 'soljson-v0.5.12-nightly.2019.8.14+commit.fb8137df.js', - 'soljson-v0.5.12-nightly.2019.8.13+commit.a6cbc3b8.js', - 'soljson-v0.5.11+commit.c082d0b4.js', - 'soljson-v0.5.11-nightly.2019.8.12+commit.b285e086.js', - 'soljson-v0.5.11-nightly.2019.8.10+commit.f5f2bbb2.js', - 'soljson-v0.5.11-nightly.2019.8.9+commit.682a3ece.js', - 'soljson-v0.5.11-nightly.2019.8.8+commit.16efcfdb.js', - 'soljson-v0.5.11-nightly.2019.8.7+commit.6166dc8e.js', - 'soljson-v0.5.11-nightly.2019.8.6+commit.cd563e52.js', - 'soljson-v0.5.11-nightly.2019.8.5+commit.29d47d5c.js', - 'soljson-v0.5.11-nightly.2019.8.2+commit.967ee944.js', - 'soljson-v0.5.11-nightly.2019.8.1+commit.aa87a607.js', - 'soljson-v0.5.11-nightly.2019.7.31+commit.32e6e356.js', - 'soljson-v0.5.11-nightly.2019.7.30+commit.92e62f1.js', - 'soljson-v0.5.11-nightly.2019.7.29+commit.2fdc07c5.js', - 'soljson-v0.5.11-nightly.2019.7.25+commit.4f7fec69.js', - 'soljson-v0.5.11-nightly.2019.7.23+commit.14699340.js', - 'soljson-v0.5.11-nightly.2019.7.22+commit.535553b5.js', - 'soljson-v0.5.11-nightly.2019.7.19+commit.508cf66d.js', - 'soljson-v0.5.11-nightly.2019.7.18+commit.1d673a3b.js', - 'soljson-v0.5.11-nightly.2019.7.17+commit.4fa78004.js', - 'soljson-v0.5.11-nightly.2019.7.16+commit.a5a7983a.js', - 'soljson-v0.5.11-nightly.2019.7.11+commit.88477bdb.js', - 'soljson-v0.5.11-nightly.2019.7.10+commit.ba922e76.js', - 'soljson-v0.5.11-nightly.2019.7.9+commit.8d006d20.js', - 'soljson-v0.5.11-nightly.2019.7.8+commit.25928767.js', - 'soljson-v0.5.11-nightly.2019.7.4+commit.3b2ebba4.js', - 'soljson-v0.5.11-nightly.2019.7.3+commit.c3c8bc09.js', - 'soljson-v0.5.11-nightly.2019.7.2+commit.6d01d15.js', - 'soljson-v0.5.11-nightly.2019.7.1+commit.b8dbf7d2.js', - 'soljson-v0.5.11-nightly.2019.6.27+commit.3597de35.js', - 'soljson-v0.5.11-nightly.2019.6.26+commit.b4a0a793.js', - 'soljson-v0.5.11-nightly.2019.6.25+commit.1cc84753.js', - 'soljson-v0.5.10+commit.5a6ea5b1.js', - 'soljson-v0.5.10-nightly.2019.6.25+commit.92529068.js', - 'soljson-v0.5.10-nightly.2019.6.24+commit.eb5b8298.js', - 'soljson-v0.5.10-nightly.2019.6.20+commit.96e3fcd.js', - 'soljson-v0.5.10-nightly.2019.6.19+commit.53f26d97.js', - 'soljson-v0.5.10-nightly.2019.6.18+commit.b6695071.js', - 'soljson-v0.5.10-nightly.2019.6.17+commit.9c5dc63e.js', - 'soljson-v0.5.10-nightly.2019.6.14+commit.4aa0c9e0.js', - 'soljson-v0.5.10-nightly.2019.6.13+commit.62bd7032.js', - 'soljson-v0.5.10-nightly.2019.6.12+commit.502d22a2.js', - 'soljson-v0.5.10-nightly.2019.6.11+commit.bd1f65d6.js', - 'soljson-v0.5.10-nightly.2019.6.7+commit.dc085bb8.js', - 'soljson-v0.5.10-nightly.2019.6.6+commit.fc35c139.js', - 'soljson-v0.5.10-nightly.2019.6.5+commit.3a331639.js', - 'soljson-v0.5.10-nightly.2019.6.4+commit.95e6b2e4.js', - 'soljson-v0.5.10-nightly.2019.5.30+commit.dd04a35c.js', - 'soljson-v0.5.10-nightly.2019.5.29+commit.c9e2d388.js', - 'soljson-v0.5.10-nightly.2019.5.28+commit.ff8898b8.js', - 'soljson-v0.5.9+commit.e560f70d.js', - 'soljson-v0.5.9-nightly.2019.5.28+commit.1b6b680.js', - 'soljson-v0.5.9-nightly.2019.5.27+commit.c14279fc.js', - 'soljson-v0.5.9-nightly.2019.5.24+commit.2a2cea08.js', - 'soljson-v0.5.9-nightly.2019.5.23+commit.7cf51876.js', - 'soljson-v0.5.9-nightly.2019.5.22+commit.f06582f9.js', - 'soljson-v0.5.9-nightly.2019.5.21+commit.e132d07.js', - 'soljson-v0.5.9-nightly.2019.5.20+commit.731abd3.js', - 'soljson-v0.5.9-nightly.2019.5.17+commit.88e9fbe6.js', - 'soljson-v0.5.9-nightly.2019.5.16+commit.46d6f395.js', - 'soljson-v0.5.9-nightly.2019.5.15+commit.a10501bb.js', - 'soljson-v0.5.9-nightly.2019.5.14+commit.563aec1d.js', - 'soljson-v0.5.9-nightly.2019.5.13+commit.a28b6224.js', - 'soljson-v0.5.9-nightly.2019.5.10+commit.661b08e1.js', - 'soljson-v0.5.9-nightly.2019.5.9+commit.8f2c8daf.js', - 'soljson-v0.5.9-nightly.2019.5.8+commit.97f16421.js', - 'soljson-v0.5.9-nightly.2019.5.7+commit.a21f8a0b.js', - 'soljson-v0.5.9-nightly.2019.5.6+commit.dee1c110.js', - 'soljson-v0.5.9-nightly.2019.5.2+commit.90f2fe6f.js', - 'soljson-v0.5.9-nightly.2019.4.30+commit.b6bcd8a1.js', - 'soljson-v0.5.8+commit.23d335f2.js', - 'soljson-v0.5.8-nightly.2019.4.30+commit.dc461b9.js', - 'soljson-v0.5.8-nightly.2019.4.29+commit.578d6180.js', - 'soljson-v0.5.8-nightly.2019.4.25+commit.eea425a3.js', - 'soljson-v0.5.8-nightly.2019.4.24+commit.f124bace.js', - 'soljson-v0.5.8-nightly.2019.4.23+commit.13518820.js', - 'soljson-v0.5.8-nightly.2019.4.18+commit.fce19bde.js', - 'soljson-v0.5.8-nightly.2019.4.17+commit.1feefa1c.js', - 'soljson-v0.5.8-nightly.2019.4.16+commit.a61931c5.js', - 'soljson-v0.5.8-nightly.2019.4.15+commit.e4e786a9.js', - 'soljson-v0.5.8-nightly.2019.4.14+commit.6c68904f.js', - 'soljson-v0.5.8-nightly.2019.4.12+commit.31abeb99.js', - 'soljson-v0.5.8-nightly.2019.4.11+commit.e97d4b4a.js', - 'soljson-v0.5.8-nightly.2019.4.10+commit.9eaaf42c.js', - 'soljson-v0.5.8-nightly.2019.4.5+commit.9ef84df4.js', - 'soljson-v0.5.8-nightly.2019.4.4+commit.ee2f5662.js', - 'soljson-v0.5.8-nightly.2019.4.3+commit.1b7878cf.js', - 'soljson-v0.5.8-nightly.2019.4.2+commit.7b0f7eb1.js', - 'soljson-v0.5.8-nightly.2019.4.1+commit.a3a60b8e.js', - 'soljson-v0.5.8-nightly.2019.3.29+commit.91a54f9b.js', - 'soljson-v0.5.8-nightly.2019.3.28+commit.2bbc41ad.js', - 'soljson-v0.5.8-nightly.2019.3.27+commit.97818f65.js', - 'soljson-v0.5.8-nightly.2019.3.26+commit.b85fc1a6.js', - 'soljson-v0.5.7+commit.6da8b019.js', - 'soljson-v0.5.7-nightly.2019.3.26+commit.d079cdbf.js', - 'soljson-v0.5.7-nightly.2019.3.25+commit.99ed3a64.js', - 'soljson-v0.5.7-nightly.2019.3.22+commit.af47da1.js', - 'soljson-v0.5.7-nightly.2019.3.21+commit.ebb8c175.js', - 'soljson-v0.5.7-nightly.2019.3.20+commit.5245a66d.js', - 'soljson-v0.5.7-nightly.2019.3.19+commit.c7824932.js', - 'soljson-v0.5.7-nightly.2019.3.18+commit.5b5c9aa2.js', - 'soljson-v0.5.7-nightly.2019.3.14+commit.d1d6d59c.js', - 'soljson-v0.5.7-nightly.2019.3.13+commit.2da906d9.js', - 'soljson-v0.5.6+commit.b259423e.js', - 'soljson-v0.5.6-nightly.2019.3.13+commit.9ccd5dfe.js', - 'soljson-v0.5.6-nightly.2019.3.12+commit.2f37cd09.js', - 'soljson-v0.5.6-nightly.2019.3.11+commit.189983a1.js', - 'soljson-v0.5.5+commit.47a71e8f.js', - 'soljson-v0.5.5-nightly.2019.3.5+commit.c283f6d8.js', - 'soljson-v0.5.5-nightly.2019.3.4+commit.5490a5cd.js', - 'soljson-v0.5.5-nightly.2019.2.28+commit.e9543d83.js', - 'soljson-v0.5.5-nightly.2019.2.27+commit.a0dcb36f.js', - 'soljson-v0.5.5-nightly.2019.2.26+commit.472a6445.js', - 'soljson-v0.5.5-nightly.2019.2.25+commit.52ee955f.js', - 'soljson-v0.5.5-nightly.2019.2.21+commit.e7a8fed0.js', - 'soljson-v0.5.5-nightly.2019.2.20+commit.c8fb2c1b.js', - 'soljson-v0.5.5-nightly.2019.2.19+commit.d9e4a10d.js', - 'soljson-v0.5.5-nightly.2019.2.18+commit.db7b38e3.js', - 'soljson-v0.5.5-nightly.2019.2.16+commit.2f0926c3.js', - 'soljson-v0.5.5-nightly.2019.2.15+commit.4081303.js', - 'soljson-v0.5.5-nightly.2019.2.14+commit.33318249.js', - 'soljson-v0.5.5-nightly.2019.2.13+commit.b1a5ffb9.js', - 'soljson-v0.5.5-nightly.2019.2.12+commit.828255fa.js', - 'soljson-v0.5.4+commit.9549d8ff.js', - 'soljson-v0.5.4-nightly.2019.2.12+commit.f0f34984.js', - 'soljson-v0.5.4-nightly.2019.2.11+commit.49cd55d3.js', - 'soljson-v0.5.4-nightly.2019.2.7+commit.caecdfab.js', - 'soljson-v0.5.4-nightly.2019.2.6+commit.e5bf1f1d.js', - 'soljson-v0.5.4-nightly.2019.2.5+commit.f3c9b41f.js', - 'soljson-v0.5.4-nightly.2019.2.4+commit.82b69963.js', - 'soljson-v0.5.4-nightly.2019.1.31+commit.ddab3f06.js', - 'soljson-v0.5.4-nightly.2019.1.30+commit.bf3968d6.js', - 'soljson-v0.5.4-nightly.2019.1.29+commit.ebf503a6.js', - 'soljson-v0.5.4-nightly.2019.1.28+commit.e6d102f2.js', - 'soljson-v0.5.4-nightly.2019.1.26+commit.ef45b28.js', - 'soljson-v0.5.4-nightly.2019.1.24+commit.2e7274b4.js', - 'soljson-v0.5.4-nightly.2019.1.23+commit.ea292393.js', - 'soljson-v0.5.4-nightly.2019.1.22+commit.26c06550.js', - 'soljson-v0.5.3+commit.10d17f24.js', - 'soljson-v0.5.3-nightly.2019.1.22+commit.d87d9a26.js', - 'soljson-v0.5.3-nightly.2019.1.21+commit.606c2b99.js', - 'soljson-v0.5.3-nightly.2019.1.19+commit.d3270bc3.js', - 'soljson-v0.5.3-nightly.2019.1.18+commit.7b759866.js', - 'soljson-v0.5.3-nightly.2019.1.17+commit.49f74a7b.js', - 'soljson-v0.5.3-nightly.2019.1.16+commit.82453a76.js', - 'soljson-v0.5.3-nightly.2019.1.15+commit.6146c59a.js', - 'soljson-v0.5.3-nightly.2019.1.14+commit.51df319.js', - 'soljson-v0.5.3-nightly.2019.1.11+commit.94688d2f.js', - 'soljson-v0.5.3-nightly.2019.1.10+commit.31033fb4.js', - 'soljson-v0.5.3-nightly.2019.1.9+commit.63319cfd.js', - 'soljson-v0.5.3-nightly.2019.1.8+commit.a0ca746c.js', - 'soljson-v0.5.3-nightly.2019.1.7+commit.f3799034.js', - 'soljson-v0.5.3-nightly.2019.1.3+commit.d597b1db.js', - 'soljson-v0.5.3-nightly.2018.12.20+commit.245ec29c.js', - 'soljson-v0.5.2+commit.1df8f40c.js', - 'soljson-v0.5.2-nightly.2018.12.19+commit.88750920.js', - 'soljson-v0.5.2-nightly.2018.12.18+commit.4b43aeca.js', - 'soljson-v0.5.2-nightly.2018.12.17+commit.12874029.js', - 'soljson-v0.5.2-nightly.2018.12.13+commit.b3e2ba15.js', - 'soljson-v0.5.2-nightly.2018.12.12+commit.85291bcb.js', - 'soljson-v0.5.2-nightly.2018.12.11+commit.599760b6.js', - 'soljson-v0.5.2-nightly.2018.12.10+commit.6240d9e7.js', - 'soljson-v0.5.2-nightly.2018.12.7+commit.52ff3c94.js', - 'soljson-v0.5.2-nightly.2018.12.6+commit.5a08ae5e.js', - 'soljson-v0.5.2-nightly.2018.12.5+commit.6efe2a52.js', - 'soljson-v0.5.2-nightly.2018.12.4+commit.e49f37be.js', - 'soljson-v0.5.2-nightly.2018.12.3+commit.e6a01d26.js', - 'soljson-v0.5.1+commit.c8a2cb62.js', - 'soljson-v0.5.1-nightly.2018.12.3+commit.a73df9bc.js', - 'soljson-v0.5.1-nightly.2018.11.30+commit.a7ca4991.js', - 'soljson-v0.5.1-nightly.2018.11.29+commit.f6d01323.js', - 'soljson-v0.5.1-nightly.2018.11.28+commit.7cbf0468.js', - 'soljson-v0.5.1-nightly.2018.11.27+commit.bc7cb301.js', - 'soljson-v0.5.1-nightly.2018.11.26+commit.f9378967.js', - 'soljson-v0.5.1-nightly.2018.11.25+commit.1e03c160.js', - 'soljson-v0.5.1-nightly.2018.11.23+commit.616ef8bc.js', - 'soljson-v0.5.1-nightly.2018.11.22+commit.dc748bc7.js', - 'soljson-v0.5.1-nightly.2018.11.21+commit.2c6e1888.js', - 'soljson-v0.5.1-nightly.2018.11.19+commit.d3f66ca0.js', - 'soljson-v0.5.1-nightly.2018.11.17+commit.5be45e73.js', - 'soljson-v0.5.1-nightly.2018.11.15+commit.9db76403.js', - 'soljson-v0.5.1-nightly.2018.11.14+commit.10d99fc3.js', - 'soljson-v0.5.1-nightly.2018.11.13+commit.74ede87a.js', - 'soljson-v0.5.0+commit.1d4f565a.js', - 'soljson-v0.5.0-nightly.2018.11.13+commit.ac980fb8.js', - 'soljson-v0.5.0-nightly.2018.11.12+commit.9f8ff27.js', - 'soljson-v0.5.0-nightly.2018.11.11+commit.405565db.js', - 'soljson-v0.5.0-nightly.2018.11.9+commit.9709dfe0.js', - 'soljson-v0.5.0-nightly.2018.11.8+commit.cc2de07b.js', - 'soljson-v0.5.0-nightly.2018.11.7+commit.a459b8c8.js', - 'soljson-v0.5.0-nightly.2018.11.5+commit.88aee34c.js', - 'soljson-v0.5.0-nightly.2018.11.4+commit.e4da724f.js', - 'soljson-v0.5.0-nightly.2018.10.30+commit.cbbbc0d5.js', - 'soljson-v0.5.0-nightly.2018.10.29+commit.b4f6ab7.js', - 'soljson-v0.5.0-nightly.2018.10.28+commit.c338b422.js', - 'soljson-v0.5.0-nightly.2018.10.26+commit.c8400353.js', - 'soljson-v0.5.0-nightly.2018.10.25+commit.f714b0dd.js', - 'soljson-v0.5.0-nightly.2018.10.24+commit.1566c2e.js', - 'soljson-v0.5.0-nightly.2018.10.23+commit.f5f977ea.js', - 'soljson-v0.5.0-nightly.2018.10.22+commit.a2f5087d.js', - 'soljson-v0.5.0-nightly.2018.10.19+commit.c13b5280.js', - 'soljson-v0.5.0-nightly.2018.10.18+commit.99dc869e.js', - 'soljson-v0.5.0-nightly.2018.10.17+commit.ba158882.js', - 'soljson-v0.5.0-nightly.2018.10.16+commit.b723893a.js', - 'soljson-v0.5.0-nightly.2018.10.15+commit.b965fd6e.js', - 'soljson-v0.5.0-nightly.2018.10.12+commit.1d312c8e.js', - 'soljson-v0.5.0-nightly.2018.10.11+commit.6b5d041e.js', - 'soljson-v0.5.0-nightly.2018.10.10+commit.6200b4b.js', - 'soljson-v0.5.0-nightly.2018.10.9+commit.4ab2e03b.js', - 'soljson-v0.5.0-nightly.2018.10.8+commit.7d2dc143.js', - 'soljson-v0.5.0-nightly.2018.10.6+commit.363b527b.js', - 'soljson-v0.5.0-nightly.2018.10.5+commit.44c1293a.js', - 'soljson-v0.5.0-nightly.2018.10.4+commit.68dfe8b6.js', - 'soljson-v0.5.0-nightly.2018.10.3+commit.b8b31eb3.js', - 'soljson-v0.5.0-nightly.2018.10.2+commit.b77b79c4.js', - 'soljson-v0.5.0-nightly.2018.10.1+commit.80012e69.js', - 'soljson-v0.5.0-nightly.2018.9.30+commit.8ef47cb6.js', - 'soljson-v0.5.0-nightly.2018.9.27+commit.963ae540.js', - 'soljson-v0.5.0-nightly.2018.9.26+commit.d72498b3.js', - 'soljson-v0.5.0-nightly.2018.9.25+commit.608f36d7.js', - 'soljson-v0.4.26+commit.4563c3fc.js', - 'soljson-v0.4.26-nightly.2018.9.25+commit.1b8334e5.js', - 'soljson-v0.4.26-nightly.2018.9.24+commit.dce1ed5a.js', - 'soljson-v0.4.26-nightly.2018.9.21+commit.8f96fe69.js', - 'soljson-v0.4.26-nightly.2018.9.20+commit.2150aea3.js', - 'soljson-v0.4.26-nightly.2018.9.19+commit.7c15f6b1.js', - 'soljson-v0.4.26-nightly.2018.9.18+commit.fcb48bce.js', - 'soljson-v0.4.26-nightly.2018.9.17+commit.2409986c.js', - 'soljson-v0.4.26-nightly.2018.9.13+commit.8b089cc8.js', - 'soljson-v0.4.25+commit.59dbf8f1.js', - 'soljson-v0.4.25-nightly.2018.9.13+commit.15c8c0d2.js', - 'soljson-v0.4.25-nightly.2018.9.12+commit.9214c7c3.js', - 'soljson-v0.4.25-nightly.2018.9.11+commit.d66e956a.js', - 'soljson-v0.4.25-nightly.2018.9.10+commit.86d85025.js', - 'soljson-v0.4.25-nightly.2018.9.6+commit.f19cddd5.js', - 'soljson-v0.4.25-nightly.2018.9.5+commit.a996ea26.js', - 'soljson-v0.4.25-nightly.2018.9.4+commit.f27d7edf.js', - 'soljson-v0.4.25-nightly.2018.9.3+commit.b9cc80b.js', - 'soljson-v0.4.25-nightly.2018.8.16+commit.a9e7ae29.js', - 'soljson-v0.4.25-nightly.2018.8.15+commit.2946b7cd.js', - 'soljson-v0.4.25-nightly.2018.8.14+commit.6ca39739.js', - 'soljson-v0.4.25-nightly.2018.8.13+commit.a2c754b3.js', - 'soljson-v0.4.25-nightly.2018.8.9+commit.63d071d6.js', - 'soljson-v0.4.25-nightly.2018.8.8+commit.d2ca9c82.js', - 'soljson-v0.4.25-nightly.2018.8.7+commit.cda3fbda.js', - 'soljson-v0.4.25-nightly.2018.8.6+commit.3684151e.js', - 'soljson-v0.4.25-nightly.2018.8.3+commit.4efbc9e.js', - 'soljson-v0.4.25-nightly.2018.8.2+commit.6003ed2a.js', - 'soljson-v0.4.25-nightly.2018.8.1+commit.21888e24.js', - 'soljson-v0.4.25-nightly.2018.7.31+commit.75c1a9bd.js', - 'soljson-v0.4.25-nightly.2018.7.30+commit.9d09e21b.js', - 'soljson-v0.4.25-nightly.2018.7.27+commit.bc51b0f6.js', - 'soljson-v0.4.25-nightly.2018.7.25+commit.ff8e9300.js', - 'soljson-v0.4.25-nightly.2018.7.24+commit.fc68d22b.js', - 'soljson-v0.4.25-nightly.2018.7.23+commit.79ddcc76.js', - 'soljson-v0.4.25-nightly.2018.7.20+commit.d3000e70.js', - 'soljson-v0.4.25-nightly.2018.7.19+commit.e3c2f20f.js', - 'soljson-v0.4.25-nightly.2018.7.18+commit.b909df45.js', - 'soljson-v0.4.25-nightly.2018.7.17+commit.56096e9c.js', - 'soljson-v0.4.25-nightly.2018.7.16+commit.98656423.js', - 'soljson-v0.4.25-nightly.2018.7.12+commit.ff9974e9.js', - 'soljson-v0.4.25-nightly.2018.7.11+commit.7910c80.js', - 'soljson-v0.4.25-nightly.2018.7.10+commit.5c404fcf.js', - 'soljson-v0.4.25-nightly.2018.7.9+commit.c42583d2.js', - 'soljson-v0.4.25-nightly.2018.7.5+commit.b1ab81ef.js', - 'soljson-v0.4.25-nightly.2018.7.4+commit.47637224.js', - 'soljson-v0.4.25-nightly.2018.7.3+commit.9f3532e.js', - 'soljson-v0.4.25-nightly.2018.7.2+commit.a5608b31.js', - 'soljson-v0.4.25-nightly.2018.6.29+commit.c9cab803.js', - 'soljson-v0.4.25-nightly.2018.6.28+commit.42680629.js', - 'soljson-v0.4.25-nightly.2018.6.27+commit.b67dfa15.js', - 'soljson-v0.4.25-nightly.2018.6.26+commit.24f124f8.js', - 'soljson-v0.4.25-nightly.2018.6.25+commit.b7003505.js', - 'soljson-v0.4.25-nightly.2018.6.22+commit.9b67bdb3.js', - 'soljson-v0.4.25-nightly.2018.6.21+commit.d104718.js', - 'soljson-v0.4.25-nightly.2018.6.20+commit.ba7fbf11.js', - 'soljson-v0.4.25-nightly.2018.6.19+commit.c72e04c3.js', - 'soljson-v0.4.25-nightly.2018.6.18+commit.4247b004.js', - 'soljson-v0.4.25-nightly.2018.6.17+commit.1692f78b.js', - 'soljson-v0.4.25-nightly.2018.6.14+commit.baeabe1c.js', - 'soljson-v0.4.25-nightly.2018.6.13+commit.3055e4ca.js', - 'soljson-v0.4.25-nightly.2018.6.12+commit.56a965ea.js', - 'soljson-v0.4.25-nightly.2018.6.11+commit.d0355619.js', - 'soljson-v0.4.25-nightly.2018.6.8+commit.81c5a6e4.js', - 'soljson-v0.4.25-nightly.2018.6.7+commit.ddd256a6.js', - 'soljson-v0.4.25-nightly.2018.6.6+commit.59b35fa5.js', - 'soljson-v0.4.25-nightly.2018.6.5+commit.7422cd73.js', - 'soljson-v0.4.25-nightly.2018.6.4+commit.a074d84.js', - 'soljson-v0.4.25-nightly.2018.6.3+commit.ef8fb63b.js', - 'soljson-v0.4.25-nightly.2018.5.30+commit.3f3d6df2.js', - 'soljson-v0.4.25-nightly.2018.5.28+commit.c223b03.js', - 'soljson-v0.4.25-nightly.2018.5.23+commit.18c651b7.js', - 'soljson-v0.4.25-nightly.2018.5.22+commit.849b1bd5.js', - 'soljson-v0.4.25-nightly.2018.5.21+commit.e97f9b6b.js', - 'soljson-v0.4.25-nightly.2018.5.18+commit.4d7b092c.js', - 'soljson-v0.4.25-nightly.2018.5.17+commit.4aa2f036.js', - 'soljson-v0.4.25-nightly.2018.5.16+commit.3897c367.js', - 'soljson-v0.4.24+commit.e67f0147.js', - 'soljson-v0.4.24-nightly.2018.5.16+commit.7f965c86.js', - 'soljson-v0.4.24-nightly.2018.5.15+commit.b8b46099.js', - 'soljson-v0.4.24-nightly.2018.5.14+commit.7a669b39.js', - 'soljson-v0.4.24-nightly.2018.5.11+commit.43803b1a.js', - 'soljson-v0.4.24-nightly.2018.5.10+commit.85d417a8.js', - 'soljson-v0.4.24-nightly.2018.5.9+commit.1e953355.js', - 'soljson-v0.4.24-nightly.2018.5.8+commit.a63bc17.js', - 'soljson-v0.4.24-nightly.2018.5.7+commit.6db7e09a.js', - 'soljson-v0.4.24-nightly.2018.5.4+commit.81d61ca0.js', - 'soljson-v0.4.24-nightly.2018.5.3+commit.72c3b3a2.js', - 'soljson-v0.4.24-nightly.2018.5.2+commit.dc18cde6.js', - 'soljson-v0.4.24-nightly.2018.4.30+commit.9e61b25d.js', - 'soljson-v0.4.24-nightly.2018.4.27+commit.1604a996.js', - 'soljson-v0.4.24-nightly.2018.4.26+commit.ef2111a2.js', - 'soljson-v0.4.24-nightly.2018.4.25+commit.81cca26f.js', - 'soljson-v0.4.24-nightly.2018.4.24+commit.258ae892.js', - 'soljson-v0.4.24-nightly.2018.4.23+commit.c7ee2ca0.js', - 'soljson-v0.4.24-nightly.2018.4.22+commit.2fae248d.js', - 'soljson-v0.4.24-nightly.2018.4.20+commit.f328431.js', - 'soljson-v0.4.24-nightly.2018.4.19+commit.27d79906.js', - 'soljson-v0.4.23+commit.124ca40d.js', - 'soljson-v0.4.23-nightly.2018.4.19+commit.ae834e3d.js', - 'soljson-v0.4.23-nightly.2018.4.18+commit.85687a37.js', - 'soljson-v0.4.23-nightly.2018.4.17+commit.5499db01.js', - 'soljson-v0.4.22+commit.4cb486ee.js', - 'soljson-v0.4.22-nightly.2018.4.16+commit.d8030c9b.js', - 'soljson-v0.4.22-nightly.2018.4.14+commit.73ca3e8a.js', - 'soljson-v0.4.22-nightly.2018.4.13+commit.2001cc6b.js', - 'soljson-v0.4.22-nightly.2018.4.12+commit.c3dc67d0.js', - 'soljson-v0.4.22-nightly.2018.4.11+commit.b7b6d0ce.js', - 'soljson-v0.4.22-nightly.2018.4.10+commit.27385d6d.js', - 'soljson-v0.4.22-nightly.2018.4.6+commit.9bd49516.js', - 'soljson-v0.4.22-nightly.2018.4.5+commit.c6adad93.js', - 'soljson-v0.4.22-nightly.2018.4.4+commit.920de496.js', - 'soljson-v0.4.22-nightly.2018.4.3+commit.3fbdd655.js', - 'soljson-v0.4.22-nightly.2018.3.30+commit.326d656a.js', - 'soljson-v0.4.22-nightly.2018.3.29+commit.c2ae33f8.js', - 'soljson-v0.4.22-nightly.2018.3.27+commit.af262281.js', - 'soljson-v0.4.22-nightly.2018.3.21+commit.8fd53c1c.js', - 'soljson-v0.4.22-nightly.2018.3.16+commit.2b2527f3.js', - 'soljson-v0.4.22-nightly.2018.3.15+commit.3f1e0d84.js', - 'soljson-v0.4.22-nightly.2018.3.14+commit.c3f07b52.js', - 'soljson-v0.4.22-nightly.2018.3.13+commit.f2614be9.js', - 'soljson-v0.4.22-nightly.2018.3.12+commit.c6e9dd13.js', - 'soljson-v0.4.22-nightly.2018.3.8+commit.fbc29f6d.js', - 'soljson-v0.4.22-nightly.2018.3.7+commit.b5e804b8.js', - 'soljson-v0.4.21+commit.dfe3193c.js', - 'soljson-v0.4.21-nightly.2018.3.7+commit.bd7bc7c4.js', - 'soljson-v0.4.21-nightly.2018.3.6+commit.a9e02acc.js', - 'soljson-v0.4.21-nightly.2018.3.5+commit.cd6ffbdf.js', - 'soljson-v0.4.21-nightly.2018.3.1+commit.cf6720ea.js', - 'soljson-v0.4.21-nightly.2018.2.28+commit.ac5485a2.js', - 'soljson-v0.4.21-nightly.2018.2.27+commit.415ac2ae.js', - 'soljson-v0.4.21-nightly.2018.2.26+commit.cd2d8936.js', - 'soljson-v0.4.21-nightly.2018.2.23+commit.cae6cc2c.js', - 'soljson-v0.4.21-nightly.2018.2.22+commit.71a34abd.js', - 'soljson-v0.4.21-nightly.2018.2.21+commit.16c7eabc.js', - 'soljson-v0.4.21-nightly.2018.2.20+commit.dcc4083b.js', - 'soljson-v0.4.21-nightly.2018.2.19+commit.839acafb.js', - 'soljson-v0.4.21-nightly.2018.2.16+commit.3f7e82d0.js', - 'soljson-v0.4.21-nightly.2018.2.15+commit.f4aa05f3.js', - 'soljson-v0.4.21-nightly.2018.2.14+commit.bb3b327c.js', - 'soljson-v0.4.20+commit.3155dd80.js', - 'soljson-v0.4.20-nightly.2018.2.13+commit.27ef9794.js', - 'soljson-v0.4.20-nightly.2018.2.12+commit.954903b5.js', - 'soljson-v0.4.20-nightly.2018.1.29+commit.a668b9de.js', - 'soljson-v0.4.20-nightly.2018.1.26+commit.bbad48bb.js', - 'soljson-v0.4.20-nightly.2018.1.25+commit.e7afde95.js', - 'soljson-v0.4.20-nightly.2018.1.24+commit.b177352a.js', - 'soljson-v0.4.20-nightly.2018.1.23+commit.31aaf433.js', - 'soljson-v0.4.20-nightly.2018.1.22+commit.e5def2da.js', - 'soljson-v0.4.20-nightly.2018.1.19+commit.eba46a65.js', - 'soljson-v0.4.20-nightly.2018.1.18+commit.33723c45.js', - 'soljson-v0.4.20-nightly.2018.1.17+commit.4715167e.js', - 'soljson-v0.4.20-nightly.2018.1.15+commit.14fcbd65.js', - 'soljson-v0.4.20-nightly.2018.1.11+commit.c20b6da.js', - 'soljson-v0.4.20-nightly.2018.1.10+commit.a75d5333.js', - 'soljson-v0.4.20-nightly.2018.1.6+commit.2548228b.js', - 'soljson-v0.4.20-nightly.2018.1.5+commit.bca01f8f.js', - 'soljson-v0.4.20-nightly.2018.1.4+commit.a0771691.js', - 'soljson-v0.4.20-nightly.2017.12.20+commit.efc198d5.js', - 'soljson-v0.4.20-nightly.2017.12.19+commit.2d800e67.js', - 'soljson-v0.4.20-nightly.2017.12.18+commit.37b70e8e.js', - 'soljson-v0.4.20-nightly.2017.12.14+commit.3d1830f3.js', - 'soljson-v0.4.20-nightly.2017.12.13+commit.bfc54463.js', - 'soljson-v0.4.20-nightly.2017.12.12+commit.1ddd4e2b.js', - 'soljson-v0.4.20-nightly.2017.12.11+commit.4a1f18c9.js', - 'soljson-v0.4.20-nightly.2017.12.8+commit.226bfe5b.js', - 'soljson-v0.4.20-nightly.2017.12.6+commit.c2109436.js', - 'soljson-v0.4.20-nightly.2017.12.5+commit.b47e023d.js', - 'soljson-v0.4.20-nightly.2017.12.4+commit.240c79e6.js', - 'soljson-v0.4.20-nightly.2017.12.1+commit.6d8d0393.js', - 'soljson-v0.4.20-nightly.2017.11.30+commit.cb16a5d3.js', - 'soljson-v0.4.19+commit.c4cbbb05.js', - 'soljson-v0.4.19-nightly.2017.11.30+commit.f5a2508e.js', - 'soljson-v0.4.19-nightly.2017.11.29+commit.7c69d88f.js', - 'soljson-v0.4.19-nightly.2017.11.22+commit.f22ac8fc.js', - 'soljson-v0.4.19-nightly.2017.11.21+commit.5c9e273d.js', - 'soljson-v0.4.19-nightly.2017.11.17+commit.2b5ef806.js', - 'soljson-v0.4.19-nightly.2017.11.16+commit.58e452d1.js', - 'soljson-v0.4.19-nightly.2017.11.15+commit.e3206d8e.js', - 'soljson-v0.4.19-nightly.2017.11.14+commit.bc39e730.js', - 'soljson-v0.4.19-nightly.2017.11.13+commit.60b2c2b.js', - 'soljson-v0.4.19-nightly.2017.11.11+commit.284c3839.js', - 'soljson-v0.4.19-nightly.2017.10.29+commit.eb140bc6.js', - 'soljson-v0.4.19-nightly.2017.10.28+commit.f9b24009.js', - 'soljson-v0.4.19-nightly.2017.10.27+commit.1e085f85.js', - 'soljson-v0.4.19-nightly.2017.10.26+commit.59d4dfbd.js', - 'soljson-v0.4.19-nightly.2017.10.24+commit.1313e9d8.js', - 'soljson-v0.4.19-nightly.2017.10.23+commit.dc6b1f02.js', - 'soljson-v0.4.19-nightly.2017.10.20+commit.bdd2858b.js', - 'soljson-v0.4.19-nightly.2017.10.19+commit.c58d9d2c.js', - 'soljson-v0.4.19-nightly.2017.10.18+commit.f7ca2421.js', - 'soljson-v0.4.18+commit.9cf6e910.js', - 'soljson-v0.4.18-nightly.2017.10.18+commit.e854da1a.js', - 'soljson-v0.4.18-nightly.2017.10.17+commit.8fbfd62d.js', - 'soljson-v0.4.18-nightly.2017.10.16+commit.dbc8655b.js', - 'soljson-v0.4.18-nightly.2017.10.15+commit.a74c9aef.js', - 'soljson-v0.4.18-nightly.2017.10.10+commit.c35496bf.js', - 'soljson-v0.4.18-nightly.2017.10.9+commit.6f832cac.js', - 'soljson-v0.4.18-nightly.2017.10.6+commit.961f8746.js', - 'soljson-v0.4.18-nightly.2017.10.5+commit.995b5525.js', - 'soljson-v0.4.18-nightly.2017.10.4+commit.c3888ab.js', - 'soljson-v0.4.18-nightly.2017.10.3+commit.5c284589.js', - 'soljson-v0.4.18-nightly.2017.10.2+commit.c6161030.js', - 'soljson-v0.4.18-nightly.2017.9.29+commit.b9218468.js', - 'soljson-v0.4.18-nightly.2017.9.28+commit.4d01d086.js', - 'soljson-v0.4.18-nightly.2017.9.27+commit.809d5ce1.js', - 'soljson-v0.4.18-nightly.2017.9.26+commit.eb5a6aac.js', - 'soljson-v0.4.18-nightly.2017.9.25+commit.a72237f2.js', - 'soljson-v0.4.18-nightly.2017.9.22+commit.a2a58789.js', - 'soljson-v0.4.17+commit.bdeb9e52.js', - 'soljson-v0.4.17-nightly.2017.9.21+commit.725b4fc2.js', - 'soljson-v0.4.17-nightly.2017.9.20+commit.c0b3e5b0.js', - 'soljson-v0.4.17-nightly.2017.9.19+commit.1fc71bd7.js', - 'soljson-v0.4.17-nightly.2017.9.18+commit.c289fd3d.js', - 'soljson-v0.4.17-nightly.2017.9.16+commit.a0d17172.js', - 'soljson-v0.4.17-nightly.2017.9.14+commit.7dd372ce.js', - 'soljson-v0.4.17-nightly.2017.9.12+commit.4770f8f4.js', - 'soljson-v0.4.17-nightly.2017.9.11+commit.fbe24da1.js', - 'soljson-v0.4.17-nightly.2017.9.6+commit.59223061.js', - 'soljson-v0.4.17-nightly.2017.9.5+commit.f242331c.js', - 'soljson-v0.4.17-nightly.2017.9.4+commit.8283f836.js', - 'soljson-v0.4.17-nightly.2017.8.31+commit.402d6e71.js', - 'soljson-v0.4.17-nightly.2017.8.29+commit.2d39a42d.js', - 'soljson-v0.4.17-nightly.2017.8.28+commit.d15cde2a.js', - 'soljson-v0.4.17-nightly.2017.8.25+commit.e945f458.js', - 'soljson-v0.4.17-nightly.2017.8.24+commit.12d9f79.js', - 'soljson-v0.4.16+commit.d7661dd9.js', - 'soljson-v0.4.16-nightly.2017.8.24+commit.78c2dcac.js', - 'soljson-v0.4.16-nightly.2017.8.23+commit.c5f11d93.js', - 'soljson-v0.4.16-nightly.2017.8.22+commit.f874fc28.js', - 'soljson-v0.4.16-nightly.2017.8.21+commit.cf60488.js', - 'soljson-v0.4.16-nightly.2017.8.16+commit.83561e13.js', - 'soljson-v0.4.16-nightly.2017.8.15+commit.dca1f45c.js', - 'soljson-v0.4.16-nightly.2017.8.14+commit.4d9790b6.js', - 'soljson-v0.4.16-nightly.2017.8.11+commit.c84de7fa.js', - 'soljson-v0.4.16-nightly.2017.8.10+commit.41e3cbe0.js', - 'soljson-v0.4.16-nightly.2017.8.9+commit.81887bc7.js', - 'soljson-v0.4.15+commit.bbb8e64f.js', - 'soljson-v0.4.15-nightly.2017.8.8+commit.41e72436.js', - 'soljson-v0.4.15-nightly.2017.8.7+commit.212454a9.js', - 'soljson-v0.4.15-nightly.2017.8.4+commit.e48730fe.js', - 'soljson-v0.4.15-nightly.2017.8.2+commit.4166ce1.js', - 'soljson-v0.4.15-nightly.2017.8.1+commit.7e07eb6e.js', - 'soljson-v0.4.15-nightly.2017.7.31+commit.93f90eb2.js', - 'soljson-v0.4.14+commit.c2215d46.js', - 'soljson-v0.4.14-nightly.2017.7.31+commit.22326189.js', - 'soljson-v0.4.14-nightly.2017.7.28+commit.7e40def6.js', - 'soljson-v0.4.14-nightly.2017.7.27+commit.1298a8df.js', - 'soljson-v0.4.14-nightly.2017.7.26+commit.d701c94.js', - 'soljson-v0.4.14-nightly.2017.7.25+commit.3c2b710b.js', - 'soljson-v0.4.14-nightly.2017.7.24+commit.cfb11ff7.js', - 'soljson-v0.4.14-nightly.2017.7.21+commit.75b48616.js', - 'soljson-v0.4.14-nightly.2017.7.20+commit.d70974ea.js', - 'soljson-v0.4.14-nightly.2017.7.19+commit.3ad326be.js', - 'soljson-v0.4.14-nightly.2017.7.18+commit.c167a31b.js', - 'soljson-v0.4.14-nightly.2017.7.14+commit.7c97546f.js', - 'soljson-v0.4.14-nightly.2017.7.13+commit.2b33e0bc.js', - 'soljson-v0.4.14-nightly.2017.7.12+commit.b981ef20.js', - 'soljson-v0.4.14-nightly.2017.7.11+commit.b17ff1b.js', - 'soljson-v0.4.14-nightly.2017.7.10+commit.6fa5d47f.js', - 'soljson-v0.4.14-nightly.2017.7.9+commit.aafcc360.js', - 'soljson-v0.4.14-nightly.2017.7.8+commit.7d1ddfc6.js', - 'soljson-v0.4.14-nightly.2017.7.6+commit.8dade9f.js', - 'soljson-v0.4.13+commit.fb4cb1a.js', - 'soljson-v0.4.13-nightly.2017.7.6+commit.40d4ee49.js', - 'soljson-v0.4.13-nightly.2017.7.5+commit.2b505e7a.js', - 'soljson-v0.4.13-nightly.2017.7.4+commit.331b0b1c.js', - 'soljson-v0.4.13-nightly.2017.7.3+commit.6e4e627b.js', - 'soljson-v0.4.12+commit.194ff033.js', - 'soljson-v0.4.12-nightly.2017.7.3+commit.c7530a8.js', - 'soljson-v0.4.12-nightly.2017.7.1+commit.6f8949f.js', - 'soljson-v0.4.12-nightly.2017.6.30+commit.568e7520.js', - 'soljson-v0.4.12-nightly.2017.6.29+commit.f5372cda.js', - 'soljson-v0.4.12-nightly.2017.6.28+commit.e19c4125.js', - 'soljson-v0.4.12-nightly.2017.6.27+commit.bc31d496.js', - 'soljson-v0.4.12-nightly.2017.6.26+commit.f8794892.js', - 'soljson-v0.4.12-nightly.2017.6.25+commit.29b8cdb5.js', - 'soljson-v0.4.12-nightly.2017.6.23+commit.793f05fa.js', - 'soljson-v0.4.12-nightly.2017.6.22+commit.1c54ce2a.js', - 'soljson-v0.4.12-nightly.2017.6.21+commit.ac977cdf.js', - 'soljson-v0.4.12-nightly.2017.6.20+commit.cb5f2f90.js', - 'soljson-v0.4.12-nightly.2017.6.19+commit.c75afb2.js', - 'soljson-v0.4.12-nightly.2017.6.16+commit.17de4a07.js', - 'soljson-v0.4.12-nightly.2017.6.15+commit.71fea1e3.js', - 'soljson-v0.4.12-nightly.2017.6.14+commit.43cfab70.js', - 'soljson-v0.4.12-nightly.2017.6.13+commit.c8c2091.js', - 'soljson-v0.4.12-nightly.2017.6.12+commit.496c2a20.js', - 'soljson-v0.4.12-nightly.2017.6.9+commit.76667fed.js', - 'soljson-v0.4.12-nightly.2017.6.8+commit.51fcfbcf.js', - 'soljson-v0.4.12-nightly.2017.6.6+commit.243e389f.js', - 'soljson-v0.4.12-nightly.2017.6.1+commit.96de7a83.js', - 'soljson-v0.4.12-nightly.2017.5.30+commit.254b5572.js', - 'soljson-v0.4.12-nightly.2017.5.29+commit.4a5dc6a4.js', - 'soljson-v0.4.12-nightly.2017.5.26+commit.e43ff797.js', - 'soljson-v0.4.12-nightly.2017.5.24+commit.cf639f48.js', - 'soljson-v0.4.12-nightly.2017.5.23+commit.14b22150.js', - 'soljson-v0.4.12-nightly.2017.5.22+commit.e3af0640.js', - 'soljson-v0.4.12-nightly.2017.5.19+commit.982f6613.js', - 'soljson-v0.4.12-nightly.2017.5.18+commit.6f9428e9.js', - 'soljson-v0.4.12-nightly.2017.5.17+commit.b4c6877a.js', - 'soljson-v0.4.12-nightly.2017.5.16+commit.2ba87fe8.js', - 'soljson-v0.4.12-nightly.2017.5.11+commit.242e4318.js', - 'soljson-v0.4.12-nightly.2017.5.10+commit.a6586f75.js', - 'soljson-v0.4.12-nightly.2017.5.6+commit.822c9057.js', - 'soljson-v0.4.12-nightly.2017.5.5+commit.582fcb9.js', - 'soljson-v0.4.12-nightly.2017.5.4+commit.25b32d9.js', - 'soljson-v0.4.11+commit.68ef5810.js', - 'soljson-v0.4.11-nightly.2017.5.3+commit.1aa0f77a.js', - 'soljson-v0.4.11-nightly.2017.5.2+commit.5aeb6352.js', - 'soljson-v0.4.11-nightly.2017.4.28+commit.f33614e1.js', - 'soljson-v0.4.11-nightly.2017.4.27+commit.abe77f48.js', - 'soljson-v0.4.11-nightly.2017.4.26+commit.3cbdf6d4.js', - 'soljson-v0.4.11-nightly.2017.4.25+commit.c3b839ca.js', - 'soljson-v0.4.11-nightly.2017.4.24+commit.a9f42157.js', - 'soljson-v0.4.11-nightly.2017.4.22+commit.aa441668.js', - 'soljson-v0.4.11-nightly.2017.4.21+commit.e3eea9fc.js', - 'soljson-v0.4.11-nightly.2017.4.20+commit.6468955f.js', - 'soljson-v0.4.11-nightly.2017.4.18+commit.82628a80.js', - 'soljson-v0.4.11-nightly.2017.4.13+commit.138c952a.js', - 'soljson-v0.4.11-nightly.2017.4.10+commit.9fe20650.js', - 'soljson-v0.4.11-nightly.2017.3.29+commit.fefb3fad.js', - 'soljson-v0.4.11-nightly.2017.3.28+commit.215184ef.js', - 'soljson-v0.4.11-nightly.2017.3.27+commit.9d769a56.js', - 'soljson-v0.4.11-nightly.2017.3.22+commit.74d7c513.js', - 'soljson-v0.4.11-nightly.2017.3.21+commit.6fb27dee.js', - 'soljson-v0.4.11-nightly.2017.3.20+commit.57bc763e.js', - 'soljson-v0.4.11-nightly.2017.3.17+commit.2f2ad42c.js', - 'soljson-v0.4.11-nightly.2017.3.16+commit.a2eb2c0a.js', - 'soljson-v0.4.11-nightly.2017.3.15+commit.157b86c.js', - 'soljson-v0.4.10+commit.f0d539ae.js', - 'soljson-v0.4.10-nightly.2017.3.15+commit.d134fda0.js', - 'soljson-v0.4.10-nightly.2017.3.14+commit.409eb9e3.js', - 'soljson-v0.4.10-nightly.2017.3.13+commit.9aab3b86.js', - 'soljson-v0.4.10-nightly.2017.3.10+commit.f1dd79c7.js', - 'soljson-v0.4.10-nightly.2017.3.9+commit.b22369d5.js', - 'soljson-v0.4.10-nightly.2017.3.8+commit.a1e350a4.js', - 'soljson-v0.4.10-nightly.2017.3.6+commit.2dac39b9.js', - 'soljson-v0.4.10-nightly.2017.3.3+commit.6bfd894f.js', - 'soljson-v0.4.10-nightly.2017.3.2+commit.5c411b47.js', - 'soljson-v0.4.10-nightly.2017.3.1+commit.6ac2c15c.js', - 'soljson-v0.4.10-nightly.2017.2.24+commit.6bbba106.js', - 'soljson-v0.4.10-nightly.2017.2.22+commit.b67fee3.js', - 'soljson-v0.4.10-nightly.2017.2.20+commit.32b7d174.js', - 'soljson-v0.4.10-nightly.2017.2.17+commit.419ab926.js', - 'soljson-v0.4.10-nightly.2017.2.16+commit.ad8e534.js', - 'soljson-v0.4.10-nightly.2017.2.15+commit.ad751bd3.js', - 'soljson-v0.4.10-nightly.2017.2.14+commit.91d5515c.js', - 'soljson-v0.4.10-nightly.2017.2.13+commit.8357bdad.js', - 'soljson-v0.4.10-nightly.2017.2.3+commit.5ce79609.js', - 'soljson-v0.4.10-nightly.2017.2.2+commit.8f9839c6.js', - 'soljson-v0.4.10-nightly.2017.2.1+commit.c1a675da.js', - 'soljson-v0.4.10-nightly.2017.1.31+commit.747db75a.js', - 'soljson-v0.4.9+commit.364da425.js', - 'soljson-v0.4.9-nightly.2017.1.31+commit.f9af2de0.js', - 'soljson-v0.4.9-nightly.2017.1.30+commit.edd3696d.js', - 'soljson-v0.4.9-nightly.2017.1.27+commit.1774e087.js', - 'soljson-v0.4.9-nightly.2017.1.26+commit.2122d2d7.js', - 'soljson-v0.4.9-nightly.2017.1.24+commit.b52a6040.js', - 'soljson-v0.4.9-nightly.2017.1.23+commit.6946902c.js', - 'soljson-v0.4.9-nightly.2017.1.20+commit.12b002b3.js', - 'soljson-v0.4.9-nightly.2017.1.19+commit.9403dd5.js', - 'soljson-v0.4.9-nightly.2017.1.18+commit.5e1908.js', - 'soljson-v0.4.9-nightly.2017.1.17+commit.6ecb4aa3.js', - 'soljson-v0.4.9-nightly.2017.1.16+commit.79e5772b.js', - 'soljson-v0.4.9-nightly.2017.1.13+commit.392ef5f4.js', - 'soljson-v0.4.8+commit.60cc1668.js', - 'soljson-v0.4.8-nightly.2017.1.13+commit.bde0b406.js', - 'soljson-v0.4.8-nightly.2017.1.12+commit.b983c749.js', - 'soljson-v0.4.8-nightly.2017.1.11+commit.4f5da2ea.js', - 'soljson-v0.4.8-nightly.2017.1.10+commit.26a90af4.js', - 'soljson-v0.4.8-nightly.2017.1.9+commit.354a10be.js', - 'soljson-v0.4.8-nightly.2017.1.6+commit.a4d7a590.js', - 'soljson-v0.4.8-nightly.2017.1.5+commit.31e6a5.js', - 'soljson-v0.4.8-nightly.2017.1.3+commit.43a5d11f.js', - 'soljson-v0.4.8-nightly.2017.1.2+commit.75a596ab.js', - 'soljson-v0.4.8-nightly.2016.12.16+commit.af8bc1c9.js', - 'soljson-v0.4.7+commit.822622cf.js', - 'soljson-v0.4.7-nightly.2016.12.15+commit.688841ae.js', - 'soljson-v0.4.7-nightly.2016.12.14+commit.e53d1255.js', - 'soljson-v0.4.7-nightly.2016.12.13+commit.9d607345.js', - 'soljson-v0.4.7-nightly.2016.12.12+commit.e53fdb49.js', - 'soljson-v0.4.7-nightly.2016.12.11+commit.84d4f3da.js', - 'soljson-v0.4.7-nightly.2016.12.8+commit.89771a44.js', - 'soljson-v0.4.7-nightly.2016.12.7+commit.fd7561ed.js', - 'soljson-v0.4.7-nightly.2016.12.6+commit.b201e148.js', - 'soljson-v0.4.7-nightly.2016.12.5+commit.34327c5d.js', - 'soljson-v0.4.7-nightly.2016.12.3+commit.9be2fb12.js', - 'soljson-v0.4.7-nightly.2016.12.2+commit.3a01a87a.js', - 'soljson-v0.4.7-nightly.2016.12.1+commit.67f274f6.js', - 'soljson-v0.4.7-nightly.2016.11.30+commit.e43a8ebc.js', - 'soljson-v0.4.7-nightly.2016.11.29+commit.71cbc4a.js', - 'soljson-v0.4.7-nightly.2016.11.28+commit.dadb4818.js', - 'soljson-v0.4.7-nightly.2016.11.26+commit.4a67a286.js', - 'soljson-v0.4.7-nightly.2016.11.25+commit.ba94b0ae.js', - 'soljson-v0.4.7-nightly.2016.11.24+commit.851f8576.js', - 'soljson-v0.4.7-nightly.2016.11.23+commit.475009b9.js', - 'soljson-v0.4.7-nightly.2016.11.22+commit.1a205ebf.js', - 'soljson-v0.4.6+commit.2dabbdf0.js', - 'soljson-v0.4.6-nightly.2016.11.22+commit.3d9a180c.js', - 'soljson-v0.4.6-nightly.2016.11.21+commit.aa48008c.js', - 'soljson-v0.4.5+commit.b318366e.js', - 'soljson-v0.4.5-nightly.2016.11.21+commit.afda210a.js', - 'soljson-v0.4.5-nightly.2016.11.17+commit.b46a14f4.js', - 'soljson-v0.4.5-nightly.2016.11.16+commit.c8116918.js', - 'soljson-v0.4.5-nightly.2016.11.15+commit.c1b1efaf.js', - 'soljson-v0.4.5-nightly.2016.11.14+commit.4f546e65.js', - 'soljson-v0.4.5-nightly.2016.11.11+commit.6248e92d.js', - 'soljson-v0.4.5-nightly.2016.11.10+commit.a40dcfef.js', - 'soljson-v0.4.5-nightly.2016.11.9+commit.c82acfd3.js', - 'soljson-v0.4.5-nightly.2016.11.8+commit.7a30e8cf.js', - 'soljson-v0.4.5-nightly.2016.11.4+commit.d97d267a.js', - 'soljson-v0.4.5-nightly.2016.11.3+commit.90a4acc3.js', - 'soljson-v0.4.5-nightly.2016.11.1+commit.9cb1d30e.js', - 'soljson-v0.4.4+commit.4633f3de.js', - 'soljson-v0.4.4-nightly.2016.10.31+commit.1d3460c4.js', - 'soljson-v0.4.4-nightly.2016.10.28+commit.e85390cc.js', - 'soljson-v0.4.4-nightly.2016.10.27+commit.76e958f6.js', - 'soljson-v0.4.4-nightly.2016.10.26+commit.34e2209b.js', - 'soljson-v0.4.4-nightly.2016.10.25+commit.f99a418b.js', - 'soljson-v0.4.3+commit.2353da71.js', - 'soljson-v0.4.3-nightly.2016.10.25+commit.d190f016.js', - 'soljson-v0.4.3-nightly.2016.10.24+commit.84b43b91.js', - 'soljson-v0.4.3-nightly.2016.10.21+commit.984b8ac1.js', - 'soljson-v0.4.3-nightly.2016.10.20+commit.9d304501.js', - 'soljson-v0.4.3-nightly.2016.10.19+commit.fd6f2b5.js', - 'soljson-v0.4.3-nightly.2016.10.18+commit.a9eb645.js', - 'soljson-v0.4.3-nightly.2016.10.17+commit.7d32937.js', - 'soljson-v0.4.3-nightly.2016.10.15+commit.482807f6.js', - 'soljson-v0.4.3-nightly.2016.10.14+commit.635b6e0.js', - 'soljson-v0.4.3-nightly.2016.10.13+commit.2951c1eb.js', - 'soljson-v0.4.3-nightly.2016.10.12+commit.def3f3ea.js', - 'soljson-v0.4.3-nightly.2016.10.11+commit.aa18a6bd.js', - 'soljson-v0.4.3-nightly.2016.10.10+commit.119bd4ad.js', - 'soljson-v0.4.3-nightly.2016.9.30+commit.d5cfb17b.js', - 'soljson-v0.4.2+commit.af6afb04.js', - 'soljson-v0.4.2-nightly.2016.9.17+commit.212e0160.js', - 'soljson-v0.4.2-nightly.2016.9.17+commit.bc8476a.js', - 'soljson-v0.4.2-nightly.2016.9.17+commit.a78e7794.js', - 'soljson-v0.4.2-nightly.2016.9.17+commit.62f13ad8.js', - 'soljson-v0.4.2-nightly.2016.9.17+commit.60f432e8.js', - 'soljson-v0.4.2-nightly.2016.9.15+commit.8a4f8c2.js', - 'soljson-v0.4.2-nightly.2016.9.15+commit.6a80511.js', - 'soljson-v0.4.2-nightly.2016.9.13+commit.2bee7e9.js', - 'soljson-v0.4.2-nightly.2016.9.12+commit.149dba9.js', - 'soljson-v0.4.2-nightly.2016.9.9+commit.51a98ab.js', - 'soljson-v0.4.1+commit.4fc6fc2c.js', - 'soljson-v0.4.1-nightly.2016.9.9+commit.79867f4.js', - 'soljson-v0.4.0+commit.acd334c9.js', - 'soljson-v0.3.6+commit.3fc68da.js', - 'soljson-v0.3.6-nightly.2016.9.8+commit.f5a513a.js', - 'soljson-v0.3.6-nightly.2016.9.7+commit.24524d6.js', - 'soljson-v0.3.6-nightly.2016.9.6+commit.114502f.js', - 'soljson-v0.3.6-nightly.2016.9.5+commit.873d8bb.js', - 'soljson-v0.3.6-nightly.2016.9.2+commit.341c943.js', - 'soljson-v0.3.6-nightly.2016.9.1+commit.b5d941d.js', - 'soljson-v0.3.6-nightly.2016.8.31+commit.3ccd198.js', - 'soljson-v0.3.6-nightly.2016.8.30+commit.cf974fd.js', - 'soljson-v0.3.6-nightly.2016.8.29+commit.b8060c5.js', - 'soljson-v0.3.6-nightly.2016.8.27+commit.91d4fa4.js', - 'soljson-v0.3.6-nightly.2016.8.26+commit.3eeefb5.js', - 'soljson-v0.3.6-nightly.2016.8.24+commit.e20afc7.js', - 'soljson-v0.3.6-nightly.2016.8.23+commit.de535a7.js', - 'soljson-v0.3.6-nightly.2016.8.22+commit.7183658.js', - 'soljson-v0.3.6-nightly.2016.8.20+commit.d736fd.js', - 'soljson-v0.3.6-nightly.2016.8.19+commit.32c93cf.js', - 'soljson-v0.3.6-nightly.2016.8.17+commit.c499470.js', - 'soljson-v0.3.6-nightly.2016.8.16+commit.970260b.js', - 'soljson-v0.3.6-nightly.2016.8.15+commit.868a167.js', - 'soljson-v0.3.6-nightly.2016.8.12+commit.9e03bda.js', - 'soljson-v0.3.6-nightly.2016.8.11+commit.7c15fa6.js', - 'soljson-v0.3.6-nightly.2016.8.10+commit.e2a46b6.js', - 'soljson-v0.3.6-nightly.2016.8.10+commit.5a37403.js', - 'soljson-v0.3.6-nightly.2016.8.10+commit.55858de.js', - 'soljson-v0.3.6-nightly.2016.8.10+commit.b7c26f4.js', - 'soljson-v0.3.5+commit.5f97274.js', - 'soljson-v0.3.5-nightly.2016.8.10+commit.cacc3b6.js', - 'soljson-v0.3.5-nightly.2016.8.10+commit.e6a031d.js', - 'soljson-v0.3.5-nightly.2016.8.10+commit.fc60839.js', - 'soljson-v0.3.5-nightly.2016.8.8+commit.c3ed550.js', - 'soljson-v0.3.5-nightly.2016.8.8+commit.b13e581.js', - 'soljson-v0.3.5-nightly.2016.8.8+commit.539afbe.js', - 'soljson-v0.3.5-nightly.2016.8.8+commit.2fcc6ec.js', - 'soljson-v0.3.5-nightly.2016.8.7+commit.f7af7de.js', - 'soljson-v0.3.5-nightly.2016.8.6+commit.e3c1bf7.js', - 'soljson-v0.3.5-nightly.2016.8.5+commit.ff60ce9.js', - 'soljson-v0.3.5-nightly.2016.8.5+commit.4542b7f.js', - 'soljson-v0.3.5-nightly.2016.8.5+commit.3c93a22.js', - 'soljson-v0.3.5-nightly.2016.8.4+commit.b83acfa.js', - 'soljson-v0.3.5-nightly.2016.8.3+commit.3b21d98.js', - 'soljson-v0.3.5-nightly.2016.7.21+commit.6610add.js', - 'soljson-v0.3.5-nightly.2016.7.19+commit.427deb4.js', - 'soljson-v0.3.5-nightly.2016.7.1+commit.48238c9.js', - 'soljson-v0.3.5-nightly.2016.6.27+commit.2ccfea8.js', - 'soljson-v0.3.5-nightly.2016.6.21+commit.b23c300.js', - 'soljson-v0.3.5-nightly.2016.6.20+commit.9da08ac.js', - 'soljson-v0.3.5-nightly.2016.6.19+commit.5917c8e.js', - 'soljson-v0.3.5-nightly.2016.6.14+commit.371690f.js', - 'soljson-v0.3.4+commit.7dab890.js', - 'soljson-v0.3.4-nightly.2016.6.8+commit.93790d.js', - 'soljson-v0.3.4-nightly.2016.6.8+commit.d593166.js', - 'soljson-v0.3.4-nightly.2016.6.8+commit.ccddd6f.js', - 'soljson-v0.3.4-nightly.2016.6.6+commit.e97ac4f.js', - 'soljson-v0.3.4-nightly.2016.6.5+commit.a0fc04.js', - 'soljson-v0.3.4-nightly.2016.6.4+commit.602bcd3.js', - 'soljson-v0.3.3+commit.4dc1cb1.js', - 'soljson-v0.3.3-nightly.2016.5.31+commit.7dab890.js', - 'soljson-v0.3.3-nightly.2016.5.30+commit.4be92c0.js', - 'soljson-v0.3.3-nightly.2016.5.28+commit.eb57a0c.js', - 'soljson-v0.3.2+commit.81ae2a7.js', - 'soljson-v0.3.2-nightly.2016.5.27+commit.4dc1cb1.js', - 'soljson-v0.3.2-nightly.2016.5.25+commit.3c2056c.js', - 'soljson-v0.3.2-nightly.2016.5.24+commit.86c65c9.js', - 'soljson-v0.3.2-nightly.2016.5.20+commit.e3c5418.js', - 'soljson-v0.3.2-nightly.2016.5.19+commit.7a51852.js', - 'soljson-v0.3.2-nightly.2016.5.18+commit.cb865fb.js', - 'soljson-v0.3.2-nightly.2016.5.17+commit.a37072.js', - 'soljson-v0.3.2-nightly.2016.5.13+commit.4b445b8.js', - 'soljson-v0.3.2-nightly.2016.5.12+commit.c06051d.js', - 'soljson-v0.3.2-nightly.2016.5.12+commit.73ede5b.js', - 'soljson-v0.3.2-nightly.2016.5.6+commit.9e36bdd.js', - 'soljson-v0.3.2-nightly.2016.5.5+commit.1b7e2d3.js', - 'soljson-v0.3.2-nightly.2016.5.3+commit.aa4dcbb.js', - 'soljson-v0.3.2-nightly.2016.5.1+commit.bee80f1.js', - 'soljson-v0.3.2-nightly.2016.4.22+commit.dd4300d.js', - 'soljson-v0.3.1+commit.c492d9b.js', - 'soljson-v0.3.1-nightly.2016.4.18+commit.81ae2a7.js', - 'soljson-v0.3.1-nightly.2016.4.15+commit.7ba6c98.js', - 'soljson-v0.3.1-nightly.2016.4.13+commit.9137506.js', - 'soljson-v0.3.1-nightly.2016.4.12+commit.3ad5e82.js', - 'soljson-v0.3.1-nightly.2016.4.7+commit.54bc2a.js', - 'soljson-v0.3.1-nightly.2016.4.5+commit.12797ed.js', - 'soljson-v0.3.1-nightly.2016.3.31+commit.c67926c.js', - 'soljson-v0.3.0+commit.11d6736.js', - 'soljson-v0.3.0-nightly.2016.3.30+commit.c2cf806.js', - 'soljson-v0.3.0-nightly.2016.3.30+commit.2acdfc5.js', - 'soljson-v0.3.0-nightly.2016.3.18+commit.e759a24.js', - 'soljson-v0.3.0-nightly.2016.3.11+commit.1f9578c.js', - 'soljson-v0.2.2+commit.ef92f56.js', - 'soljson-v0.2.2-nightly.2016.3.10+commit.34d714f.js', - 'soljson-v0.2.2-nightly.2016.3.2+commit.32f3a65.js', - 'soljson-v0.2.2-nightly.2016.3.1+commit.2bb315.js', - 'soljson-v0.2.2-nightly.2016.2.22+commit.8339330.js', - 'soljson-v0.2.2-nightly.2016.2.19+commit.3738107.js', - 'soljson-v0.2.2-nightly.2016.2.18+commit.565d717.js', - 'soljson-v0.2.1+commit.91a6b35.js', - 'soljson-v0.2.1-nightly.2016.2.13+commit.a14185a.js', - 'soljson-v0.2.1-nightly.2016.2.11+commit.c6c3c78.js', - 'soljson-v0.2.1-nightly.2016.2.10+commit.7b5d96c.js', - 'soljson-v0.2.1-nightly.2016.2.3+commit.fad2d4d.js', - 'soljson-v0.2.0+commit.4dc2445.js', - 'soljson-v0.2.0-nightly.2016.1.28+commit.bdbb7d8.js', - 'soljson-v0.2.0-nightly.2016.1.26+commit.9b9d10b.js', - 'soljson-v0.2.0-nightly.2016.1.24+commit.194679f.js', - 'soljson-v0.2.0-nightly.2016.1.20+commit.67c855c.js', - 'soljson-v0.2.0-nightly.2016.1.19+commit.d21c427.js', - 'soljson-v0.2.0-nightly.2016.1.18+commit.2340e8.js', - 'soljson-v0.2.0-nightly.2016.1.15+commit.cc4b4f5.js', - 'soljson-v0.2.0-nightly.2016.1.14+commit.ca45cfe.js', - 'soljson-v0.2.0-nightly.2016.1.13+commit.d2f18c7.js', - 'soljson-v0.2.0-nightly.2016.1.12+commit.2c1aac.js', - 'soljson-v0.2.0-nightly.2016.1.11+commit.aa645d1.js', - 'soljson-v0.2.0-nightly.2016.1.5+commit.b158e48.js', - 'soljson-v0.2.0-nightly.2016.1.4+commit.252bd14.js', - 'soljson-v0.2.0-nightly.2015.12.21+commit.6b711d0.js', - 'soljson-v0.2.0-nightly.2015.12.18+commit.6c6295b.js', - 'soljson-v0.2.0-nightly.2015.12.17+commit.fe23cc8.js', - 'soljson-v0.2.0-nightly.2015.12.15+commit.591a4f1.js', - 'soljson-v0.2.0-nightly.2015.12.14+commit.98684cc.js', - 'soljson-v0.2.0-nightly.2015.12.10+commit.e709895.js', - 'soljson-v0.2.0-nightly.2015.12.7+commit.15a1468.js', - 'soljson-v0.2.0-nightly.2015.12.6+commit.ba8bc45.js', - 'soljson-v0.2.0-nightly.2015.12.4+commit.2e4aa9.js', - 'soljson-v0.1.7+commit.b4e666c.js', - 'soljson-v0.1.7-nightly.2015.11.26+commit.f86451c.js', - 'soljson-v0.1.7-nightly.2015.11.24+commit.8d16c6e.js', - 'soljson-v0.1.7-nightly.2015.11.23+commit.2554d61.js', - 'soljson-v0.1.7-nightly.2015.11.19+commit.58110b2.js', - 'soljson-v0.1.6+commit.d41f8b7.js', - 'soljson-v0.1.6-nightly.2015.11.16+commit.c881d10.js', - 'soljson-v0.1.6-nightly.2015.11.12+commit.321b1ed.js', - 'soljson-v0.1.6-nightly.2015.11.7+commit.94ea61c.js', - 'soljson-v0.1.6-nightly.2015.11.3+commit.48ffa08.js', - 'soljson-v0.1.6-nightly.2015.11.2+commit.665344e.js', - 'soljson-v0.1.6-nightly.2015.10.27+commit.22723da.js', - 'soljson-v0.1.6-nightly.2015.10.26+commit.e77decc.js', - 'soljson-v0.1.6-nightly.2015.10.23+commit.7a9f8d9.js', - 'soljson-v0.1.6-nightly.2015.10.22+commit.cb8f663.js', - 'soljson-v0.1.5+commit.23865e3.js', - 'soljson-v0.1.5-nightly.2015.10.16+commit.52eaa47.js', - 'soljson-v0.1.5-nightly.2015.10.15+commit.984ab6a.js', - 'soljson-v0.1.5-nightly.2015.10.13+commit.e11e10f.js', - 'soljson-v0.1.4+commit.5f6c3cd.js', - 'soljson-v0.1.4-nightly.2015.10.6+commit.d35a4b8.js', - 'soljson-v0.1.4-nightly.2015.10.5+commit.a33d173.js', - 'soljson-v0.1.4-nightly.2015.10.5+commit.7ff6762.js', - 'soljson-v0.1.4-nightly.2015.10.2+commit.795c894.js', - 'soljson-v0.1.3+commit.28f561.js', - 'soljson-v0.1.3-nightly.2015.9.29+commit.3ff932c.js', - 'soljson-v0.1.3-nightly.2015.9.28+commit.4457170.js', - 'soljson-v0.1.3-nightly.2015.9.25+commit.4457170.js', - 'soljson-v0.1.2+commit.d0d36e3.js', - 'soljson-v0.1.1+commit.6ff4cd6.js', -]; - -const releases = { - '0.6.2': 'soljson-v0.6.2+commit.bacdbe57.js', - '0.6.1': 'soljson-v0.6.1+commit.e6f7d5a4.js', - '0.6.0': 'soljson-v0.6.0+commit.26b70077.js', - '0.5.16': 'soljson-v0.5.16+commit.9c3226ce.js', - '0.5.15': 'soljson-v0.5.15+commit.6a57276f.js', - '0.5.14': 'soljson-v0.5.14+commit.1f1aaa4.js', - '0.5.13': 'soljson-v0.5.13+commit.5b0b510c.js', - '0.5.12': 'soljson-v0.5.12+commit.7709ece9.js', - '0.5.11': 'soljson-v0.5.11+commit.c082d0b4.js', - '0.5.10': 'soljson-v0.5.10+commit.5a6ea5b1.js', - '0.5.9': 'soljson-v0.5.9+commit.e560f70d.js', - '0.5.8': 'soljson-v0.5.8+commit.23d335f2.js', - '0.5.7': 'soljson-v0.5.7+commit.6da8b019.js', - '0.5.6': 'soljson-v0.5.6+commit.b259423e.js', - '0.5.5': 'soljson-v0.5.5+commit.47a71e8f.js', - '0.5.4': 'soljson-v0.5.4+commit.9549d8ff.js', - '0.5.3': 'soljson-v0.5.3+commit.10d17f24.js', - '0.5.2': 'soljson-v0.5.2+commit.1df8f40c.js', - '0.5.1': 'soljson-v0.5.1+commit.c8a2cb62.js', - '0.5.0': 'soljson-v0.5.0+commit.1d4f565a.js', - '0.4.26': 'soljson-v0.4.26+commit.4563c3fc.js', - '0.4.25': 'soljson-v0.4.25+commit.59dbf8f1.js', - '0.4.24': 'soljson-v0.4.24+commit.e67f0147.js', - '0.4.23': 'soljson-v0.4.23+commit.124ca40d.js', - '0.4.22': 'soljson-v0.4.22+commit.4cb486ee.js', - '0.4.21': 'soljson-v0.4.21+commit.dfe3193c.js', - '0.4.20': 'soljson-v0.4.20+commit.3155dd80.js', - '0.4.19': 'soljson-v0.4.19+commit.c4cbbb05.js', - '0.4.18': 'soljson-v0.4.18+commit.9cf6e910.js', - '0.4.17': 'soljson-v0.4.17+commit.bdeb9e52.js', - '0.4.16': 'soljson-v0.4.16+commit.d7661dd9.js', - '0.4.15': 'soljson-v0.4.15+commit.bbb8e64f.js', - '0.4.14': 'soljson-v0.4.14+commit.c2215d46.js', - '0.4.13': 'soljson-v0.4.13+commit.fb4cb1a.js', - '0.4.12': 'soljson-v0.4.12+commit.194ff033.js', - '0.4.11': 'soljson-v0.4.11+commit.68ef5810.js', - '0.4.10': 'soljson-v0.4.10+commit.f0d539ae.js', - '0.4.9': 'soljson-v0.4.9+commit.364da425.js', - '0.4.8': 'soljson-v0.4.8+commit.60cc1668.js', - '0.4.7': 'soljson-v0.4.7+commit.822622cf.js', - '0.4.6': 'soljson-v0.4.6+commit.2dabbdf0.js', - '0.4.5': 'soljson-v0.4.5+commit.b318366e.js', - '0.4.4': 'soljson-v0.4.4+commit.4633f3de.js', - '0.4.3': 'soljson-v0.4.3+commit.2353da71.js', - '0.4.2': 'soljson-v0.4.2+commit.af6afb04.js', - '0.4.1': 'soljson-v0.4.1+commit.4fc6fc2c.js', - '0.4.0': 'soljson-v0.4.0+commit.acd334c9.js', - '0.3.6': 'soljson-v0.3.6+commit.3fc68da.js', - '0.3.5': 'soljson-v0.3.5+commit.5f97274.js', - '0.3.4': 'soljson-v0.3.4+commit.7dab890.js', - '0.3.3': 'soljson-v0.3.3+commit.4dc1cb1.js', - '0.3.2': 'soljson-v0.3.2+commit.81ae2a7.js', - '0.3.1': 'soljson-v0.3.1+commit.c492d9b.js', - '0.3.0': 'soljson-v0.3.0+commit.11d6736.js', - '0.2.2': 'soljson-v0.2.2+commit.ef92f56.js', - '0.2.1': 'soljson-v0.2.1+commit.91a6b35.js', - '0.2.0': 'soljson-v0.2.0+commit.4dc2445.js', - '0.1.7': 'soljson-v0.1.7+commit.b4e666c.js', - '0.1.6': 'soljson-v0.1.6+commit.d41f8b7.js', - '0.1.5': 'soljson-v0.1.5+commit.23865e3.js', - '0.1.4': 'soljson-v0.1.4+commit.5f6c3cd.js', - '0.1.3': 'soljson-v0.1.3+commit.28f561.js', - '0.1.2': 'soljson-v0.1.2+commit.d0d36e3.js', - '0.1.1': 'soljson-v0.1.1+commit.6ff4cd6.js', -}; - -export default { - allVersions: soljsonSources, - releases, -}; diff --git a/timber/src/utils-merkle-tree.mjs b/timber/src/utils-merkle-tree.mjs deleted file mode 100644 index 15a3ca54d..000000000 --- a/timber/src/utils-merkle-tree.mjs +++ /dev/null @@ -1,380 +0,0 @@ -/** -@module utils.js -@author iAmMichaelConnor -@desc Set of utilities for merkle-tree calculations -*/ - -/* eslint-disable no-bitwise */ // bit operations are essential for merkle-tree computations. - -import config from 'config'; -import utils from './utils.mjs'; -import logger from './logger.mjs'; - -function rightShift(integer, shift) { - return Math.floor(integer / 2 ** shift); -} - -function leftShift(integer, shift) { - return integer * 2 ** shift; -} - -// INDEX CONVERSIONS - -function leafIndexToNodeIndex(_leafIndex, _height) { - const leafIndex = Number(_leafIndex); - const treeWidth = 2 ** _height; - return leafIndex + treeWidth - 1; -} - -function nodeIndexToLeafIndex(_nodeIndex, _height) { - const nodeIndex = Number(_nodeIndex); - const treeWidth = 2 ** _height; - return nodeIndex + 1 - treeWidth; -} - -// function nodeIndexToRow(_nodeIndex) { -// const nodeIndex = Number(_nodeIndex); -// return Math.floor(Math.log2(nodeIndex + 1)); -// } - -// function nodeIndexToLevel(_nodeIndex) { -// const row = nodeIndexToRow(_nodeIndex); -// return treeHeight - row; -// } - -// 'DECIMAL' NODE INDICES - -function siblingNodeIndex(_nodeIndex) { - const nodeIndex = Number(_nodeIndex); - /* - odd? then the node is a left-node, so sibling is to the right. - even? then the node is a right-node, so sibling is to the left. - */ - return nodeIndex % 2 === 1 ? nodeIndex + 1 : nodeIndex - 1; -} - -function parentNodeIndex(_nodeIndex) { - const nodeIndex = Number(_nodeIndex); - return nodeIndex % 2 === 1 ? rightShift(nodeIndex, 1) : rightShift(nodeIndex - 1, 1); -} - -function leftChildNodeIndex(_nodeIndex) { - const nodeIndex = Number(_nodeIndex); - return leftShift(nodeIndex, 1) + 1; -} - -function rightChildNodeIndex(_nodeIndex) { - const nodeIndex = Number(_nodeIndex); - return leftShift(nodeIndex, 1) + 2; -} - -// BINARY INDICES - -function siblingBinaryIndex(binaryIndex) { - /* - even? then the node is a left-node, so sibling is to the right. - odd? then the node is a right-node, so sibling is to the left. - */ - return binaryIndex % 2 === 0 ? binaryIndex + 1 : binaryIndex - 1; -} - -function parentBinaryIndex(binaryIndex) { - // the root has no binary index; it's a special case - if (binaryIndex === 0 || binaryIndex === 1) return 'root'; - - return rightShift(binaryIndex, 1); -} - -function leftChildBinaryIndex(binaryIndex) { - // the root is a special case with no binary index; it's input as a string 'root' - if (binaryIndex === 'root') return 0; - - return leftShift(binaryIndex, 1); -} - -function rightChildBinaryIndex(binaryIndex) { - // the root is a special case with no binary index; it's input as a string 'root' - if (binaryIndex === 'root') return 1; - - return leftShift(binaryIndex, 1) + 1; -} - -// COMPLEX TREE FUNCTIONS - -/** -Recursively calculate the indices of the path from a particular leaf up to the root. -@param {integer} nodeIndex - the nodeIndex of the leaf for which we wish to calculate the siblingPathIndices. Not to be confused with leafIndex. -*/ -function getPathIndices(_nodeIndex) { - const nodeIndex = Number(_nodeIndex); - if (nodeIndex === 0) return [0]; // terminal case - - const indices = getPathIndices(parentNodeIndex(nodeIndex)); - - // push this node to the final output array, as we escape from the recursion: - indices.push(nodeIndex); - return indices; -} - -/** -Recursively calculate the indices of the sibling path of a particular leaf up to the root. -@param {integer} nodeIndex - the nodeIndex of the leaf for which we wish to calculate the siblingPathIndices. Not to be confused with leafIndex. -*/ -function getSiblingPathIndices(_nodeIndex) { - const nodeIndex = Number(_nodeIndex); - if (nodeIndex === 0) return [0]; // terminal case - - const indices = getSiblingPathIndices(parentNodeIndex(nodeIndex)); - - // push the sibling of this node to the final output array, as we escape from the recursion: - indices.push(siblingNodeIndex(nodeIndex)); - return indices; -} - -/** -A js implementation of the corresponding Solidity function in MerkleTree.sol -*/ -function getFrontierSlot(leafIndex) { - let slot = 0; - if (leafIndex % 2 === 1) { - let exp1 = 1; - let pow1 = 2; - let pow2 = pow1 << 1; - while (slot === 0) { - if ((leafIndex + 1 - pow1) % pow2 === 0) { - slot = exp1; - } else { - pow1 = pow2; - pow2 <<= 1; - exp1 += 1; - } - } - } - return slot; -} - -/** - * Special function which calculates the root from a given frontier and the - * corresponding leafIndex of the right-most leaf at the time the frontier was * solidified. - * @param {Array} frontier - * @param {Number} leafIndex - * @param {Number} height - the height of the tree - */ -function calculateRootFromFrontier(frontier, leafIndex, height) { - logger.debug(`\nsrc/utils-merkle-tree calculateRootFromFrontier()`); - - // get the lowest level of the frontier which can be hashed against a zero. We'll then begin hashing from that level to get the root. - const slot = getFrontierSlot(leafIndex); - - let nodeValue = frontier[slot]; - let nodeIndex = leafIndexToNodeIndex(leafIndex, height); - - // We only know the leaf's nodeIndex, but we want the nodeIndex of the leaf's ancestor at the level = `slot`. - for (let level = 1; level <= slot; level++) { - nodeIndex = parentNodeIndex(nodeIndex); // skipped over if the slot = 0. - } - - let nodeValueFull; // full bit-length (not yet truncated) - for (let level = slot + 1; level <= height; level++) { - if (nodeIndex % 2 === 0) { - // even nodeIndex - nodeValueFull = utils.concatenateThenHash(frontier[level - 1], nodeValue); // the parentValue, but will become the nodeValue of the next level - } else { - // odd nodeIndex - nodeValueFull = utils.concatenateThenHash(nodeValue, config.ZERO); // the parentValue, but will become the nodeValue of the next level - } - nodeValue = utils.ensure0x(nodeValueFull.slice(-config.NODE_HASHLENGTH * 2)); // truncate hashed value, so it 'fits' into the next hash. - nodeIndex = parentNodeIndex(nodeIndex); // move one row up the tree - } - - return nodeValueFull; // the root -} - -/** -A js implementation of the corresponding Solidity function in MerkleTree.sol -*/ -async function updateNodes(leafValues, currentLeafCount, frontier, height, updateNodesFunction) { - logger.debug(`\nsrc/utils-merkle-tree updateNodes()`); - const treeWidth = 2 ** height; - const newFrontier = frontier; - - // check that space exists in the tree: - const numberOfLeavesAvailable = treeWidth - currentLeafCount; - const numberOfLeaves = Math.min(leafValues.length, numberOfLeavesAvailable); - - let slot; - let nodeIndex; - let nodeValueFull; // the node value before truncation (truncation is sometimes done so that the nodeValue (when concatenated with another) fits into a single hashing round in the next hashing iteration up the tree). - let nodeValue; // the truncated nodeValue - - // consider each new leaf in turn, from left to right: - for ( - let leafIndex = currentLeafCount; - leafIndex < currentLeafCount + numberOfLeaves; - leafIndex++ - ) { - nodeValueFull = leafValues[leafIndex - currentLeafCount]; - logger.silly(`nodeValueFull: ${nodeValueFull}, hashlength: ${config.NODE_HASHLENGTH}`); - if (!utils.isHex(nodeValueFull)) { - nodeValueFull = utils.convertBase(nodeValueFull.toString(), 10, 16); - logger.silly(`nodeValueFull: ${nodeValueFull}, hashlength: ${config.NODE_HASHLENGTH}`); - } - nodeValue = utils.ensure0x(nodeValueFull.slice(-config.NODE_HASHLENGTH * 2)); // truncate hashed value, so it 'fits' into the next hash. - logger.silly(`nodeValue: ${nodeValue})`); - nodeIndex = leafIndexToNodeIndex(leafIndex, height); // convert the leafIndex to a nodeIndex - - slot = getFrontierSlot(leafIndex); // determine at which level we will next need to store a nodeValue - - if (slot === 0) { - logger.silly('below slot'); - logger.silly('level 0'); - logger.silly(`slot: ${slot}`); - newFrontier[slot] = nodeValue; // store in frontier - logger.silly(`frontier ${JSON.stringify(frontier, null, 2)}`); - continue; // eslint-disable-line no-continue - } - - // hash up to the level whose nodeValue we'll store in the frontier slot: - for (let level = 1; level <= slot; level++) { - logger.silly('below slot'); - logger.silly(`level ${level}`); - logger.silly(`slot ${slot}`); - if (nodeIndex % 2 === 0) { - // even nodeIndex - logger.silly(`leafIndex ${leafIndex}`); - logger.silly(`nodeIndex ${nodeIndex}`); - logger.silly(`left input ${frontier[level - 1]}`); - logger.silly(`right input ${nodeValue}`); - nodeValueFull = utils.concatenateThenHash(frontier[level - 1], nodeValue); // the parentValue, but will become the nodeValue of the next level - nodeValue = utils.ensure0x(nodeValueFull.slice(-config.NODE_HASHLENGTH * 2)); // truncate hashed value, so it 'fits' into the next hash. - logger.silly(`output ${nodeValue}`); - } else { - // odd nodeIndex - logger.silly(`leafIndex ${leafIndex}`); - logger.silly(`nodeIndex ${nodeIndex}`); - logger.silly(`left input ${nodeValue}`); - logger.silly(`right input ${config.ZERO}`); - nodeValueFull = utils.concatenateThenHash(nodeValue, config.ZERO); // the parentValue, but will become the nodeValue of the next level - nodeValue = utils.ensure0x(nodeValueFull.slice(-config.NODE_HASHLENGTH * 2)); // truncate hashed value, so it 'fits' into the next hash. - logger.silly(`output ${nodeValue}`); - } - nodeIndex = parentNodeIndex(nodeIndex); // move one row up the tree - - // add the node to the db: - const node = { - value: nodeValue, - nodeIndex, - }; - if (!updateNodesFunction) { - // e.g. for use NOT with a db - logger.silly(node); - } else { - await updateNodesFunction(node); // eslint-disable-line no-await-in-loop - } - } - - newFrontier[slot] = nodeValue; // store in frontier - logger.silly(`frontier, ${JSON.stringify(frontier, null, 2)}`); - } - - // So far we've added all leaves, and hashed up to a particular level of the tree. We now need to continue hashing from that level until the root: - for (let level = slot + 1; level <= height; level++) { - logger.silly('above slot'); - logger.silly(`level, ${level}`); - logger.silly(`slot, ${slot}`); - if (nodeIndex % 2 === 0) { - // even nodeIndex - logger.silly(`nodeIndex, ${nodeIndex}`); - logger.silly(`left input, ${frontier[level - 1]}`); - logger.silly(`right input, ${nodeValue}`); - nodeValueFull = utils.concatenateThenHash(frontier[level - 1], nodeValue); // the parentValue, but will become the nodeValue of the next level - nodeValue = `0x${nodeValueFull.slice(-config.NODE_HASHLENGTH * 2)}`; // truncate hashed value, so it 'fits' into the next hash. - logger.silly(`output: ${nodeValue}`); - } else { - // odd nodeIndex - logger.silly(`nodeIndex, ${nodeIndex}`); - logger.silly(`left input, ${nodeValue}`); - logger.silly(`right input, ${config.ZERO}`); - nodeValueFull = utils.concatenateThenHash(nodeValue, config.ZERO); // the parentValue, but will become the nodeValue of the next level - nodeValue = `0x${nodeValueFull.slice(-config.NODE_HASHLENGTH * 2)}`; // truncate hashed value, so it 'fits' into the next hash. - logger.silly(`output, ${nodeValue}`); - } - nodeIndex = parentNodeIndex(nodeIndex); // move one row up the tree - const node = { - value: nodeIndex === 0 ? nodeValueFull : nodeValue, // we can add the full 32-byte root (nodeIndex=0) to the db, because it doesn't need to fit into another hash round. - nodeIndex, - }; - if (!updateNodesFunction) { - logger.debug(`node, ${node}`); - } else { - // add the node to the db - await updateNodesFunction(node); // eslint-disable-line no-await-in-loop - } - } - const root = nodeValueFull; - logger.debug(`root: ${root}`); - - return [root, newFrontier]; -} - -/** -Calculates the exact number of hashes required to add a consecutive batch of leaves to a tree -@param {integer} maxLeafIndex - the highest leafIndex of the batch -@param {integer} minLeafIndex - the lowest leafIndex of the batch -@param {integer} height - the height of the merkle tree -*/ -function getNumberOfHashes(maxLeafIndex, minLeafIndex, height) { - let hashCount = 0; - let increment; - let hi = Number(maxLeafIndex); - let lo = Number(minLeafIndex); - const batchSize = hi - lo + 1; - const binHi = hi.toString(2); // converts to binary - const bitLength = binHi.length; - - for (let level = 0; level < bitLength; level += 1) { - increment = hi - lo; - hashCount += increment; - hi = rightShift(hi, 1); - lo = rightShift(lo, 1); - } - return hashCount + height - (batchSize - 1); -} - -/** -For debugging the correctness of getNumberOfHashes: Loops through a calculation of the numberOfHashes for a given batch size, at every leafIndex of the tree. -@param {integer} batchSize - the number of leaves in the batch -@param {integer} height - the height of the merkle tree -*/ -function loopNumberOfHashes(batchSize, height) { - let lo; - let hi; - const width = 2 ** height; - for (let i = 0; i < width - batchSize + 1; i += 1) { - lo = i; - hi = i + batchSize - 1; - const numberOfHashes = getNumberOfHashes(hi, lo, height); - logger.silly(`(${hi}, ${lo}) = ${numberOfHashes}`); - } - return true; -} - -export default { - leafIndexToNodeIndex, - nodeIndexToLeafIndex, - siblingNodeIndex, - parentNodeIndex, - leftChildNodeIndex, - rightChildNodeIndex, - siblingBinaryIndex, - parentBinaryIndex, - leftChildBinaryIndex, - rightChildBinaryIndex, - getPathIndices, - getSiblingPathIndices, - getFrontierSlot, - calculateRootFromFrontier, - updateNodes, - getNumberOfHashes, - loopNumberOfHashes, -}; diff --git a/timber/src/utils-poll.mjs b/timber/src/utils-poll.mjs deleted file mode 100644 index 95ff34e5a..000000000 --- a/timber/src/utils-poll.mjs +++ /dev/null @@ -1,81 +0,0 @@ -/** -@module utils-poll.js contains all of the logic for starting and stopping a poll. -@author iAmMichaelConnor -*/ -import logger from './logger.mjs'; -/** -@param {function} pollingFunction - function MUST return false for 'unsuccessful' results. -@param {number} interval - polling frequency (in milliseconds) -@param {object} args = an object of arguments which are to be passed to the pollingFunction each poll. -*/ -const poll = async (pollingFunction, interval, args) => { - logger.info('Polling...'); - // this is called as a Promise which only resolves when the conditions of the pollingFunction have been satisfied (i.e. once the pollingFunction returns something other than false). - const checkPollCondition = async (resolve, reject) => { - const response = await pollingFunction(args); // polling function must return a FALSE if unsuccessful. - if (response === false) { - // if the polling function was unsuccessful, poll again: - logger.info('...'); - setTimeout(checkPollCondition, interval, resolve, reject); - } else { - // if the polling function was successful, resolve this poll. - resolve(response); - } - }; - return new Promise(checkPollCondition); -}; - -// EXAMPLES - -let exampleResponse; -let delayIncrementer = 1000; - -const exampleDelayToResolution = async () => { - exampleResponse = false; - setTimeout(() => { - exampleResponse = true; - }, 25000); -}; - -function delayedPromise(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -const exampleQueryDelay = async () => { - await delayedPromise(delayIncrementer); - delayIncrementer *= 2; - return exampleResponse; -}; - -const exampleQuery = async () => { - const response = await exampleQueryDelay(); - return response; -}; - -/** -EXAMPLE ONLY - an example of a pollingFunction -@returns {boolean} - ALWAYS!!! -*/ -const examplePollingFunction = async () => { - logger.debug('in pollingFunction'); - const response = await exampleQuery(); - logger.silly(`response: ${response}`); - return response; -}; - -/** -EXAMPLE ONLY - an invokation of a poll -Execute from command line with: - -node -e 'require("./utils-poll").examplePoll()' - -*/ -async function examplePoll() { - exampleDelayToResolution(); - await poll(examplePollingFunction, 1000); -} - -export default { - examplePoll, - poll, -}; diff --git a/timber/src/utils-web3.mjs b/timber/src/utils-web3.mjs deleted file mode 100644 index 6d4e341a5..000000000 --- a/timber/src/utils-web3.mjs +++ /dev/null @@ -1,281 +0,0 @@ -/** -@module utils-web3.js -@author MichaelConnorOfficial -@desc Set of utilities to make web3 methods easier to use -*/ - -// First we need to connect to a websocket provider. -// Important Note: Subscribe method only works with a websocket provider! - -import fs from 'fs'; -import Web3 from './web3.mjs'; -import logger from './logger.mjs'; - -const web3 = Web3.connect(); - -// GETTERS!!! - -/** -@returns {Number} Returns the current block number. -*/ -async function getBlockNumber() { - const blockNumber = await web3.eth.getBlockNumber(); - return blockNumber; -} - -/** -Returns a block matching the block number or block hash. -@param {String|Number} blockHashOrBlockNumber The block number or block hash. Or the string "genesis", "latest" or "pending" as in the default block parameter. -@param {Boolean} returnTransactionObjects - (optional, default false) If true, the returned block will contain all transactions as objects, if false it will only contains the transaction hashes. -@returns {Object} Block. Returns a block matching the block number or block hash. -*/ -async function getBlock(blockHashOrBlockNumber, returnTransactionObjects) { - const block = await web3.eth.getBlock(blockHashOrBlockNumber, returnTransactionObjects); - return block; -} - -/** -Returns a block matching the block number or block hash. -@param {String|Number} blockHashOrBlockNumber The block number or block hash. Or the string "genesis", "latest" or "pending" as in the default block parameter. -@returns {Number} Returns the number of transactions in a given block. -*/ -async function getBlockTransactionCount(blockHashOrBlockNumber) { - const blockTxCount = await web3.eth.getBlockTransactionCount(blockHashOrBlockNumber); - return blockTxCount; -} - -/** -Returns a block matching the block number or block hash. -@param {String|Number} hashStringOrNumber A block number or hash. Or the string "genesis", "latest" or "pending" as in the default block parameter. -@param {Number} indexNumber - The transactions index position. -@returns {Object} Returns a transaction object based on a block hash or number and the transactions index position. -*/ -async function getTransactionFromBlock(hashStringOrNumber, indexNumber) { - logger.debug(`Getting transaction ${indexNumber} from Block ${hashStringOrNumber}`); - - const txReceipt = await web3.eth.getTransactionFromBlock(hashStringOrNumber, indexNumber); - - logger.silly(`txReceipt.input: ${JSON.stringify(txReceipt.input, null, 2)}`); - - return txReceipt; -} - -// EVENTS!!! - -// a list for saving subscribed event instances -let events = {}; - -function getContractInterface(contractName) { - logger.debug(`./src/utils-web3 getContractInterface(${contractName})`); - - const path = `./build/contracts/${contractName}.json`; - const contractInterface = JSON.parse(fs.readFileSync(path)); - logger.silly(`contractInterface: ${JSON.stringify(contractInterface, null, 2)}`); - return contractInterface; -} - -async function getContractAddress(contractName) { - logger.debug(`./src/utils-web3 getContractAddress(${contractName})`); - let deployedAddress; - const contractInterface = getContractInterface(contractName); - - const networkId = await web3.eth.net.getId(); - logger.silly(`networkId: ${networkId}`); - - if (contractInterface && contractInterface.networks && contractInterface.networks[networkId]) { - deployedAddress = contractInterface.networks[networkId].address; - } - - logger.silly(`deployed address: ${deployedAddress}`); - - return deployedAddress; -} - -// returns a web3 contract instance (as opposed to a truffle-contract instance) -async function getContractInstance(contractName, deployedAddress) { - logger.debug(`./src/utils-web3 getContractInstance(${contractName}, ${deployedAddress})`); - - // interface: - const contractInterface = getContractInterface(contractName); - - // address: - // eslint-disable-next-line no-param-reassign - if (!deployedAddress) deployedAddress = await getContractAddress(contractName); - - // instance: - let contractInstance; - - if (!deployedAddress) { - contractInstance = new web3.eth.Contract(contractInterface.abi); - } else { - contractInstance = new web3.eth.Contract(contractInterface.abi, deployedAddress); - } - return contractInstance; -} - -// returns a web3 contract instance (rather than a truffle-contract instance) -function getContractBytecode(contractName) { - const contractInterface = getContractInterface(contractName); - const { bytecode } = contractInterface; - logger.silly(`bytecode: ${JSON.stringify(bytecode, null, 2)}`); - return bytecode; -} - -function addNewEvent(eventObject) { - const { blockNumber } = eventObject.eventData; - const { address } = eventObject.eventData; - const eventName = eventObject.eventData.event; - - events[address] = events[address] === undefined ? {} : events[address]; - - events[address][eventName] = - events[address][eventName] === undefined ? {} : events[address][eventName]; - - events[address][eventName][blockNumber] = - events[address][eventName][blockNumber] === undefined - ? [] - : events[address][eventName][blockNumber]; - - events[address][eventName][blockNumber].push(eventObject); - - return events; -} - -async function subscribeToEvent( - contractName, - contractInstance, - deployedAddress, - eventName, - fromBlock = null, - responder, - responseFunction, - responseFunctionArgs = {}, - removerFunction, -) { - logger.info(`Subscribing to event...`); - logger.info(`contractName: ${contractName}`); - logger.info(`eventName: ${eventName}`); - logger.info(`fromBlock: ${fromBlock}`); - - if (!contractInstance) { - logger.info( - `Contract instance not provided. Generating a contractInstance from the contractName ${contractName} and deployedAddress ${deployedAddress}...`, - ); - contractInstance = getContractInstance(contractName, deployedAddress); // eslint-disable-line no-param-reassign - } else { - logger.info(`Contract instance provided.`); - deployedAddress = contractInstance._address; // eslint-disable-line no-param-reassign, no-underscore-dangle - logger.info(deployedAddress); - } - - /* - We use the eventJsonInterface to extract the event's topic signature, in order to subscribe. - - eventJsonInterface object example: - { anonymous: false, - inputs: - [ { indexed: true, name: 'myEventParam1', type: 'uint256' }, - { indexed: true, name: 'myEventParam2', type: 'bytes32' }, - { indexed: true, name: 'myEventParam3', type: 'address' }, - { indexed: false, name: 'myEventParam4', type: 'bytes1' }, - { indexed: false, - name: 'myEventParam5', - type: 'uint256[]' } ], - name: 'MyEventName', - type: 'event', - signature: '0x881cc8af0159324ccea314ad98a0cf26fe0e460c2afa693c92f591613d4de7b2' } - */ - const eventJsonInterface = web3.utils._.find( - contractInstance._jsonInterface, // eslint-disable-line no-underscore-dangle - o => o.name === eventName && o.type === 'event', - ); - - logger.silly(`eventJsonInterface: ${JSON.stringify(eventJsonInterface, null, 2)}`); - - const eventSubscription = await contractInstance.events[eventName]({ - fromBlock, - topics: [eventJsonInterface.signature], - }); - - /* eventData example - { - returnValues: { - myIndexedParam: 20, - myOtherIndexedParam: '0x123456789...', - myNonIndexParam: 'My String' - }, - raw: { - data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385', - topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385'] - }, - event: 'MyEvent', - signature: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', - logIndex: 0, - transactionIndex: 0, - transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385', - blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', - blockNumber: 1234, - address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe' - } - */ - eventSubscription.on('data', eventData => { - logger.info(`New ${contractName}, ${eventName}, event detected`); - logger.silly(`Event Data: ${JSON.stringify(eventData, null, 2)}`); - - const eventObject = { - eventData, - eventJsonInterface, - }; - - // let's add the eventObject to the list of events: - events = addNewEvent(eventObject, events); - - logger.silly(`events: ${JSON.stringify(events, null, 2)}, { depth: null }`); - - responder(eventObject, responseFunction, responseFunctionArgs); - }); - // we also need to listen for changes to events, which happens if we get a - // chain reorg that removes the event. - eventSubscription.on('changed', eventData => { - logger.info(`New ${contractName}, ${eventName}, event removal`); - const eventObject = { - eventData, - eventJsonInterface, - }; - responder(eventObject, removerFunction, responseFunctionArgs); - }); - - return eventSubscription; -} - -async function unsubscribe(subscription) { - logger.debug('Unsubscribing...'); - if (!subscription) { - logger.warn('There is nothing to unsubscribe from'); - return; - } - logger.silly(JSON.stringify(subscription, null, 2)); - // unsubscribes the subscription - await subscription.unsubscribe((error, success) => { - logger.silly(`we're in subscription.unsubscribe, ${error}, ${success}`); - if (success) { - logger.info('Successfully unsubscribed!'); - } - if (error) { - throw new Error(error); - } - }); -} - -export default { - getBlockNumber, - getBlock, - getBlockTransactionCount, - getTransactionFromBlock, - getContractInterface, - getContractAddress, - getContractInstance, - getContractBytecode, - subscribeToEvent, - unsubscribe, -}; diff --git a/timber/src/utils.mjs b/timber/src/utils.mjs deleted file mode 100644 index 195087720..000000000 --- a/timber/src/utils.mjs +++ /dev/null @@ -1,288 +0,0 @@ -/** -@module utils.js -@author Westlad,Chaitanya-Konda,iAmMichaelConnor -@desc Set of utilities -*/ -import config from 'config'; -import createKeccakHash from 'keccak'; -import crypto from 'crypto'; -import safeBuffer from 'safe-buffer'; -import logger from './logger.mjs'; - -const { Buffer } = safeBuffer; - -// BW6 not yet implemented - -const mimcCurves = { - BLS12_377: { - exponent: 11, - rounds: 74, - modulus: BigInt('8444461749428370424248824938781546531375899335154063827935233455917409239041'), - }, - ALT_BN_254: { - exponent: 7, - rounds: 91, - modulus: BigInt( - '21888242871839275222246405745257275088548364400416034343698204186575808495617', - ), - }, - BW6_761: { - exponent: 23, - rounds: 84, - modulus: BigInt( - '258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177', - ), - }, -}; - -function parseToDigitsArray(str, base) { - const digits = str.split(''); - const ary = []; - for (let i = digits.length - 1; i >= 0; i -= 1) { - const n = parseInt(digits[i], base); - if (Number.isNaN(n)) return null; - ary.push(n); - } - return ary; -} - -function add(x, y, base) { - const z = []; - const n = Math.max(x.length, y.length); - let carry = 0; - let i = 0; - while (i < n || carry) { - const xi = i < x.length ? x[i] : 0; - const yi = i < y.length ? y[i] : 0; - const zi = carry + xi + yi; - z.push(zi % base); - carry = Math.floor(zi / base); - i += 1; - } - return z; -} - -/** Helper function for the converting any base to any base - Returns a*x, where x is an array of decimal digits and a is an ordinary - JavaScript number. base is the number base of the array x. - */ -function multiplyByNumber(num, x, base) { - if (num < 0) return null; - if (num === 0) return []; - - let result = []; - let power = x; - // eslint-disable-next-line no-constant-condition - while (true) { - // eslint-disable-next-line no-bitwise - if (num & 1) { - result = add(result, power, base); - } - num >>= 1; // eslint-disable-line - if (num === 0) break; - power = add(power, power, base); - } - return result; -} - -/** Helper function for the converting any base to any base - */ -function convertBase(str, fromBase, toBase) { - const digits = parseToDigitsArray(str, fromBase); - if (digits === null) return null; - - let outArray = []; - let power = [1]; - for (let i = 0; i < digits.length; i += 1) { - // invariant: at this point, fromBase^i = power - if (digits[i]) { - outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase); - } - power = multiplyByNumber(fromBase, power, toBase); - } - - let out = ''; - for (let i = outArray.length - 1; i >= 0; i -= 1) { - out += outArray[i].toString(toBase); - } - // if the original input was equivalent to zero, then 'out' will still be empty ''. Let's check for zero. - if (out === '') { - let sum = 0; - for (let i = 0; i < digits.length; i += 1) { - sum += digits[i]; - } - if (sum === 0) out = '0'; - } - - return out; -} - -/** -utility function to check that a string has a leading 0x (which the Solidity -compiler uses to check for a hex string). It adds it if it's not present. If -it is present then it returns the string unaltered -*/ -function ensure0x(hex = '') { - const hexString = hex.toString(); - if (typeof hexString === 'string' && hexString.indexOf('0x') !== 0) { - return `0x${hexString}`; - } - return hexString; -} - -// Converts integer value strings to hex values -function decToHex(decStr) { - const hex = ensure0x(convertBase(decStr, 10, 16)); - return hex; -} - -/** -utility function to remove a leading 0x on a string representing a hex number. -If no 0x is present then it returns the string un-altered. -*/ -function strip0x(hex) { - if (typeof hex === 'undefined') return ''; - if (typeof hex === 'string' && hex.indexOf('0x') === 0) { - return hex.slice(2).toString(); - } - return hex.toString(); -} - -/** -utility function to check that a string is hexadecimal -*/ -function isHex(value) { - if (typeof value !== 'string') return false; - if (value.indexOf('0x') !== 0) return false; - const regexp = /^[0-9a-fA-F]+$/; - return regexp.test(strip0x(value)); -} - -/** -Utility function to concatenate two hex strings and return as buffer -Looks like the inputs are somehow being changed to decimal! -*/ -function concatenate(a, b) { - const length = a.length + b.length; - const buffer = Buffer.allocUnsafe(length); // creates a buffer object of length 'length' - for (let i = 0; i < a.length; i += 1) { - buffer[i] = a[i]; - } - for (let j = 0; j < b.length; j += 1) { - buffer[a.length + j] = b[j]; - } - return buffer; -} - -/** -Utility function to: -- convert each item in items to a 'buffer' of bytes (2 hex values), convert those bytes into decimal representation -- 'concatenate' each decimally-represented byte together into 'concatenated bytes' -- hash the 'buffer' of 'concatenated bytes' (sha256) (sha256 returns a hex output) -- truncate the result to the right-most 64 bits -Return: -createHash: we're creating a sha256 hash -update: [input string to hash (an array of bytes (in decimal representaion) [byte, byte, ..., byte] which represents the result of: item1, item2, item3. Note, we're calculating hash(item1, item2, item3) ultimately] -digest: [output format ("hex" in our case)] -slice: [begin value] outputs the items in the array on and after the 'begin value' -*/ -function addMod(addMe, m) { - return addMe.reduce((e, acc) => (e + acc) % m, BigInt(0)); -} - -function powerMod(base, exponent, m) { - if (m === BigInt(1)) return BigInt(0); - let result = BigInt(1); - let b = base % m; - let e = exponent; - while (e > BigInt(0)) { - if (e % BigInt(2) === BigInt(1)) result = (result * b) % m; - e >>= BigInt(1); // eslint-disable-line no-bitwise - b = (b * b) % m; - } - return result; -} - -function keccak256Hash(item) { - const preimage = strip0x(item); - const h = `0x${createKeccakHash('keccak256').update(preimage, 'hex').digest('hex')}`; - return h; -} - -/** -mimc encryption function -@param {String} x - the input value -@param {String} k - the key value -@param {String} seed - input seed for first round (=0n for a hash) -@param {int} exponent - the exponent -*/ -function mimcpe(x, k, seed, roundCount, exponent, m) { - let xx = x; - let t; - let c = seed; - for (let i = 0; i < roundCount; i++) { - c = keccak256Hash(c); - t = addMod([xx, BigInt(c), k], m); // t = x + c_i + k - xx = powerMod(t, BigInt(exponent), m); // t^7 - } - // Result adds key again as blinding factor - return addMod([xx, k], m); -} - -function mimcpemp(x, k, seed, roundCount, exponent, m) { - let r = k; - let i; - for (i = 0; i < x.length; i++) { - r = (r + (x[i] % m) + mimcpe(x[i], r, seed, roundCount, exponent, m)) % m; - } - return r; -} - -function mimcHash(...msgs) { - const { rounds, exponent, modulus } = !config.CURVE - ? mimcCurves.ALT_BN_254 - : mimcCurves[config.CURVE]; - logger.silly(`curve: ${config.CURVE} rounds: ${rounds} exp ${exponent} mod ${modulus}`); - const mimc = '0x6d696d63'; // this is 'mimc' in hex as a nothing-up-my-sleeve seed - return `0x${mimcpemp( - msgs.map(BigInt), - BigInt(0), // k - keccak256Hash(mimc), // seed - rounds, // rounds of hashing - exponent, // exponent - modulus, // modulus - ) - .toString(16) // hex string - can remove 0s - .padStart(64, '0')}`; // so pad -} - -function shaHash(...items) { - const concatvalue = items - .map(item => Buffer.from(strip0x(item), 'hex')) - .reduce((acc, item) => concatenate(acc, item)); - - const h = `0x${crypto.createHash('sha256').update(concatvalue, 'hex').digest('hex')}`; - return h; -} - -function concatenateThenHash(...items) { - let h; - if (config.HASH_TYPE === 'mimc') { - h = mimcHash(...items); - } else { - h = shaHash(...items); - } - return h; -} - -export default { - convertBase, - decToHex, - ensure0x, - strip0x, - isHex, - concatenate, - mimcHash, - shaHash, - concatenateThenHash, -}; diff --git a/timber/src/web3.mjs b/timber/src/web3.mjs deleted file mode 100644 index e83ad6f94..000000000 --- a/timber/src/web3.mjs +++ /dev/null @@ -1,60 +0,0 @@ -/** -@module web3.js -@desc -@author liju jose -*/ - -import Web3 from 'web3'; -import config from 'config'; -import logger from './logger.mjs'; - -const { INFURA_PROJECT_SECRET } = process.env; - -export default { - connection() { - return this.web3; - }, - - /** - * Connects to web3 and then sets proper handlers for events - */ - connect() { - if (this.web3) return this.web3; - - logger.info('Blockchain Connecting ...'); - - let provider; - if (config.USE_INFURA) { - if (!INFURA_PROJECT_SECRET) throw Error('env INFURA_PROJECT_SECRET not set'); - - provider = new Web3.providers.WebsocketProvider(config.web3.url, { - ...config.web3.options, - headers: { - authorization: `Basic ${Buffer.from(`:${INFURA_PROJECT_SECRET}`).toString('base64')}`, - }, - }); - } else { - provider = new Web3.providers.WebsocketProvider(config.web3.url, config.web3.options); - } - - provider.on('error', err => logger.error(err)); - provider.on('connect', () => logger.info('Blockchain Connected ...')); - provider.on('end', () => logger.error('Blockchain Disconnected')); - - this.web3 = new Web3(provider); - - return this.web3; - }, - - /** - * Checks the status of connection - * - * @return {Boolean} - Resolves to true or false - */ - isConnected() { - if (this.web3) { - return this.web3.eth.net.isListening(); - } - return false; - }, -}; diff --git a/timber/src/web3.notes b/timber/src/web3.notes deleted file mode 100644 index 7dabf2722..000000000 --- a/timber/src/web3.notes +++ /dev/null @@ -1,132 +0,0 @@ -/** -MIKE'S NOTES ON USEFUL WEB3 FUNCTIONS, AND THE OBJECTS THEY PRODUCE: - -web3.eth.getBlockNumber([callback]) // Returns the current block number. -// web3.eth.getCode(address [, defaultBlock] [, callback]) //gets bytecode (not needed) -web3.eth.getBlock(blockHashOrBlockNumber [, returnTransactionObjects] [, callback]) // Returns a block matching the block number or block hash. -web3.eth.getBlockTransactionCount(blockHashOrBlockNumber [, callback]) // Returns the number of transaction in a given block. -//web3.eth.getTransaction(transactionHash [, callback]) // Returns a transaction matching the given transaction hash. -web3.eth.getTransactionFromBlock(hashStringOrNumber, indexNumber [, callback]) // Returns a transaction based on a block hash or number and the transactions index position. -//web3.eth.getTransactionReceipt(hash [, callback]) // Returns the receipt of a transaction by transaction hash. -web3.eth.call(callObject [, defaultBlock] [, callback]) // Executes a message call transaction, which is directly executed in the VM of the node, but never mined into the blockchain. - -// TRANSACTION OBJECT -// Promise - A transaction object its hash transactionHash: -// -// hash 32 Bytes - String: Hash of the transaction. -// nonce - Number: The number of transactions made by the sender prior to this one. -// blockHash 32 Bytes - String: Hash of the block where this transaction was in. null when its pending. -// blockNumber - Number: Block number where this transaction was in. null when its pending. -// transactionIndex - Number: Integer of the transactions index position in the block. null when its pending. -// from - String: Address of the sender. -// to - String: Address of the receiver. null when its a contract creation transaction. -// value - String: Value transferred in wei. -// gasPrice - String: The wei per unit of gas provided by the sender in wei. -// gas - Number: Gas provided by the sender. -// input - String: The data sent along with the transaction. - -/* -e.g. - -web3.eth.getTransaction('0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b§234').then(console.log); -> { - "hash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b", - "nonce": 2, - "blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46", - "blockNumber": 3, - "transactionIndex": 0, - "from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", - "to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f", - "value": '123450000000000000', - "gas": 314159, - "gasPrice": '2000000000000', - "input": "0x57cb2fc4" -} -*/ - -// BLOCK -// Promise - The block object: -// -// number - Number: The block number. null when its pending block. -// hash 32 Bytes - String: Hash of the block. null when its pending block. -// parentHash 32 Bytes - String: Hash of the parent block. -// nonce 8 Bytes - String: Hash of the generated proof-of-work. null when its pending block. -// sha3Uncles 32 Bytes - String: SHA3 of the uncles data in the block. -// logsBloom 256 Bytes - String: The bloom filter for the logs of the block. null when its pending block. -// transactionsRoot 32 Bytes - String: The root of the transaction trie of the block -// stateRoot 32 Bytes - String: The root of the final state trie of the block. -// receiptsRoot 32 Bytes - String: Transaction receipts are used to store the state after a transaction has been executed and are kept in an index-keyed trie. The hash of its root is placed in the block header as the receipts root. -// miner - String: The address of the beneficiary to whom the mining rewards were given. -// difficulty - String: Integer of the difficulty for this block. -// totalDifficulty - String: Integer of the total difficulty of the chain until this block. -// extraData - String: The “extra data” field of this block. -// size - Number: Integer the size of this block in bytes. -// gasLimit - Number: The maximum gas allowed in this block. -// gasUsed - Number: The total used gas by all transactions in this block. -// timestamp - Number | String: The unix timestamp for when the block was collated (returns a string if a overflow got detected). -// transactions - Array: Array of transaction objects, or 32 Bytes transaction hashes depending on the returnTransactionObjects parameter. -// uncles - Array: Array of uncle hashes. - -/* -e.g. - -web3.eth.getBlock(3150).then(console.log); -> { - "number": 3, - "hash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46", - "parentHash": "0x2302e1c0b972d00932deb5dab9eb2982f570597d9d42504c05d9c2147eaf9c88", - "nonce": "0xfb6e1a62d119228b", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "transactionsRoot": "0x3a1b03875115b79539e5bd33fb00d8f7b7cd61929d5a3c574f507b8acf415bee", - "stateRoot": "0xf1133199d44695dfa8fd1bcfe424d82854b5cebef75bddd7e40ea94cda515bcb", - "receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421', - "miner": "0x8888f1f195afa192cfee860698584c030f4c9db1", - "difficulty": '21345678965432', - "totalDifficulty": '324567845321', - "size": 616, - "extraData": "0x", - "gasLimit": 3141592, - "gasUsed": 21662, - "timestamp": 1429287689, - "transactions": [ - "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b" - ], - "uncles": [] -} -*/ - -// Transaction RECEIPT -/* -Promise returns Object - A transaction receipt object, or null when no receipt was found: - -status - Boolean: TRUE if the transaction was successful, FALSE, if the EVM reverted the transaction. -blockHash 32 Bytes - String: Hash of the block where this transaction was in. -blockNumber - Number: Block number where this transaction was in. -transactionHash 32 Bytes - String: Hash of the transaction. -transactionIndex- Number: Integer of the transactions index position in the block. -from - String: Address of the sender. -to - String: Address of the receiver. null when its a contract creation transaction. -contractAddress - String: The contract address created, if the transaction was a contract creation, otherwise null. -cumulativeGasUsed - Number: The total amount of gas used when this transaction was executed in the block. -gasUsed- Number: The amount of gas used by this specific transaction alone. -logs - Array: Array of log objects, which this transaction generated. -*/ -/* -e.g. -const receipt = web3.eth.getTransactionReceipt('0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b') - .then(console.log); -> { - "status": true, - "transactionHash": "0x9fc76417374aa880d4449a1f7f31ec597f00b1f6f3dd2d66f4c9c6c445836d8b", - "transactionIndex": 0, - "blockHash": "0xef95f2f1ed3ca60b048b4bf67cde2195961e0bba6f70bcbea9a2c4e133e34b46", - "blockNumber": 3, - "contractAddress": "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe", - "cumulativeGasUsed": 314159, - "gasUsed": 30234, - "logs": [{ - // logs as returned by getPastLogs, etc. - }, ...] -} -*/ From 045740c84a16ec2a6141208b2d20502305a19ae9 Mon Sep 17 00:00:00 2001 From: ilyasridhuan Date: Mon, 22 Nov 2021 10:36:10 +0800 Subject: [PATCH 4/4] refactor: remove from startup script --- start-nightfall | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/start-nightfall b/start-nightfall index 02d3d5ad1..e1b4dfe91 100755 --- a/start-nightfall +++ b/start-nightfall @@ -47,16 +47,6 @@ trap "docker-compose $FILE $STUBS down --remove-orphans -t 1; exit 1" SIGHUP SIG docker-compose -f docker-compose.yml $FILE $STUBS down --remove-orphans # if-else block checks - volume exist and then removes it. -if [[ $(echo $VOLUME_LIST | grep nightfall_3_timber-database-volume1) ]]; then - echo -n 'Removing ' - docker volume rm nightfall_3_timber-database-volume1 -fi - -if [[ $(echo $VOLUME_LIST | grep nightfall_3_timber-database-volume2) ]]; then - echo -n 'Removing ' - docker volume rm nightfall_3_timber-database-volume2 -fi - if [[ $(echo $VOLUME_LIST | grep nightfall_3_mongodb1) ]]; then echo -n 'Removing ' docker volume rm nightfall_3_mongodb1