From 6fe40d89d3530c5e57ac59f8ad4650da5c995ad5 Mon Sep 17 00:00:00 2001 From: sam bacha Date: Tue, 17 Aug 2021 03:04:33 -0700 Subject: [PATCH] v0.1.0 Signed-off-by: sam bacha --- .eslintignore | 1 + .eslintrc.json | 64 + .gitignore | 5 + .prettierrc.js | 3 + Procfile | 4 + example.env | 55 + package-lock.json | 4558 +++++++++++++++++ package.json | 85 + src/_websocket-server.ts | 135 + src/abis/I1Inchv2.json | 310 ++ src/abis/I1Inchv3.json | 254 + src/abis/Multicall2.json | 167 + src/listener-commons.ts | 142 + src/listener-confirmation.ts | 89 + src/listener-mempool.ts | 49 + src/models/BlockSchema.ts | 54 + src/models/HashSchema.ts | 12 + src/models/PoolsSchema.ts | 22 + src/models/TokenSchema.ts | 27 + src/models/TransactionSchema.ts | 103 + src/models/WhalesSchema.ts | 17 + src/models/index.ts | 15 + .../_uni_sushi/_decoders/getMempoolData.ts | 50 + .../_uni_sushi/_v2/handleSwap.ts | 74 + .../_uni_sushi/_v3/getV3InternalSwap.ts | 67 + .../_uni_sushi/_v3/handleMultiSwap.ts | 97 + .../_uni_sushi/_v3/handleSwap.ts | 97 + src/swapsDecoders/_uni_sushi/pending.ts | 77 + src/utils/_websocket/utils.ts | 115 + src/utils/configs/utils.ts | 102 + src/utils/dev-utils/drop-transactions.ts | 28 + src/utils/dev-utils/reset-blocks.ts | 23 + src/utils/dev-utils/reset-pools.ts | 23 + src/utils/dev-utils/reset-tokens.ts | 23 + src/utils/dev-utils/reset-transactions-c.ts | 23 + src/utils/dev-utils/reset-transactions-p.ts | 23 + src/utils/dev-utils/reset-transactions-t-h.ts | 24 + src/utils/dev-utils/reset-transactions.ts | 28 + src/utils/initServer/create-indexes.ts | 93 + src/utils/initServer/init-pools.ts | 127 + src/utils/initServer/init-tokens.ts | 79 + src/utils/initServer/init-whales.ts | 55 + src/utils/initServer/set-heroku.ts | 204 + src/utils/mongo/config.ts | 99 + src/utils/mongo/saveBlock.ts | 33 + src/utils/mongo/saveConfirmed.ts | 227 + src/utils/mongo/savePending.ts | 24 + src/utils/mongo/savePools.ts | 17 + src/utils/mongo/saveToken.ts | 111 + src/utils/mongo/saveWhale.ts | 24 + src/utils/web3/abis-interfaces.ts | 16 + src/utils/web3/checkTxs.ts | 37 + src/utils/web3/getBlocks.ts | 69 + src/utils/web3/getContractData.ts | 38 + src/utils/web3/getTokens.ts | 112 + src/utils/web3/getTransactions.ts | 66 + src/utils/web3/providers.ts | 93 + src/utils/web3/utils.ts | 53 + tsconfig.json | 18 + 59 files changed, 8640 insertions(+) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 .prettierrc.js create mode 100644 Procfile create mode 100644 example.env create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/_websocket-server.ts create mode 100644 src/abis/I1Inchv2.json create mode 100644 src/abis/I1Inchv3.json create mode 100644 src/abis/Multicall2.json create mode 100644 src/listener-commons.ts create mode 100644 src/listener-confirmation.ts create mode 100644 src/listener-mempool.ts create mode 100644 src/models/BlockSchema.ts create mode 100644 src/models/HashSchema.ts create mode 100644 src/models/PoolsSchema.ts create mode 100644 src/models/TokenSchema.ts create mode 100644 src/models/TransactionSchema.ts create mode 100644 src/models/WhalesSchema.ts create mode 100644 src/models/index.ts create mode 100644 src/swapsDecoders/_uni_sushi/_decoders/getMempoolData.ts create mode 100644 src/swapsDecoders/_uni_sushi/_v2/handleSwap.ts create mode 100644 src/swapsDecoders/_uni_sushi/_v3/getV3InternalSwap.ts create mode 100644 src/swapsDecoders/_uni_sushi/_v3/handleMultiSwap.ts create mode 100644 src/swapsDecoders/_uni_sushi/_v3/handleSwap.ts create mode 100644 src/swapsDecoders/_uni_sushi/pending.ts create mode 100644 src/utils/_websocket/utils.ts create mode 100644 src/utils/configs/utils.ts create mode 100644 src/utils/dev-utils/drop-transactions.ts create mode 100644 src/utils/dev-utils/reset-blocks.ts create mode 100644 src/utils/dev-utils/reset-pools.ts create mode 100644 src/utils/dev-utils/reset-tokens.ts create mode 100644 src/utils/dev-utils/reset-transactions-c.ts create mode 100644 src/utils/dev-utils/reset-transactions-p.ts create mode 100644 src/utils/dev-utils/reset-transactions-t-h.ts create mode 100644 src/utils/dev-utils/reset-transactions.ts create mode 100644 src/utils/initServer/create-indexes.ts create mode 100644 src/utils/initServer/init-pools.ts create mode 100644 src/utils/initServer/init-tokens.ts create mode 100644 src/utils/initServer/init-whales.ts create mode 100644 src/utils/initServer/set-heroku.ts create mode 100644 src/utils/mongo/config.ts create mode 100644 src/utils/mongo/saveBlock.ts create mode 100644 src/utils/mongo/saveConfirmed.ts create mode 100644 src/utils/mongo/savePending.ts create mode 100644 src/utils/mongo/savePools.ts create mode 100644 src/utils/mongo/saveToken.ts create mode 100644 src/utils/mongo/saveWhale.ts create mode 100644 src/utils/web3/abis-interfaces.ts create mode 100644 src/utils/web3/checkTxs.ts create mode 100644 src/utils/web3/getBlocks.ts create mode 100644 src/utils/web3/getContractData.ts create mode 100644 src/utils/web3/getTokens.ts create mode 100644 src/utils/web3/getTransactions.ts create mode 100644 src/utils/web3/providers.ts create mode 100644 src/utils/web3/utils.ts create mode 100644 tsconfig.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +build/ diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..6da574a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,64 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:node/recommended", + "prettier" + ], + "plugins": [ + "node", + "prettier" + ], + "rules": { + "prettier/prettier": "error", + "block-scoped-var": "error", + "eqeqeq": "error", + "no-var": "error", + "prefer-const": "error", + "eol-last": "error", + "prefer-arrow-callback": "error", + "no-trailing-spaces": "error", + "quotes": ["warn", "single", { "avoidEscape": true }], + "no-restricted-properties": [ + "error", + { + "object": "describe", + "property": "only" + }, + { + "object": "it", + "property": "only" + } + ] + }, + "overrides": [ + { + "files": ["**/*.ts", "**/*.tsx"], + "parser": "@typescript-eslint/parser", + "extends": [ + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-warning-comments": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/camelcase": "off", + "node/no-missing-import": "off", + "node/no-empty-function": "off", + "node/no-unsupported-features/es-syntax": "off", + "node/no-missing-require": "off", + "node/shebang": "off", + "no-dupe-class-members": "off", + "require-atomic-updates": "off" + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + } + } + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9862ef3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +node_modules +lib/ +.env + diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..ff15483 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,3 @@ +module.exports = { + ...require('gts/.prettierrc.json') +} diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..a5a9e2d --- /dev/null +++ b/Procfile @@ -0,0 +1,4 @@ +web: node ./dist/_websocket-server.js +worker-a: node ./dist/listener-commons.js +worker-b: node ./dist/listener-mempool.js +worker-c: node ./dist/listener-confirmation.js \ No newline at end of file diff --git a/example.env b/example.env new file mode 100644 index 0000000..36b8b87 --- /dev/null +++ b/example.env @@ -0,0 +1,55 @@ +ATLAS_STRING=mongodb+srv://${MONGO_DB_USRNAME:PASS}.mongodb.net/mempool?ssl=true&authSource=admin&retryWrites=true&w=majority +DB_USER= +DB_PW= +DB_NAME= +COLLECTION_PREFIX= + +MAIN_API_WS_URL='' +BLOCKNATIVE_API_KEY='' +INFURA_KEY1='' +INFURA_KEY2='' +INFURA_KEY3='' +INFURA_KEY4='' +ALCHEMY_KEY1='' +ALCHEMY_KEY2='' +ETHERSCAN_KEY='' +ETHERSCAN_KEY2='' +POKT_KEY='' +GET_BLOCK_KEY='' + +CORS_ORIGIN='' +GAS_STATION_API_URL='' +BLOCKNATIVE_API_URL='' + +UNIV2="0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" +UNIV3="0xE592427A0AEce92De3Edee1F18E0157C05861564" +SUSHIV2="0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F" + +WRAPPED="https://wrapped.tokensoft.eth.link/" +YEARN="https://yearn.science/static/tokenlist.json" +SUSHISWAP="https://raw.githubusercontent.com/sushiswapclassic/token-list/master/sushiswap.tokenlist.json" +ONE_INCH="https://tokens.1inch.eth.link" +COINGECKO="https://tokens.coingecko.com/uniswap/all.json" +COMPOUND="https://raw.githubusercontent.com/compound-finance/token-list/master/compound.tokenlist.json" +DEFIPRIME="https://defiprime.com/defiprime.tokenlist.json" +MESSARI="https://messari.io/tokenlist/messari-verified" +OPYN="https://raw.githubusercontent.com/opynfinance/opyn-tokenlist/master/opyn-v1.tokenlist.json" +SNX="https://synths.snx.eth.link/" +SET="https://raw.githubusercontent.com/SetProtocol/uniswap-tokenlist/main/set.tokenlist.json" +AVE="https://tokenlist.aave.eth.link" +AGORA="https://datafi.theagora.eth.link" +CMCDEFI="https://defi.cmc.eth.link" +CMCSTABLECOIN="https://stablecoin.cmc.eth.link" +CMC200ERC20="https://erc20.cmc.eth.link" +KLEROS="https://t2crtokens.eth.link" +FURUCOMBO="https://cdn.furucombo.app/furucombo.tokenlist.json" +KYBER="https://api.kyber.network/tokenlist" +MYCRYPTOAPI="https://uniswap.mycryptoapi.com/" +ZAPPER="https://zapper.fi/api/token-list" +ZERION="https://tokenlist.zerion.eth.link" + +# Heroku +# cant run on free tier more than 20 days of the month +#HEROKU_APP_NAME_CONFIRMED_WORKER='' +#HEROKU_APP_NAME_PENDING_WORKER='' +#HEROKU_APP_NAME_WEBSOCKET_WORKER='' diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a528059 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4558 @@ +{ + "name": "eth-mempool-monitor", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "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" + } + }, + "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 + } + } + }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "dev": true, + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "@ethersproject/abi": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.4.0.tgz", + "integrity": "sha512-9gU2H+/yK1j2eVMdzm6xvHSnMxk8waIHQGYCZg5uvAyH0rsAzxkModzBSpbAkAuhKFEovC2S9hM4nPuLym8IZw==", + "requires": { + "@ethersproject/address": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/constants": "^5.4.0", + "@ethersproject/hash": "^5.4.0", + "@ethersproject/keccak256": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/strings": "^5.4.0" + } + }, + "@ethersproject/abstract-provider": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz", + "integrity": "sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ==", + "requires": { + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/networks": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/transactions": "^5.4.0", + "@ethersproject/web": "^5.4.0" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz", + "integrity": "sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA==", + "requires": { + "@ethersproject/abstract-provider": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0" + } + }, + "@ethersproject/address": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.4.0.tgz", + "integrity": "sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q==", + "requires": { + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/keccak256": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/rlp": "^5.4.0" + } + }, + "@ethersproject/base64": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.4.0.tgz", + "integrity": "sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ==", + "requires": { + "@ethersproject/bytes": "^5.4.0" + } + }, + "@ethersproject/basex": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.4.0.tgz", + "integrity": "sha512-J07+QCVJ7np2bcpxydFVf/CuYo9mZ7T73Pe7KQY4c1lRlrixMeblauMxHXD0MPwFmUHZIILDNViVkykFBZylbg==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/properties": "^5.4.0" + } + }, + "@ethersproject/bignumber": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.4.1.tgz", + "integrity": "sha512-fJhdxqoQNuDOk6epfM7yD6J8Pol4NUCy1vkaGAkuujZm0+lNow//MKu1hLhRiYV4BsOHyBv5/lsTjF+7hWwhJg==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "bn.js": "^4.11.9" + } + }, + "@ethersproject/bytes": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.4.0.tgz", + "integrity": "sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA==", + "requires": { + "@ethersproject/logger": "^5.4.0" + } + }, + "@ethersproject/constants": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.4.0.tgz", + "integrity": "sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q==", + "requires": { + "@ethersproject/bignumber": "^5.4.0" + } + }, + "@ethersproject/contracts": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.4.1.tgz", + "integrity": "sha512-m+z2ZgPy4pyR15Je//dUaymRUZq5MtDajF6GwFbGAVmKz/RF+DNIPwF0k5qEcL3wPGVqUjFg2/krlCRVTU4T5w==", + "requires": { + "@ethersproject/abi": "^5.4.0", + "@ethersproject/abstract-provider": "^5.4.0", + "@ethersproject/abstract-signer": "^5.4.0", + "@ethersproject/address": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/constants": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/transactions": "^5.4.0" + } + }, + "@ethersproject/hash": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.4.0.tgz", + "integrity": "sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA==", + "requires": { + "@ethersproject/abstract-signer": "^5.4.0", + "@ethersproject/address": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/keccak256": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/strings": "^5.4.0" + } + }, + "@ethersproject/hdnode": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.4.0.tgz", + "integrity": "sha512-pKxdS0KAaeVGfZPp1KOiDLB0jba11tG6OP1u11QnYfb7pXn6IZx0xceqWRr6ygke8+Kw74IpOoSi7/DwANhy8Q==", + "requires": { + "@ethersproject/abstract-signer": "^5.4.0", + "@ethersproject/basex": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/pbkdf2": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/sha2": "^5.4.0", + "@ethersproject/signing-key": "^5.4.0", + "@ethersproject/strings": "^5.4.0", + "@ethersproject/transactions": "^5.4.0", + "@ethersproject/wordlists": "^5.4.0" + } + }, + "@ethersproject/json-wallets": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.4.0.tgz", + "integrity": "sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ==", + "requires": { + "@ethersproject/abstract-signer": "^5.4.0", + "@ethersproject/address": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/hdnode": "^5.4.0", + "@ethersproject/keccak256": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/pbkdf2": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/random": "^5.4.0", + "@ethersproject/strings": "^5.4.0", + "@ethersproject/transactions": "^5.4.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "@ethersproject/keccak256": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.4.0.tgz", + "integrity": "sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "js-sha3": "0.5.7" + } + }, + "@ethersproject/logger": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.4.0.tgz", + "integrity": "sha512-xYdWGGQ9P2cxBayt64d8LC8aPFJk6yWCawQi/4eJ4+oJdMMjEBMrIcIMZ9AxhwpPVmnBPrsB10PcXGmGAqgUEQ==" + }, + "@ethersproject/networks": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.4.2.tgz", + "integrity": "sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw==", + "requires": { + "@ethersproject/logger": "^5.4.0" + } + }, + "@ethersproject/pbkdf2": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.4.0.tgz", + "integrity": "sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/sha2": "^5.4.0" + } + }, + "@ethersproject/properties": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.4.0.tgz", + "integrity": "sha512-7jczalGVRAJ+XSRvNA6D5sAwT4gavLq3OXPuV/74o3Rd2wuzSL035IMpIMgei4CYyBdialJMrTqkOnzccLHn4A==", + "requires": { + "@ethersproject/logger": "^5.4.0" + } + }, + "@ethersproject/providers": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.4.3.tgz", + "integrity": "sha512-VURwkaWPoUj7jq9NheNDT5Iyy64Qcyf6BOFDwVdHsmLmX/5prNjFrgSX3GHPE4z1BRrVerDxe2yayvXKFm/NNg==", + "requires": { + "@ethersproject/abstract-provider": "^5.4.0", + "@ethersproject/abstract-signer": "^5.4.0", + "@ethersproject/address": "^5.4.0", + "@ethersproject/basex": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/constants": "^5.4.0", + "@ethersproject/hash": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/networks": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/random": "^5.4.0", + "@ethersproject/rlp": "^5.4.0", + "@ethersproject/sha2": "^5.4.0", + "@ethersproject/strings": "^5.4.0", + "@ethersproject/transactions": "^5.4.0", + "@ethersproject/web": "^5.4.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "@ethersproject/random": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.4.0.tgz", + "integrity": "sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0" + } + }, + "@ethersproject/rlp": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.4.0.tgz", + "integrity": "sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0" + } + }, + "@ethersproject/sha2": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.4.0.tgz", + "integrity": "sha512-siheo36r1WD7Cy+bDdE1BJ8y0bDtqXCOxRMzPa4bV1TGt/eTUUt03BHoJNB6reWJD8A30E/pdJ8WFkq+/uz4Gg==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "hash.js": "1.1.7" + } + }, + "@ethersproject/shims": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/shims/-/shims-5.4.0.tgz", + "integrity": "sha512-J/M1oudCBPw4T8pBoE8wO65dIJruGBSZ1HyKVSygO3rF95Sq1LasQFEfKNzJl2nJP20ni4eXTNlEdKFKoVxnpw==" + }, + "@ethersproject/signing-key": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.4.0.tgz", + "integrity": "sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "@ethersproject/solidity": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.4.0.tgz", + "integrity": "sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ==", + "requires": { + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/keccak256": "^5.4.0", + "@ethersproject/sha2": "^5.4.0", + "@ethersproject/strings": "^5.4.0" + } + }, + "@ethersproject/strings": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.4.0.tgz", + "integrity": "sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/constants": "^5.4.0", + "@ethersproject/logger": "^5.4.0" + } + }, + "@ethersproject/transactions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.4.0.tgz", + "integrity": "sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ==", + "requires": { + "@ethersproject/address": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/constants": "^5.4.0", + "@ethersproject/keccak256": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/rlp": "^5.4.0", + "@ethersproject/signing-key": "^5.4.0" + } + }, + "@ethersproject/units": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.4.0.tgz", + "integrity": "sha512-Z88krX40KCp+JqPCP5oPv5p750g+uU6gopDYRTBGcDvOASh6qhiEYCRatuM/suC4S2XW9Zz90QI35MfSrTIaFg==", + "requires": { + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/constants": "^5.4.0", + "@ethersproject/logger": "^5.4.0" + } + }, + "@ethersproject/wallet": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.4.0.tgz", + "integrity": "sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ==", + "requires": { + "@ethersproject/abstract-provider": "^5.4.0", + "@ethersproject/abstract-signer": "^5.4.0", + "@ethersproject/address": "^5.4.0", + "@ethersproject/bignumber": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/hash": "^5.4.0", + "@ethersproject/hdnode": "^5.4.0", + "@ethersproject/json-wallets": "^5.4.0", + "@ethersproject/keccak256": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/random": "^5.4.0", + "@ethersproject/signing-key": "^5.4.0", + "@ethersproject/transactions": "^5.4.0", + "@ethersproject/wordlists": "^5.4.0" + } + }, + "@ethersproject/web": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.4.0.tgz", + "integrity": "sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og==", + "requires": { + "@ethersproject/base64": "^5.4.0", + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/strings": "^5.4.0" + } + }, + "@ethersproject/wordlists": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.4.0.tgz", + "integrity": "sha512-FemEkf6a+EBKEPxlzeVgUaVSodU7G0Na89jqKjmWMlDB0tomoU8RlEMgUvXyqtrg8N4cwpLh8nyRnm1Nay1isA==", + "requires": { + "@ethersproject/bytes": "^5.4.0", + "@ethersproject/hash": "^5.4.0", + "@ethersproject/logger": "^5.4.0", + "@ethersproject/properties": "^5.4.0", + "@ethersproject/strings": "^5.4.0" + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@openzeppelin/contracts": { + "version": "3.4.1-solc-0.7-2", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-3.4.1-solc-0.7-2.tgz", + "integrity": "sha512-tAG9LWg8+M2CMu7hIsqHPaTyG4uDzjr6mhvH96LvOpLZZj6tgzTluBt+LsCf1/QaYrlis6pITvpIaIhE+iZB+Q==" + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@sushiswap/core": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@sushiswap/core/-/core-1.4.2.tgz", + "integrity": "sha512-Khd2i6Bob9uk7dCgVkhUioEoxRP28m6aj25MegAHvnJyxZPVzZDhxSkeL6wdv5MeAp2DwHkYqUq03KDfVTTP4Q==" + }, + "@sushiswap/sdk": { + "version": "5.0.0-canary.7", + "resolved": "https://registry.npmjs.org/@sushiswap/sdk/-/sdk-5.0.0-canary.7.tgz", + "integrity": "sha512-21IsU1yB+RETZZs2ORoMLNTRNYNln10bDTVwX7wpntCCdjeACnOyYb/I8yli2cNaajJWPZt62gGoCP5ntndSyg==", + "requires": { + "@uniswap/v2-core": "^1.0.0", + "big.js": "^5.2.2", + "decimal.js-light": "^2.5.0", + "jsbi": "^3.1.1", + "tiny-invariant": "^1.1.0", + "tiny-warning": "^1.0.3", + "toformat": "^2.0.0" + } + }, + "@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==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bson": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz", + "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", + "requires": { + "@types/node": "*" + }, + "dependencies": { + "@types/node": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz", + "integrity": "sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==" + } + } + }, + "@types/component-emitter": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", + "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "@types/mongodb": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz", + "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", + "requires": { + "@types/bson": "*", + "@types/node": "*" + }, + "dependencies": { + "@types/node": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz", + "integrity": "sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==" + } + } + }, + "@types/node": { + "version": "14.17.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", + "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", + "dev": true + }, + "@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.2.tgz", + "integrity": "sha512-x4EMgn4BTfVd9+Z+r+6rmWxoAzBaapt4QFqE+d8L8sUtYZYLDTK6VG/y/SMMWA5t1/BVU5Kf+20rX4PtWzUYZg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.29.2", + "@typescript-eslint/scope-manager": "4.29.2", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.2.tgz", + "integrity": "sha512-P6mn4pqObhftBBPAv4GQtEK7Yos1fz/MlpT7+YjH9fTxZcALbiiPKuSIfYP/j13CeOjfq8/fr9Thr2glM9ub7A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.29.2", + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/typescript-estree": "4.29.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.2.tgz", + "integrity": "sha512-WQ6BPf+lNuwteUuyk1jD/aHKqMQ9jrdCn7Gxt9vvBnzbpj7aWEf+aZsJ1zvTjx5zFxGCt000lsbD9tQPEL8u6g==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.29.2", + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/typescript-estree": "4.29.2", + "debug": "^4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.2.tgz", + "integrity": "sha512-mfHmvlQxmfkU8D55CkZO2sQOueTxLqGvzV+mG6S/6fIunDiD2ouwsAoiYCZYDDK73QCibYjIZmGhpvKwAB5BOA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/visitor-keys": "4.29.2" + } + }, + "@typescript-eslint/types": { + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.2.tgz", + "integrity": "sha512-K6ApnEXId+WTGxqnda8z4LhNMa/pZmbTFkDxEBLQAbhLZL50DjeY0VIDCml/0Y3FlcbqXZrABqrcKxq+n0LwzQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.2.tgz", + "integrity": "sha512-TJ0/hEnYxapYn9SGn3dCnETO0r+MjaxtlWZ2xU+EvytF0g4CqTpZL48SqSNn2hXsPolnewF30pdzR9a5Lj3DNg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.29.2", + "@typescript-eslint/visitor-keys": "4.29.2", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.29.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.2.tgz", + "integrity": "sha512-bDgJLQ86oWHJoZ1ai4TZdgXzJxsea3Ee9u9wsTAvjChdj2WLcVsgWYAPeY7RQMn16tKrlQaBnpKv7KBfs4EQag==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.29.2", + "eslint-visitor-keys": "^2.0.0" + } + }, + "@uniswap/lib": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@uniswap/lib/-/lib-1.1.1.tgz", + "integrity": "sha512-2yK7sLpKIT91TiS5sewHtOa7YuM8IuBXVl4GZv2jZFys4D2sY7K5vZh6MqD25TPA95Od+0YzCVq6cTF2IKrOmg==" + }, + "@uniswap/sdk-core": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@uniswap/sdk-core/-/sdk-core-3.0.1.tgz", + "integrity": "sha512-WbeDkhZ9myVR0VnHOdTrb8nHKKkqTFa5uE9RvUbG3eyDt2NWWDwhhqGHwAWJEHG405l30Fa1u3PogHDFsIOQlA==", + "requires": { + "@ethersproject/address": "^5.0.2", + "big.js": "^5.2.2", + "decimal.js-light": "^2.5.0", + "jsbi": "^3.1.4", + "tiny-invariant": "^1.1.0", + "toformat": "^2.0.0" + } + }, + "@uniswap/v2-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@uniswap/v2-core/-/v2-core-1.0.0.tgz", + "integrity": "sha512-BJiXrBGnN8mti7saW49MXwxDBRFiWemGetE58q8zgfnPPzQKq55ADltEILqOt6VFZ22kVeVKbF8gVd8aY3l7pA==" + }, + "@uniswap/v2-periphery": { + "version": "1.1.0-beta.0", + "resolved": "https://registry.npmjs.org/@uniswap/v2-periphery/-/v2-periphery-1.1.0-beta.0.tgz", + "integrity": "sha512-6dkwAMKza8nzqYiXEr2D86dgW3TTavUvCR0w2Tu33bAbM8Ah43LKAzH7oKKPRT5VJQaMi1jtkGs1E8JPor1n5g==", + "requires": { + "@uniswap/lib": "1.1.1", + "@uniswap/v2-core": "1.0.0" + } + }, + "@uniswap/v2-sdk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@uniswap/v2-sdk/-/v2-sdk-3.0.0.tgz", + "integrity": "sha512-UyAZHCQaV/4XCsgR+o+daP0E6rLUOY0H2G10P1cxGI1c3uxZe3/mXIHq+kUkeW8kxHC0622TckFYWnkiWkjULg==", + "requires": { + "@ethersproject/address": "^5.0.0", + "@ethersproject/solidity": "^5.0.0", + "@uniswap/sdk-core": "^3.0.0-alpha.3", + "tiny-invariant": "^1.1.0", + "tiny-warning": "^1.0.3" + } + }, + "@uniswap/v3-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@uniswap/v3-core/-/v3-core-1.0.0.tgz", + "integrity": "sha512-kSC4djMGKMHj7sLMYVnn61k9nu+lHjMIxgg9CDQT+s2QYLoA56GbSK9Oxr+qJXzzygbkrmuY6cwgP6cW2JXPFA==" + }, + "@uniswap/v3-periphery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@uniswap/v3-periphery/-/v3-periphery-1.0.0.tgz", + "integrity": "sha512-kRqUrjnyh+X1wJdSENPDFr9sjRVebv2KyLtfqDOPij0dXJ69GspFU2qrZXjouc6LYdkWG7x3fagiTlw0eGniYQ==", + "requires": { + "@openzeppelin/contracts": "3.4.1-solc-0.7-2", + "@uniswap/lib": "^4.0.1-alpha", + "@uniswap/v2-core": "1.0.1", + "@uniswap/v3-core": "1.0.0", + "base64-sol": "1.0.1" + }, + "dependencies": { + "@uniswap/lib": { + "version": "4.0.1-alpha", + "resolved": "https://registry.npmjs.org/@uniswap/lib/-/lib-4.0.1-alpha.tgz", + "integrity": "sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA==" + }, + "@uniswap/v2-core": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@uniswap/v2-core/-/v2-core-1.0.1.tgz", + "integrity": "sha512-MtybtkUPSyysqLY2U210NBDeCHX+ltHt3oADGdjqoThZaFRDKwM6k1Nb3F0A3hk5hwuQvytFWhrWHOEq6nVJ8Q==" + } + } + }, + "@uniswap/v3-sdk": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@uniswap/v3-sdk/-/v3-sdk-3.3.2.tgz", + "integrity": "sha512-oADWpKPkmtgnrBr8xUmLURZnH1wO2HFPoQw/K2gI2ZLjyR1xkAbZT6X+hjLaXCdOI+PN5WMZo3/OiPUJC2X1bA==", + "requires": { + "@ethersproject/abi": "^5.0.12", + "@ethersproject/solidity": "^5.0.9", + "@uniswap/sdk-core": "^3.0.1", + "@uniswap/v3-periphery": "1.0.0", + "tiny-invariant": "^1.1.0", + "tiny-warning": "^1.0.3" + } + }, + "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" + } + }, + "acorn": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", + "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true + }, + "acorn-walk": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", + "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==", + "dev": true + }, + "aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "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 + }, + "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 + }, + "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 + }, + "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": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "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": "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" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "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=" + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" + }, + "base64-sol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/base64-sol/-/base64-sol-1.0.1.tgz", + "integrity": "sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg==" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" + }, + "bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "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 + }, + "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" + } + }, + "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": "5.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.0.1.tgz", + "integrity": "sha512-49VBlw+PrWEF51aCmy7QIteYPIFZxSpvqBdP/2itCPPlJ49kj9zg/XPRFrdkne2W+CfwXUls8exMvu1RysZpKA==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.0", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "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=" + }, + "bson": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true + } + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.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" + } + }, + "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" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "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" + } + }, + "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 + }, + "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 + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "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==", + "dev": true, + "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=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "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" + } + }, + "consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "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" + } + }, + "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=" + }, + "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-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "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 + }, + "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" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "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 + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "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==", + "dev": true + }, + "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=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "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" + } + }, + "dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=", + "dev": true, + "requires": { + "xtend": "^4.0.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": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-5.1.1.tgz", + "integrity": "sha512-aMWot7H5aC8L4/T8qMYbLdvKlZOdJTH54FxfdFunTGvhMx1BHkJOntWArsVfgAZVwAO9LC2sryPWRcEeUzCe5w==", + "requires": { + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~4.0.0", + "ws": "~7.4.2" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "engine.io-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", + "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", + "requires": { + "base64-arraybuffer": "0.1.4" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "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": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", + "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-prettier": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.0.tgz", + "integrity": "sha512-UDK6rJT6INSfcOo545jiaOwB701uAIt2/dR7WnFQoGCVl1/EMqdANBmwUaqqQ45aXprsTGzSa39LI1PyuRBxxw==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "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 + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "ethers": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.4.tgz", + "integrity": "sha512-zaTs8yaDjfb0Zyj8tT6a+/hEkC+kWAA350MWRp6yP5W7NdGcURRPMOpOU+6GtkfxV9wyJEShWesqhE/TjdqpMA==", + "requires": { + "@ethersproject/abi": "5.4.0", + "@ethersproject/abstract-provider": "5.4.1", + "@ethersproject/abstract-signer": "5.4.1", + "@ethersproject/address": "5.4.0", + "@ethersproject/base64": "5.4.0", + "@ethersproject/basex": "5.4.0", + "@ethersproject/bignumber": "5.4.1", + "@ethersproject/bytes": "5.4.0", + "@ethersproject/constants": "5.4.0", + "@ethersproject/contracts": "5.4.1", + "@ethersproject/hash": "5.4.0", + "@ethersproject/hdnode": "5.4.0", + "@ethersproject/json-wallets": "5.4.0", + "@ethersproject/keccak256": "5.4.0", + "@ethersproject/logger": "5.4.0", + "@ethersproject/networks": "5.4.2", + "@ethersproject/pbkdf2": "5.4.0", + "@ethersproject/properties": "5.4.0", + "@ethersproject/providers": "5.4.3", + "@ethersproject/random": "5.4.0", + "@ethersproject/rlp": "5.4.0", + "@ethersproject/sha2": "5.4.0", + "@ethersproject/signing-key": "5.4.0", + "@ethersproject/solidity": "5.4.0", + "@ethersproject/strings": "5.4.0", + "@ethersproject/transactions": "5.4.0", + "@ethersproject/units": "5.4.0", + "@ethersproject/wallet": "5.4.0", + "@ethersproject/web": "5.4.0", + "@ethersproject/wordlists": "5.4.0" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "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" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "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==", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "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==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", + "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "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 + } + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "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": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "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.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "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==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "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" + } + }, + "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-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "requires": { + "ini": "2.0.0" + } + }, + "globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "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" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "gts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/gts/-/gts-3.1.0.tgz", + "integrity": "sha512-Pbj3ob1VR1IRlEVEBNtKoQ1wHOa8cZz62KEojK8Fn/qeS2ClWI4gLNfhek3lD68aZSmUEg8TFb6AHXIwUMgyqQ==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "^4.2.0", + "@typescript-eslint/parser": "^4.2.0", + "chalk": "^4.1.0", + "eslint": "^7.10.0", + "eslint-config-prettier": "^7.0.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.1.4", + "execa": "^5.0.0", + "inquirer": "^7.3.3", + "json5": "^2.1.3", + "meow": "^9.0.0", + "ncp": "^2.0.0", + "prettier": "^2.1.2", + "rimraf": "^3.0.2", + "update-notifier": "^5.0.0", + "write-file-atomic": "^3.0.3" + }, + "dependencies": { + "eslint-config-prettier": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", + "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "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-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.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" + } + }, + "helmet": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz", + "integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==" + }, + "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" + } + }, + "hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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==", + "dev": true + }, + "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=" + } + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "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" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "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 + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "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": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + } + }, + "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-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "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-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-core-module": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", + "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "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": "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 + }, + "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-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "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-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-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=", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "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 + }, + "js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbi": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.1.6.tgz", + "integrity": "sha512-CGjq13y28FrBA5mAU+rsfHaVKEF9jrw3PhzZpIzTeMiPsT0XRDAS6E7QS8/ZTmFQUtl2MDJsxKQoYJzAhF7B1w==" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "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==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "kareem": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", + "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "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" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "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 + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "map-obj": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", + "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", + "dev": true + }, + "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 + }, + "meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "dependencies": { + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "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.49.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", + "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==" + }, + "mime-types": { + "version": "2.1.32", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", + "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "requires": { + "mime-db": "1.49.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "mongodb": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz", + "integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==", + "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.13.7", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.7.tgz", + "integrity": "sha512-ADIvftZ+KfoTALMZ0n8HvBlezFhcUd73hQaHQDwQ+3X+JZlqE47fUy9yhFZ2SjT+qzmuaCcIXCfhewIc38t2fQ==", + "requires": { + "@types/mongodb": "^3.5.27", + "bson": "^1.1.4", + "kareem": "2.3.2", + "mongodb": "3.6.11", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.8.3", + "mquery": "3.2.5", + "ms": "2.1.2", + "optional-require": "1.0.x", + "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==" + }, + "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==" + } + } + }, + "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=" + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "dev": true + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "normalize-package-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", + "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.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==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "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=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "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==" + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "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=", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "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": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.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 + } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "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=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "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=" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "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 + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "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=", + "dev": true + }, + "prettier": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", + "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "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==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "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" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "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==", + "dev": true + }, + "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==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, + "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" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + } + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "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 + } + } + }, + "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" + } + }, + "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" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "regexp-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "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" + } + }, + "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==", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "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==" + }, + "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==" + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "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" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "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 + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.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" + } + }, + "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 + } + } + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "socket.io": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.3.tgz", + "integrity": "sha512-tLkaY13RcO4nIRh1K2hT5iuotfTaIQw7cVIe0FUykN3SuQi0cm7ALxuyT5/CtDswOMWUzMGTibxYNx/gU7In+Q==", + "requires": { + "@types/cookie": "^0.4.0", + "@types/cors": "^2.8.10", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.1", + "engine.io": "~5.1.1", + "socket.io-adapter": "~2.3.1", + "socket.io-parser": "~4.0.4" + }, + "dependencies": { + "@types/node": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz", + "integrity": "sha512-Sr7BhXEAer9xyGuCN3Ek9eg9xPviCF2gfu9kTfuU2HkTVAMYSDeX40fvpmo72n5nansg3nsBjuQBrsS28r+NUw==" + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "socket.io-adapter": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.1.tgz", + "integrity": "sha512-8cVkRxI8Nt2wadkY6u60Y4rpW3ejA1rxgcK2JuyIhmF+RMNpTy1QRtkHIDUOf3B4HlQwakMsWbKftMv/71VMmw==" + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "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" + } + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "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" + } + }, + "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" + } + }, + "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" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^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": "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" + } + }, + "table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "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==", + "dev": true + }, + "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" + } + }, + "toformat": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/toformat/-/toformat-2.0.0.tgz", + "integrity": "sha512-03SWBVop6nU8bpyZCx7SodpYznbZF5R4ljwNLBcTQzKOD9xuihRo/psX58llS1BMFhhAI08H3luot5GoXJz2pQ==" + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true + }, + "ts-node": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.0.tgz", + "integrity": "sha512-FstYHtQz6isj8rBtYMN4bZdnXN1vq4HCbqn9vdNQcInRqtB86PePJQIxE6es0PhxKWhj2PHuwbG40H+bxkZPmg==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "0.6.1", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + } + }, + "ts-node-dev": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.8.tgz", + "integrity": "sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg==", + "dev": true, + "requires": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.5", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^9.0.0", + "tsconfig": "^7.0.0" + }, + "dependencies": { + "ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + } + } + }, + "tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "requires": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "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==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true + }, + "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" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^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==", + "dev": true, + "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=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "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=" + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "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" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.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" + } + }, + "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 + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "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": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" + }, + "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 + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..bf0c145 --- /dev/null +++ b/package.json @@ -0,0 +1,85 @@ +{ + "name": "eth-mempool-monitor", + "private": true, + "version": "0.1.0", + "author": "SEE CONTRIBUTORS", + "engines": { + "node": ">=14.0.0" +}, + "license": "GPL-3.0-or-later", + "keywords": [ + "ethereum", + "uniswap", + "defi", + "mempool", + "sushiswap" + ], + "scripts": { + "init:db": "npx ts-node ./src/utils/initServer/create-indexes.ts", + "init:tokens": "npx ts-node ./src/utils/initServer/init-tokens.ts", + "init:pools": "npx ts-node ./src/utils/initServer/init-pools.ts", + "init:txs": "npx ts-node ./src/utils/initServer/init-whales.ts", + "dev:common": "npx ts-node-dev ./src/listener-commons.ts", + "dev:mempool": "npx ts-node-dev ./src/listener-mempool.ts", + "dev:confirm": "npx ts-node-dev ./src/listener-confirmation.ts", + "dev:ws": "npx ts-node-dev ./src/_websocket-server.ts", + "init:heroku": "npx ts-node ./src/utils/initServer/set-heroku.ts", + "reset:hard": "npx ts-node ./src/utils/dev-utils/drop-transactions.ts", + "reset:txs": "npx ts-node ./src/utils/dev-utils/reset-transactions.ts", + "reset:txc": "npx ts-node ./src/utils/dev-utils/reset-transactions-c.ts", + "reset:txp`": "npx ts-node ./src/utils/dev-utils/reset-transactions-p.ts", + "reset:t-h": "npx ts-node ./src/utils/dev-utils/reset-transactions-t-h.ts", + "reset:pools": "npx ts-node ./src/utils/dev-utils/reset-pools.ts", + "reset:blocks": "npx ts-node ./src/utils/dev-utils/reset-blocks.ts", + "reset:tokens": "npx ts-node ./src/utils/dev-utils/reset-tokens.ts", + "web-worker": "node ./dist/_websocket-server.js", + "worker-common": " node ./dist/listener-commons.js", + "worker-mempool": "node ./dist/listener-mempool.js", + "worker-confirm": "node ./dist/listener-confirmation.js", + "run-workers": "npm run-script worker-common && npm run-mempool && npm run-script worker-confirm", + "clean": "npx gts clean", + "lint": "npx gts lint", + "build": "npx tsc -b", + "compile": "NODE_ENV=production npx tsc -b", + "fix": "npx gts fix", + "test:db": "npm run init:db", + "pretest": "npm run-script init:tokens && npm run-script init:txs", + "posttest": "npm run lint" + }, + "devDependencies": { + "@types/express": "^4.17.12", + "@types/node": "^14.11.2", + "eslint": "^7.32.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-prettier": "^3.1.3", + "gts": "^3.1.0", + "prettier": "^2.2.1", + "ts-node": "^10.0.0", + "ts-node-dev": "^1.1.6", + "tslib": "^2.3.1", + "typescript": "^4.0.3" + }, + "dependencies": { + "@ethersproject/address": "^5.0.0-beta", + "@ethersproject/contracts": "^5.0.0-bet", + "@ethersproject/networks": "^5.0.0-beta", + "@ethersproject/providers": "^5.0.0-beta", + "@ethersproject/shims": "^5.4.0", + "@sushiswap/core": "1.4.2", + "@sushiswap/sdk": "5.0.0-canary.7", + "@uniswap/sdk-core": "^3.0.0", + "@uniswap/v2-core": "1.0.0", + "@uniswap/v2-periphery": "^1.1.0-beta.0", + "@uniswap/v2-sdk": "^3.0.0-alpha.2", + "@uniswap/v3-core": "1.0.0", + "@uniswap/v3-periphery": "1.0.0", + "@uniswap/v3-sdk": "^3.0.0", + "consola": "^2.15.3", + "dotenv": "^8.2.0", + "ethers": "^5.3.1", + "express": "^4.16.4", + "helmet": "^4.6.0", + "mongoose": "^5.11.15", + "socket.io": "^4.0.0" + } +} diff --git a/src/_websocket-server.ts b/src/_websocket-server.ts new file mode 100644 index 0000000..3925294 --- /dev/null +++ b/src/_websocket-server.ts @@ -0,0 +1,135 @@ +import {Socket} from 'socket.io'; +import { + startSocketServer, + explorerNS, + emmitChange, + getAddressFilter, + getSpaceFilter, +} from './utils/_websocket/utils'; +import {startMongo, mongoUtils, models} from './utils/mongo/config'; +import {_log} from './utils/configs/utils'; + +const {UPDATE_ONLY, INSERT_ONLY, FIRST_QUERY, INS_PEND, DEL_PEND, INS_CONF} = + mongoUtils; +const {txM, g} = models; +const serverName = 'web'; + +let lastBlockNumber = 0; +let usersCount = 0; + +startMongo(serverName).then(started => { + if (started) { + startSocketServer(serverName).then(startedSocket => { + if (startedSocket) { + _log.start('startRooms Go!'); + startRooms(); + _log.start('startWatchers Go!'); + startWatchers(); + } else { + _log.warn('---> startedSocket ', startedSocket); + } + }); + } else { + _log.warn('---> started ', started); + } +}); + +const startRooms = () => { + explorerNS.on('connection', async (socket: Socket) => { + usersCount++; + _log.info('------> Connected! = Count =', usersCount); + + joinToBlocks(socket); + joinToAddress(socket); + + socket.on('disconnect', () => { + usersCount--; + _log.info('<------ Disconnected! = Count =', usersCount); + }); + }); +}; + +const startWatchers = () => { + watchBlocks(); + watchTrashTxs(); + watchPendingTxs(); + watchConfirmedTxs(); +}; + +const watchTrashTxs = () => { + g.trash.watch(INSERT_ONLY).on('change', (data: any) => { + emmitChange(DEL_PEND, data.fullDocument); + }); +}; + +const watchPendingTxs = () => { + txM.pending.watch(INSERT_ONLY).on('change', (data: any) => { + emmitChange(INS_PEND, data.fullDocument); + }); +}; + +const watchConfirmedTxs = () => { + txM.confirmed.watch(INSERT_ONLY).on('change', (data: any) => { + const {fullDocument} = data; + emmitChange(DEL_PEND, fullDocument); + emmitChange(INS_CONF, fullDocument); + }); +}; + +const watchBlocks = () => { + g.blocks.watch(UPDATE_ONLY).on('change', async (data: any) => { + const {_doc} = await g.blocks.findById(data.documentKey._id); + const {fullyUpdated, blockNumber} = _doc; + + if (fullyUpdated === true) { + lastBlockNumber = blockNumber; + explorerNS.emit('new_block', _doc); + } + }); +}; + +const joinToBlocks = (socket: Socket) => { + socket.on('join_to_blocks', async () => { + try { + const {id} = socket; + const {_doc} = await g.blocks.findOne({fullyUpdated: true}, null, { + sort: {timestampTx: -1}, + }); + console.log('_doc', _doc); + if (_doc) explorerNS.to(id).emit('last_block', _doc); + } catch (e: any) { + _log.error('join_to_blocks catch', e); + } + }); +}; + +const joinToAddress = (socket: Socket) => { + socket.on('join_to_address', async (request: any) => { + const {id} = socket; + for (const room of socket.rooms) if (room !== id) socket.leave(room); + + const {address, dexSpaces} = request; + const _or_from_to = getAddressFilter(address); + const _or_filter_dexes = getSpaceFilter(dexSpaces); + + const query = { + $and: [_or_from_to, _or_filter_dexes], + }; + + txM.pending.find(query, null, FIRST_QUERY, (e, docs) => { + if (!e) explorerNS.to(id).emit('pending_txs', docs); + }); + txM.confirmed.find(query, null, FIRST_QUERY, (e, docs) => { + if (!e) explorerNS.to(id).emit('confirmed_txs', docs); + }); + + try { + const {isV2, isV3, isV2Sushi} = dexSpaces; + isV2 && socket.join(address + 'v2'); + isV3 && socket.join(address + 'v3'); + isV2Sushi && socket.join(address + 'v2sh'); + } catch (e: any) { + _log.warn('---> dexSpaces join catch', e); + } + }); +}; diff --git a/src/abis/I1Inchv2.json b/src/abis/I1Inchv2.json new file mode 100644 index 0000000..f802825 --- /dev/null +++ b/src/abis/I1Inchv2.json @@ -0,0 +1,310 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "Error", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IERC20", + "name": "dstToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "dstReceiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "spentAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "returnAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minReturnAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "guaranteedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "referrer", + "type": "address" + } + ], + "name": "Swapped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IOneInchCaller", + "name": "caller", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "dstToken", + "type": "address" + }, + { + "internalType": "address", + "name": "srcReceiver", + "type": "address" + }, + { + "internalType": "address", + "name": "dstReceiver", + "type": "address" + }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "minReturnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "guaranteedAmount", + "type": "uint256" + }, + { "internalType": "uint256", "name": "flags", "type": "uint256" }, + { "internalType": "address", "name": "referrer", "type": "address" }, + { "internalType": "bytes", "name": "permit", "type": "bytes" } + ], + "internalType": "struct OneInchExchange.SwapDescription", + "name": "desc", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "targetWithMandatory", + "type": "uint256" + }, + { "internalType": "uint256", "name": "gasLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "internalType": "struct IOneInchCaller.CallDescription[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "discountedSwap", + "outputs": [{ "internalType": "uint256", "name": "returnAmount", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract IERC20", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "rescueFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IOneInchCaller", + "name": "caller", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "dstToken", + "type": "address" + }, + { + "internalType": "address", + "name": "srcReceiver", + "type": "address" + }, + { + "internalType": "address", + "name": "dstReceiver", + "type": "address" + }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "minReturnAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "guaranteedAmount", + "type": "uint256" + }, + { "internalType": "uint256", "name": "flags", "type": "uint256" }, + { "internalType": "address", "name": "referrer", "type": "address" }, + { "internalType": "bytes", "name": "permit", "type": "bytes" } + ], + "internalType": "struct OneInchExchange.SwapDescription", + "name": "desc", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "targetWithMandatory", + "type": "uint256" + }, + { "internalType": "uint256", "name": "gasLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "internalType": "struct IOneInchCaller.CallDescription[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "swap", + "outputs": [{ "internalType": "uint256", "name": "returnAmount", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/src/abis/I1Inchv3.json b/src/abis/I1Inchv3.json new file mode 100644 index 0000000..d561719 --- /dev/null +++ b/src/abis/I1Inchv3.json @@ -0,0 +1,254 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "Error", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IERC20", + "name": "dstToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "dstReceiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "spentAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "returnAmount", + "type": "uint256" + } + ], + "name": "Swapped", + "type": "event" + }, + { + "inputs": [], + "name": "destroy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAggregationExecutor", + "name": "caller", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "dstToken", + "type": "address" + }, + { + "internalType": "address", + "name": "srcReceiver", + "type": "address" + }, + { + "internalType": "address", + "name": "dstReceiver", + "type": "address" + }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "minReturnAmount", + "type": "uint256" + }, + { "internalType": "uint256", "name": "flags", "type": "uint256" }, + { "internalType": "bytes", "name": "permit", "type": "bytes" } + ], + "internalType": "struct AggregationRouterV3.SwapDescription", + "name": "desc", + "type": "tuple" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "discountedSwap", + "outputs": [ + { "internalType": "uint256", "name": "returnAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "gasLeft", "type": "uint256" }, + { "internalType": "uint256", "name": "chiSpent", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract IERC20", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "rescueFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IAggregationExecutor", + "name": "caller", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "dstToken", + "type": "address" + }, + { + "internalType": "address", + "name": "srcReceiver", + "type": "address" + }, + { + "internalType": "address", + "name": "dstReceiver", + "type": "address" + }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "minReturnAmount", + "type": "uint256" + }, + { "internalType": "uint256", "name": "flags", "type": "uint256" }, + { "internalType": "bytes", "name": "permit", "type": "bytes" } + ], + "internalType": "struct AggregationRouterV3.SwapDescription", + "name": "desc", + "type": "tuple" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "swap", + "outputs": [ + { "internalType": "uint256", "name": "returnAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "gasLeft", "type": "uint256" } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "uint256", "name": "minReturn", "type": "uint256" }, + { "internalType": "bytes32[]", "name": "", "type": "bytes32[]" } + ], + "name": "unoswap", + "outputs": [{ "internalType": "uint256", "name": "returnAmount", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "srcToken", + "type": "address" + }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "uint256", "name": "minReturn", "type": "uint256" }, + { "internalType": "bytes32[]", "name": "pools", "type": "bytes32[]" }, + { "internalType": "bytes", "name": "permit", "type": "bytes" } + ], + "name": "unoswapWithPermit", + "outputs": [{ "internalType": "uint256", "name": "returnAmount", "type": "uint256" }], + "stateMutability": "payable", + "type": "function" + }, + { "stateMutability": "payable", "type": "receive" } +] diff --git a/src/abis/Multicall2.json b/src/abis/Multicall2.json new file mode 100644 index 0000000..24a0374 --- /dev/null +++ b/src/abis/Multicall2.json @@ -0,0 +1,167 @@ +{ + "abi": [ + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "bytes", "name": "callData", "type": "bytes" } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "aggregate", + "outputs": [ + { "internalType": "uint256", "name": "blockNumber", "type": "uint256" }, + { "internalType": "bytes[]", "name": "returnData", "type": "bytes[]" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "bytes", "name": "callData", "type": "bytes" } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "blockAndAggregate", + "outputs": [ + { "internalType": "uint256", "name": "blockNumber", "type": "uint256" }, + { "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }, + { + "components": [ + { "internalType": "bool", "name": "success", "type": "bool" }, + { "internalType": "bytes", "name": "returnData", "type": "bytes" } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "blockNumber", "type": "uint256" }], + "name": "getBlockHash", + "outputs": [{ "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [{ "internalType": "uint256", "name": "blockNumber", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockCoinbase", + "outputs": [{ "internalType": "address", "name": "coinbase", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockDifficulty", + "outputs": [{ "internalType": "uint256", "name": "difficulty", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockGasLimit", + "outputs": [{ "internalType": "uint256", "name": "gaslimit", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockTimestamp", + "outputs": [{ "internalType": "uint256", "name": "timestamp", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "addr", "type": "address" }], + "name": "getEthBalance", + "outputs": [{ "internalType": "uint256", "name": "balance", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastBlockHash", + "outputs": [{ "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "requireSuccess", "type": "bool" }, + { + "components": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "bytes", "name": "callData", "type": "bytes" } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryAggregate", + "outputs": [ + { + "components": [ + { "internalType": "bool", "name": "success", "type": "bool" }, + { "internalType": "bytes", "name": "returnData", "type": "bytes" } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bool", "name": "requireSuccess", "type": "bool" }, + { + "components": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "bytes", "name": "callData", "type": "bytes" } + ], + "internalType": "struct Multicall2.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryBlockAndAggregate", + "outputs": [ + { "internalType": "uint256", "name": "blockNumber", "type": "uint256" }, + { "internalType": "bytes32", "name": "blockHash", "type": "bytes32" }, + { + "components": [ + { "internalType": "bool", "name": "success", "type": "bool" }, + { "internalType": "bytes", "name": "returnData", "type": "bytes" } + ], + "internalType": "struct Multicall2.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ] +} diff --git a/src/listener-commons.ts b/src/listener-commons.ts new file mode 100644 index 0000000..39c493d --- /dev/null +++ b/src/listener-commons.ts @@ -0,0 +1,142 @@ +import {startMongo, models} from './utils/mongo/config'; +import {ENV, _log, KEYS, nowMs, timeout} from './utils/configs/utils'; +import {mainWsComm} from './utils/web3/providers'; +import {getBlockInfo, getBlock} from './utils/web3/getBlocks'; +import {saveBlock, updateBlock} from './utils/mongo/saveBlock'; +import {pendingOld} from './utils/mongo/saveConfirmed'; + +const {txM, g} = models; +const { + BLOCKNATIVE_API_URL, + GAS_STATION_API_URL, + BLOCKNATIVE_API_OPT, + GAS_STATION_API_OPT, +} = KEYS; +const {ES_BLOCK} = ENV; + +const FIXER_INTERVAL: number = 60000 * 1; +const FIXER_INTERVAL_G: number = 60000 * 60; + +const serverName = 'qnCommons'; + +startMongo(serverName).then(async started => { + await timeout(5000); + if (started) { + _log.start('startFixer Go run every', FIXER_INTERVAL / 60000, 'minutes'); + startFixerJustKill(); + startFixerG(); + startBlocks(); + + setInterval(() => { + startFixerJustKill(); + }, FIXER_INTERVAL); + + setInterval(() => { + startFixerG(); + }, FIXER_INTERVAL_G); + + setInterval(() => { + proccessBlockQueue(); + }, 10000); + } else { + _log.warn('---> startFixer ', started); + } +}); + +const startBlocks = async () => { + _log.start('startBlocks Go!'); + + mainWsComm.on('block', async (number: any) => { + proccessBlock(number); + }); +}; + +const proccessBlock = async (number: number) => { + try { + _log.info('New Block: ', ES_BLOCK + number); + const block = await getBlock(number, mainWsComm); + + if (block) { + saveBlock({ + blockLink: ES_BLOCK + block.number, + blockHash: block.hash, + blockNumber: block.number, + timestampTx: nowMs(), + blockHeader: block, + by: serverName, + }); + } + } catch (e: any) { + _log.error('ProccessBlock catch ', number, e); + } + return; +}; + +const proccessBlockQueue = async () => { + try { + const b = await models.g.blocks.findOne({fullyUpdated: false}, null, { + sort: {timestampTx: -1}, + }); + if (b) { + if (b.blockNumber) { + const [gasnowResponse, bncResponseData] = await Promise.all([ + getBlockInfo(GAS_STATION_API_URL, GAS_STATION_API_OPT), + getBlockInfo(BLOCKNATIVE_API_URL, BLOCKNATIVE_API_OPT), + ]); + + if (bncResponseData && gasnowResponse) { + await updateBlock(b.blockHash, b.blockNumber, { + responseData: bncResponseData, + responseDataGas: gasnowResponse, + }); + } + } + } + } catch (e: any) { + _log.warn('proccessBlockQueue catch', e.message); + } + + return; +}; + +const startFixerJustKill = async () => { + const old_txs = 7; + + const end = new Date(); + end.setMinutes(new Date().getMinutes() - old_txs); + _log.start( + 'startFixer starting to fix all txs older than', + old_txs, + 'minutes' + ); + + const _txM = await txM.pending.find({timestampTx: {$lt: end.getTime()}}, {}); + if (_txM) fixOlds(_txM); +}; + +const fixOlds = async (oldTxs: Array) => { + try { + for (const tx of oldTxs) { + const nTx = {...tx._doc}; + delete nTx._id; + pendingOld({...nTx}, serverName); + } + } catch (e) { + _log.error('fixOlds catch ', e); + } +}; + +const startFixerG = async () => { + const old_g = 240; + + const end = new Date(); + end.setMinutes(new Date().getMinutes() - old_g); + _log.start( + 'startFixerG starting to delete all trash hashes older than', + old_g, + 'minutes' + ); + + await g.hashes.deleteMany({timestampTx: {$lt: end.getTime()}}, {}); + await g.trash.deleteMany({timestampTx: {$lt: end.getTime()}}, {}); +}; diff --git a/src/listener-confirmation.ts b/src/listener-confirmation.ts new file mode 100644 index 0000000..3d3f856 --- /dev/null +++ b/src/listener-confirmation.ts @@ -0,0 +1,89 @@ +import {startMongo, models} from './utils/mongo/config'; +import {escan2, MAIN_WS_PROVIDER, providersForLC} from './utils/web3/providers'; +import {_log, timeout} from './utils/configs/utils'; +import {getPendingTxResponse} from './utils/web3/getTransactions'; +import {proccessPending as pendingTx_uni_sushi} from './swapsDecoders/_uni_sushi/pending'; +import {pendingToConfirm, trashToconfirm} from './utils/mongo/saveConfirmed'; + +const {txM, g} = models; +const {whales} = g; +const serverName = 'qnConfirmed'; +const SwV2SH = [ + '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822', + '0x000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f', +]; +const SwapV2 = [ + '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822', + '0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d', +]; +const SwapV3 = [ + '0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67', + '0x000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564', +]; + +let whalesCache = new Array(); + +startMongo(serverName).then(async started => { + await timeout(5000); + + if (started) { + whales.find({}, null, {}, (e, docs) => { + if (!e) whalesCache = docs; + }); + await timeout(2000); + + _log.start('SwapV3 listenRouter Go!'); + listenRouter(SwapV3, false); + _log.start('SwapV2 listenRouter Go!'); + listenRouter(SwapV2, true); + _log.start('SwV2SH listenRouter Go!'); + listenRouter(SwV2SH, true); + } else { + _log.error('---> started ', started); + } +}); + +const listenRouter = async (filter: Array, isV2: boolean) => { + try { + MAIN_WS_PROVIDER.on( + { + topics: filter, + }, + async (data: any) => { + const hash = data.transactionHash; + const [knownTx_, knownTx_g_] = await Promise.all([ + txM.pending.findOne({hash}, null, {}), + g.trash.findOne({hash}, null, {}), + ]); + if (knownTx_) { + const knownTx = knownTx_._doc; + const nTx = {...knownTx}; + delete nTx._id; + pendingToConfirm(nTx, {}, serverName); + return; + } + + if (knownTx_g_) { + const knownTx_g = knownTx_g_._doc; + const nTx = {...knownTx_g}; + delete nTx._id; + trashToconfirm(nTx, {}, serverName); + return; + } + + const tx = await getPendingTxResponse(hash, providersForLC, escan2); + if (tx) { + const whaleData = whalesCache.find(w => + w ? w.address.toLowerCase() === tx.from.toLowerCase() : false + ); + pendingTx_uni_sushi(tx, whaleData, true, providersForLC); + } else { + _log.error('getPendingTxResponse ', hash, 'not found confirmed tx?'); + } + } + ); + } catch (e: any) { + _log.error('listen V2 catch ', e); + } + return; +}; diff --git a/src/listener-mempool.ts b/src/listener-mempool.ts new file mode 100644 index 0000000..96c8271 --- /dev/null +++ b/src/listener-mempool.ts @@ -0,0 +1,49 @@ +import {startMongo, models} from './utils/mongo/config'; +import {escan1, MAIN_WS_PROVIDER, providersForLM} from './utils/web3/providers'; +import {nowMs, timeout, _log} from './utils/configs/utils'; +import {getPendingTxResponse} from './utils/web3/getTransactions'; +import {proccessPending as pendingTx_uni_sushi} from './swapsDecoders/_uni_sushi/pending'; + +const {g} = models; +const {whales, hashes} = g; +const serverName = 'qnPending'; + +let whalesCache = new Array(); + +startMongo(serverName).then(async started => { + await timeout(5000); + + if (started) { + whales.find({}, null, {}, (e, docs) => { + if (!e) whalesCache = docs; + }); + + startListenPending(); + } else { + _log.warn('---> started ', started); + } +}); + +const startListenPending = () => { + MAIN_WS_PROVIDER._subscribe( + 'pending', + ['newPendingTransactions'], + async (hash: string) => { + new hashes({ + hash, + txHash: hash, + timestampTx: nowMs(), + }).save(async (e: any) => { + if (!e) { + const tx = await getPendingTxResponse(hash, providersForLM, escan1); + if (tx) { + const whaleData = whalesCache.find(w => + w ? w.address.toLowerCase() === tx.from.toLowerCase() : false + ); + pendingTx_uni_sushi(tx, whaleData, false, providersForLM); + } + } + }); + } + ); +}; diff --git a/src/models/BlockSchema.ts b/src/models/BlockSchema.ts new file mode 100644 index 0000000..f4ecd97 --- /dev/null +++ b/src/models/BlockSchema.ts @@ -0,0 +1,54 @@ +import {Schema} from 'mongoose'; + +const BlockHeaderSchema = new Schema({ + author: String, + difficulty: String, + extraData: String, + gasLimit: Number, + gasUsed: Number, + hash: String, + miner: String, + nonce: String, + parentHash: String, + size: Number, + sha3Uncles: String, + transactionRoot: String, + stateRoot: String, + receiptRoot: String, + timestamp: String, + number: Number, +}); + +const BlockNativeSchema = new Schema({ + system: String, + network: String, + unit: String, + maxPrice: Number, + currentBlockNumber: Number, + msSinceLastBlock: Number, + blockPrices: Array, +}); + +const BlockGasSchema = new Schema({ + fastest: Number, + fast: Number, + safeLow: Number, + average: Number, +}); + +const BlockSchema = new Schema( + { + blockLink: String, + blockHash: String, + blockNumber: Number, + fullyUpdated: Boolean, + responseData: BlockNativeSchema, + blockHeader: BlockHeaderSchema, + responseDataGas: BlockGasSchema, + by: String, + timestampTx: Number, + }, + {autoIndex: false} +); + +export {BlockSchema}; diff --git a/src/models/HashSchema.ts b/src/models/HashSchema.ts new file mode 100644 index 0000000..fc72c60 --- /dev/null +++ b/src/models/HashSchema.ts @@ -0,0 +1,12 @@ +import {Schema} from 'mongoose'; + +const HashSchema = new Schema( + { + hash: String, + txHash: String, + timestampTx: Number, + }, + {autoIndex: false} +); + +export {HashSchema}; diff --git a/src/models/PoolsSchema.ts b/src/models/PoolsSchema.ts new file mode 100644 index 0000000..762dd3a --- /dev/null +++ b/src/models/PoolsSchema.ts @@ -0,0 +1,22 @@ +import {Schema} from 'mongoose'; + +const PoolsSchema = new Schema( + { + address: String, + hashAddress: String, + t0: String, + t1: String, + transactionHash: String, + timestampTx: Number, + blockNumber: Number, + isV2: Boolean, + isV3: Boolean, + isV2Sushi: Boolean, + state: {}, + immutables: {}, + decoded: {}, + }, + {autoIndex: false} +); + +export {PoolsSchema}; diff --git a/src/models/TokenSchema.ts b/src/models/TokenSchema.ts new file mode 100644 index 0000000..e577493 --- /dev/null +++ b/src/models/TokenSchema.ts @@ -0,0 +1,27 @@ +import {Schema} from 'mongoose'; + +const TokenSchema = new Schema( + { + address: String, + hashAddress: String, + chainId: Number, + name: String, + symbol: String, + decimals: Number, + logoURI: String, + by: String, + + timestampTx: Number, + msV3: Number, + msV2: Number, + msV2Sushi: Number, + + isGeneral: Boolean, + isV2: Boolean, + isV3: Boolean, + isV2Sushi: Boolean, + }, + {autoIndex: false} +); + +export {TokenSchema}; diff --git a/src/models/TransactionSchema.ts b/src/models/TransactionSchema.ts new file mode 100644 index 0000000..3e68dce --- /dev/null +++ b/src/models/TransactionSchema.ts @@ -0,0 +1,103 @@ +import {Schema} from 'mongoose'; + +interface IContractSharkTx { + status?: string; // current status of the transaction + hash?: string; + txHash?: string; + to?: string; + + isV2?: boolean; + isV3?: boolean; + isV2Sushi?: boolean; + isV2Bal?: boolean; + + from?: string; + gas?: any; + gasPrice?: any; + gasUsed?: string; // present on on-chain txns + nonce?: number; + value?: any; + blockHash?: string; + cumulativeGasUsed?: number; + transactionHash?: string; + blockNumber?: number; + data: string; + timestampTx: number; // the UTC time of first detection of current status + transactionIndex?: number; // optional, present if status confirmed, failed + logsBloom?: string; + + // CUSTOM DATA + links?: { + etherscan?: string; + }; + fromTokenAddress?: string; + toTokenAddress?: string; + checkedPath?: any; + // CUSTOM DATA + whaleData?: any; + // FOR PENDING + mempoolData?: any; + // FOR CONFIRMED + logs?: any; + events?: any; + + // wich server, when + notes?: { + message?: string; + timestampTx?: number; + }; +} + +const TransactionSchema = new Schema( + { + status: String, // current status of the transaction + hash: String, + txHash: String, + to: String, + + isV2: Boolean, + isV3: Boolean, + isV2Sushi: Boolean, + isV2Bal: Boolean, + + from: String, + gas: Number, + gasPrice: String, + gasUsed: String, // present on on-chain txns + nonce: Number, + value: String, + blockHash: String, + cumulativeGasUsed: Number, + transactionHash: String, + blockNumber: Number, + data: String, + timestampTx: Number, // the UTC time of first detection of current status + transactionIndex: Number, // optional, present if status confirmed, failed + logsBloom: String, + + // CUSTOM DATA + links: { + etherscan: String, + }, + fromTokenAddress: String, + toTokenAddress: String, + checkedPath: Schema.Types.Mixed, + + // CUSTOM DATA + whaleData: Schema.Types.Mixed, + // FOR PENDING + mempoolData: Schema.Types.Mixed, + // FOR CONFIRMED + logs: Schema.Types.Mixed, + events: Schema.Types.Mixed, + + // wich server, when + notes: { + message: String, + timestampTx: Number, + }, + }, + {autoIndex: false} +); + +export {TransactionSchema, IContractSharkTx}; diff --git a/src/models/WhalesSchema.ts b/src/models/WhalesSchema.ts new file mode 100644 index 0000000..a4ddf83 --- /dev/null +++ b/src/models/WhalesSchema.ts @@ -0,0 +1,17 @@ +import {Schema} from 'mongoose'; + +const WhalesSchema = new Schema( + { + address: String, + hashAddress: String, + timestampTx: Number, + twitter: { + timestamp: Number, + tweetID: String, + handle: String, + }, + }, + {autoIndex: false} +); + +export {WhalesSchema}; diff --git a/src/models/index.ts b/src/models/index.ts new file mode 100644 index 0000000..739a3d0 --- /dev/null +++ b/src/models/index.ts @@ -0,0 +1,15 @@ +import {TokenSchema} from './TokenSchema'; +import {TransactionSchema} from './TransactionSchema'; +import {BlockSchema} from './BlockSchema'; +import {WhalesSchema} from './WhalesSchema'; +import {HashSchema} from './HashSchema'; +import {PoolsSchema} from './PoolsSchema'; + +export { + TokenSchema, + TransactionSchema, + BlockSchema, + WhalesSchema, + HashSchema, + PoolsSchema, +}; diff --git a/src/swapsDecoders/_uni_sushi/_decoders/getMempoolData.ts b/src/swapsDecoders/_uni_sushi/_decoders/getMempoolData.ts new file mode 100644 index 0000000..418d8cd --- /dev/null +++ b/src/swapsDecoders/_uni_sushi/_decoders/getMempoolData.ts @@ -0,0 +1,50 @@ +import {_log} from '../../../utils/configs/utils'; +import {IContractSharkTx} from '../../../models/TransactionSchema'; +import {V3_SWAP_FNAME} from '../../../utils/web3/utils'; + +const {EO, EOS, EI, EIS} = V3_SWAP_FNAME; + +export const getMempoolData = async ( + tx: IContractSharkTx, + tokens: Array, + dexSpace: string +) => { + try { + const {value, mempoolData} = tx; + const {decodedData, txMethod} = mempoolData; + + const isExactOutV3 = txMethod === EOS || txMethod === EO; + const isExactInV3 = txMethod === EI || txMethod === EIS; + + let amountIn = null; + let amountOut = null; + + if (isExactOutV3 || isExactInV3) { + amountIn = isExactOutV3 + ? decodedData['amountInMaximum'] + : decodedData['amountIn']; + amountOut = isExactOutV3 + ? decodedData['amountOut'] + : decodedData['amountOutMinimum']; + } else { + amountIn = decodedData['amountIn'] || decodedData['amountInMax'] || value; + amountOut = decodedData['amountOut'] || decodedData['amountOutMin']; + } + if (amountIn && amountOut) { + const tl = tokens.length - 1; + const t0 = tokens[0]; + const t1 = tokens[tl]; + + return { + amountIn: amountIn.toString(), + amountOut: amountOut.toString(), + input: t0, + output: t1, + tokens, + }; + } + } catch (e: any) { + _log.error('getMempoolData catch', dexSpace, tx.hash, e); + } + return null; +}; diff --git a/src/swapsDecoders/_uni_sushi/_v2/handleSwap.ts b/src/swapsDecoders/_uni_sushi/_v2/handleSwap.ts new file mode 100644 index 0000000..81425c9 --- /dev/null +++ b/src/swapsDecoders/_uni_sushi/_v2/handleSwap.ts @@ -0,0 +1,74 @@ +import {nowMs, _log} from '../../../utils/configs/utils'; +import {createPending} from '../../../utils/mongo/savePending'; +import {createConfirm} from '../../../utils/mongo/saveConfirmed'; +import {getTokens} from '../../../utils/web3/getTokens'; +import {IContractSharkTx} from '../../../models/TransactionSchema'; +import {getMempoolData} from '../_decoders/getMempoolData'; +import {models} from '../../../utils/mongo/config'; + +const {g} = models; +const {hashes} = g; +const pName = 'qnPending_v2'; + +export const handleSwap = async ( + tx: IContractSharkTx, + dexSpace: string, + directConfirm: boolean, + providers: Array +) => { + try { + const {checkedPath} = tx.mempoolData; + const tks = await getTokens(checkedPath, pName, dexSpace, providers); + + if (tks && checkedPath && tks.length === checkedPath.length) { + const mempoolData = await getMempoolData(tx, tks, dexSpace); + const l = tks.length - 1; + const firstToken = tks[0]; + const lastToken = tks[l]; + const fromTokenAddress = firstToken ? firstToken.address : checkedPath[0]; + const toTokenAddress = lastToken ? lastToken.address : checkedPath[l]; + if (mempoolData) { + const toCreate = { + ...tx, + fromTokenAddress, + toTokenAddress, + checkedPath, + mempoolData: { + ...tx.mempoolData, + ...mempoolData, + }, + }; + if (directConfirm) { + new hashes({ + hash: tx.hash, + txHash: tx.hash, + timestampTx: nowMs(), + }).save(async (e: any) => { + if (!e) { + createConfirm(toCreate, 'directConfirm'); + } + }); + } else { + createPending(toCreate, dexSpace); + } + } else { + _log.warn( + 'handleSwap', + dexSpace, + tx.hash, + 'no mempool data after compute swap?' + ); + } + } else { + _log.warn( + 'handleSwap', + dexSpace, + tx.hash, + 'not tks or tks.length !== checkedPath.length' + ); + } + } catch (e: any) { + _log.error('handleSwap', dexSpace, tx.hash, e); + } + return; +}; diff --git a/src/swapsDecoders/_uni_sushi/_v3/getV3InternalSwap.ts b/src/swapsDecoders/_uni_sushi/_v3/getV3InternalSwap.ts new file mode 100644 index 0000000..a4dfc53 --- /dev/null +++ b/src/swapsDecoders/_uni_sushi/_v3/getV3InternalSwap.ts @@ -0,0 +1,67 @@ +import {checksum, _log} from '../../../utils/configs/utils'; +import {iUniV3Router} from '../../../utils/web3/abis-interfaces'; +import { + V3_SWAP_SIGS, + _V3_FNAME_ONLY_SWAP, + _V3_SIGS_ONLY_SWAP, +} from '../../../utils/web3/utils'; + +const {exactInputSig, exactOutputSig} = V3_SWAP_SIGS; + +async function getV3InternalSwap(decodeMe: string) { + try { + const innerMethodSig = decodeMe.substring(0, 10); + const isSwap = _V3_SIGS_ONLY_SWAP.indexOf(innerMethodSig); + + if (isSwap >= 0) { + const innerMethod = _V3_FNAME_ONLY_SWAP[isSwap]; + const decodedInnerData = iUniV3Router.decodeFunctionData( + innerMethod, + decodeMe + )[0]; + + let fromTokenAddress = null; + let midTokenAddress = null; + let toTokenAddress = null; + let fee = null; + let checkedPath = []; + + if (innerMethodSig === exactOutputSig) { + const path = decodedInnerData['path']; + fromTokenAddress = checksum('0x' + path.slice(94, 134)); + midTokenAddress = checksum('0x' + path.slice(48, 88)); + toTokenAddress = checksum(path.slice(0, 42)); + checkedPath = []; + } else if (innerMethodSig === exactInputSig) { + const path = decodedInnerData['path']; + fromTokenAddress = checksum(path.slice(0, 42)); + midTokenAddress = checksum('0x' + path.slice(48, 88)); + toTokenAddress = checksum('0x' + path.slice(94, 134)); + checkedPath = []; + } else { + fromTokenAddress = checksum(decodedInnerData['tokenIn']); + toTokenAddress = checksum(decodedInnerData['tokenOut']); + fee = decodedInnerData['fee']; + } + + checkedPath.push(fromTokenAddress); + midTokenAddress && checkedPath.push(midTokenAddress); + checkedPath.push(toTokenAddress); + + if (checkedPath.length > 0) { + return { + checkedPath, + innerMethod, + decodedInnerData, + fee, + }; + } + // + } + } catch (e: any) { + _log.error('internalSwap', e.message); + } + return null; +} + +export {getV3InternalSwap}; diff --git a/src/swapsDecoders/_uni_sushi/_v3/handleMultiSwap.ts b/src/swapsDecoders/_uni_sushi/_v3/handleMultiSwap.ts new file mode 100644 index 0000000..26492f5 --- /dev/null +++ b/src/swapsDecoders/_uni_sushi/_v3/handleMultiSwap.ts @@ -0,0 +1,97 @@ +import {nowMs, _log} from '../../../utils/configs/utils'; +import {getMempoolData} from '../_decoders/getMempoolData'; +import {createPending} from '../../../utils/mongo/savePending'; +import {createConfirm} from '../../../utils/mongo/saveConfirmed'; +import {getTokens} from '../../../utils/web3/getTokens'; +import {_V3_FNAME_ONLY_SWAP} from '../../../utils/web3/utils'; +import {IContractSharkTx} from '../../../models/TransactionSchema'; +import {getV3InternalSwap} from './getV3InternalSwap'; +import {models} from '../../../utils/mongo/config'; + +const {g} = models; +const {hashes} = g; + +const pName = 'qnPending_v3_multiswap'; + +export const handleMultiSwap = async ( + tx: IContractSharkTx, + dexSpace: string, + directConfirm: boolean, + providers: Array +) => { + try { + const {decodedData} = tx.mempoolData; + let fromTokenAddress = ''; + let toTokenAddress = ''; + const multiSwapCalls = []; + + for (let i = 0; i < decodedData.length; i++) { + const internalCall = await getV3InternalSwap(decodedData[i]); + if (internalCall) { + const {decodedInnerData, checkedPath, innerMethod, fee} = internalCall; + if (_V3_FNAME_ONLY_SWAP.indexOf(innerMethod) >= 0) { + if (fromTokenAddress === '') { + fromTokenAddress = checkedPath[0]; + } + toTokenAddress = checkedPath[checkedPath.length - 1]; + + const tks = await getTokens(checkedPath, pName, dexSpace, providers); + if (tks && tks.length === checkedPath.length) { + const innerCall = await getMempoolData( + { + ...tx, + mempoolData: { + txMethod: innerMethod, + decodedData: decodedInnerData, + fee, + }, + }, + tks, + dexSpace + ); + if (innerCall) { + multiSwapCalls.push(innerCall); + } + } else { + _log.warn( + 'handleMultiSwap', + dexSpace, + tx.hash, + 'not tks or tks.length !== checkedPath.length' + ); + } + } + } + } + if (multiSwapCalls.length > 0) { + for (const swapCall of multiSwapCalls) { + const toCreate = { + ...tx, + fromTokenAddress: swapCall.input.address, + toTokenAddress: swapCall.output.address, + mempoolData: { + ...tx.mempoolData, + multiSwapCalls, + ...swapCall, + }, + }; + if (directConfirm) { + new hashes({ + hash: tx.hash, + txHash: tx.hash, + timestampTx: nowMs(), + }).save(async (e: any) => { + if (!e) { + createConfirm(toCreate, 'directConfirm'); + } + }); + } else { + createPending(toCreate, dexSpace); + } + } + } + } catch (e: any) { + _log.error('handleMultiswap catch', dexSpace, e.message, tx.hash); + } + return; +}; diff --git a/src/swapsDecoders/_uni_sushi/_v3/handleSwap.ts b/src/swapsDecoders/_uni_sushi/_v3/handleSwap.ts new file mode 100644 index 0000000..5016858 --- /dev/null +++ b/src/swapsDecoders/_uni_sushi/_v3/handleSwap.ts @@ -0,0 +1,97 @@ +import {checksum, nowMs, _log} from '../../../utils/configs/utils'; +import {getMempoolData} from '../_decoders/getMempoolData'; +import {createPending} from '../../../utils/mongo/savePending'; +import {createConfirm} from '../../../utils/mongo/saveConfirmed'; +import {getTokens} from '../../../utils/web3/getTokens'; +import {V3_SWAP_FNAME} from '../../../utils/web3/utils'; +import {IContractSharkTx} from '../../../models/TransactionSchema'; +import {models} from '../../../utils/mongo/config'; + +const {g} = models; +const {hashes} = g; + +const {EI, EIS, EO, EOS} = V3_SWAP_FNAME; +const pName = 'qnPending_v3_swap'; + +export const handleSwap = async ( + tx: IContractSharkTx, + dexSpace: string, + directConfirm: boolean, + providers: Array +) => { + try { + const {txMethod, decodedData} = tx.mempoolData; + let fromTokenAddress = ''; + let midTokenAddress = null; + let toTokenAddress = ''; + let fee = null; + const checkedPath = []; + + if (txMethod === EIS || txMethod === EOS) { + fromTokenAddress = checksum(decodedData['tokenIn']); + toTokenAddress = checksum(decodedData['tokenOut']); + fee = decodedData['fee']; + } else if (txMethod === EO || txMethod === EI) { + const path = decodedData['path']; + midTokenAddress = checksum('0x' + path.slice(48, 88)); + + fromTokenAddress = checksum( + txMethod === EO ? '0x' + path.slice(94, 134) : path.slice(0, 42) + ); + toTokenAddress = checksum( + txMethod === EI ? '0x' + path.slice(94, 134) : path.slice(0, 42) + ); + } + checkedPath.push(fromTokenAddress); + midTokenAddress && checkedPath.push(midTokenAddress); + checkedPath.push(toTokenAddress); + + if (checkedPath.length > 0) { + const tks = await getTokens(checkedPath, pName, dexSpace, providers); + if (tks && tks.length === checkedPath.length) { + const mempoolData = await getMempoolData( + { + ...tx, + mempoolData: {txMethod, decodedData, checkedPath, fee}, + }, + tks, + dexSpace + ); + if (mempoolData) { + const toCreate = { + ...tx, + fromTokenAddress, + toTokenAddress, + mempoolData: { + ...tx.mempoolData, + ...mempoolData, + }, + }; + if (directConfirm) { + new hashes({ + hash: tx.hash, + txHash: tx.hash, + timestampTx: nowMs(), + }).save(async (e: any) => { + if (!e) { + createConfirm(toCreate, 'directConfirm'); + } + }); + } else { + createPending(toCreate, dexSpace); + } + } + } else { + _log.warn( + 'handleSwap', + dexSpace, + tx.hash, + 'not tks or tks.length !== checkedPath.length' + ); + } + } + } catch (e: any) { + _log.error('handleSwap catch', dexSpace, e.message, tx.hash); + } + return; +}; diff --git a/src/swapsDecoders/_uni_sushi/pending.ts b/src/swapsDecoders/_uni_sushi/pending.ts new file mode 100644 index 0000000..6a452ed --- /dev/null +++ b/src/swapsDecoders/_uni_sushi/pending.ts @@ -0,0 +1,77 @@ +import {_log, ROUTERS} from '../../utils/configs/utils'; +import { + iSushiV2Router, + iUniV2Router, + iUniV3Router, +} from '../../utils/web3/abis-interfaces'; +import {TransactionResponse} from '@ethersproject/abstract-provider'; +import {_V3_FUNC_ALLOWED_METHODS, _MULTICALL} from '../../utils/web3/utils'; +import {handleMultiSwap as handleMultiSwapV3} from './_v3/handleMultiSwap'; +import {handleSwap as handleSwapV3} from './_v3/handleSwap'; +import {handleSwap as handleSwapV2} from './_v2/handleSwap'; +import {checkTx} from '../../utils/web3/checkTxs'; + +const dexSpacev2 = 'v2'; +const dexSpacev3 = 'v3'; +const dexSpacev2sh = 'v2sh'; + +export const proccessPending = async ( + tx: TransactionResponse, + whaleData: any, + directConfirm: boolean, + providers: Array +) => { + try { + const isUniSpaceV2 = tx.to === ROUTERS.UNIV2; + const isSushiSpaceV2 = tx.to === ROUTERS.SUSHIV2; + const isUniSpaceV3 = tx.to === ROUTERS.UNIV3; + + if (isUniSpaceV2 || isSushiSpaceV2 || isUniSpaceV3) { + let parsedTx = null; + let dexSpace = null; + + if (isUniSpaceV2) { + parsedTx = iUniV2Router.parseTransaction(tx); + dexSpace = dexSpacev2; + } else if (isSushiSpaceV2) { + parsedTx = iSushiV2Router.parseTransaction(tx); + dexSpace = dexSpacev2sh; + } else if (isUniSpaceV3) { + parsedTx = iUniV3Router.parseTransaction(tx); + dexSpace = dexSpacev3; + } + + if (parsedTx && dexSpace) { + const txMethod = parsedTx.functionFragment.name; + + if (_V3_FUNC_ALLOWED_METHODS.includes(txMethod)) { + const nTx = { + ...checkTx(tx, whaleData, false, true, false), + mempoolData: { + txMethod, + decodedData: parsedTx.args[0], + }, + }; + txMethod === _MULTICALL + ? handleMultiSwapV3(nTx, dexSpace, directConfirm, providers) + : handleSwapV3(nTx, dexSpace, directConfirm, providers); + } else if (txMethod.includes('swap')) { + const nTx = { + ...checkTx(tx, whaleData, isUniSpaceV2, false, isSushiSpaceV2), + mempoolData: { + txMethod, + decodedData: parsedTx.args, + checkedPath: parsedTx.args['path'], + }, + }; + handleSwapV2(nTx, dexSpace, directConfirm, providers); + } + } else { + _log.warn('proccessPending cant parse tx?', tx.hash); + } + } + } catch (e: any) { + _log.error('proccessPending catch', e.message, tx.hash); + } + return; +}; diff --git a/src/utils/_websocket/utils.ts b/src/utils/_websocket/utils.ts new file mode 100644 index 0000000..664bf1b --- /dev/null +++ b/src/utils/_websocket/utils.ts @@ -0,0 +1,115 @@ +import 'dotenv/config'; +import {Server, Namespace} from 'socket.io'; +import express from 'express'; +import http from 'http'; +import {_log} from '../configs/utils'; +import path from 'path'; +import 'dotenv/config'; +/**import helmet from 'helmet'*/ +const app = express(); + +const distDir = path.join(__dirname, '../../../client_build/'); + +//app.use(helmet({ contentSecurityPolicy: process.env.NODE_CONFIG_ENV === 'production' ? undefined : false })) + +app.disable('x-powered-by'); + +const SOCKET_OPTS = { + cors: { + origin: process.env.CORS_ORIGIN || '*', + methods: ['GET', 'POST'], + credentials: true, + }, +}; + +const SOCKET_PORT = process.env.PORT || 3001; + +let explorerNS: Namespace; + +const emmitChange = (_ACTION: string, fullDocument: any) => { + try { + if (fullDocument && _ACTION) { + const {fromTokenAddress, toTokenAddress, isV2, isV3, isV2Sushi} = + fullDocument; + const target = isV2 ? 'v2' : isV3 ? 'v3' : isV2Sushi ? 'v2sh' : null; + + if (target) { + explorerNS.to(fromTokenAddress + target).emit(_ACTION, fullDocument); + explorerNS.to(toTokenAddress + target).emit(_ACTION, fullDocument); + } + } + } catch (e: any) { + _log.error('emmitChange catch', e); + } +}; + +const getSpaceFilter = (dexSpaces: any) => { + try { + const {isV2, isV3, isV2Sushi} = dexSpaces; + const array = []; + if (isV2 && isV2 === true) { + array.push({isV2: true}); + } + if (isV3 && isV3 === true) { + array.push({isV3: true}); + } + if (isV2Sushi && isV2Sushi === true) { + array.push({isV2Sushi: true}); + } + return { + $or: array, + }; + } catch (e: any) { + _log.error('getSpaceFilter catch', e); + } + return {}; +}; + +const getAddressFilter = (address: string) => { + try { + return { + $or: [ + { + fromTokenAddress: address, + }, + { + toTokenAddress: address, + }, + // TODO: in front { checkedPath: address } + ], + }; + } catch (e: any) { + _log.error('getAddressFilter catch', e); + } + return {}; +}; + +const startSocketServer = async (serverName: string): Promise => { + return new Promise(resolve => { + const app = express(); + const server = http.createServer(app); + const io = new Server(server, SOCKET_OPTS); + app.use(express.static(distDir)); + + app.get('*', (req, res) => { + res.sendFile(path.resolve(distDir, 'index.html')); + }); + + server.listen(SOCKET_PORT, () => { + _log.ready( + `${serverName} on SOCKET_PORT ${SOCKET_PORT} CORS ${SOCKET_OPTS.cors.origin}`, + 'WebApp server on: http://localhost:' + SOCKET_PORT + ); + explorerNS = io.of('/explorer'); + resolve(true); + }); + }); +}; + +export { + explorerNS, + startSocketServer, + emmitChange, + getSpaceFilter, + getAddressFilter, +}; diff --git a/src/utils/configs/utils.ts b/src/utils/configs/utils.ts new file mode 100644 index 0000000..1321879 --- /dev/null +++ b/src/utils/configs/utils.ts @@ -0,0 +1,102 @@ +import 'dotenv/config'; +import consola from 'consola'; +import {ethers} from 'ethers'; + +const _log = consola; + +const checksum = ethers.utils.getAddress; + +const timeout = (ms: number) => { + return new Promise(resolve => setTimeout(resolve, ms)); +}; + +const nowMs = () => { + return new Date().getTime(); +}; + +const nowDate = () => { + return new Date(); +}; + +const ENV = { + ATLAS_STRING: process.env.ATLAS_STRING || '', + COLLECTION_PREFIX: process.env.COLLECTION_PREFIX || '', + CORS_ORIGIN: process.env.CORS_ORIGIN || '', + ES_TX: 'https://etherscan.io/tx/', + ES_ADDRESS: 'https://etherscan.io/address/', + ES_BLOCK: 'https://etherscan.io/block/', +}; + +const KEYS = { + GAS_STATION_API_URL: process.env.GAS_STATION_API_URL || '', + GAS_STATION_API_OPT: {}, + BLOCKNATIVE_API_URL: process.env.BLOCKNATIVE_API_URL || '', + BLOCKNATIVE_API_OPT: { + headers: {Authorization: process.env.BLOCKNATIVE_API_KEY || ''}, + }, + MAIN_WS: process.env.MAIN_WS || '', + INFURA_KEY1: process.env.INFURA_KEY1 || '', + INFURA_KEY2: process.env.INFURA_KEY2 || '', + INFURA_KEY3: process.env.INFURA_KEY3 || '', + INFURA_KEY4: process.env.INFURA_KEY4 || '', + ETHERSCAN_KEY1: process.env.ETHERSCAN_KEY1 || '', + ETHERSCAN_KEY2: process.env.ETHERSCAN_KEY2 || '', + ALCHEMY_KEY1: process.env.ALCHEMY_KEY1 || '', + ALCHEMY_KEY2: process.env.ALCHEMY_KEY2 || '', + GET_BLOCK_KEY: process.env.GET_BLOCK_KEY || '', + POKT_KEY: process.env.POKT_KEY || '', +}; + +const ROUTERS = { + UNIV3: checksum(process.env.UNIV3 || ''), + UNIV2: checksum(process.env.UNIV2 || ''), + SUSHIV2: checksum(process.env.SUSHIV2 || ''), +}; + +const TOKEN_LIST_ALL = Array( + process.env.WRAPPED || '', + process.env.YEARN || '', + process.env.ROLL || '', + process.env.SUSHISWAP || '', + process.env.ONE_INCH || '', + process.env.COINGECKO || '', + process.env.COMPOUND || '', + process.env.DEFIPRIME || '', + process.env.MESSARI || '', + process.env.OPYN || '', + process.env.SNX || '', + process.env.SET || '', + process.env.AVE || '', + process.env.AGORA || '', + process.env.CMCDEFI || '', + process.env.CMCSTABLECOIN || '', + process.env.CMC200ERC20 || '', + process.env.KLEROS || '', + process.env.FURUCOMBO || '', + process.env.KYBER || '', + process.env.MYCRYPTOAPI || '', + process.env.ZAPPER || '', + process.env.UMA || '', + process.env.BAZAR || '', + process.env.ZERION || '' +); + +function getRandomInt(min: number, max: number) { + min = Math.ceil(min); + max = Math.floor(max); + const res = Math.floor(Math.random() * (max - min + 1)) + min; + return res; +} + +export { + ENV, + ROUTERS, + KEYS, + TOKEN_LIST_ALL, + nowDate, + nowMs, + timeout, + _log, + checksum, + getRandomInt, +}; diff --git a/src/utils/dev-utils/drop-transactions.ts b/src/utils/dev-utils/drop-transactions.ts new file mode 100644 index 0000000..6291e48 --- /dev/null +++ b/src/utils/dev-utils/drop-transactions.ts @@ -0,0 +1,28 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'dropTransactions'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.txM.pending.collection.drop(); + + await models.txM.confirmed.collection.drop(); + + await models.g.hashes.collection.drop(); + await models.g.trash.collection.drop(); + _log.ready('done'); +}; diff --git a/src/utils/dev-utils/reset-blocks.ts b/src/utils/dev-utils/reset-blocks.ts new file mode 100644 index 0000000..f474663 --- /dev/null +++ b/src/utils/dev-utils/reset-blocks.ts @@ -0,0 +1,23 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'resetBlocks'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.g.blocks.deleteMany({}, {}); + _log.ready('done'); +}; diff --git a/src/utils/dev-utils/reset-pools.ts b/src/utils/dev-utils/reset-pools.ts new file mode 100644 index 0000000..89d581e --- /dev/null +++ b/src/utils/dev-utils/reset-pools.ts @@ -0,0 +1,23 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'resetPools'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.g.pools.deleteMany({}, {}); + _log.ready('done'); +}; diff --git a/src/utils/dev-utils/reset-tokens.ts b/src/utils/dev-utils/reset-tokens.ts new file mode 100644 index 0000000..82087fc --- /dev/null +++ b/src/utils/dev-utils/reset-tokens.ts @@ -0,0 +1,23 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'resetTokens'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.g.tokens.deleteMany({}, {}); + _log.ready('done'); +}; diff --git a/src/utils/dev-utils/reset-transactions-c.ts b/src/utils/dev-utils/reset-transactions-c.ts new file mode 100644 index 0000000..09ecea6 --- /dev/null +++ b/src/utils/dev-utils/reset-transactions-c.ts @@ -0,0 +1,23 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'resetTransactionsConfirmed'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.txM.confirmed.deleteMany({}, {}); + _log.ready('done'); +}; diff --git a/src/utils/dev-utils/reset-transactions-p.ts b/src/utils/dev-utils/reset-transactions-p.ts new file mode 100644 index 0000000..b8d6677 --- /dev/null +++ b/src/utils/dev-utils/reset-transactions-p.ts @@ -0,0 +1,23 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'resetTransactionsPending'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.txM.pending.deleteMany({}, {}); + _log.ready('done'); +}; diff --git a/src/utils/dev-utils/reset-transactions-t-h.ts b/src/utils/dev-utils/reset-transactions-t-h.ts new file mode 100644 index 0000000..12741ab --- /dev/null +++ b/src/utils/dev-utils/reset-transactions-t-h.ts @@ -0,0 +1,24 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'resetTransactionsTH'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.g.trash.deleteMany({}, {}); + await models.g.hashes.deleteMany({}, {}); + _log.ready('done'); +}; diff --git a/src/utils/dev-utils/reset-transactions.ts b/src/utils/dev-utils/reset-transactions.ts new file mode 100644 index 0000000..5875374 --- /dev/null +++ b/src/utils/dev-utils/reset-transactions.ts @@ -0,0 +1,28 @@ +import {startMongo, models} from '../mongo/config'; +import {_log} from '../configs/utils'; + +const serverName = 'resetTransactions'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + start(); +}; + +const start = async () => { + _log.start(serverName); + await models.txM.pending.deleteMany({}, {}); + + await models.txM.confirmed.deleteMany({}, {}); + + await models.g.trash.deleteMany({}, {}); + await models.g.hashes.deleteMany({}, {}); + _log.ready('done'); +}; diff --git a/src/utils/initServer/create-indexes.ts b/src/utils/initServer/create-indexes.ts new file mode 100644 index 0000000..3a535e7 --- /dev/null +++ b/src/utils/initServer/create-indexes.ts @@ -0,0 +1,93 @@ +import {_log} from '../configs/utils'; +import { + TokenSchema, + TransactionSchema, + BlockSchema, + WhalesSchema, + HashSchema, +} from '../../models/index'; +import {models, startMongo} from '../mongo/config'; + +const {g, txM} = models; +const serverName = 'createIndexes'; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startServer = () => { + _log.start('---> startServer ', serverName); + createIndexes(); +}; + +const createIndexes = () => { + HashSchema.index({hash: 'text'}, {unique: true}); + HashSchema.index({txHash: 'hashed'}); + HashSchema.index({timestampTx: -1}); + HashSchema.index({timestampTx: 1}); + + TransactionSchema.index({hash: 'text'}, {unique: true}); + TransactionSchema.index({txHash: 'hashed'}); + TransactionSchema.index({timestampTx: -1}); + TransactionSchema.index({timestampTx: 1}); + TransactionSchema.index({fromTokenAddress: 'hashed'}); + TransactionSchema.index({toTokenAddress: 'hashed'}); + + TokenSchema.index({address: 'text'}, {unique: true}); + TokenSchema.index({hashAddress: 'hashed'}); + TokenSchema.index({timestampTx: -1}); + TokenSchema.index({timestampTx: 1}); + TokenSchema.index({msV3: 1}); + TokenSchema.index({msV3: -1}); + TokenSchema.index({msV2: 1}); + TokenSchema.index({msV2: -1}); + TokenSchema.index({msV2Sushi: 1}); + TokenSchema.index({msV2Sushi: -1}); + TokenSchema.index({msV2Bal: 1}); + TokenSchema.index({msV2Bal: -1}); + + WhalesSchema.index({address: 'text'}, {unique: true}); + WhalesSchema.index({hashAddress: 'hashed'}); + WhalesSchema.index({timestampTx: -1}); + WhalesSchema.index({timestampTx: 1}); + + BlockSchema.index({blockHash: 'text'}, {unique: true}); + BlockSchema.index({blockNumber: 1}, {unique: true}); + BlockSchema.index({blockNumber: -1}); + BlockSchema.index({timestampTx: -1}); + BlockSchema.index({timestampTx: 1}); + + txM.confirmed.createIndexes((e: any) => { + if (e) _log.error(e); + else _log.ready('txM.confirmed.'); + }); + txM.pending.createIndexes((e: any) => { + if (e) _log.error(e); + else _log.ready('txM.pending.'); + }); + + g.tokens.createIndexes((e: any) => { + if (e) _log.error(e); + else _log.ready('g.tokens'); + }); + g.whales.createIndexes((e: any) => { + if (e) _log.error(e); + else _log.ready('g.whales'); + }); + g.trash.createIndexes((e: any) => { + if (e) _log.error(e); + else _log.ready('g.trash'); + }); + g.blocks.createIndexes((e: any) => { + if (e) _log.error(e); + else _log.ready('g.blocks.'); + }); + g.hashes.createIndexes((e: any) => { + if (e) _log.error(e); + else _log.ready('g.hashes.'); + }); +}; diff --git a/src/utils/initServer/init-pools.ts b/src/utils/initServer/init-pools.ts new file mode 100644 index 0000000..8d990c0 --- /dev/null +++ b/src/utils/initServer/init-pools.ts @@ -0,0 +1,127 @@ +import {ethers} from 'ethers'; +import {models, startMongo} from '../mongo/config'; +import {checksum, nowMs, timeout, _log} from '../configs/utils'; +import {mainWsComm} from '../web3/providers'; +import {savePools} from '../mongo/savePools'; + +const serverName = 'initPools'; +const {g} = models; + +const factoryv2 = checksum('0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f'); +const factoryv3 = checksum('0x1F98431c8aD98523631AE4a59f267346ea31F984'); +const factoryv2sh = checksum('0xc0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac'); +const poolCreated = ethers.utils.id( + 'PoolCreated(address,address,uint24,int24,address)' +); +const pairCreated = ethers.utils.id( + 'PairCreated(address,address,address,uint256)' +); + +const startServer = () => { + _log.start('---> startServer ', serverName); + startAddPools(); +}; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startAddPoolsGet = async ( + fromBlock: any, + lastBlock: any, + dex: string, + factory: any, + filterTopics: any +) => { + try { + _log.info( + 'startAddPoolsGet fromBlock lastBlock dex', + fromBlock, + lastBlock, + dex + ); + const toBlock = fromBlock + 100000; + const filter = { + address: factory, + fromBlock, + toBlock: toBlock >= lastBlock ? 'latest' : toBlock, + topics: [filterTopics], + }; + const result = await mainWsComm.getLogs(filter); + + if (result) + for (const r of result) { + const data = r.data; + const topics = r.topics; + const t0 = checksum('0x' + topics[1].slice(66 - 40, 112)); + const t1 = checksum('0x' + topics[2].slice(66 - 40, 112)); + const address = checksum('0x' + data.slice(130 - 40, 130)); + const v2Address = checksum('0x' + data.slice(26, 66)); + const transactionHash = r.transactionHash; + const p = { + address: dex === 'v3' ? address : v2Address, + hashAddress: dex === 'v3' ? address : v2Address, + t0, + t1, + transactionHash, + timestampTx: nowMs(), + blockNumber: r.blockNumber, + isV3: dex === 'v3', + isV2: dex === 'v2', + isV2Sushi: dex === 'v2sh', + }; + savePools(p); + await timeout(10); + } + if (toBlock <= lastBlock) { + await startAddPoolsGet(toBlock, lastBlock, dex, factory, filterTopics); + } else { + _log.ready('startAddPoolsGet DONE', toBlock, lastBlock, dex); + } + } catch (e) { + _log.error(e); + } + return; +}; + +const startAddPools = async () => { + try { + const lastBlock = await mainWsComm.getBlockNumber(); + + const pv2 = await g.pools.findOne({isV2: true}, null, { + sort: {blockNumber: -1}, + }); + const pv3 = await g.pools.findOne({isV3: true}, null, { + sort: {blockNumber: -1}, + }); + const pv2sh = await g.pools.findOne({isV2Sushi: true}, null, { + sort: {blockNumber: -1}, + }); + + let iv2 = 10000835; + let iv3 = 12369621; + let iv2sh = 10794229; + + if (pv2) { + iv2 = pv2.blockNumber; + } + if (pv3) { + iv3 = pv3.blockNumber; + } + if (pv2sh) { + iv2sh = pv2sh.blockNumber; + } + + await startAddPoolsGet(iv3, lastBlock, 'v3', factoryv3, poolCreated); + await startAddPoolsGet(iv2, lastBlock, 'v2', factoryv2, pairCreated); + await startAddPoolsGet(iv2sh, lastBlock, 'v2sh', factoryv2sh, pairCreated); + } catch (e) { + _log.error(e); + } +}; + +export {startAddPools as fetchNewPools}; diff --git a/src/utils/initServer/init-tokens.ts b/src/utils/initServer/init-tokens.ts new file mode 100644 index 0000000..6f0782c --- /dev/null +++ b/src/utils/initServer/init-tokens.ts @@ -0,0 +1,79 @@ +import {get} from 'https'; +import {timeout, TOKEN_LIST_ALL, _log} from '../configs/utils'; +import {startMongo, models} from '../mongo/config'; +import {saveToken} from '../mongo/saveToken'; + +const serverName = 'initTokens'; +const dexSpace = 'all'; + +const startServer = () => { + _log.start('---> startServer ', serverName); + addTokens(); +}; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const addTokens = async () => { + await models.g.tokens.deleteMany({}, {}); + + const tokenCount = await models.g.tokens.countDocuments(); + _log.info('tokenCount', tokenCount); + + if (tokenCount > 0) { + _log.warn('tokens not empty', tokenCount); + } else { + for (let l = 0; l < TOKEN_LIST_ALL.length; l++) { + try { + if (TOKEN_LIST_ALL[l] !== '') { + _log.info('----------------------------------'); + _log.start('-getList ', TOKEN_LIST_ALL[l]); + await getList(TOKEN_LIST_ALL[l]); + _log.ready('-getList ', TOKEN_LIST_ALL[l]); + } else { + _log.warn('invalid list?', TOKEN_LIST_ALL[l]); + } + } catch (e) { + _log.error(serverName, e.message); + } + await timeout(6000); + } + } +}; + +const getList = async (list: string): Promise => { + _log.info('starting getList'); + return new Promise(resolve => { + get(list, res => { + if (res) { + let body = ''; + + res.on('error', e => { + _log.error('get res', serverName, e.message); + resolve(true); + }); + + res.on('data', chunk => { + body += chunk; + }); + + res.on('end', async () => { + const tokenList = JSON.parse(body).tokens; + for (const token of tokenList) { + if (token && token.address) saveToken(token, serverName, dexSpace); + } + _log.info('resolved getList'); + resolve(true); + }); + } + }).on('error', e => { + _log.error('getList', serverName, e.message); + resolve(true); + }); + }); +}; diff --git a/src/utils/initServer/init-whales.ts b/src/utils/initServer/init-whales.ts new file mode 100644 index 0000000..00f0824 --- /dev/null +++ b/src/utils/initServer/init-whales.ts @@ -0,0 +1,55 @@ +import {get} from 'https'; +import {_log} from '../configs/utils'; +import {startMongo} from '../mongo/config'; +import {saveWhale} from '../mongo/saveWhale'; + +const serverName = 'initWhales'; +const URLData = + 'https://raw.githubusercontent.com/Uniswap/sybil-list/master/verified.json'; + +const startServer = () => { + _log.start('---> startServer ', serverName); + startAddWhales(); +}; + +startMongo(serverName).then(started => { + if (started) { + startServer(); + } else { + _log.error('---> started ', serverName, started); + } +}); + +const startAddWhales = () => { + try { + get(URLData, res => { + if (res) { + let body = ''; + + res.on('error', e => { + _log.warn(e.message); + }); + + res.on('data', chunk => { + body += chunk; + }); + + res.on('end', () => { + const whalesList = JSON.parse(body); + const whalesArray = Object.entries(whalesList); + + for (const whale of whalesArray) { + saveWhale({ + address: whale[0], + twitter: whale[1], + }); + } + }); + } + }).on('error', e => { + _log.error(serverName, e.message); + }); + } catch (e) { + _log.error(serverName, e.message); + } +}; diff --git a/src/utils/initServer/set-heroku.ts b/src/utils/initServer/set-heroku.ts new file mode 100644 index 0000000..192a655 --- /dev/null +++ b/src/utils/initServer/set-heroku.ts @@ -0,0 +1,204 @@ +import 'dotenv/config'; +import {exec} from 'child_process'; +import {_log} from '../configs/utils'; + +const callbackpew = (error: any, stdout: string, stderr: string) => { + if (error) _log.info(error); + if (stdout) _log.info(stdout); + if (stderr) _log.info(stderr); +}; + +exec( + 'heroku config:set ATLAS_STRING="' + + process.env.ATLAS_STRING + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set DB_NAME="' + + process.env.DB_NAME + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set COLLECTION_PREFIX="' + + process.env.COLLECTION_PREFIX + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set CORS_ORIGIN="' + + process.env.CORS_ORIGIN + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set GAS_STATION_API_URL="' + + process.env.GAS_STATION_API_URL + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set BLOCKNATIVE_API_URL="' + + process.env.BLOCKNATIVE_API_URL + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set BLOCKNATIVE_API_KEY="' + + process.env.BLOCKNATIVE_API_KEY + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set MAIN_WS="' + + process.env.MAIN_WS + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set INFURA_KEY1="' + + process.env.INFURA_KEY1 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set INFURA_KEY2="' + + process.env.INFURA_KEY2 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set INFURA_KEY3="' + + process.env.INFURA_KEY3 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set INFURA_KEY4="' + + process.env.INFURA_KEY4 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set ALCHEMY_KEY1="' + + process.env.ALCHEMY_KEY1 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set ALCHEMY_KEY2="' + + process.env.ALCHEMY_KEY2 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set ETHERSCAN_KEY1="' + + process.env.ETHERSCAN_KEY1 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set ETHERSCAN_KEY2="' + + process.env.ETHERSCAN_KEY2 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set POKT_KEY="' + + process.env.POKT_KEY + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set GET_BLOCK_KEY="' + + process.env.GET_BLOCK_KEY + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set UNIV2="' + + process.env.UNIV2 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set UNIV3="' + + process.env.UNIV3 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set SUSHIV2="' + + process.env.SUSHIV2 + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set REACT_APP_CHAIN_ID="' + + process.env.REACT_APP_CHAIN_ID + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set REACT_APP_GOOGLE_ANALYTICS_ID="' + + process.env.REACT_APP_GOOGLE_ANALYTICS_ID + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set REACT_APP_NETWORK_URL="' + + process.env.REACT_APP_NETWORK_URL + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set SKIP_PREFLIGHT_CHECK="' + + process.env.SKIP_PREFLIGHT_CHECK + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set REACT_APP_WS_URL_CONTRACTSHARK="' + + process.env.REACT_APP_WS_URL_CONTRACTSHARK + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set REACT_APP_APP_IS_OFFLINE="' + + process.env.REACT_APP_APP_IS_OFFLINE + + '" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); +exec( + 'heroku config:set NPM_CONFIG_PRODUCTION="false" -a ' + + process.env.HEROKU_APP_NAME, + callbackpew +); diff --git a/src/utils/mongo/config.ts b/src/utils/mongo/config.ts new file mode 100644 index 0000000..9fecd9c --- /dev/null +++ b/src/utils/mongo/config.ts @@ -0,0 +1,99 @@ +import 'dotenv/config'; +import mongoose from 'mongoose'; +import {_log, ENV} from '../configs/utils'; +import {BlockSchema} from '../../models/BlockSchema'; +import {TokenSchema} from '../../models/TokenSchema'; +import {TransactionSchema} from '../../models/TransactionSchema'; +import {WhalesSchema} from '../../models/WhalesSchema'; +import {HashSchema} from '../../models/HashSchema'; +import {PoolsSchema} from '../../models/PoolsSchema'; + +const PENDING = '_PENDING-txs'; +const CONFIRMED = '_CONFIRMED-txs'; + +const TRASH = '_COMMON-TRASH-txs'; +const BLOCKS = '_COMMON-BLOCKS'; +const WHALES = '_COMMON-WHALES'; +const HASHES = '_COMMON-HASHES'; +const POOLS = '_COMMON-POOLS'; +const TOKENS = '_COMMON-TOKENS'; + +const params = { + useCreateIndex: true, + useNewUrlParser: true, + useUnifiedTopology: true, + useFindAndModify: false, + autoIndex: false, +}; + +process.on('uncaughtException', err => { + console.log('uncaughtException', err); +}); + +process.on('unhandledRejection', (reason, p) => { + _log.error('Unhandled Rejection at: Promise', p, 'reason:', reason); + // application specific logging, throwing an error, or other logic here +}); + +const startMongo = async (serverName: string): Promise => { + return new Promise(resolve => { + mongoose.connect(ENV.ATLAS_STRING || '', params, (e: any) => { + if (!e) { + _log.success( + `${serverName} | MONGO OK CONNECT | ${ENV.COLLECTION_PREFIX}` + ); + checkMongo(serverName); + } else { + _log.error(`${serverName} | MOGNO FAIL CONNECT | `, e.message); + } + resolve(true); + }); + }); +}; + +const checkMongo = (serverName: string) => { + mongoose.connection.on('error', (e: any) => { + if (e) _log.error(`${serverName} | MONGO ERROR | `, e.message); + }); + + mongoose.connection.on('disconnected', () => { + _log.error(`${serverName} | MONGO DISCONNECT | `); + }); +}; + +const mongoUtils = { + UPDATE_ONLY: [{$match: {operationType: 'update'}}], + INSERT_ONLY: [{$match: {operationType: 'insert'}}], + DELETE_ONLY: [{$match: {operationType: 'delete'}}], + + FIRST_QUERY: { + limit: 20, + sort: {timestampTx: -1}, + }, + + LAST_QUERY: { + limit: 200, + sort: {timestampTx: 1}, + }, + INS_PEND: 'insert_pending_tx', + DEL_PEND: 'delete_pending_tx', + INS_CONF: 'insert_confirmed_tx', + ignoreAddressNamespace: ['0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'], +}; + +const models = { + g: { + trash: mongoose.model(TRASH, TransactionSchema), + blocks: mongoose.model(BLOCKS, BlockSchema), + whales: mongoose.model(WHALES, WhalesSchema), + hashes: mongoose.model(HASHES, HashSchema), + tokens: mongoose.model(TOKENS, TokenSchema), + pools: mongoose.model(POOLS, PoolsSchema), + }, + txM: { + pending: mongoose.model(PENDING, TransactionSchema), + confirmed: mongoose.model(CONFIRMED, TransactionSchema), + }, +}; + +export {models, mongoUtils, startMongo}; diff --git a/src/utils/mongo/saveBlock.ts b/src/utils/mongo/saveBlock.ts new file mode 100644 index 0000000..76db462 --- /dev/null +++ b/src/utils/mongo/saveBlock.ts @@ -0,0 +1,33 @@ +import {_log} from '../configs/utils'; +import {models} from './config'; + +const {g} = models; + +const saveBlock = async (doc: any) => { + try { + new g.blocks({...doc, fullyUpdated: false}).save((e: any) => { + if (e) _log.error('savedBlock error ', e.message); + }); + } catch (e: any) { + _log.error('not saveBlock', e); + } + return; +}; + +const updateBlock = async (blockHash: any, blockNumber: any, newData: any) => { + try { + g.blocks.updateOne( + {blockHash}, + {...newData, fullyUpdated: true}, + {}, + (e: any) => { + if (!e) _log.success('updatedBlock OK ', blockNumber); + } + ); + } catch (e: any) { + _log.error('not updatedBlock', e); + } + return; +}; + +export {saveBlock, updateBlock}; diff --git a/src/utils/mongo/saveConfirmed.ts b/src/utils/mongo/saveConfirmed.ts new file mode 100644 index 0000000..b1d597d --- /dev/null +++ b/src/utils/mongo/saveConfirmed.ts @@ -0,0 +1,227 @@ +import {nowMs, _log} from '../configs/utils'; +import {models} from './config'; + +const pendingOld = async (back: any, message: string) => { + try { + await models.txM.pending.deleteOne({hash: back.hash}); + } catch (e: any) { + _log.error('pendingOld ', e.message); + } + try { + const timestampTx = nowMs(); + new models.g.trash({ + ...back, + status: 'old', + timestampTx, + notes: { + message, + timestampTx, + }, + }).save((e: any) => { + if (!e) + _log.success( + back.isV2 + ? 'V2_pendingOld' + : back.isV3 + ? 'V3_pendingOld' + : back.isV2Sushi + ? 'V2SH_pendingOld' + : ' _pendingOld', + '|', + back.hash + ); + }); + } catch (e: any) { + _log.error('pendingOld ', e.message); + } + return; +}; + +const pendingToDropped = async (back: any, message: string) => { + try { + await models.txM.pending.deleteOne({hash: back.hash}); + } catch (e: any) { + _log.error('pendingToDropped ', e.message); + } + try { + const timestampTx = nowMs(); + new models.g.trash({ + ...back, + status: 'dropped', + timestampTx, + notes: { + message, + timestampTx, + }, + }).save((e: any) => { + if (!e) + _log.success( + back.isV2 + ? 'V2_Dropped' + : back.isV3 + ? 'V3_Dropped' + : back.isV2Sushi + ? 'V2SH_Dropped' + : ' _Dropped', + '|', + back.hash + ); + }); + } catch (e: any) { + _log.error('pendingToDropped ', e.message); + } + return; +}; + +const pendingToFailed = async (back: any, tx: any, message: string) => { + try { + await models.txM.pending.deleteOne({hash: back.hash}); + } catch (e: any) { + _log.error('pendingToFailed ', e.message); + } + try { + const timestampTx = nowMs(); + new models.g.trash({ + ...back, + ...tx, + timestampTx, + status: 'failed', + notes: { + message, + timestampTx, + }, + }).save((e: any) => { + if (!e) + _log.success( + back.isV2 + ? 'V2_Failed' + : back.isV3 + ? 'V3_Failed' + : back.isV2Sushi + ? 'V2SH_Failed' + : ' Failed', + '|', + back.hash + ); + }); + } catch (e: any) { + _log.error('pendingToFailed ', e.message); + } + return; +}; + +const pendingToConfirm = async (back: any, tx: any, message: string) => { + try { + await models.txM.pending.deleteOne({hash: back.hash}); + } catch (e: any) { + _log.error('pendingToConfirm ', e.message); + } + try { + const timestampTx = nowMs(); + new models.txM.confirmed({ + ...back, + ...tx, + timestampTx, + status: 'confirmed', + notes: { + message, + timestampTx, + }, + }).save((e: any) => { + if (!e) + _log.success( + back.isV2 + ? 'V2_Confirmed' + : back.isV3 + ? 'V3_Confirmed' + : back.isV2Sushi + ? 'V2SH_Confirmed' + : ' _Confirmed', + '|', + back.hash + ); + }); + } catch (e: any) { + _log.error('pendingToConfirm ', e.message); + } + return; +}; + +const createConfirm = async (tx: any, message: string) => { + try { + const timestampTx = nowMs(); + new models.txM.confirmed({ + ...tx, + timestampTx, + status: 'confirmed', + notes: { + message, + timestampTx, + }, + }).save((e: any) => { + if (!e) + _log.success( + 'createConfirm', + tx.isV2 + ? 'V2_Confirmed' + : tx.isV3 + ? 'V3_Confirmed' + : tx.isV2Sushi + ? 'V2SH_Confirmed' + : ' _Confirmed', + '|', + tx.hash + ); + }); + } catch (e: any) { + _log.error('createConfirm ', e.message); + } + return; +}; + +const trashToconfirm = async (back: any, tx: any, message: string) => { + try { + await models.g.trash.deleteOne({hash: back.hash}); + } catch (e: any) { + _log.error('trashToconfirm ', e.message); + } + try { + const timestampTx = nowMs(); + new models.txM.confirmed({ + ...back, + ...tx, + timestampTx, + status: 'confirmed', + notes: { + message, + timestampTx, + }, + }).save((e: any) => { + if (!e) + _log.success( + 'trashToconfirm', + back.isV2 + ? 'V2_Confirmed' + : back.isV3 + ? 'V3_Confirmed' + : back.isV2Sushi + ? 'V2SH_Confirmed' + : ' _Confirmed', + '|', + back.hash + ); + }); + } catch (e: any) { + _log.error('trashToconfirm ', e.message); + } + return; +}; + +export { + trashToconfirm, + pendingToConfirm, + pendingToFailed, + pendingToDropped, + createConfirm, + pendingOld, +}; diff --git a/src/utils/mongo/savePending.ts b/src/utils/mongo/savePending.ts new file mode 100644 index 0000000..f49700f --- /dev/null +++ b/src/utils/mongo/savePending.ts @@ -0,0 +1,24 @@ +import {IContractSharkTx} from '../../models/TransactionSchema'; +import {nowMs, _log} from '../configs/utils'; +import {models} from './config'; + +const createPending = async (tx: IContractSharkTx, message: string) => { + try { + const timestampTx = nowMs(); + new models.txM.pending({ + ...tx, + notes: { + message, + timestampTx, + }, + }).save((e: any) => { + if (!e) _log.info('New Pending Saved', '|', tx.hash, '|', message); + if (e) _log.error(e); + }); + } catch (e: any) { + _log.error('txM catch', e.message); + } + return; +}; + +export {createPending}; diff --git a/src/utils/mongo/savePools.ts b/src/utils/mongo/savePools.ts new file mode 100644 index 0000000..a033c09 --- /dev/null +++ b/src/utils/mongo/savePools.ts @@ -0,0 +1,17 @@ +import {_log} from '../configs/utils'; +import {models} from './config'; + +const {g} = models; + +const savePools = async (data: any) => { + try { + new g.pools(data).save((e: any, doc: any) => { + //if (!e) _log.success('savedPools', doc.address); + }); + } catch (e) { + _log.error('savedPools', e.message); + } + return; +}; + +export {savePools}; diff --git a/src/utils/mongo/saveToken.ts b/src/utils/mongo/saveToken.ts new file mode 100644 index 0000000..9d195d0 --- /dev/null +++ b/src/utils/mongo/saveToken.ts @@ -0,0 +1,111 @@ +import {_log, checksum, nowMs} from '../configs/utils'; +import {models} from './config'; +import {_WETH_ADDRESS, _ETH_ADDRESS} from '../web3/utils'; + +const {g} = models; + +async function saveToken( + tokenData: any, + by: string, + dexSpace: string +): Promise { + try { + const address = checksum(tokenData.address); + const isGeneral = checkDex(dexSpace, 'all'); + const isV2 = isGeneral ? true : checkDex(dexSpace, 'v2'); + const isV2Sushi = isGeneral ? true : checkDex(dexSpace, 'v2sh'); + const isV3 = isGeneral ? true : checkDex(dexSpace, 'v3'); + + const now = nowMs(); + + const tokenDoc = { + ...tokenData, + address, + hashAddress: address, + by, + isGeneral, + isV2, + isV3, + isV2Sushi, + timestampTx: now, + msV3: isV3 ? now : null, + msV2: isV2 ? now : null, + msV2Sushi: isV2Sushi ? now : null, + }; + delete tokenDoc._id; + delete tokenDoc.__v; + + new g.tokens(tokenDoc).save((e: any) => { + if (!e) + _log.success('SAVED TOKEN || ', address, dexSpace, tokenDoc.symbol); + }); + } catch (e: any) { + _log.error('savedToken catch', tokenData, e); + } + return null; +} + +async function updateToken( + tokenData: any, + by: string, + dexSpace: string +): Promise { + try { + const address = checksum(tokenData.address); + const token = await g.tokens.findOne({address}, null, {}); + if (token) { + const _doc = token._doc; + const isGeneral = _doc.isGeneral ? true : checkDex(dexSpace, 'all'); + const isV2 = isGeneral + ? true + : _doc.isV2 + ? true + : checkDex(dexSpace, 'v2'); + const isV3 = isGeneral + ? true + : _doc.isV3 + ? true + : checkDex(dexSpace, 'v3'); + const isV2Sushi = isGeneral + ? true + : _doc.isV2Sushi + ? true + : checkDex(dexSpace, 'v2sh'); + + const now = nowMs(); + + const tokenDoc = { + ..._doc, + ...tokenData, + by, + isGeneral, + isV2, + isV3, + isV2Sushi, + msV3: isV3 ? (_doc.msV3 ? _doc.msV3 : now) : null, + msV2: isV2 ? (_doc.msV2 ? _doc.msV2 : now) : null, + msV2Sushi: isV2Sushi ? (_doc.msV2Sushi ? _doc.msV2Sushi : now) : null, + }; + delete tokenDoc._id; + + g.tokens.updateOne({address}, {...tokenDoc}, {}, (e: any) => { + if (!e) + _log.success('UPDATED TOKEN || ', address, dexSpace, tokenDoc.symbol); + }); + } + } catch (e: any) { + _log.error('tokens.updateOne catch', tokenData, e); + } + return null; +} + +const checkDex = (dexSpace: string, checkTo: string): boolean => { + try { + return dexSpace === checkTo; + } catch (e: any) { + _log.error('checkDex', e.message); + } + return false; +}; + +export {saveToken, updateToken}; diff --git a/src/utils/mongo/saveWhale.ts b/src/utils/mongo/saveWhale.ts new file mode 100644 index 0000000..181da70 --- /dev/null +++ b/src/utils/mongo/saveWhale.ts @@ -0,0 +1,24 @@ +import {checksum, nowMs, _log} from '../configs/utils'; +import {models} from './config'; + +const {g} = models; + +const saveWhale = async (whale: any) => { + try { + const w = { + address: checksum(whale.address), + hashAddress: checksum(whale.address), + twitter: whale.twitter.twitter, + timestampTx: nowMs(), + }; + + new g.whales(w).save((e: any, doc: any) => { + if (!e) _log.success('savedWhale', doc.address); + }); + } catch (e) { + _log.error('not savedWhale', e.message); + } + return; +}; + +export {saveWhale}; diff --git a/src/utils/web3/abis-interfaces.ts b/src/utils/web3/abis-interfaces.ts new file mode 100644 index 0000000..97234da --- /dev/null +++ b/src/utils/web3/abis-interfaces.ts @@ -0,0 +1,16 @@ +import {Interface} from '@ethersproject/abi'; +import SushiV2Router from '@sushiswap/core/build/abi/IUniswapV2Router02.json'; +import {abi as UniV2Router} from '@uniswap/v2-periphery/build/IUniswapV2Router02.json'; +import {abi as UniV3Router} from '@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'; +import {abi as IUniswapV3PoolABI} from '@uniswap/v3-core/artifacts/contracts/interfaces/IUniswapV3Pool.sol/IUniswapV3Pool.json'; +import {abi as IUniswapV2PairABI} from '@uniswap/v2-core/build/IUniswapV2Pair.json'; +import {abi as _erc20abi} from '@uniswap/v2-core/build/ERC20.json'; +import {abi as _multicallabi} from '../../abis/Multicall2.json'; + +export const erc20abi = _erc20abi; +export const multicallabi = _multicallabi; +export const iUniV2Router = new Interface(UniV2Router); +export const iUniV3Router = new Interface(UniV3Router); +export const iSushiV2Router = new Interface(SushiV2Router); +export const iUniswapV3PoolABI = new Interface(IUniswapV3PoolABI); +export const iUniswapV2PairABI = new Interface(IUniswapV2PairABI); diff --git a/src/utils/web3/checkTxs.ts b/src/utils/web3/checkTxs.ts new file mode 100644 index 0000000..52f4909 --- /dev/null +++ b/src/utils/web3/checkTxs.ts @@ -0,0 +1,37 @@ +import {ENV, _log, nowMs} from '../configs/utils'; +import {IContractSharkTx} from '../../models/TransactionSchema'; +import {TransactionResponse} from '@ethersproject/abstract-provider'; +import {Currency, Price} from '@uniswap/sdk-core'; + +const checkTx = ( + tx: TransactionResponse, + whaleData: any, + isV2: boolean, + isV3: boolean, + isV2Sushi: boolean +): IContractSharkTx => { + return { + ...tx, + txHash: tx.hash, + isV2, + isV3, + isV2Sushi, + links: {etherscan: ENV.ES_TX + tx.hash}, + status: 'pending', + timestampTx: nowMs(), + whaleData, + }; +}; + +const getPrice = (price: Price) => { + return { + priceFrom: price.toSignificant(6), + priceFromInverted: price.invert().toSignificant(6), + priceTo: price.invert().toSignificant(6), + priceToInverted: price.toSignificant(6), + label: `${price.baseCurrency.symbol} per ${price.quoteCurrency.symbol}`, + labelInverted: `${price.quoteCurrency.symbol} per ${price.baseCurrency.symbol}`, + }; +}; + +export {getPrice, checkTx}; diff --git a/src/utils/web3/getBlocks.ts b/src/utils/web3/getBlocks.ts new file mode 100644 index 0000000..29a9593 --- /dev/null +++ b/src/utils/web3/getBlocks.ts @@ -0,0 +1,69 @@ +import {get} from 'https'; +import {mainWsComm} from './providers'; +import {_log} from '../configs/utils'; + +const getBlock = async (number: number, provider: any) => { + try { + const block = await getFromBackupProviders(number, provider); + return block; + } catch (e: any) { + _log.error('getBlock catch', number, e.message); + } +}; + +const getFromBackupProviders = async (number: number, provider: any) => { + try { + const blockResponse = await goGetIt(provider, number); + if (blockResponse) { + return blockResponse; + } + } catch (e: any) { + if (e.message === 'noNetwork') { + const blockResponse = await goGetIt(mainWsComm, number); + if (blockResponse) { + return blockResponse; + } + } + } + return null; +}; + +const goGetIt = async (provider: any, number: number) => { + try { + const _blockResponse = await provider.getBlock(number); + if (_blockResponse) return _blockResponse; + } catch (e: any) { + throw new Error(e.event); + } + return null; +}; + +async function getBlockInfo(url: string, opts: any): Promise { + return new Promise(resolve => { + get(url, opts, res => { + if (res) { + let body = ''; + + res.on('error', (e: any) => { + _log.error(e.message); + resolve(null); + }); + + res.on('data', chunk => { + body += chunk; + }); + + res.on('end', () => { + const responseData = JSON.parse(body); + if (responseData) resolve(responseData); + else resolve(null); + }); + } + }).on('error', (e: any) => { + _log.error('Get getBlockInfo on error', e.message); + resolve(null); + }); + }); +} + +export {getBlockInfo, getBlock}; diff --git a/src/utils/web3/getContractData.ts b/src/utils/web3/getContractData.ts new file mode 100644 index 0000000..9fb6de0 --- /dev/null +++ b/src/utils/web3/getContractData.ts @@ -0,0 +1,38 @@ +import {ethers} from 'ethers'; +import {checksum, getRandomInt, _log} from '../configs/utils'; +import {erc20abi} from './abis-interfaces'; +import {MAINNET} from './utils'; + +const getContractData = async ( + contractAddress: string, + providers: Array +): Promise => { + try { + const address = checksum(contractAddress); + + const contract = new ethers.Contract( + address, + erc20abi, + providers[getRandomInt(1, providers.length - 1)] + ); + + const [decimals, name, symbol] = await Promise.all([ + contract.functions.decimals(), + contract.functions.name(), + contract.functions.symbol(), + ]); + + return { + chainId: MAINNET, + address, + decimals: decimals[0], + name: name[0], + symbol: symbol[0], + }; + } catch (e: any) { + _log.error('GetContractData catch', contractAddress, e); + } + return null; +}; + +export {getContractData, MAINNET}; diff --git a/src/utils/web3/getTokens.ts b/src/utils/web3/getTokens.ts new file mode 100644 index 0000000..c7bfb2d --- /dev/null +++ b/src/utils/web3/getTokens.ts @@ -0,0 +1,112 @@ +import {WETH9} from '@uniswap/sdk-core'; +import {Token} from '@uniswap/sdk-core'; +import {Token as TokenSushi, WETH} from '@sushiswap/sdk'; +import {checksum, _log} from '../configs/utils'; +import {MAINNET, _WETH_ADDRESS, _ETH_ADDRESS} from '../../utils/web3/utils'; +import {getContractData} from './getContractData'; +import {models} from '../mongo/config'; +import {saveToken, updateToken} from '../mongo/saveToken'; + +const newTokenUni = (data: any): Token | null => { + try { + if (data) + return new Token( + MAINNET, + checksum(data.address), + data.decimals, + data.symbol, + data.name + ); + } catch (e: any) {} + return null; +}; + +const newTokenSushi = (data: any): TokenSushi | null => { + try { + if (data) + return new TokenSushi( + MAINNET, + checksum(data.address), + Number(data.decimals), + data.symbol, + data.name + ); + } catch (e: any) { + _log.warn('newTokenSushi catch', data); + } + return null; +}; + +const getTokens = async ( + checkedPath: Array, + pName: string, + dexSpace: string, + providers: Array +) => { + try { + if (checkedPath && pName && dexSpace) { + const tks = []; + + for (const address of checkedPath) { + if (!address) { + _log.warn('getTokens bad checkedPath??', checkedPath); + return null; + } else if (address === _WETH_ADDRESS || address === _ETH_ADDRESS) { + if (dexSpace === 'v2sh') tks.push(WETH[MAINNET]); + else tks.push(WETH9[MAINNET]); + } else { + const t = await models.g.tokens.findOne({address}, null, {}); + + if (!t) { + const contractToken = await getContractData(address, providers); + if (contractToken) { + if (dexSpace === 'v2sh') { + tks.push(newTokenSushi(contractToken)); + } else { + tks.push(newTokenUni(contractToken)); + } + saveToken(contractToken, pName, dexSpace); + } + } else { + const tokenData = t._doc; + + if (dexSpace === 'v2sh') { + tks.push(newTokenSushi(tokenData)); + if (tokenData.isV2Sushi === false) { + updateToken(tokenData, pName, dexSpace); + } + } + if (dexSpace === 'v2') { + tks.push(newTokenUni(tokenData)); + if (tokenData.isV2 === false) { + updateToken(tokenData, pName, dexSpace); + } + } + + if (dexSpace === 'v3') { + tks.push(newTokenUni(tokenData)); + if (tokenData.isV3 === false) { + updateToken(tokenData, pName, dexSpace); + } + } + } + } + } + if (tks.length === checkedPath.length) { + return tks; + } else { + _log.warn( + 'getTokens tks.length === checkedPath.length', + tks.length === checkedPath.length + ); + } + } else { + _log.error('getTokens data error', checkedPath, pName, dexSpace); + } + } catch (e: any) { + _log.error('getTokens catch', e.message); + } + return null; +}; + +export {getTokens, newTokenSushi, newTokenUni}; diff --git a/src/utils/web3/getTransactions.ts b/src/utils/web3/getTransactions.ts new file mode 100644 index 0000000..6be3e60 --- /dev/null +++ b/src/utils/web3/getTransactions.ts @@ -0,0 +1,66 @@ +import {_log} from '../configs/utils'; + +const getPendingTxResponse = async ( + hash: string, + providers: Array, + escan: any +) => { + try { + const _txResponse = await getFromBackupProviders(hash, providers, escan); + return _txResponse; + } catch (e: any) { + _log.error('getPendingTxResponse catch ', hash); + } + return null; +}; + +const getFromBackupProviders = async ( + hash: string, + providers: Array, + escan: any +) => { + try { + const txResponse = await goGetIt(hash, providers, escan); + if (txResponse) { + const {to, from} = txResponse; + if (to && from) { + return txResponse; + } + } + } catch (e: any) { + if (e.message === 'noNetwork') { + const txResponse = await goGetIt(hash, providers, escan); + if (txResponse) { + const {to, from} = txResponse; + if (to && from) { + return txResponse; + } + } + } + } + return null; +}; + +const goGetIt = async (hash: string, providers: Array, escan: any) => { + const l = providers.length - 1; + + for (let i = l; i >= 0; i--) { + try { + const _txResponse = await providers[i].getTransaction(hash); + if (_txResponse) return _txResponse; + } catch (e: any) { + _log.info(e.message); + } + } + + try { + const _txResponse = await escan.getTransaction(hash); + if (_txResponse) return _txResponse; + } catch (e: any) { + _log.info(e.message); + } + + return null; +}; + +export {getPendingTxResponse}; diff --git a/src/utils/web3/providers.ts b/src/utils/web3/providers.ts new file mode 100644 index 0000000..9fa5dbd --- /dev/null +++ b/src/utils/web3/providers.ts @@ -0,0 +1,93 @@ +import {providers} from 'ethers'; +import {KEYS, _log} from '../configs/utils'; + +const network = { + name: 'homestead', + chainId: 1, +}; + +const { + INFURA_KEY1, + INFURA_KEY2, + INFURA_KEY3, + INFURA_KEY4, + ALCHEMY_KEY1, + ALCHEMY_KEY2, + ETHERSCAN_KEY1, + ETHERSCAN_KEY2, + POKT_KEY, + GET_BLOCK_KEY, + MAIN_WS, +} = KEYS; + +const {WebSocketProvider, EtherscanProvider, StaticJsonRpcProvider} = providers; + +const MAIN_WS_PROVIDER = new WebSocketProvider(MAIN_WS, network); +const mainWsLMem = new WebSocketProvider( + 'wss://mainnet.infura.io/ws/v3/' + INFURA_KEY1, + network +); +const mainWsComm = new WebSocketProvider( + 'wss://mainnet.infura.io/ws/v3/' + INFURA_KEY2, + network +); +const mainWsLConf = new WebSocketProvider( + 'wss://mainnet.infura.io/ws/v3/' + INFURA_KEY3, + network +); + +const mainWsExtra = new WebSocketProvider( + 'wss://mainnet.infura.io/ws/v3/' + INFURA_KEY4, + network +); + +const alcheWs1 = new WebSocketProvider( + 'wss://eth-mainnet.alchemyapi.io/v2/' + ALCHEMY_KEY1, + network +); +const alcheWs2 = new WebSocketProvider( + 'wss://eth-mainnet.alchemyapi.io/v2/' + ALCHEMY_KEY2, + network +); + +const escan1 = new EtherscanProvider(network, ETHERSCAN_KEY1); +const escan2 = new EtherscanProvider(network, ETHERSCAN_KEY2); + +const linkpool = new WebSocketProvider( + 'wss://api.zmok.io/mainnet/8ylcxy8gvmbuhipq', + network +); +const linkpool2 = new WebSocketProvider( + 'wss://api.zmok.io/mainnet/v1cuawrr6xgfrx1r', + network +); +const getblock = new WebSocketProvider( + 'wss://eth.getblock.io/mainnet/?api_key=' + GET_BLOCK_KEY, + network +); +const pokt = new StaticJsonRpcProvider( + 'https://eth-mainnet.gateway.pokt.network/v1/lb/' + POKT_KEY, + network +); + +const providersForLM: Array = [ + mainWsLMem, + mainWsExtra, + alcheWs1, + linkpool, +]; +const providersForLC: Array = [ + mainWsLConf, + mainWsLConf, + alcheWs2, + linkpool2, +]; + +export { + providersForLM, + providersForLC, + mainWsComm, + escan1, + escan2, + MAIN_WS_PROVIDER, +}; diff --git a/src/utils/web3/utils.ts b/src/utils/web3/utils.ts new file mode 100644 index 0000000..f25fc8b --- /dev/null +++ b/src/utils/web3/utils.ts @@ -0,0 +1,53 @@ +const MAINNET = 1; +const _WETH_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'; +const _ETH_ADDRESS = '0x0000000000000000000000000000000000000000'; + +const _MULTICALL = 'multicall'; + +const _V3_FUNC_ALLOWED_METHODS = new Array( + 'multicall', + 'exactInputSingle', + 'exactInput', + 'exactOutputSingle', + 'exactOutput' +); + +//Same Order +const _V3_FNAME_ONLY_SWAP = new Array( + 'exactInputSingle', + 'exactInput', + 'exactOutputSingle', + 'exactOutput' +); +const _V3_SIGS_ONLY_SWAP = new Array( + '0x414bf389', + '0xc04b8d59', + '0xdb3e2198', + '0xf28c0498' +); + +const V3_SWAP_FNAME = { + EIS: 'exactInputSingle', + EI: 'exactInput', + EOS: 'exactOutputSingle', + EO: 'exactOutput', +}; + +const V3_SWAP_SIGS = { + exactInputSingleSig: '0x414bf389', + exactInputSig: '0xc04b8d59', + exactOutputSingleSig: '0xdb3e2198', + exactOutputSig: '0xf28c0498', +}; + +export { + V3_SWAP_SIGS, + V3_SWAP_FNAME, + _V3_SIGS_ONLY_SWAP, + _V3_FNAME_ONLY_SWAP, + _V3_FUNC_ALLOWED_METHODS, + _MULTICALL, + _ETH_ADDRESS, + _WETH_ADDRESS, + MAINNET, +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3a1c53f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "./node_modules/gts/tsconfig-google.json", + "compilerOptions": { + "resolveJsonModule": true, + "esModuleInterop": true, + "declaration": true, + "declarationMap": true, + "rootDir": "./src", + "outDir": "./lib", + "sourceMap": true, + "strict": true, + "skipLibCheck": true + }, + "include": [ + "src/**/*.ts" + ], + "exclude": ["test", "node_modules"] +} \ No newline at end of file