From 9e07004d0eb1635c744c62aa1bc64b96c8eeac08 Mon Sep 17 00:00:00 2001 From: vic-en Date: Fri, 30 Jul 2021 13:23:53 +0100 Subject: [PATCH 01/43] [WIP] add test script for uniswap v2 --- package-lock.json | 7781 +++++++++++------------------------------ package.json | 7 +- tests/example.test.js | 117 + yarn.lock | 51 +- 4 files changed, 2191 insertions(+), 5765 deletions(-) create mode 100644 tests/example.test.js diff --git a/package-lock.json b/package-lock.json index 25e46d6..86c021b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,189 +4,12 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.12.13" - } - }, - "@babel/compat-data": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.4.tgz", - "integrity": "sha512-i2wXrWQNkH6JplJQGn3Rd2I4Pij8GdHkXwHMxm+zV5YG/Jci+bCNrWZEWC4o+umiDkRrRs4dVzH3X4GP7vyjQQ==", - "dev": true - }, - "@babel/core": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.3.tgz", - "integrity": "sha512-jB5AmTKOCSJIZ72sd78ECEhuPiDMKlQdDI/4QRI6lzYATx5SSogS1oQA2AoPecRCknm30gHi2l+QVvNUu3wZAg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.3", - "@babel/helper-compilation-targets": "^7.13.16", - "@babel/helper-module-transforms": "^7.14.2", - "@babel/helpers": "^7.14.0", - "@babel/parser": "^7.14.3", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.2", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - } - }, - "@babel/generator": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", - "integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.2", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.4.tgz", - "integrity": "sha512-JgdzOYZ/qGaKTVkn5qEDV/SXAh8KcyUVkCoSWGN8T3bwrgd6m+/dJa2kVGi6RJYJgEYPBdZ84BZp9dUjNWkBaA==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.14.4", - "@babel/helper-validator-option": "^7.12.17", - "browserslist": "^4.16.6", - "semver": "^6.3.0" - } - }, - "@babel/helper-function-name": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", - "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/types": "^7.14.2" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", - "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", - "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", - "dev": true, - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-module-imports": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", - "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", - "dev": true, - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-module-transforms": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.2.tgz", - "integrity": "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.13.12", - "@babel/helper-replace-supers": "^7.13.12", - "@babel/helper-simple-access": "^7.13.12", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/helper-validator-identifier": "^7.14.0", - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.2" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", - "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - }, - "@babel/helper-replace-supers": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.4.tgz", - "integrity": "sha512-zZ7uHCWlxfEAAOVDYQpEf/uyi1dmeC7fX4nCf2iz9drnCwi1zvwXL3HwWWNXUQEJ1k23yVn3VbddiI9iJEXaTQ==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", - "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", - "dev": true, - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", - "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, "@babel/helper-validator-identifier": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "dev": true }, - "@babel/helper-validator-option": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", - "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz", - "integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg==", - "dev": true, - "requires": { - "@babel/template": "^7.12.13", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.14.0" - } - }, "@babel/highlight": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", @@ -198,137 +21,6 @@ "js-tokens": "^4.0.0" } }, - "@babel/parser": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.4.tgz", - "integrity": "sha512-ArliyUsWDUqEGfWcmzpGUzNfLxTdTp6WU4IuP6QFSp9gGfWS6boxFCkJSJ/L4+RG8z/FnIU3WxCk6hPL9SSWeA==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz", - "integrity": "sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", - "dev": true - } - } - }, "@babel/runtime": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz", @@ -337,43 +29,6 @@ "regenerator-runtime": "^0.13.4" } }, - "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" - } - }, - "@babel/traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", - "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.2", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.2", - "@babel/types": "^7.14.2", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.4.tgz", - "integrity": "sha512-lCj4aIs0xUefJFQnwwQv2Bxg7Omd6bgquZ6LGC+gGMh6/s5qDVfjuCMlDmYQ15SLsWHd9n+X3E75lKIhl5Lkiw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - }, "@balancer-labs/sor": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@balancer-labs/sor/-/sor-0.3.3.tgz", @@ -383,12 +38,6 @@ "isomorphic-fetch": "^2.2.1" } }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, "@dabh/diagnostics": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", @@ -805,1563 +454,1327 @@ "@ethersproject/strings": "^5.3.0" } }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "@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": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "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" - } - }, - "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 - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" } }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "@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 }, - "@jest/console": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.0.2.tgz", - "integrity": "sha512-/zYigssuHLImGeMAACkjI4VLAiiJznHgAl3xnFT19iWyct2LhrH3KXOjHRmxBGTkiPLZKKAJAgaPpiU9EZ9K+w==", + "@nodelib/fs.walk": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", + "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", "dev": true, "requires": { - "@jest/types": "^27.0.2", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.0.2", - "jest-util": "^27.0.2", - "slash": "^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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" } }, - "@jest/core": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.0.5.tgz", - "integrity": "sha512-g73//jF0VwsOIrWUC9Cqg03lU3QoAMFxVjsm6n6yNmwZcQPN/o8w+gLWODw5VfKNFZT38otXHWxc6b8eGDUpEA==", + "@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==" + }, + "@perp/contract": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@perp/contract/-/contract-1.1.0.tgz", + "integrity": "sha512-79O3DoGYtC6Nu9TnzC6aUTwCuEfe3+CIZr9a27Uh26MQ0jHkCq2Rc4sz35k3ChuN9zL2ZmrsAR+mO785QGZFpw==" + }, + "@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 + }, + "@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": { - "@jest/console": "^27.0.2", - "@jest/reporters": "^27.0.5", - "@jest/test-result": "^27.0.2", - "@jest/transform": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^27.0.2", - "jest-config": "^27.0.5", - "jest-haste-map": "^27.0.5", - "jest-message-util": "^27.0.2", - "jest-regex-util": "^27.0.1", - "jest-resolve": "^27.0.5", - "jest-resolve-dependencies": "^27.0.5", - "jest-runner": "^27.0.5", - "jest-runtime": "^27.0.5", - "jest-snapshot": "^27.0.5", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", - "jest-watcher": "^27.0.2", - "micromatch": "^4.0.4", - "p-each-series": "^2.1.0", - "rimraf": "^3.0.0", - "slash": "^3.0.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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } + "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.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", + "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", + "dev": true + }, + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" } }, - "@jest/environment": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.0.5.tgz", - "integrity": "sha512-IAkJPOT7bqn0GiX5LPio6/e1YpcmLbrd8O5EFYpAOZ6V+9xJDsXjdgN2vgv9WOKIs/uA1kf5WeD96HhlBYO+FA==", + "@types/connect": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", + "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", "dev": true, "requires": { - "@jest/fake-timers": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/node": "*", - "jest-mock": "^27.0.3" + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.12.tgz", + "integrity": "sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "@jest/fake-timers": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.0.5.tgz", - "integrity": "sha512-d6Tyf7iDoKqeUdwUKrOBV/GvEZRF67m7lpuWI0+SCD9D3aaejiOQZxAOxwH2EH/W18gnfYaBPLi0VeTGBHtQBg==", + "@types/express-serve-static-core": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.21.tgz", + "integrity": "sha512-gwCiEZqW6f7EoR8TTEfalyEhb1zA5jQJnRngr97+3pzMaO1RKoI1w2bw07TK72renMUVWcWS5mLI6rk1NqN0nA==", "dev": true, "requires": { - "@jest/types": "^27.0.2", - "@sinonjs/fake-timers": "^7.0.2", "@types/node": "*", - "jest-message-util": "^27.0.2", - "jest-mock": "^27.0.3", - "jest-util": "^27.0.2" + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/mathjs": { + "version": "9.4.2", + "resolved": "https://registry.npmjs.org/@types/mathjs/-/mathjs-9.4.2.tgz", + "integrity": "sha512-GF5g1vJmvKdWIWsE53XX7EDAyCaZ9p6gaYm1xhlXn5JjrY/NJrOfJN3fBxS3wyZpVh3QqKoMkS2WjFwxWMHOTw==", + "dev": true, + "requires": { + "mathjs": "*" } }, - "@jest/globals": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.0.5.tgz", - "integrity": "sha512-qqKyjDXUaZwDuccpbMMKCCMBftvrbXzigtIsikAH/9ca+kaae8InP2MDf+Y/PdCSMuAsSpHS6q6M25irBBUh+Q==", + "@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/node": { + "version": "15.12.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", + "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==" + }, + "@types/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", + "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", "dev": true, "requires": { - "@jest/environment": "^27.0.5", - "@jest/types": "^27.0.2", - "expect": "^27.0.2" + "@types/mime": "^1", + "@types/node": "*" } }, - "@jest/reporters": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.0.5.tgz", - "integrity": "sha512-4uNg5+0eIfRafnpgu3jCZws3NNcFzhu5JdRd1mKQ4/53+vkIqwB6vfZ4gn5BdGqOaLtYhlOsPaL5ATkKzyBrJw==", + "@typescript-eslint/eslint-plugin": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz", + "integrity": "sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==", "dev": true, "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.0.2", - "@jest/test-result": "^27.0.2", - "@jest/transform": "^27.0.5", - "@jest/types": "^27.0.2", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.4", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.3", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^27.0.5", - "jest-resolve": "^27.0.5", - "jest-util": "^27.0.2", - "jest-worker": "^27.0.2", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.0.0" + "@typescript-eslint/experimental-utils": "4.28.0", + "@typescript-eslint/scope-manager": "4.28.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "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 - }, - "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==", + "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": { - "has-flag": "^4.0.0" + "lru-cache": "^6.0.0" } } } }, - "@jest/source-map": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.1.tgz", - "integrity": "sha512-yMgkF0f+6WJtDMdDYNavmqvbHtiSpwRN2U/W+6uztgfqgkq/PXdKPqjBTUF1RD/feth4rH5N3NW0T5+wIuln1A==", + "@typescript-eslint/experimental-utils": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz", + "integrity": "sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.28.0", + "@typescript-eslint/types": "4.28.0", + "@typescript-eslint/typescript-estree": "4.28.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" }, "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "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" + } + }, + "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 } } }, - "@jest/test-result": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.0.2.tgz", - "integrity": "sha512-gcdWwL3yP5VaIadzwQtbZyZMgpmes8ryBAJp70tuxghiA8qL4imJyZex+i+USQH2H4jeLVVszhwntgdQ97fccA==", + "@typescript-eslint/parser": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.0.tgz", + "integrity": "sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==", "dev": true, "requires": { - "@jest/console": "^27.0.2", - "@jest/types": "^27.0.2", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@typescript-eslint/scope-manager": "4.28.0", + "@typescript-eslint/types": "4.28.0", + "@typescript-eslint/typescript-estree": "4.28.0", + "debug": "^4.3.1" } }, - "@jest/test-sequencer": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.0.5.tgz", - "integrity": "sha512-opztnGs+cXzZ5txFG2+omBaV5ge/0yuJNKbhE3DREMiXE0YxBuzyEa6pNv3kk2JuucIlH2Xvgmn9kEEHSNt/SA==", + "@typescript-eslint/scope-manager": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", + "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", "dev": true, "requires": { - "@jest/test-result": "^27.0.2", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.5", - "jest-runtime": "^27.0.5" + "@typescript-eslint/types": "4.28.0", + "@typescript-eslint/visitor-keys": "4.28.0" } }, - "@jest/transform": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.0.5.tgz", - "integrity": "sha512-lBD6OwKXSc6JJECBNk4mVxtSVuJSBsQrJ9WCBisfJs7EZuYq4K6vM9HmoB7hmPiLIDGeyaerw3feBV/bC4z8tg==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.0.2", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.5", - "jest-regex-util": "^27.0.1", - "jest-util": "^27.0.2", - "micromatch": "^4.0.4", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "@typescript-eslint/types": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", + "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz", + "integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.28.0", + "@typescript-eslint/visitor-keys": "4.28.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "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 - }, - "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==", + "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": { - "has-flag": "^4.0.0" + "lru-cache": "^6.0.0" } } } }, - "@jest/types": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.2.tgz", - "integrity": "sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg==", + "@typescript-eslint/visitor-keys": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", + "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" + "@typescript-eslint/types": "4.28.0", + "eslint-visitor-keys": "^2.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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 - }, - "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" - } } } }, - "@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 + "@uniswap/lib": { + "version": "4.0.1-alpha", + "resolved": "https://registry.npmjs.org/@uniswap/lib/-/lib-4.0.1-alpha.tgz", + "integrity": "sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA==" }, - "@nodelib/fs.walk": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz", - "integrity": "sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA==", - "dev": true, + "@uniswap/sdk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@uniswap/sdk/-/sdk-3.0.3.tgz", + "integrity": "sha512-t4s8bvzaCFSiqD2qfXIm3rWhbdnXp+QjD3/mRaeVDHK7zWevs6RGEb1ohMiNgOCTZANvBayb4j8p+XFdnMBadQ==", "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@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" } }, - "@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==" + "@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==" }, - "@perp/contract": { + "@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.1.0", - "resolved": "https://registry.npmjs.org/@perp/contract/-/contract-1.1.0.tgz", - "integrity": "sha512-79O3DoGYtC6Nu9TnzC6aUTwCuEfe3+CIZr9a27Uh26MQ0jHkCq2Rc4sz35k3ChuN9zL2ZmrsAR+mO785QGZFpw==" + "resolved": "https://registry.npmjs.org/@uniswap/v3-periphery/-/v3-periphery-1.1.0.tgz", + "integrity": "sha512-fZU0Ohf4uIpHxMEKuTjdjIPM/fWPh35m5sRAKo93RqAlwPD8UmMhngXEwcC4Hj8fz3bimmoY++2DiniGUVzpdQ==", + "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", + "hardhat-watcher": "^2.1.1" + } }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, + "abi-decoder": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/abi-decoder/-/abi-decoder-2.4.0.tgz", + "integrity": "sha512-TOLU2q1HgYOjs1GKGtVzaqrYkar6I2fT9a80rzx6/9EJ/5crb4nCGuro0grZayixem93T7omrajYmLiMkYDLDA==", "requires": { - "type-detect": "4.0.8" + "web3-eth-abi": "^1.2.1", + "web3-utils": "^1.2.1" } }, - "@sinonjs/fake-timers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", - "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", - "dev": true, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "requires": { - "@sinonjs/commons": "^1.7.0" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" } }, - "@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==", + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "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": { - "defer-to-connect": "^1.0.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "@terra-money/terra.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@terra-money/terra.js/-/terra.js-1.8.0.tgz", - "integrity": "sha512-j42IPi8HwHhYMe5mugEtRxtvRt5njm29Dg6UlXExibA22Fa99MWj2n+HWQ7kFOlunEm9B8a8OK2wLA4GhGMiQA==", + "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": { - "axios": "^0.21.1", - "bech32": "^2.0.0", - "bip32": "^2.0.6", - "bip39": "^3.0.3", - "bufferutil": "^4.0.1", - "crypto-js": "3.3.0", - "decimal.js": "^10.2.1", - "readable-stream": "^3.6.0", - "secp256k1": "^4.0.2", - "tmp": "^0.2.1", - "utf-8-validate": "^5.0.2", - "ws": "^7.4.2" + "string-width": "^3.0.0" }, "dependencies": { - "bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - } - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@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 + "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" + } + } + } }, - "@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "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 }, - "@tsconfig/node16": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", - "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", + "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 }, - "@types/babel__core": { - "version": "7.1.14", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz", - "integrity": "sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.2.tgz", - "integrity": "sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==", - "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==", "requires": { - "@babel/types": "^7.0.0" + "color-convert": "^1.9.0" } }, - "@types/babel__template": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz", - "integrity": "sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==", - "dev": true, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, - "@types/babel__traverse": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.1.tgz", - "integrity": "sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } + "app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==" }, - "@types/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true }, - "@types/connect": { - "version": "3.4.34", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", - "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", - "dev": true, + "argle": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/argle/-/argle-1.1.1.tgz", + "integrity": "sha1-DP47wDLDay9IukK5wX+J9wYH6ZQ=", "requires": { - "@types/node": "*" + "lodash.isfunction": "^3.0.8", + "lodash.isnumber": "^3.0.3" } }, - "@types/express": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.12.tgz", - "integrity": "sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q==", + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" + "sprintf-js": "~1.0.2" } }, - "@types/express-serve-static-core": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.21.tgz", - "integrity": "sha512-gwCiEZqW6f7EoR8TTEfalyEhb1zA5jQJnRngr97+3pzMaO1RKoI1w2bw07TK72renMUVWcWS5mLI6rk1NqN0nA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "requires": { - "@types/node": "*" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" } }, - "@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "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 }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } + "array-uniq": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", + "integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0=" }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", "dev": true, "requires": { - "@types/istanbul-lib-report": "*" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" } }, - "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "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 }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true + "available-typed-arrays": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", + "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==" }, - "@types/mathjs": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/@types/mathjs/-/mathjs-9.4.2.tgz", - "integrity": "sha512-GF5g1vJmvKdWIWsE53XX7EDAyCaZ9p6gaYm1xhlXn5JjrY/NJrOfJN3fBxS3wyZpVh3QqKoMkS2WjFwxWMHOTw==", - "dev": true, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "mathjs": "*" + "follow-redirects": "^1.10.0" } }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "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 }, - "@types/node": { - "version": "15.12.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.4.tgz", - "integrity": "sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==" + "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==" }, - "@types/prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-hkc1DATxFLQo4VxPDpMH1gCkPpBbpOoJ/4nhuXw4n63/0R6bCpQECj4+K226UJ4JO/eJQz+1mC2I7JsWanAdQw==", - "dev": true + "bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" }, - "@types/qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==", - "dev": true + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", - "dev": true + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" }, - "@types/serve-static": { - "version": "1.13.9", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", - "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, - "@types/stack-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", - "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", - "dev": true + "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==" }, - "@types/yargs": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.3.tgz", - "integrity": "sha512-YlFfTGS+zqCgXuXNV26rOIeETOkXnGQXP/pjjL9P0gO/EP9jTmc7pUBhx+jVEIxpq41RX33GQ7N3DzOSfZoglQ==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "20.2.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz", - "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.0.tgz", - "integrity": "sha512-KcF6p3zWhf1f8xO84tuBailV5cN92vhS+VT7UJsPzGBm9VnQqfI9AsiMUFUCYHTYPg1uCCo+HyiDnpDuvkAMfQ==", - "dev": true, + "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": { - "@typescript-eslint/experimental-utils": "4.28.0", - "@typescript-eslint/scope-manager": "4.28.0", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "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" }, "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "lru-cache": "^6.0.0" + "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, - "@typescript-eslint/experimental-utils": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.0.tgz", - "integrity": "sha512-9XD9s7mt3QWMk82GoyUpc/Ji03vz4T5AYlHF9DcoFNfJ/y3UAclRsfGiE2gLfXtyC+JRA3trR7cR296TEb1oiQ==", + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.28.0", - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/typescript-estree": "4.28.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" }, "dependencies": { - "eslint-utils": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "requires": { - "eslint-visitor-keys": "^2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "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==", + "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" + } + }, + "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" + } + }, + "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 } } }, - "@typescript-eslint/parser": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.0.tgz", - "integrity": "sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==", + "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": { - "@typescript-eslint/scope-manager": "4.28.0", - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/typescript-estree": "4.28.0", - "debug": "^4.3.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "@typescript-eslint/scope-manager": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.0.tgz", - "integrity": "sha512-eCALCeScs5P/EYjwo6se9bdjtrh8ByWjtHzOkC4Tia6QQWtQr3PHovxh3TdYTuFcurkYI4rmFsRFpucADIkseg==", - "dev": true, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "requires": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0" + "fill-range": "^7.0.1" } }, - "@typescript-eslint/types": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.0.tgz", - "integrity": "sha512-p16xMNKKoiJCVZY5PW/AfILw2xe1LfruTcfAKBj3a+wgNYP5I9ZEKNDOItoRt53p4EiPV6iRSICy8EPanG9ZVA==", + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "@typescript-eslint/typescript-estree": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.0.tgz", - "integrity": "sha512-m19UQTRtxMzKAm8QxfKpvh6OwQSXaW1CdZPoCaQuLwAq7VZMNuhJmZR4g5281s2ECt658sldnJfdpSZZaxUGMQ==", + "buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" + }, + "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": { - "@typescript-eslint/types": "4.28.0", - "@typescript-eslint/visitor-keys": "4.28.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "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": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "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": { - "lru-cache": "^6.0.0" + "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 } } }, - "@typescript-eslint/visitor-keys": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.0.tgz", - "integrity": "sha512-PjJyTWwrlrvM5jazxYF5ZPs/nl0kHDZMVbuIcbpawVXaDPelp3+S9zpOz5RmVUfS/fD5l5+ZXNKnWhNYjPzCvw==", - "dev": true, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "requires": { - "@typescript-eslint/types": "4.28.0", - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "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 - } + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" } }, - "@uniswap/lib": { - "version": "4.0.1-alpha", - "resolved": "https://registry.npmjs.org/@uniswap/lib/-/lib-4.0.1-alpha.tgz", - "integrity": "sha512-f6UIliwBbRsgVLxIaBANF6w09tYqc6Y/qXdsrbEmXHyFA7ILiKrIwRFXe1yOg8M3cksgVsO9N7yuL2DdCGQKBA==" + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true }, - "@uniswap/sdk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@uniswap/sdk/-/sdk-3.0.3.tgz", - "integrity": "sha512-t4s8bvzaCFSiqD2qfXIm3rWhbdnXp+QjD3/mRaeVDHK7zWevs6RGEb1ohMiNgOCTZANvBayb4j8p+XFdnMBadQ==", - "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" - } + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, - "@uniswap/sdk-core": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@uniswap/sdk-core/-/sdk-core-1.0.10.tgz", - "integrity": "sha512-8aD3xkzNDI3Ffh7PdLIcmraZr/6knqQuamVOv96EN8lhouEYH2ZuRbBWb7eZa/W7NwOLjlXM7XHi5gWJKzvbkg==", + "capture-console": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/capture-console/-/capture-console-1.0.1.tgz", + "integrity": "sha1-22PDmscyOQGbrdf7sQFD7aOA/3E=", "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" + "argle": "~1.1.1", + "lodash.isfunction": "~3.0.8", + "randomstring": "~1.1.5" } }, - "@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-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.1.0", - "resolved": "https://registry.npmjs.org/@uniswap/v3-periphery/-/v3-periphery-1.1.0.tgz", - "integrity": "sha512-fZU0Ohf4uIpHxMEKuTjdjIPM/fWPh35m5sRAKo93RqAlwPD8UmMhngXEwcC4Hj8fz3bimmoY++2DiniGUVzpdQ==", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "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", - "hardhat-watcher": "^2.1.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "@uniswap/v3-sdk": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@uniswap/v3-sdk/-/v3-sdk-1.0.8.tgz", - "integrity": "sha512-Kg0P4KZI07m6B6L5EEtkEX/Q6QOdbWnVAHiy8y1XJOxORGw4DS0vklG5IRJAVhgLsVlosbmjxELsBjVMuKtypQ==", + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", "requires": { - "@ethersproject/abi": "^5.0.12", - "@ethersproject/solidity": "^5.0.9", - "@uniswap/sdk-core": "^1.0.10", - "@uniswap/v3-periphery": "1.0.0", - "tiny-invariant": "^1.1.0", - "tiny-warning": "^1.0.3" - }, - "dependencies": { - "@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" - } - } + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" } }, - "abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "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 }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "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 }, - "abi-decoder": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/abi-decoder/-/abi-decoder-2.4.0.tgz", - "integrity": "sha512-TOLU2q1HgYOjs1GKGtVzaqrYkar6I2fT9a80rzx6/9EJ/5crb4nCGuro0grZayixem93T7omrajYmLiMkYDLDA==", + "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": { - "web3-eth-abi": "^1.2.1", - "web3-utils": "^1.2.1" + "mimic-response": "^1.0.0" } }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "color-convert": "^1.9.1", + "color-string": "^1.5.2" } }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" + "color-name": "1.1.3" + }, + "dependencies": { + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } } }, - "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" + "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==" }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "color-string": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", "requires": { - "debug": "4" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "color": "3.0.x", + "text-hex": "1.0.x" } }, - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "complex.js": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.13.tgz", + "integrity": "sha512-UEWd3G3/kd3lJmsdLsDh9qfinJlujL4hIFn3Vo4/G5eqehPsgCHf2CLhFs77tVkOp2stt/jbNit7Q1XFANFltA==" + }, + "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": { - "string-width": "^3.0.0" + "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" }, "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": { + "make-dir": { "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==", + "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": { - "ansi-regex": "^4.1.0" + "semver": "^6.0.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, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", "requires": { - "type-fest": "^0.21.3" + "safe-buffer": "5.1.2" }, "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 + "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==" } } }, - "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==", - "requires": { - "color-convert": "^1.9.0" - } + "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==" }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, - "app-root-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", - "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==" + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "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=" }, - "argle": { + "create-require": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/argle/-/argle-1.1.1.tgz", - "integrity": "sha1-DP47wDLDay9IukK5wX+J9wYH6ZQ=", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-fetch": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", + "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", "requires": { - "lodash.isfunction": "^3.0.8", - "lodash.isnumber": "^3.0.3" + "node-fetch": "2.6.1" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + } } }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "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": { - "sprintf-js": "~1.0.2" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "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 }, - "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", - "dev": true, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } } }, - "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 + "decimal.js": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", + "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==" }, - "array-uniq": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", - "integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0=" + "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==" }, - "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", - "dev": true, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "mimic-response": "^1.0.0" } }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "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 }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "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 }, - "available-typed-arrays": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", - "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==" + "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 }, - "axios": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", - "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "requires": { - "follow-redirects": "^1.10.0" + "object-keys": "^1.0.12" } }, - "babel-jest": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.0.5.tgz", - "integrity": "sha512-bTMAbpCX7ldtfbca2llYLeSFsDM257aspyAOpsdrdSrBqoLkWCy4HPYTXtXWaSLgFPjrJGACL65rzzr4RFGadw==", + "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": { - "@jest/transform": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^27.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "slash": "^3.0.0" + "path-type": "^4.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { + "path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "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" - } } } }, - "babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", - "test-exclude": "^6.0.0" + "esutils": "^2.0.2" } }, - "babel-plugin-jest-hoist": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.1.tgz", - "integrity": "sha512-sqBF0owAcCDBVEDtxqfYr2F36eSHdx7lAVGyYuOBRnKdD6gzcy0I0XrAYCZgOA3CRrLhmR+Uae9nogPzmAtOfQ==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.0.1.tgz", - "integrity": "sha512-nIBIqCEpuiyhvjQs2mVNwTxQQa2xk70p9Dd/0obQGBf8FBzbnI8QhQKzLsWMN2i6q+5B0OcWDtrboBX5gmOLyA==", + "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": { - "babel-plugin-jest-hoist": "^27.0.1", - "babel-preset-current-node-syntax": "^1.0.0" + "is-obj": "^2.0.0" } }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true }, - "base-x": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", - "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", + "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": { - "safe-buffer": "^5.0.1" + "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" } }, - "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==" - }, - "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==" + "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 }, - "bignumber.js": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "requires": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" + "iconv-lite": "^0.6.2" }, "dependencies": { - "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } } } }, - "bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", + "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": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - }, - "dependencies": { - "@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" - } + "once": "^1.4.0" } }, - "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==" + "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" + } }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "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": { - "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" - }, - "dependencies": { - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "is-arrayish": "^0.2.1" } }, - "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "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-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + }, + "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=" + }, + "eslint": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz", + "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==", "dev": true, "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.2", + "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": { + "@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" + } + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2372,9 +1785,9 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -2390,3714 +1803,1266 @@ "color-name": "~1.1.4" } }, - "has-flag": { + "escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "supports-color": { - "version": "7.2.0", + "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 + }, + "globals": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", + "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "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 + }, + "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" + } + }, + "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" } - }, - "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 } } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "eslint-config-prettier": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", + "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", "dev": true }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - } - }, - "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "requires": { - "base-x": "^3.0.2" - } - }, - "bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "requires": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "eslint-config-standard": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", "dev": true }, - "buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" - }, - "bufferutil": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", - "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", - "requires": { - "node-gyp-build": "^4.2.0" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", "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" + "debug": "^2.6.9", + "resolve": "^1.13.1" }, "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==", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "pump": "^3.0.0" + "ms": "2.0.0" } }, - "lowercase-keys": { + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "eslint-module-utils": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", + "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "debug": "^3.2.7", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + } } }, - "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 - }, - "caniuse-lite": { - "version": "1.0.30001235", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001235.tgz", - "integrity": "sha512-zWEwIVqnzPkSAXOUlQnPW2oKoYb2aLQ4Q5ejdjBcnH63rfypaW34CxaeBn1VMya2XaEU3P/R2qHpWyj+l0BT1A==", - "dev": true - }, - "capture-console": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-console/-/capture-console-1.0.1.tgz", - "integrity": "sha1-22PDmscyOQGbrdf7sQFD7aOA/3E=", + "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": { - "argle": "~1.1.1", - "lodash.isfunction": "~3.0.8", - "randomstring": "~1.1.5" + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "eslint-plugin-import": { + "version": "2.23.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", + "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true + "array-includes": "^3.1.3", + "array.prototype.flat": "^1.2.4", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.1", + "find-up": "^2.0.0", + "has": "^1.0.3", + "is-core-module": "^2.4.0", + "minimatch": "^3.0.4", + "object.values": "^1.1.3", + "pkg-up": "^2.0.0", + "read-pkg-up": "^3.0.0", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + } + } }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "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": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "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 + } } }, - "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 - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "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": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "prettier-linter-helpers": "^1.0.0" } }, - "cjs-module-lexer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.1.tgz", - "integrity": "sha512-jVamGdJPDeuQilKhvVn1h3knuMOZzr8QDnpk+M9aMlCaMkTDd6fBWPhiDqFvFZ07pL0liqabAiuy8SY4jGHeaw==", + "eslint-plugin-promise": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz", + "integrity": "sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng==", "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==", + "eslint-plugin-standard": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz", + "integrity": "sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ==", "dev": true }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "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": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" } }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "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": { - "mimic-response": "^1.0.0" + "eslint-visitor-keys": "^1.1.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "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 }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==" }, - "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "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": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.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==", + "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": { - "color-name": "1.1.3" + "estraverse": "^5.1.0" }, "dependencies": { - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true } } }, - "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==" - }, - "color-string": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", - "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", + "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": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "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 + } } }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", - "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" - } + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", "requires": { - "delayed-stream": "~1.0.0" + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" } }, - "complex.js": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.13.tgz", - "integrity": "sha512-UEWd3G3/kd3lJmsdLsDh9qfinJlujL4hIFn3Vo4/G5eqehPsgCHf2CLhFs77tVkOp2stt/jbNit7Q1XFANFltA==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "ethereum-bloom-filters": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.9.tgz", + "integrity": "sha512-GiK/RQkAkcVaEdxKVkPcG07PQ5vD7v2MFSHgZmBJSfMzNRHimntdBithsHAT89tAXnIpzVDWt8iaCD1DvkaxGg==", + "requires": { + "js-sha3": "^0.8.0" + }, + "dependencies": { + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + } + } }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, + "ethers": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.3.1.tgz", + "integrity": "sha512-xCKmC0gsZ9gks89ZfK3B1y6LlPdvX5fxDtu9SytnpdDJR1M7pmJI+4H0AxQPMgUYr7GtQdmECLR0gWdJQ+lZYw==", "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" + "@ethersproject/abi": "5.3.1", + "@ethersproject/abstract-provider": "5.3.0", + "@ethersproject/abstract-signer": "5.3.0", + "@ethersproject/address": "5.3.0", + "@ethersproject/base64": "5.3.0", + "@ethersproject/basex": "5.3.0", + "@ethersproject/bignumber": "5.3.0", + "@ethersproject/bytes": "5.3.0", + "@ethersproject/constants": "5.3.0", + "@ethersproject/contracts": "5.3.0", + "@ethersproject/hash": "5.3.0", + "@ethersproject/hdnode": "5.3.0", + "@ethersproject/json-wallets": "5.3.0", + "@ethersproject/keccak256": "5.3.0", + "@ethersproject/logger": "5.3.0", + "@ethersproject/networks": "5.3.1", + "@ethersproject/pbkdf2": "5.3.0", + "@ethersproject/properties": "5.3.0", + "@ethersproject/providers": "5.3.1", + "@ethersproject/random": "5.3.0", + "@ethersproject/rlp": "5.3.0", + "@ethersproject/sha2": "5.3.0", + "@ethersproject/signing-key": "5.3.0", + "@ethersproject/solidity": "5.3.0", + "@ethersproject/strings": "5.3.0", + "@ethersproject/transactions": "5.3.0", + "@ethersproject/units": "5.3.0", + "@ethersproject/wallet": "5.3.0", + "@ethersproject/web": "5.3.0", + "@ethersproject/wordlists": "5.3.0" }, "dependencies": { - "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, + "@ethersproject/abi": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.3.1.tgz", + "integrity": "sha512-F98FWTJG7nWWAQ4DcV6R0cSlrj67MWK3ylahuFbzkumem5cLWg1p7fZ3vIdRoS1c7TEf55Lvyx0w7ICR47IImw==", "requires": { - "semver": "^6.0.0" + "@ethersproject/address": "^5.3.0", + "@ethersproject/bignumber": "^5.3.0", + "@ethersproject/bytes": "^5.3.0", + "@ethersproject/constants": "^5.3.0", + "@ethersproject/hash": "^5.3.0", + "@ethersproject/keccak256": "^5.3.0", + "@ethersproject/logger": "^5.3.0", + "@ethersproject/properties": "^5.3.0", + "@ethersproject/strings": "^5.3.0" + } + }, + "@ethersproject/networks": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.3.1.tgz", + "integrity": "sha512-6uQKHkYChlsfeiZhQ8IHIqGE/sQsf25o9ZxAYpMxi15dLPzz3IxOEF5KiSD32aHwsjXVBKBSlo+teAXLlYJybw==", + "requires": { + "@ethersproject/logger": "^5.3.0" } } } }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "ethjs-unit": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", + "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", "requires": { - "safe-buffer": "5.1.2" + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" }, "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "bn.js": { + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" } } }, - "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==" - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", "requires": { - "safe-buffer": "~5.1.1" + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "dependencies": { + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, - "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=" - }, - "create-hash": { + "express-ipfilter": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "resolved": "https://registry.npmjs.org/express-ipfilter/-/express-ipfilter-1.2.0.tgz", + "integrity": "sha512-nPXKMuhqVjX7+Vny4XsrpdqlX4YAGcanE0gh5xzpfmNTsINGAgPnpk67kb0No3p1m4vGQQLU6hdaXRxsuGNlTA==", "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "ip": "~1.1.0", + "lodash": "^4.17.11", + "proxy-addr": "^2.0.4", + "range_check": "^1.2.0" } }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "express-winston": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/express-winston/-/express-winston-4.1.0.tgz", + "integrity": "sha512-0DaIjvNADBzC/K4Qw3UwEQc8HRjbajTaP/M43rw0LJpZcQ7SQTPfxkLsnx3ABHEO7EFNQXTpqL0BZPiwkGV8hg==", "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "chalk": "^2.4.2", + "lodash": "^4.17.20" } }, - "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==", + "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 }, - "cross-fetch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", - "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", - "requires": { - "node-fetch": "2.6.1" - }, - "dependencies": { - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" - } - } + "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 }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" } }, - "crypto-js": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz", - "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==" - }, - "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==", + "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 }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "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 }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", "dev": true, "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } + "reusify": "^1.0.4" } }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "fecha": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", + "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" + }, + "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": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" + "flat-cache": "^3.0.4" } }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "file-stream-rotator": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.5.7.tgz", + "integrity": "sha512-VYb3HZ/GiAGUCrfeakO8Mp54YGswNUHvL7P09WQcXAJNSj3iQ5QraYSp3cIn1MUyw6uzfgN/EFOarCNa4JvUHQ==", "requires": { - "ms": "2.1.2" + "moment": "^2.11.2" + } + }, + "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==", + "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" }, "dependencies": { + "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" + } + }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, - "decimal.js": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.1.tgz", - "integrity": "sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw==" - }, - "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==" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "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": { - "mimic-response": "^1.0.0" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, - "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 + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, - "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 + "follow-redirects": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, - "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 + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } + "fraction.js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz", + "integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "delayed-stream": { + "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "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=" - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "diff-sequences": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.1.tgz", - "integrity": "sha512-XPLijkfJUh/PIBnfkcSHgvD6tlYixmcMAn3osTk6jt+H0v/mgURto1XUiD9DKuGX5NDoVS6dSlA23gd9FUaCFg==", + "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 }, - "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, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { - "path-type": "^4.0.0" - }, - "dependencies": { - "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 - } + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" } }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "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": { - "esutils": "^2.0.2" + "pump": "^3.0.0" } }, - "dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "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": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } + "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" } }, - "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, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "requires": { - "is-obj": "^2.0.0" + "is-glob": "^4.0.1" } }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "electron-to-chromium": { - "version": "1.3.749", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.749.tgz", - "integrity": "sha512-F+v2zxZgw/fMwPz/VUGIggG4ZndDsYy0vlpthi3tjmDZlcfbhN5mYW0evXUsBr2sUtuDANFtle410A9u/sd/4A==", - "dev": true - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", "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" + "min-document": "^2.19.0", + "process": "^0.11.10" } }, - "emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dev": true, + "requires": { + "ini": "1.3.7" + } }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "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": { - "iconv-lite": "^0.6.2" + "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": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true } } }, - "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==", + "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": { - "once": "^1.4.0" + "@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" } }, - "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, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "hardhat-watcher": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/hardhat-watcher/-/hardhat-watcher-2.1.1.tgz", + "integrity": "sha512-zilmvxAYD34IofBrwOliQn4z92UiDmt2c949DW4Gokf0vS0qk4YTfVCi/LmUBICThGygNANE3WfnRTpjCJGtDA==", "requires": { - "ansi-colors": "^4.1.1" + "chokidar": "^3.4.3" } }, - "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, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "requires": { - "is-arrayish": "^0.2.1" + "function-bind": "^1.1.1" } }, - "es-abstract": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", - "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "has-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": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", - "object-inspect": "^1.10.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" } }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "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": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "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 }, - "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==", + "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 }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-latex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", - "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + "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=" + } + } }, - "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=" + "http-status-codes": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.1.4.tgz", + "integrity": "sha512-MZVIsLKGVOVE1KEnldppe6Ij+vmemMuApDfjhVSLzyYP+td0bREEYyAoIw9yFePoBXManCuBqmiNP5FqJS5Xkg==" }, - "eslint": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.28.0.tgz", - "integrity": "sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==", - "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": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.2", - "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": { - "@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" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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-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 - }, - "globals": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", - "integrity": "sha512-74/FduwI/JaIrr1H8e71UbDE+5x7pIPs1C2rrwC52SszOo043CsWOZEMW7o2Y58xwm9b+0RBKDxY5n2sUpEFxA==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "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 - }, - "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" - } - }, - "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" - } - } + "safer-buffer": ">= 2.1.2 < 3" } }, - "eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "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 }, - "eslint-config-standard": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", - "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, - "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "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": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, - "eslint-module-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", - "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "debug": "^3.2.7", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } + "once": "^1.3.0", + "wrappy": "1" } }, - "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" - } + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "eslint-plugin-import": { - "version": "2.23.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", - "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", - "dev": true, - "requires": { - "array-includes": "^3.1.3", - "array.prototype.flat": "^1.2.4", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.1", - "find-up": "^2.0.0", - "has": "^1.0.3", - "is-core-module": "^2.4.0", - "minimatch": "^3.0.4", - "object.values": "^1.1.3", - "pkg-up": "^2.0.0", - "read-pkg-up": "^3.0.0", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - } - } + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true }, - "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 - } - } + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" }, - "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, + "ip6": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.0.4.tgz", + "integrity": "sha1-RMWp23njnUBSAbTXjROzhw5I2zE=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", "requires": { - "prettier-linter-helpers": "^1.0.0" + "call-bind": "^1.0.0" } }, - "eslint-plugin-promise": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz", - "integrity": "sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng==", - "dev": true - }, - "eslint-plugin-standard": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz", - "integrity": "sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ==", + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "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" - } + "is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" }, - "eslint-utils": { + "is-binary-path": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "requires": { - "eslint-visitor-keys": "^1.1.0" + "binary-extensions": "^2.0.0" } }, - "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 - }, - "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, + "is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "call-bind": "^1.0.2" } }, - "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 + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "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": { - "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 - } + "ci-info": "^2.0.0" } }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", "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 - } + "has": "^1.0.3" } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==" }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "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 }, - "eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" }, - "ethereum-bloom-filters": { + "is-generator-function": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.9.tgz", - "integrity": "sha512-GiK/RQkAkcVaEdxKVkPcG07PQ5vD7v2MFSHgZmBJSfMzNRHimntdBithsHAT89tAXnIpzVDWt8iaCD1DvkaxGg==", - "requires": { - "js-sha3": "^0.8.0" - }, - "dependencies": { - "js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - } - } + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", + "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==" }, - "ethers": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.3.1.tgz", - "integrity": "sha512-xCKmC0gsZ9gks89ZfK3B1y6LlPdvX5fxDtu9SytnpdDJR1M7pmJI+4H0AxQPMgUYr7GtQdmECLR0gWdJQ+lZYw==", + "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==", "requires": { - "@ethersproject/abi": "5.3.1", - "@ethersproject/abstract-provider": "5.3.0", - "@ethersproject/abstract-signer": "5.3.0", - "@ethersproject/address": "5.3.0", - "@ethersproject/base64": "5.3.0", - "@ethersproject/basex": "5.3.0", - "@ethersproject/bignumber": "5.3.0", - "@ethersproject/bytes": "5.3.0", - "@ethersproject/constants": "5.3.0", - "@ethersproject/contracts": "5.3.0", - "@ethersproject/hash": "5.3.0", - "@ethersproject/hdnode": "5.3.0", - "@ethersproject/json-wallets": "5.3.0", - "@ethersproject/keccak256": "5.3.0", - "@ethersproject/logger": "5.3.0", - "@ethersproject/networks": "5.3.1", - "@ethersproject/pbkdf2": "5.3.0", - "@ethersproject/properties": "5.3.0", - "@ethersproject/providers": "5.3.1", - "@ethersproject/random": "5.3.0", - "@ethersproject/rlp": "5.3.0", - "@ethersproject/sha2": "5.3.0", - "@ethersproject/signing-key": "5.3.0", - "@ethersproject/solidity": "5.3.0", - "@ethersproject/strings": "5.3.0", - "@ethersproject/transactions": "5.3.0", - "@ethersproject/units": "5.3.0", - "@ethersproject/wallet": "5.3.0", - "@ethersproject/web": "5.3.0", - "@ethersproject/wordlists": "5.3.0" - }, - "dependencies": { - "@ethersproject/abi": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.3.1.tgz", - "integrity": "sha512-F98FWTJG7nWWAQ4DcV6R0cSlrj67MWK3ylahuFbzkumem5cLWg1p7fZ3vIdRoS1c7TEf55Lvyx0w7ICR47IImw==", - "requires": { - "@ethersproject/address": "^5.3.0", - "@ethersproject/bignumber": "^5.3.0", - "@ethersproject/bytes": "^5.3.0", - "@ethersproject/constants": "^5.3.0", - "@ethersproject/hash": "^5.3.0", - "@ethersproject/keccak256": "^5.3.0", - "@ethersproject/logger": "^5.3.0", - "@ethersproject/properties": "^5.3.0", - "@ethersproject/strings": "^5.3.0" - } - }, - "@ethersproject/networks": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.3.1.tgz", - "integrity": "sha512-6uQKHkYChlsfeiZhQ8IHIqGE/sQsf25o9ZxAYpMxi15dLPzz3IxOEF5KiSD32aHwsjXVBKBSlo+teAXLlYJybw==", - "requires": { - "@ethersproject/logger": "^5.3.0" - } - } + "is-extglob": "^2.1.1" } }, - "ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk=", - "requires": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" - } - } + "is-hex-prefixed": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", + "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", "dev": true, "requires": { - "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" - }, - "dependencies": { - "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 - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - } + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" } }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" + }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", "dev": true }, - "expect": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.2.tgz", - "integrity": "sha512-YJFNJe2+P2DqH+ZrXy+ydRQYO87oxRUonZImpDodR1G7qo3NYd3pL+NQ9Keqpez3cehczYwZDBC3A7xk3n7M/w==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "ansi-styles": "^5.0.0", - "jest-get-type": "^27.0.1", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-regex-util": "^27.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "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==" }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } + "is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==" }, - "express-ipfilter": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/express-ipfilter/-/express-ipfilter-1.2.0.tgz", - "integrity": "sha512-nPXKMuhqVjX7+Vny4XsrpdqlX4YAGcanE0gh5xzpfmNTsINGAgPnpk67kb0No3p1m4vGQQLU6hdaXRxsuGNlTA==", - "requires": { - "ip": "~1.1.0", - "lodash": "^4.17.11", - "proxy-addr": "^2.0.4", - "range_check": "^1.2.0" - } + "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 }, - "express-winston": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/express-winston/-/express-winston-4.1.0.tgz", - "integrity": "sha512-0DaIjvNADBzC/K4Qw3UwEQc8HRjbajTaP/M43rw0LJpZcQ7SQTPfxkLsnx3ABHEO7EFNQXTpqL0BZPiwkGV8hg==", - "requires": { - "chalk": "^2.4.2", - "lodash": "^4.17.20" - } - }, - "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.5", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", - "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.0", - "merge2": "^1.3.0", - "micromatch": "^4.0.2", - "picomatch": "^2.2.1" - } - }, - "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=", + "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 }, - "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" - }, - "fastq": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", - "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" - }, - "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" - } - }, - "file-stream-rotator": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.5.7.tgz", - "integrity": "sha512-VYb3HZ/GiAGUCrfeakO8Mp54YGswNUHvL7P09WQcXAJNSj3iQ5QraYSp3cIn1MUyw6uzfgN/EFOarCNa4JvUHQ==", - "requires": { - "moment": "^2.11.2" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "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" - }, - "dependencies": { - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" } }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "fn.name": { + "is-stream": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" - }, - "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" - }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fraction.js": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz", - "integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==" - }, - "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=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "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 - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "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" - } - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, - "global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "requires": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", - "dev": true, - "requires": { - "ini": "1.3.7" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "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" - } - }, - "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true - }, - "hardhat-watcher": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/hardhat-watcher/-/hardhat-watcher-2.1.1.tgz", - "integrity": "sha512-zilmvxAYD34IofBrwOliQn4z92UiDmt2c949DW4Gokf0vS0qk4YTfVCi/LmUBICThGygNANE3WfnRTpjCJGtDA==", - "requires": { - "chokidar": "^3.4.3" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "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": "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 - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "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=" - } - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http-status-codes": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.1.4.tgz", - "integrity": "sha512-MZVIsLKGVOVE1KEnldppe6Ij+vmemMuApDfjhVSLzyYP+td0bREEYyAoIw9yFePoBXManCuBqmiNP5FqJS5Xkg==" - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "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 - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "import-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 - }, - "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "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" - } - }, - "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 - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", - "dev": true - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" - }, - "ip6": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.0.4.tgz", - "integrity": "sha1-RMWp23njnUBSAbTXjROzhw5I2zE=" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "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-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-generator-function": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", - "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==" - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" - }, - "is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", - "dev": true, - "requires": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - } - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" - }, - "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==" - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-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-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==" - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", - "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", - "requires": { - "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.0-next.2", - "foreach": "^2.0.5", - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "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 - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, - "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "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 - }, - "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" - } - }, - "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" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "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 - } - } - }, - "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "javascript-natural-sort": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=" - }, - "jest": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.0.5.tgz", - "integrity": "sha512-4NlVMS29gE+JOZvgmSAsz3eOjkSsHqjTajlIsah/4MVSmKvf3zFP/TvgcLoWe2UVHiE9KF741sReqhF0p4mqbQ==", - "dev": true, - "requires": { - "@jest/core": "^27.0.5", - "import-local": "^3.0.2", - "jest-cli": "^27.0.5" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "jest-cli": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.0.5.tgz", - "integrity": "sha512-kZqY020QFOFQKVE2knFHirTBElw3/Q0kUbDc3nMfy/x+RQ7zUY89SUuzpHHJoSX1kX7Lq569ncvjNqU3Td/FCA==", - "dev": true, - "requires": { - "@jest/core": "^27.0.5", - "@jest/test-result": "^27.0.2", - "@jest/types": "^27.0.2", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "import-local": "^3.0.2", - "jest-config": "^27.0.5", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", - "prompts": "^2.0.1", - "yargs": "^16.0.3" - } - }, - "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" - } - } - } - }, - "jest-changed-files": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.0.2.tgz", - "integrity": "sha512-eMeb1Pn7w7x3wue5/vF73LPCJ7DKQuC9wQUR5ebP9hDPpk5hzcT/3Hmz3Q5BOFpR3tgbmaWhJcMTVgC8Z1NuMw==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "execa": "^5.0.0", - "throat": "^6.0.1" - } - }, - "jest-circus": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.0.5.tgz", - "integrity": "sha512-p5rO90o1RTh8LPOG6l0Fc9qgp5YGv+8M5CFixhMh7gGHtGSobD1AxX9cjFZujILgY8t30QZ7WVvxlnuG31r8TA==", - "dev": true, - "requires": { - "@jest/environment": "^27.0.5", - "@jest/test-result": "^27.0.2", - "@jest/types": "^27.0.2", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.0.2", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.2", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-runtime": "^27.0.5", - "jest-snapshot": "^27.0.5", - "jest-util": "^27.0.2", - "pretty-format": "^27.0.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-config": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.0.5.tgz", - "integrity": "sha512-zCUIXag7QIXKEVN4kUKbDBDi9Q53dV5o3eNhGqe+5zAbt1vLs4VE3ceWaYrOub0L4Y7E9pGfM84TX/0ARcE+Qw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^27.0.5", - "@jest/types": "^27.0.2", - "babel-jest": "^27.0.5", - "chalk": "^4.0.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "is-ci": "^3.0.0", - "jest-circus": "^27.0.5", - "jest-environment-jsdom": "^27.0.5", - "jest-environment-node": "^27.0.5", - "jest-get-type": "^27.0.1", - "jest-jasmine2": "^27.0.5", - "jest-regex-util": "^27.0.1", - "jest-resolve": "^27.0.5", - "jest-runner": "^27.0.5", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", - "micromatch": "^4.0.4", - "pretty-format": "^27.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", - "dev": true - }, - "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" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-ci": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz", - "integrity": "sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==", - "dev": true, - "requires": { - "ci-info": "^3.1.1" - } - }, - "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" - } - } - } - }, - "jest-diff": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.2.tgz", - "integrity": "sha512-BFIdRb0LqfV1hBt8crQmw6gGQHVDhM87SpMIZ45FPYKReZYG5er1+5pIn2zKqvrJp6WNox0ylR8571Iwk2Dmgw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.0.1", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-docblock": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.1.tgz", - "integrity": "sha512-TA4+21s3oebURc7VgFV4r7ltdIJ5rtBH1E3Tbovcg7AV+oLfD5DcJ2V2vJ5zFA9sL5CFd/d2D6IpsAeSheEdrA==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.0.2.tgz", - "integrity": "sha512-OLMBZBZ6JkoXgUenDtseFRWA43wVl2BwmZYIWQws7eS7pqsIvePqj/jJmEnfq91ALk3LNphgwNK/PRFBYi7ITQ==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "chalk": "^4.0.0", - "jest-get-type": "^27.0.1", - "jest-util": "^27.0.2", - "pretty-format": "^27.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-environment-jsdom": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.0.5.tgz", - "integrity": "sha512-ToWhViIoTl5738oRaajTMgYhdQL73UWPoV4GqHGk2DPhs+olv8OLq5KoQW8Yf+HtRao52XLqPWvl46dPI88PdA==", - "dev": true, - "requires": { - "@jest/environment": "^27.0.5", - "@jest/fake-timers": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/node": "*", - "jest-mock": "^27.0.3", - "jest-util": "^27.0.2", - "jsdom": "^16.6.0" - } - }, - "jest-environment-node": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.0.5.tgz", - "integrity": "sha512-47qqScV/WMVz5OKF5TWpAeQ1neZKqM3ySwNveEnLyd+yaE/KT6lSMx/0SOx60+ZUcVxPiESYS+Kt2JS9y4PpkQ==", - "dev": true, - "requires": { - "@jest/environment": "^27.0.5", - "@jest/fake-timers": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/node": "*", - "jest-mock": "^27.0.3", - "jest-util": "^27.0.2" - } - }, - "jest-get-type": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.1.tgz", - "integrity": "sha512-9Tggo9zZbu0sHKebiAijyt1NM77Z0uO4tuWOxUCujAiSeXv30Vb5D4xVF4UR4YWNapcftj+PbByU54lKD7/xMg==", - "dev": true - }, - "jest-haste-map": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.0.5.tgz", - "integrity": "sha512-3LFryGSHxwPFHzKIs6W0BGA2xr6g1MvzSjR3h3D8K8Uqy4vbRm/grpGHzbPtIbOPLC6wFoViRrNEmd116QWSkw==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.0.1", - "jest-serializer": "^27.0.1", - "jest-util": "^27.0.2", - "jest-worker": "^27.0.2", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - } - }, - "jest-jasmine2": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.0.5.tgz", - "integrity": "sha512-m3TojR19sFmTn79QoaGy1nOHBcLvtLso6Zh7u+gYxZWGcza4rRPVqwk1hciA5ZOWWZIJOukAcore8JRX992FaA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^27.0.5", - "@jest/source-map": "^27.0.1", - "@jest/test-result": "^27.0.2", - "@jest/types": "^27.0.2", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.0.2", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.2", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-runtime": "^27.0.5", - "jest-snapshot": "^27.0.5", - "jest-util": "^27.0.2", - "pretty-format": "^27.0.2", - "throat": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-leak-detector": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.0.2.tgz", - "integrity": "sha512-TZA3DmCOfe8YZFIMD1GxFqXUkQnIoOGQyy4hFCA2mlHtnAaf+FeOMxi0fZmfB41ZL+QbFG6BVaZF5IeFIVy53Q==", - "dev": true, - "requires": { - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" - } - }, - "jest-matcher-utils": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz", - "integrity": "sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "pretty-format": "^27.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-message-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.2.tgz", - "integrity": "sha512-rTqWUX42ec2LdMkoUPOzrEd1Tcm+R1KfLOmFK+OVNo4MnLsEaxO5zPDb2BbdSmthdM/IfXxOZU60P/WbWF8BTw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.2", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", - "pretty-format": "^27.0.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-mock": { - "version": "27.0.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.0.3.tgz", - "integrity": "sha512-O5FZn5XDzEp+Xg28mUz4ovVcdwBBPfAhW9+zJLO0Efn2qNbYcDaJvSlRiQ6BCZUCVOJjALicuJQI9mRFjv1o9Q==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "@types/node": "*" - } - }, - "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true - }, - "jest-regex-util": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.1.tgz", - "integrity": "sha512-6nY6QVcpTgEKQy1L41P4pr3aOddneK17kn3HJw6SdwGiKfgCGTvH02hVXL0GU8GEKtPH83eD2DIDgxHXOxVohQ==", - "dev": true - }, - "jest-resolve": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.0.5.tgz", - "integrity": "sha512-Md65pngRh8cRuWVdWznXBB5eDt391OJpdBaJMxfjfuXCvOhM3qQBtLMCMTykhuUKiBMmy5BhqCW7AVOKmPrW+Q==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "chalk": "^4.0.0", - "escalade": "^3.1.1", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", - "resolve": "^1.20.0", - "slash": "^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" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-resolve-dependencies": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.5.tgz", - "integrity": "sha512-xUj2dPoEEd59P+nuih4XwNa4nJ/zRd/g4rMvjHrZPEBWeWRq/aJnnM6mug+B+Nx+ILXGtfWHzQvh7TqNV/WbuA==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "jest-regex-util": "^27.0.1", - "jest-snapshot": "^27.0.5" - } - }, - "jest-runner": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.0.5.tgz", - "integrity": "sha512-HNhOtrhfKPArcECgBTcWOc+8OSL8GoFoa7RsHGnfZR1C1dFohxy9eLtpYBS+koybAHlJLZzNCx2Y/Ic3iEtJpQ==", - "dev": true, - "requires": { - "@jest/console": "^27.0.2", - "@jest/environment": "^27.0.5", - "@jest/test-result": "^27.0.2", - "@jest/transform": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-docblock": "^27.0.1", - "jest-environment-jsdom": "^27.0.5", - "jest-environment-node": "^27.0.5", - "jest-haste-map": "^27.0.5", - "jest-leak-detector": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-resolve": "^27.0.5", - "jest-runtime": "^27.0.5", - "jest-util": "^27.0.2", - "jest-worker": "^27.0.2", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } - } - }, - "jest-runtime": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.0.5.tgz", - "integrity": "sha512-V/w/+VasowPESbmhXn5AsBGPfb35T7jZPGZybYTHxZdP7Gwaa+A0EXE6rx30DshHKA98lVCODbCO8KZpEW3hiQ==", - "dev": true, - "requires": { - "@jest/console": "^27.0.2", - "@jest/environment": "^27.0.5", - "@jest/fake-timers": "^27.0.5", - "@jest/globals": "^27.0.5", - "@jest/source-map": "^27.0.1", - "@jest/test-result": "^27.0.2", - "@jest/transform": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.5", - "jest-message-util": "^27.0.2", - "jest-mock": "^27.0.3", - "jest-regex-util": "^27.0.1", - "jest-resolve": "^27.0.5", - "jest-snapshot": "^27.0.5", - "jest-util": "^27.0.2", - "jest-validate": "^27.0.2", - "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^16.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "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" - } - } - } - }, - "jest-serializer": { - "version": "27.0.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.1.tgz", - "integrity": "sha512-svy//5IH6bfQvAbkAEg1s7xhhgHTtXu0li0I2fdKHDsLP2P2MOiscPQIENQep8oU2g2B3jqLyxKKzotZOz4CwQ==", - "dev": true, - "requires": { - "@types/node": "*", - "graceful-fs": "^4.2.4" - } - }, - "jest-snapshot": { - "version": "27.0.5", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.0.5.tgz", - "integrity": "sha512-H1yFYdgnL1vXvDqMrnDStH6yHFdMEuzYQYc71SnC/IJnuuhW6J16w8GWG1P+qGd3Ag3sQHjbRr0TcwEo/vGS+g==", - "dev": true, - "requires": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/parser": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.0.5", - "@jest/types": "^27.0.2", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.0.2", - "graceful-fs": "^4.2.4", - "jest-diff": "^27.0.2", - "jest-get-type": "^27.0.1", - "jest-haste-map": "^27.0.5", - "jest-matcher-utils": "^27.0.2", - "jest-message-util": "^27.0.2", - "jest-resolve": "^27.0.5", - "jest-util": "^27.0.2", - "natural-compare": "^1.4.0", - "pretty-format": "^27.0.2", - "semver": "^7.3.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "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" - } - }, - "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" - } - } - } - }, - "jest-util": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.2.tgz", - "integrity": "sha512-1d9uH3a00OFGGWSibpNYr+jojZ6AckOMCXV2Z4K3YXDnzpkAaXQyIpY14FOJPiUmil7CD+A6Qs+lnnh6ctRbIA==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "@types/node": "*", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^3.0.0", - "picomatch": "^2.2.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", - "dev": true - }, - "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" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-ci": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz", - "integrity": "sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==", - "dev": true, - "requires": { - "ci-info": "^3.1.1" - } - }, - "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" - } - } - } + "is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==" }, - "jest-validate": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.0.2.tgz", - "integrity": "sha512-UgBF6/oVu1ofd1XbaSotXKihi8nZhg0Prm8twQ9uCuAfo59vlxCXMPI/RKmrZEVgi3Nd9dS0I8A0wzWU48pOvg==", - "dev": true, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "requires": { - "@jest/types": "^27.0.2", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.0.1", - "leven": "^3.1.0", - "pretty-format": "^27.0.2" - }, - "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" - } - }, - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } + "has-symbols": "^1.0.2" } }, - "jest-watcher": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.0.2.tgz", - "integrity": "sha512-8nuf0PGuTxWj/Ytfw5fyvNn/R80iXY8QhIT0ofyImUvdnoaBdT6kob0GmhXR+wO+ALYVnh8bQxN4Tjfez0JgkA==", - "dev": true, + "is-typed-array": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", "requires": { - "@jest/test-result": "^27.0.2", - "@jest/types": "^27.0.2", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.0.2", - "string-length": "^4.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "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" - } - } + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" } }, - "jest-worker": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.2.tgz", - "integrity": "sha512-EoBdilOTTyOgmHXtw/cPc+ZrCA0KJMrkXzkrPGNwLmnvvlN1nj7MPrxpT7m+otSv2e1TLaVffzDnE/LB14zJMg==", - "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 + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "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": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" } }, + "javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=" + }, "js-sha3": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", @@ -6124,120 +3089,6 @@ "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-3.1.4.tgz", "integrity": "sha512-52QRRFSsi9impURE8ZUbzAMCLjPm4THO7H2fcuIvaaeFTbSysvkodbQQXIVsNgq/ypDbq6dJiuGKL0vZ/i9hUg==" }, - "jsdom": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", - "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.5", - "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "acorn": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", - "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "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, - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -6262,15 +3113,6 @@ "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" - } - }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -6280,12 +3122,6 @@ "json-buffer": "3.0.0" } }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -6300,12 +3136,6 @@ "package-json": "^6.3.0" } }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6402,15 +3232,6 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "dev": true, - "requires": { - "tmpl": "1.0.x" - } - }, "mathjs": { "version": "9.4.2", "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-9.4.2.tgz", @@ -6427,16 +3248,6 @@ "typed-function": "^2.0.0" } }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -6447,12 +3258,6 @@ "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", @@ -6492,12 +3297,6 @@ "mime-db": "1.48.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", @@ -6525,6 +3324,7 @@ "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" } @@ -6545,11 +3345,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6561,11 +3356,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, - "node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -6575,29 +3365,6 @@ "is-stream": "^1.0.1" } }, - "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, - "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", - "dev": true - }, "nodemon": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.7.tgz", @@ -6673,15 +3440,6 @@ "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" - } - }, "number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", @@ -6698,12 +3456,6 @@ } } }, - "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6765,18 +3517,9 @@ "one-time": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "requires": { - "fn.name": "1.x.x" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "requires": { - "mimic-fn": "^2.1.0" + "fn.name": "1.x.x" } }, "optionator": { @@ -6799,27 +3542,6 @@ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true }, - "p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", - "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-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", @@ -6856,12 +3578,6 @@ "json-parse-better-errors": "^1.0.1" } }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -6876,7 +3592,8 @@ "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=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "3.1.1", @@ -6912,32 +3629,11 @@ } } }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, - "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } - }, "pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", @@ -7019,26 +3715,6 @@ "fast-diff": "^1.1.2" } }, - "pretty-format": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.2.tgz", - "integrity": "sha512-mXKbbBPnYTG7Yra9qFBtqj+IXcsvxsvOBco3QHxtxTl+hHKq6QdzMZ+q0CtL4ORHZgwGImRr2XZUX2EWzORxig==", - "dev": true, - "requires": { - "@jest/types": "^27.0.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -7055,16 +3731,6 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "prompts": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", - "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -7074,12 +3740,6 @@ "ipaddr.js": "1.9.1" } }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -7200,12 +3860,6 @@ } } }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -7319,12 +3973,6 @@ "rc": "^1.2.8" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -7341,23 +3989,6 @@ "path-parse": "^1.0.6" } }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } - } - }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -7383,19 +4014,11 @@ "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" } }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7415,30 +4038,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, "scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, - "secp256k1": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", - "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "requires": { - "elliptic": "^6.5.2", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - }, "seedrandom": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", @@ -7517,15 +4121,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7577,12 +4172,6 @@ } } }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7620,12 +4209,6 @@ } } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", @@ -7687,23 +4270,6 @@ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, - "stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -7714,16 +4280,6 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, "string-width": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", @@ -7776,12 +4332,6 @@ "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-hex-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", @@ -7804,39 +4354,6 @@ "has-flag": "^3.0.0" } }, - "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, "table": { "version": "6.7.1", "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", @@ -7877,27 +4394,6 @@ "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", "dev": true }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, "text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -7909,12 +4405,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -7930,43 +4420,11 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" }, - "tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "requires": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - } - }, "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.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "requires": { - "rimraf": "^3.0.0" - } - }, - "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -8000,26 +4458,6 @@ "nopt": "~1.0.10" } }, - "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", @@ -8092,12 +4530,6 @@ "prelude-ls": "^1.2.1" } }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -8127,11 +4559,6 @@ "is-typedarray": "^1.0.0" } }, - "typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, "typescript": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", @@ -8189,12 +4616,6 @@ "crypto-random-string": "^2.0.0" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -8289,14 +4710,6 @@ "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", "integrity": "sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk=" }, - "utf-8-validate": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz", - "integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==", - "requires": { - "node-gyp-build": "^4.2.0" - } - }, "utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", @@ -8331,25 +4744,6 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, - "v8-to-istanbul": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.0.0.tgz", - "integrity": "sha512-LkmXi8UUNxnCC+JlH7/fsfsKr5AU110l+SYGJimWNkWhxbN5EyeOtm1MJ0hhvqMMOhGwBj1Fp70Yv9i+hX0QAg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "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", @@ -8365,33 +4759,6 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "dev": true, - "requires": { - "makeerror": "1.0.x" - } - }, "web3-eth-abi": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.3.6.tgz", @@ -8435,43 +4802,11 @@ "utf8": "3.0.0" } }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, "whatwg-fetch": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.6.0.tgz", - "integrity": "sha512-os0KkeeqUOl7ccdDT1qqUcS4KH4tcBTSKK5Nl5WKb2lyxInIZ/CpjkqKa1Ss12mjfdcRX9mHmPPs7/SxG1Hbdw==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8516,14 +4851,6 @@ "string-width": "^4.0.0" } }, - "wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha1-CNP1IFbGZnkplyb63g1DKudLRwQ=", - "requires": { - "bs58check": "<3.0.0" - } - }, "winston": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", @@ -8607,37 +4934,6 @@ "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" - } - } - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8699,29 +4995,11 @@ "xhr-request": "^1.1.0" } }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -8733,27 +5011,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "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", diff --git a/package.json b/package.json index a10b69b..08e9968 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "capture-console": "^1.0.1", "cross-fetch": "^3.0.6", "debug": "^4.2.0", + "esm": "^3.2.25", "ethers": "^5.3.1", "express": "^4.17.1", "express-ipfilter": "^1.1.2", @@ -49,18 +50,20 @@ "lodash": "^4.17.20", "mathjs": "^9.3.0", "moment": "^2.29.1", + "pm2": "^4.5.6", "util": "^0.12.3", "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.4", - "yaml": "^1.10.2", - "pm2": "^4.5.6" + "yaml": "^1.10.2" }, "devDependencies": { + "@types/chai": "^4.2.10", "@types/express": "^4.17.12", "@types/jest": "^26.0.24", "@types/mathjs": "^9.4.2", "@typescript-eslint/eslint-plugin": "^4.26.1", "@typescript-eslint/parser": "^4.26.1", + "chai": "^4.2.0", "eslint": "^7.25.0", "eslint-config-prettier": "^8.3.0", "eslint-config-standard": "^16.0.3", diff --git a/tests/example.test.js b/tests/example.test.js new file mode 100644 index 0000000..50a83dc --- /dev/null +++ b/tests/example.test.js @@ -0,0 +1,117 @@ +// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts +import YAML from 'yaml'; +import fs from 'fs'; +import axios from 'axios'; +import https from 'https'; +import { assert, expect } from 'chai'; + +const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir +const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); +const config = YAML.parseDocument(file); + +const tokens = ['WETH', 'DAI', 'MKR', 'USDC']; +const privateKey = config.get('PRIVATE_KEY'); + +const httpsAgent = axios.create({ + httpsAgent: new https.Agent({ + ca: fs.readFileSync(config.get('CERT_PATH') + "/ca_cert.pem"), + cert: fs.readFileSync(config.get('CERT_PATH') + "/client_cert.pem"), + key: fs.readFileSync(config.get('CERT_PATH') + "/client_key.pem"), + rejectUnauthorized: false + }) +}); + +async function request(method, path, params) { + try { + let response; + const gatewayAddress = "https://localhost:5000"; + if (method === "get") { + response = await httpsAgent.get(gatewayAddress + path, params); + } else { // post + params.privateKey = privateKey; + response = await httpsAgent.post(gatewayAddress + path, params); + } + return response.data; + } catch (err) { + console.log(`${path}-${err}`) + } +} + +describe('Tests Ethereum endpoints', () => { + it('Tests Ethereum endpoints', async () => { + + }) + }); +async function ethTests() { + // console.log(tokens); + // console.log(privateKey); + + // call / + const result = await request("get", "/", {}); + // confirm expected response + test('responseOfRootEndpoint', () => { + expect(result).toEqual("ok"); + }) + + // call /balances + const balancesResponse1 = await request("post", "/eth/balances", {tokenList: tokens}); + // confirm and save balances + //console.log(balanceResponse) + const balances = {}; + balances["ZERO"] = "0"; + + // call /balances with invalid token symbol + // confirm expected error message + + // call /allowances + // confirm and save allowances + const allowances = {}; + const allowancesResponse1 = await request("post", "/eth/allowances", {tokenList: tokens, connector: "uniswap"}); + allowances["ZERO"] = "0"; + + // call /balances with invalid token symbol + const balancesResponse2 = await request("post", "/eth/balances", {tokenList: ["ABC", "XYZ"]}); + // confirm expected error message + + // call /approve on each token + const approve1 = await request("post", "/eth/approve", {token: tokens[0], connector: "uniswap", amount: 5}); + // confirm that allowance changed correctly + const allowancesResponse2 = await request("post", "/eth/allowances", {tokenList: tokens, connector: "uniswap"}); + + // call /approve with invalid spender address + const approve2 = await request("post", "/eth/approve", {token: tokens[0], connector: "nill", amount: 5}); + // confirm expected error message + + // call /approve with invalid token symbol + const approve3 = await request("post", "/eth/approve", {token: "ABC", connector: "uniswap", amount: 5}); + // confirm expected error message + + // call /approve with invalid amount + const approve4 = await request("post", "/eth/approve", {token: tokens[0], connector: "uniswap", amount: -5}); + // confirm expected error message +} + +async function uniTests() { + // call /start + const start = await request("get", "/eth/uniswap/start", {pairs: [`${tokens[0]}-${tokens[1]}`]}); + // call /gas-limit + const gasLimit = await request("post", "/eth/uniswap/gas-limit", {}); + + // generate all posible unique combinations of tokens + + // call with different combinations of tokens: + // price buy + + // price sell + // trade buy + // trade sell + + // add tests for extreme values of limitPrice - buy and sell + + // add tests for extreme values of minimumSlippage + +} + +//Promise.resolve(); +ethTests() +uniTests() diff --git a/yarn.lock b/yarn.lock index d1799c3..e318813 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1180,6 +1180,11 @@ "@types/connect" "*" "@types/node" "*" +"@types/chai@^4.2.10": + version "4.2.21" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.21.tgz#9f35a5643129df132cf3b5c1ec64046ea1af0650" + integrity sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg== + "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -1732,6 +1737,11 @@ array.prototype.flat@^1.2.4: define-properties "^1.1.3" es-abstract "^1.18.0-next.1" +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2156,6 +2166,18 @@ capture-console@^1.0.1: lodash.isfunction "~3.0.8" randomstring "~1.1.5" +chai@^4.2.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.1" + type-detect "^4.0.5" + chalk@3.0.0, chalk@^3.0.0, chalk@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -2191,6 +2213,11 @@ charm@~0.1.1: resolved "https://registry.yarnpkg.com/charm/-/charm-0.1.2.tgz#06c21eed1a1b06aeb67553cdc53e23274bac2296" integrity sha1-BsIe7RobBq62dVPNxT4jJ0usIpY= +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + chokidar@^3.2.2, chokidar@^3.4.3, chokidar@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" @@ -2574,6 +2601,13 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -3052,6 +3086,11 @@ eslint@^7.25.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" +esm@^3.2.25: + version "3.2.25" + resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" + integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== + espree@^7.3.0, espree@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" @@ -3555,6 +3594,11 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -5767,6 +5811,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + pbkdf2@^3.0.9: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -7104,7 +7153,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8: +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== From 1fbdc1f28ba99c061cef24e427586b5643ca4a1d Mon Sep 17 00:00:00 2001 From: vic-en Date: Mon, 2 Aug 2021 18:12:52 +0100 Subject: [PATCH 02/43] simplify uniswap v3 price related functions --- src/routes/uniswap_v3.ts | 28 +----- src/services/uniswap_v3.js | 182 +++++++++---------------------------- 2 files changed, 49 insertions(+), 161 deletions(-) diff --git a/src/routes/uniswap_v3.ts b/src/routes/uniswap_v3.ts index 3d8c723..6e20ddd 100644 --- a/src/routes/uniswap_v3.ts +++ b/src/routes/uniswap_v3.ts @@ -24,9 +24,6 @@ const eth = new EthereumService(ethConfig); const uniswap = new UniswapV3(globalConfig.getConfig('ETHEREUM_CHAIN')); -uniswap.generate_tokens(); -setTimeout(uniswap.update_pairs.bind(uniswap), 2000); - const fees = new Fees(); const swapMoreThanMaxPriceError = 'Price too high'; @@ -135,12 +132,6 @@ router.get('/start', async (req, res) => { error: 'pairs query param required', }); } - let gasPrice; - if (typeof req.query.gasPrice === 'string') { - gasPrice = parseFloat(req.query.gasPrice); - } else { - gasPrice = fees.ethGasPrice; - } // get token contract address and cache paths for (let pair of pairs) { @@ -159,23 +150,12 @@ router.get('/start', async (req, res) => { orderedPairs.push(pair.reverse().join('-')); } - uniswap.extend_update_pairs([ - baseTokenContractInfo, - quoteTokenContractInfo, - ]); - - const gasLimit = estimateGasLimit(); - const gasCost = await fees.getGasCost(gasPrice, gasLimit); - const result = { network: eth.networkName, timestamp: initTime, latency: latency(initTime, Date.now()), success: true, pairs: orderedPairs, - gasPrice: gasPrice, - gasLimit: gasLimit, - gasCost: gasCost, }; res.status(200).json(result); } else { @@ -250,7 +230,7 @@ router.post('/trade', async (req: Request, res: Response) => { ); if (side === 'BUY') { - const price = trade.executionPrice.invert().toSignificant(8); + const price = parseFloat(trade.executionPrice.invert().toSignificant(8)); logger.info(`uniswap.route - Price: ${price.toString()}`); if (!limitPrice || price <= limitPrice) { // pass swaps to exchange-proxy to complete trade @@ -286,7 +266,7 @@ router.post('/trade', async (req: Request, res: Response) => { } } else { // sell - const price = trade.executionPrice.toSignificant(8); + const price = parseFloat(trade.executionPrice.toSignificant(8)); logger.info(`Price: ${price.toString()}`); if (!limitPrice || price >= limitPrice) { // pass swaps to exchange-proxy to complete trade @@ -305,7 +285,7 @@ router.post('/trade', async (req: Request, res: Response) => { quote: quoteTokenAddress, amount: parseFloat(req.body.amount), expectedOut: expectedAmount.toSignificant(8), - price: parseFloat(price), + price: price, gasPrice: gasPrice, gasLimit, gasCost: gasCost, @@ -419,7 +399,7 @@ router.post('/price', async (req: Request, res: Response) => { gasLimit: gasLimit, gasCost: gasCost, }; - debug( + logger.info( `Mid Price ${baseTokenContractInfo.symbol}-${ quoteTokenContractInfo.symbol } | (rate:${JSON.stringify( diff --git a/src/services/uniswap_v3.js b/src/services/uniswap_v3.js index b2df4b2..414d88a 100644 --- a/src/services/uniswap_v3.js +++ b/src/services/uniswap_v3.js @@ -7,7 +7,6 @@ const uniV3 = require('@uniswap/v3-sdk'); const ethers = require('ethers'); const globalConfig = require('../services/configuration_manager').configManagerInstance; -const routeTokens = require('../static/uniswap_route_tokens.json'); const nftArtifact = require('@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'); const routerArtifact = require('@uniswap/v3-periphery/artifacts/contracts/SwapRouter.sol/SwapRouter.json'); @@ -33,17 +32,8 @@ export default class UniswapV3 { this.nftManager = globalConfig.getConfig('UNISWAP_V3_NFT_MANAGER'); this.core = globalConfig.getConfig('UNISWAP_V3_CORE'); this.slippage = globalConfig.getConfig('UNISWAP_ALLOWED_SLIPPAGE'); - this.pairsCacheTime = globalConfig.getConfig('UNISWAP_PAIRS_CACHE_TIME'); this.gasLimit = GAS_LIMIT; - this.expireTokenPairUpdate = UPDATE_PERIOD; - this.zeroReserveCheckInterval = globalConfig.getConfig( - 'UNISWAP_NO_RESERVE_CHECK_INTERVAL' - ); - this.zeroReservePairs = {}; // No reserve pairs this.tokenList = {}; - this.pools = {}; - this.tokenSwapList = {}; - this.cachedRoutes = {}; this.abiDecoder = abiDecoder; switch (network) { @@ -154,7 +144,6 @@ export default class UniswapV3 { ) { let fetchPrice = [], prices = []; - this.extend_update_pairs([tokenInAddressInfo, tokenOutAddressInfo]); const tokenIn = this.get_token(tokenInAddressInfo); const tokenOut = this.get_token(tokenOutAddressInfo); const poolContract = new ethers.Contract( @@ -193,167 +182,85 @@ This swap section of this code is a duplicate of Uniswap v2 with little modifica Note that extending the uniswap v2 code may be possible in the future if uniswap v2 is updated to use the new uniswap/sdk-core library. */ /////////////////////////////////////////////////////// Swap section - generate_tokens() { - for (let token of routeTokens[this.network]) { - this.get_token(token); - } - } - - extend_update_pairs(tokens = []) { - for (let token of tokens) { - if ( - !Object.prototype.hasOwnProperty.call(this.tokenList, token.address) - ) { - this.get_token(token); - } - this.tokenSwapList[token.address] = - Date.now() + this.expireTokenPairUpdate; - } - } - async update_pairs() { - // Remove banned pairs after ban period - if (Object.keys(this.zeroReservePairs).length > 0) { - for (let pair in this.zeroReservePairs) { - if (this.zeroReservePairs[pair] <= Date.now()) { - delete this.zeroReservePairs[pair]; - // delete this.tokenList[token]; - } + async get_pairs(firstToken, secondToken) { + let poolDataRequests = []; + let pools = []; + try { + for (let tier of ['LOW', 'MEDIUM', 'HIGH']) { + let poolAddress = uniV3.Pool.getAddress( + firstToken, + secondToken, + FeeAmount[tier] + ); + poolDataRequests.push( + this.get_pool_state( + poolAddress, + FeeAmount[tier], + this.provider + ) + ); } + } catch (err) { + logger.error(err); } - // Generate all possible pair combinations of tokens - // This is done by generating an upper triangular matrix or right triangular matrix - if (Object.keys(this.tokenSwapList).length > 0) { - for (let tokenAddr in this.tokenSwapList) { - if (this.tokenSwapList[tokenAddr] <= Date.now()) { - delete this.tokenSwapList[tokenAddr]; - // delete this.tokenList[tokenAddr]; - } - } - - let tokens = Object.keys(this.tokenList); - var firstToken, secondToken, position; - let length = tokens.length; - let pairs = []; - let poolDataRequests = []; - for (firstToken = 0; firstToken < length; firstToken++) { - for ( - secondToken = firstToken + 1; - secondToken < length; - secondToken++ - ) { + await Promise.allSettled(poolDataRequests).then((values) => { + for (let position = 0; position < poolDataRequests.length; position++) { + if (values[position].status === 'fulfilled') { try { - for (let tier of ['LOW', 'MEDIUM', 'HIGH']) { - let poolAddress = uniV3.Pool.getAddress( - this.tokenList[tokens[firstToken]], - this.tokenList[tokens[secondToken]], - FeeAmount[tier] - ); - if ( - !Object.prototype.hasOwnProperty.call( - this.zeroReservePairs, - poolAddress - ) - ) { - pairs.push([ - poolAddress, - this.tokenList[tokens[firstToken]], - this.tokenList[tokens[secondToken]], - ]); - poolDataRequests.push( - this.get_pool_state( - poolAddress, - FeeAmount[tier], - this.provider - ) - ); - } - } + let poolData = values[position].value; + pools.push(new uniV3.Pool( + firstToken, + secondToken, + poolData.fee, + poolData.sqrtPriceX96.toString(), + poolData.liquidity.toString(), + poolData.tick, + poolData.tickProvider + )); } catch (err) { logger.error(err); } } } - - await Promise.allSettled(poolDataRequests).then((values) => { - for (position = 0; position < poolDataRequests.length; position++) { - if (values[position].status === 'fulfilled') { - try { - let poolData = values[position].value; - this.pools[pairs[position][0]] = new uniV3.Pool( - pairs[position][1], - pairs[position][2], - poolData.fee, - poolData.sqrtPriceX96.toString(), - poolData.liquidity.toString(), - poolData.tick, - poolData.tickProvider - ); - } catch (err) { - debug(err); - } - } else { - this.zeroReservePairs[pairs[position][0]] = - Date.now() + this.zeroReserveCheckInterval; - } - } - }); - } - setTimeout(this.update_pairs.bind(this), 4000); + }); + return pools; } async priceSwapIn(tokenIn, tokenOut, tokenInAmount) { - this.extend_update_pairs([tokenIn, tokenOut]); - const tIn = this.tokenList[tokenIn.address]; - const tOut = this.tokenList[tokenOut.address]; + const tIn = this.get_token(tokenIn); + const tOut = this.get_token(tokenOut); const tokenAmountIn = new uni.CurrencyAmount.fromRawAmount( tIn, ethers.utils.parseUnits(tokenInAmount, tIn.decimals) ); - if (Object.values(this.pools).length === 0) { - throw 'Connector not ready'; - } + const pools = await this.get_pairs(tIn, tOut); const trades = await uniV3.Trade.bestTradeExactIn( - Object.values(this.pools), + pools, tokenAmountIn, tOut, { maxHops: 1 } ); - let trade; - if (trades === undefined) { - trade = this.cachedRoutes[tIn.symbol + tOut.Symbol]; - } else { - this.cachedRoutes[tIn.symbol + tOut.Symbol] = trades[0]; - trade = trades[0]; - } + let trade = trades[0] const expectedAmount = trade.minimumAmountOut(this.get_slippage()); return { trade, expectedAmount }; } async priceSwapOut(tokenIn, tokenOut, tokenOutAmount) { - this.extend_update_pairs([tokenIn, tokenOut]); - const tOut = this.tokenList[tokenOut.address]; - const tIn = this.tokenList[tokenIn.address]; + const tIn = this.get_token(tokenIn); + const tOut = this.get_token(tokenOut); const tokenAmountOut = new uni.CurrencyAmount.fromRawAmount( tOut, ethers.utils.parseUnits(tokenOutAmount, tOut.decimals) ); - if (Object.values(this.pools).length === 0) { - throw 'Connector not ready'; - } + const pools = await this.get_pairs(tIn, tOut); const trades = await uniV3.Trade.bestTradeExactOut( - Object.values(this.pools), + pools, tIn, tokenAmountOut, { maxHops: 1 } ); - let trade; - if (trades === undefined) { - trade = this.cachedRoutes[tIn.symbol + tOut.Symbol]; - } else { - this.cachedRoutes[tIn.symbol + tOut.Symbol] = trades[0]; - trade = trades[0]; - } + let trade = trades[0] const expectedAmount = trade.maximumAmountIn(this.get_slippage()); return { trade, expectedAmount }; } @@ -609,3 +516,4 @@ Note that extending the uniswap v2 code may be possible in the future if uniswap } } /////////////////////////////////////////////////////////// End of LP section +exports.default = UniswapV3; From d3c1032e1d6bafa347ce8649a6b2534bc91ee124 Mon Sep 17 00:00:00 2001 From: vic-en Date: Mon, 2 Aug 2021 18:17:50 +0100 Subject: [PATCH 03/43] git update postman collection and rename start endpoint --- src/routes/uniswap_v3.ts | 2 +- ...swap_V3_postman_collection_02_08_2021.json | 788 ++++++++++++++++++ 2 files changed, 789 insertions(+), 1 deletion(-) create mode 100644 test/postman/Uniswap_V3_postman_collection_02_08_2021.json diff --git a/src/routes/uniswap_v3.ts b/src/routes/uniswap_v3.ts index 6e20ddd..20d1623 100644 --- a/src/routes/uniswap_v3.ts +++ b/src/routes/uniswap_v3.ts @@ -118,7 +118,7 @@ router.post('/result', async (req: Request, res: Response) => { } }); -router.get('/start', async (req, res) => { +router.get('/order-pairs', async (req, res) => { /* GET: /eth/uniswap/v3/start?pairs=["WETH-USDC"]&gasPrice=30 */ diff --git a/test/postman/Uniswap_V3_postman_collection_02_08_2021.json b/test/postman/Uniswap_V3_postman_collection_02_08_2021.json new file mode 100644 index 0000000..474c156 --- /dev/null +++ b/test/postman/Uniswap_V3_postman_collection_02_08_2021.json @@ -0,0 +1,788 @@ +{ + "info": { + "_postman_id": "5de36bfa-027e-46e3-810d-219e42c75314", + "name": "Uniswap V3", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "uniswap v3 endpoints", + "item": [ + { + "name": "eth/uniswap/v3", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/order-pairs", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "pairs", + "value": "[\"COIN1-COIN3\"]", + "type": "text", + "disabled": true + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/order-pairs?pairs=[\"WETH-USDC\"]", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "order-pairs" + ], + "query": [ + { + "key": "pairs", + "value": "[\"WETH-USDC\"]" + }, + { + "key": null, + "value": "[\"WETH-USDC\", \"DAI-USDT\", \"BAT-WBTC\"]", + "disabled": true + }, + { + "key": "pairs", + "value": "[\"COIN1-COIN3\"]", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/gas-limit", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/gas-limit", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "gas-limit" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/result", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "logs", + "value": "[\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x3D2097889B97A9eF23B3eA8FC10c626fbda29099\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000008ac7230489e80000\",\n \"logIndex\": 115,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x809F5A762e7b0CC75C42cd76098b85CB7BD2BA64\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 116,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x7C0a35c75cb73ef794546Bb8C5F7F0912A3d0b29\",\n \"topics\": [\n \"0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde\",\n \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88\",\n \"0x0000000000000000000000000000000000000000000000000000000000000f78\",\n \"0x0000000000000000000000000000000000000000000000000000000000001b30\"\n ],\n \"data\": \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 117,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x\",\n \"logIndex\": 118,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 119,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n }\n ]", + "type": "text" + }, + { + "key": "pair", + "value": "COIN1-COIN3", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/result", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "result" + ], + "query": [ + { + "key": "", + "value": "", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/price(current price)", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "COIN3", + "type": "text" + }, + { + "key": "quote", + "value": "COIN1", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "amount", + "value": "0.1", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "price" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/price(historical price)", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "COIN3", + "type": "text" + }, + { + "key": "quote", + "value": "COIN1", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tier", + "value": "MEDIUM", + "type": "text" + }, + { + "key": "seconds", + "value": "1", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "price" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/trade", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "COIN3", + "type": "text" + }, + { + "key": "quote", + "value": "COIN1", + "type": "text" + }, + { + "key": "amount", + "value": "0.1", + "type": "text" + }, + { + "key": "limitPrice", + "value": "0", + "type": "text", + "disabled": true + }, + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/trade", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "trade" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenId", + "value": "3883", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/position", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "position" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/add-position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "token0", + "value": "COIN3", + "type": "text" + }, + { + "key": "token1", + "value": "COIN1", + "type": "text" + }, + { + "key": "fee", + "value": "MEDIUM", + "type": "text" + }, + { + "key": "lowerPrice", + "value": "0.1", + "type": "text" + }, + { + "key": "upperPrice", + "value": "1.4", + "type": "text" + }, + { + "key": "amount0", + "value": "0.00000001", + "type": "text" + }, + { + "key": "amount1", + "value": "0.001", + "type": "text" + }, + { + "key": "tokenId", + "value": "3709", + "type": "text", + "disabled": true + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/add-position", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "add-position" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/collect-fees", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tokenId", + "value": "3414", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3//collect-fees", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "", + "collect-fees" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/remove-position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tokenId", + "value": "3883", + "type": "text" + }, + { + "key": "reducePercent", + "value": "100", + "type": "text" + }, + { + "key": "getFee", + "value": "True", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/remove-position", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "remove-position" + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "ethereum", + "item": [ + { + "name": "eth", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth" + ] + } + }, + "response": [] + }, + { + "name": "eth/balances", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"COIN1\", \"COIN2\"]", + "description": "[\"COIN1\", \"COIN2\"]", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balances", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balances" + ] + } + }, + "response": [] + }, + { + "name": "eth/allowances", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"COIN1\", \"COIN2\"]", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/allowances", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "allowances" + ] + } + }, + "response": [] + }, + { + "name": "eth/approve", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "token", + "value": "WETH", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + }, + { + "key": "amount", + "value": "0", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/approve", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "approve" + ] + } + }, + "response": [] + }, + { + "name": "eth/poll", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "txHash", + "value": "0xaeba03944a5df71a1888a85473939bd2da31f2f6325d3c3a36a673158dfd9324", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/poll", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "poll" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file From af4876d939ddcc5dc03d607b3941d76aaf6d22a0 Mon Sep 17 00:00:00 2001 From: vic-en Date: Tue, 3 Aug 2021 18:44:04 +0100 Subject: [PATCH 04/43] add test script for uniswap --- tests/example.test.js | 136 +++++++++++++++++++++++++++++------------- 1 file changed, 93 insertions(+), 43 deletions(-) diff --git a/tests/example.test.js b/tests/example.test.js index 50a83dc..3e7ff51 100644 --- a/tests/example.test.js +++ b/tests/example.test.js @@ -3,21 +3,26 @@ import YAML from 'yaml'; import fs from 'fs'; import axios from 'axios'; import https from 'https'; -import { assert, expect } from 'chai'; +import { assert } from 'chai'; const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); const config = YAML.parseDocument(file); -const tokens = ['WETH', 'DAI', 'MKR', 'USDC']; +const tokens = ["WETH", "DAI"]; const privateKey = config.get('PRIVATE_KEY'); + +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + const httpsAgent = axios.create({ httpsAgent: new https.Agent({ ca: fs.readFileSync(config.get('CERT_PATH') + "/ca_cert.pem"), cert: fs.readFileSync(config.get('CERT_PATH') + "/client_cert.pem"), key: fs.readFileSync(config.get('CERT_PATH') + "/client_key.pem"), - rejectUnauthorized: false + rejectUnauthorized: true }) }); @@ -26,92 +31,137 @@ async function request(method, path, params) { let response; const gatewayAddress = "https://localhost:5000"; if (method === "get") { - response = await httpsAgent.get(gatewayAddress + path, params); + response = await httpsAgent.get(gatewayAddress + path, {params: params}); } else { // post - params.privateKey = privateKey; - response = await httpsAgent.post(gatewayAddress + path, params); + params["privateKey"] = privateKey; + response = await httpsAgent.post(gatewayAddress + path, params); } return response.data; } catch (err) { - console.log(`${path}-${err}`) + // console.log(`${path} - ${err}`) } } -describe('Tests Ethereum endpoints', () => { - it('Tests Ethereum endpoints', async () => { - - }) - }); async function ethTests() { - // console.log(tokens); + console.log(tokens); // console.log(privateKey); // call / const result = await request("get", "/", {}); // confirm expected response - test('responseOfRootEndpoint', () => { - expect(result).toEqual("ok"); - }) + console.log(result) + assert.equal(result, "ok") + // call /balances - const balancesResponse1 = await request("post", "/eth/balances", {tokenList: tokens}); + const balancesResponse = await request("post", "/eth/balances", {tokenList: JSON.stringify(tokens)}); // confirm and save balances - //console.log(balanceResponse) - const balances = {}; - balances["ZERO"] = "0"; + // console.log(balancesResponse) + const balances = balancesResponse.balances; + assert.isAbove(parseFloat(balances.ETH), 0, "Pls ensure there is some native token"); // call /balances with invalid token symbol // confirm expected error message + const balancesResponse1 = await request("post", "/eth/balances", {tokenList: JSON.stringify(["ABC", "XYZ"])}); + assert.isNaN(parseFloat(balancesResponse1.balances.ABC), "ABC is a valid token."); + assert.isNaN(parseFloat(balancesResponse1.balances.XYZ), "XYZ is a valid token."); // call /allowances // confirm and save allowances - const allowances = {}; - const allowancesResponse1 = await request("post", "/eth/allowances", {tokenList: tokens, connector: "uniswap"}); - allowances["ZERO"] = "0"; - - // call /balances with invalid token symbol - const balancesResponse2 = await request("post", "/eth/balances", {tokenList: ["ABC", "XYZ"]}); - // confirm expected error message - - // call /approve on each token - const approve1 = await request("post", "/eth/approve", {token: tokens[0], connector: "uniswap", amount: 5}); - // confirm that allowance changed correctly - const allowancesResponse2 = await request("post", "/eth/allowances", {tokenList: tokens, connector: "uniswap"}); + const allowancesResponse1 = await request("post", "/eth/allowances", {tokenList: JSON.stringify(tokens), connector: "uniswap"}); + // console.log(allowancesResponse1); + let allowances = allowancesResponse1.approvals; + + for (let token of tokens){ + if (parseFloat(allowances[token]) < 1000.0) { + // call /approve on each token + let approve1 = await request("post", "/eth/approve", {token: token, connector: "uniswap", amount: '5000'}); + console.log(approve1); + while (allowances[token] !== approve1.amount) { + console.log("Waiting for atleast 1 block time to give time for approval to be mined."); + await sleep(13000); + // confirm that allowance changed correctly + let allowancesResponse2 = await request("post", "/eth/allowances", {tokenList: JSON.stringify(tokens), connector: "uniswap"}); + allowances = allowancesResponse2.approvals; + } + } + } // call /approve with invalid spender address - const approve2 = await request("post", "/eth/approve", {token: tokens[0], connector: "nill", amount: 5}); + const approve3 = await request("post", "/eth/approve", {token: tokens[0], connector: "nill"}); // confirm expected error message + assert.notExists(approve3); // call /approve with invalid token symbol - const approve3 = await request("post", "/eth/approve", {token: "ABC", connector: "uniswap", amount: 5}); + const approve4 = await request("post", "/eth/approve", {token: "ABC", connector: "uniswap"}); // confirm expected error message + assert.notExists(approve4); // call /approve with invalid amount - const approve4 = await request("post", "/eth/approve", {token: tokens[0], connector: "uniswap", amount: -5}); + const approve5 = await request("post", "/eth/approve", {token: tokens[0], connector: "uniswap", amount: 'number'}); // confirm expected error message + assert.notExists(approve5); } -async function uniTests() { +async function unitTests() { // call /start - const start = await request("get", "/eth/uniswap/start", {pairs: [`${tokens[0]}-${tokens[1]}`]}); + let pair = `${tokens[0]}-${tokens[1]}`; + const start = await request("get", "/eth/uniswap/start", {pairs: JSON.stringify([pair])}); // call /gas-limit const gasLimit = await request("post", "/eth/uniswap/gas-limit", {}); - // generate all posible unique combinations of tokens - - // call with different combinations of tokens: // price buy + const buyPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: + 'buy'}); // price sell + const sellPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: + 'sell'}); + // trade buy + const buy = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: + 'buy', limitPrice: buyPrice.price}); + assert.hasAnyKeys(buy, ['txHash'], "Buy trade failed."); + console.log(`Buy hash - ${buy.txHash}`); + let done = false; + let tx1, tx2; + while ( !done ) { + tx1 = await request("post", "/eth/poll", {txHash: buy.txHash}); + console.log(tx1); + done = tx1.confirmed; + } + assert.equal(tx1.receipt.status, 1, "Buy trade reverted."); + + done = false; + + // trade sell + const sell = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: + 'sell', limitPrice: sellPrice.price}); + assert.hasAnyKeys(sell, ['txHash'], "Sell trade failed."); + console.log(`Buy hash - ${sell.txHash}`); + while ( !done ) { + tx2 = await request("post", "/eth/poll", {txHash: sell.txHash}); + console.log(tx2); + done = tx2.confirmed; + } + assert.equal(tx2.receipt.status, 1, "Sell trade reverted."); + // add tests for extreme values of limitPrice - buy and sell + assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: + 'buy', limitPrice: buyPrice.price / 1000})); // add tests for extreme values of minimumSlippage + assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: + 'sell', limitPrice: sellPrice.price * 1000})); } -//Promise.resolve(); -ethTests() -uniTests() + +(async() => { + await ethTests(); + await unitTests(); +})(); + + From 05bcc3f25b23ddf780a3a02e425b588c7fc767bf Mon Sep 17 00:00:00 2001 From: vic-en Date: Tue, 3 Aug 2021 18:45:08 +0100 Subject: [PATCH 05/43] rename example example.test.js file to uniswap.v2.test.js --- tests/{example.test.js => uniswap.v2.test.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{example.test.js => uniswap.v2.test.js} (100%) diff --git a/tests/example.test.js b/tests/uniswap.v2.test.js similarity index 100% rename from tests/example.test.js rename to tests/uniswap.v2.test.js From f54f7f2a5d4dc1df9c9fc02d1122c71ab1bec62e Mon Sep 17 00:00:00 2001 From: vic-en Date: Tue, 3 Aug 2021 19:01:30 +0100 Subject: [PATCH 06/43] include asserts for basic requirements for the script --- tests/uniswap.v2.test.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tests/uniswap.v2.test.js b/tests/uniswap.v2.test.js index 3e7ff51..502a7eb 100644 --- a/tests/uniswap.v2.test.js +++ b/tests/uniswap.v2.test.js @@ -44,7 +44,8 @@ async function request(method, path, params) { async function ethTests() { console.log(tokens); - // console.log(privateKey); + assert.isAtLeast(tokens.length, 2, "Pls provise atlease 2 tokens"); + assert.exists(privateKey, "Pls include PRIVATE_KEY in conf file"); // call / const result = await request("get", "/", {}); @@ -73,7 +74,7 @@ async function ethTests() { let allowances = allowancesResponse1.approvals; for (let token of tokens){ - if (parseFloat(allowances[token]) < 1000.0) { + if (parseFloat(allowances[token]) < 1000.0) { // call /approve on each token let approve1 = await request("post", "/eth/approve", {token: token, connector: "uniswap", amount: '5000'}); console.log(approve1); @@ -111,15 +112,15 @@ async function unitTests() { const gasLimit = await request("post", "/eth/uniswap/gas-limit", {}); // price buy - const buyPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: + const buyPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: 'buy'}); // price sell - const sellPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: + const sellPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: 'sell'}); // trade buy - const buy = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: + const buy = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: 'buy', limitPrice: buyPrice.price}); assert.hasAnyKeys(buy, ['txHash'], "Buy trade failed."); console.log(`Buy hash - ${buy.txHash}`); @@ -136,7 +137,7 @@ async function unitTests() { // trade sell - const sell = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: + const sell = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: 'sell', limitPrice: sellPrice.price}); assert.hasAnyKeys(sell, ['txHash'], "Sell trade failed."); console.log(`Buy hash - ${sell.txHash}`); @@ -149,11 +150,11 @@ async function unitTests() { // add tests for extreme values of limitPrice - buy and sell - assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: + assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: 'buy', limitPrice: buyPrice.price / 1000})); // add tests for extreme values of minimumSlippage - assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: + assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: 'sell', limitPrice: sellPrice.price * 1000})); } @@ -163,5 +164,3 @@ async function unitTests() { await ethTests(); await unitTests(); })(); - - From c4d786b1ac0010878c019d410946f586d117de10 Mon Sep 17 00:00:00 2001 From: vic-en Date: Thu, 5 Aug 2021 12:43:08 +0100 Subject: [PATCH 07/43] move script file to /tests/script/ and add readme file --- tests/scripts/README.md | 24 ++++++++++++++++++++++++ tests/{ => scripts}/uniswap.v2.test.js | 2 ++ 2 files changed, 26 insertions(+) create mode 100644 tests/scripts/README.md rename tests/{ => scripts}/uniswap.v2.test.js (97%) diff --git a/tests/scripts/README.md b/tests/scripts/README.md new file mode 100644 index 0000000..4196e1c --- /dev/null +++ b/tests/scripts/README.md @@ -0,0 +1,24 @@ +![Hummingbot](https://i.ibb.co/X5zNkKw/blacklogo-with-text.png) + +---- + +The aim of Hummingbot Gateway Test scripts is to test endpoints related to supported decentralized protocols in an ideal order in each script. + +## Requirements + +- [Have gateway server properly configured and running](https://docs.hummingbot.io/gateway/installation/) +- Ensure you have the following line containing your private key in the gateway's `global_conf.yml` file: + +```bash +PRIVATE_KEY: "********" +``` + +** Note that test scripts are expected to be run on thesame machine running the gateway server. ** + +## How to run test scripts + +- Simply run `node -r esm NAME_OF_SCRIPT` .i.e. to run `uniswap.v2.test.js`, run: + +```bash +node -r esm uniswap.v2.test.js +``` diff --git a/tests/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js similarity index 97% rename from tests/uniswap.v2.test.js rename to tests/scripts/uniswap.v2.test.js index 502a7eb..446c6e8 100644 --- a/tests/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -124,6 +124,7 @@ async function unitTests() { 'buy', limitPrice: buyPrice.price}); assert.hasAnyKeys(buy, ['txHash'], "Buy trade failed."); console.log(`Buy hash - ${buy.txHash}`); + await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction let done = false; let tx1, tx2; while ( !done ) { @@ -141,6 +142,7 @@ async function unitTests() { 'sell', limitPrice: sellPrice.price}); assert.hasAnyKeys(sell, ['txHash'], "Sell trade failed."); console.log(`Buy hash - ${sell.txHash}`); + await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction while ( !done ) { tx2 = await request("post", "/eth/poll", {txHash: sell.txHash}); console.log(tx2); From 304677da8ba627365ce485f8f60b609bba3b66ef Mon Sep 17 00:00:00 2001 From: vic-en Date: Thu, 5 Aug 2021 13:04:02 +0100 Subject: [PATCH 08/43] update test script readme --- tests/scripts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/README.md b/tests/scripts/README.md index 4196e1c..20a5de2 100644 --- a/tests/scripts/README.md +++ b/tests/scripts/README.md @@ -13,7 +13,7 @@ The aim of Hummingbot Gateway Test scripts is to test endpoints related to suppo PRIVATE_KEY: "********" ``` -** Note that test scripts are expected to be run on thesame machine running the gateway server. ** +*** Note that test scripts are expected to be run on thesame machine running the gateway server. *** ## How to run test scripts From 9b925b4f4a2b9161ac0b56d0179ac3b512d7933a Mon Sep 17 00:00:00 2001 From: vic-en Date: Thu, 5 Aug 2021 13:10:58 +0100 Subject: [PATCH 09/43] revert /order-pairs back to /start --- src/routes/uniswap_v3.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/uniswap_v3.ts b/src/routes/uniswap_v3.ts index 20d1623..6e20ddd 100644 --- a/src/routes/uniswap_v3.ts +++ b/src/routes/uniswap_v3.ts @@ -118,7 +118,7 @@ router.post('/result', async (req: Request, res: Response) => { } }); -router.get('/order-pairs', async (req, res) => { +router.get('/start', async (req, res) => { /* GET: /eth/uniswap/v3/start?pairs=["WETH-USDC"]&gasPrice=30 */ From d0d86f9db8d99528e479a11c44dfb00b2dd94708 Mon Sep 17 00:00:00 2001 From: vic-en Date: Thu, 5 Aug 2021 13:12:12 +0100 Subject: [PATCH 10/43] delete last postman collection --- ...swap_V3_postman_collection_02_08_2021.json | 788 ------------------ 1 file changed, 788 deletions(-) delete mode 100644 test/postman/Uniswap_V3_postman_collection_02_08_2021.json diff --git a/test/postman/Uniswap_V3_postman_collection_02_08_2021.json b/test/postman/Uniswap_V3_postman_collection_02_08_2021.json deleted file mode 100644 index 474c156..0000000 --- a/test/postman/Uniswap_V3_postman_collection_02_08_2021.json +++ /dev/null @@ -1,788 +0,0 @@ -{ - "info": { - "_postman_id": "5de36bfa-027e-46e3-810d-219e42c75314", - "name": "Uniswap V3", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "uniswap v3 endpoints", - "item": [ - { - "name": "eth/uniswap/v3", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/order-pairs", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "", - "value": "", - "type": "text" - } - ], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "pairs", - "value": "[\"COIN1-COIN3\"]", - "type": "text", - "disabled": true - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/order-pairs?pairs=[\"WETH-USDC\"]", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "order-pairs" - ], - "query": [ - { - "key": "pairs", - "value": "[\"WETH-USDC\"]" - }, - { - "key": null, - "value": "[\"WETH-USDC\", \"DAI-USDT\", \"BAT-WBTC\"]", - "disabled": true - }, - { - "key": "pairs", - "value": "[\"COIN1-COIN3\"]", - "disabled": true - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/gas-limit", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "gas-limit" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/result", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "logs", - "value": "[\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x3D2097889B97A9eF23B3eA8FC10c626fbda29099\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000008ac7230489e80000\",\n \"logIndex\": 115,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x809F5A762e7b0CC75C42cd76098b85CB7BD2BA64\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 116,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x7C0a35c75cb73ef794546Bb8C5F7F0912A3d0b29\",\n \"topics\": [\n \"0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde\",\n \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88\",\n \"0x0000000000000000000000000000000000000000000000000000000000000f78\",\n \"0x0000000000000000000000000000000000000000000000000000000000001b30\"\n ],\n \"data\": \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 117,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x\",\n \"logIndex\": 118,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 119,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n }\n ]", - "type": "text" - }, - { - "key": "pair", - "value": "COIN1-COIN3", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/result", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "result" - ], - "query": [ - { - "key": "", - "value": "", - "disabled": true - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(current price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "amount", - "value": "0.1", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "price" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(historical price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tier", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "seconds", - "value": "1", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "price" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "amount", - "value": "0.1", - "type": "text" - }, - { - "key": "limitPrice", - "value": "0", - "type": "text", - "disabled": true - }, - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/trade", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "trade" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenId", - "value": "3883", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/position", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "position" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/add-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "token0", - "value": "COIN3", - "type": "text" - }, - { - "key": "token1", - "value": "COIN1", - "type": "text" - }, - { - "key": "fee", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "lowerPrice", - "value": "0.1", - "type": "text" - }, - { - "key": "upperPrice", - "value": "1.4", - "type": "text" - }, - { - "key": "amount0", - "value": "0.00000001", - "type": "text" - }, - { - "key": "amount1", - "value": "0.001", - "type": "text" - }, - { - "key": "tokenId", - "value": "3709", - "type": "text", - "disabled": true - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/add-position", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "add-position" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/collect-fees", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "3414", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3//collect-fees", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "", - "collect-fees" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/remove-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "3883", - "type": "text" - }, - { - "key": "reducePercent", - "value": "100", - "type": "text" - }, - { - "key": "getFee", - "value": "True", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/remove-position", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "remove-position" - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "ethereum", - "item": [ - { - "name": "eth", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth" - ] - } - }, - "response": [] - }, - { - "name": "eth/balances", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"COIN1\", \"COIN2\"]", - "description": "[\"COIN1\", \"COIN2\"]", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balances", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balances" - ] - } - }, - "response": [] - }, - { - "name": "eth/allowances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"COIN1\", \"COIN2\"]", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/allowances", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "allowances" - ] - } - }, - "response": [] - }, - { - "name": "eth/approve", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "token", - "value": "WETH", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "amount", - "value": "0", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/approve", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "approve" - ] - } - }, - "response": [] - }, - { - "name": "eth/poll", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "txHash", - "value": "0xaeba03944a5df71a1888a85473939bd2da31f2f6325d3c3a36a673158dfd9324", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/poll", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "poll" - ] - } - }, - "response": [] - } - ] - } - ] -} \ No newline at end of file From 5125d8843b8e2feeb61c24c24376da02d2c5aa80 Mon Sep 17 00:00:00 2001 From: vic-en Date: Fri, 6 Aug 2021 23:56:15 +0100 Subject: [PATCH 11/43] update httpagent --- tests/scripts/uniswap.v2.test.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index 446c6e8..6ec7bee 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -9,6 +9,8 @@ const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); const config = YAML.parseDocument(file); +const host = "localhost"; +const port = 5000; const tokens = ["WETH", "DAI"]; const privateKey = config.get('PRIVATE_KEY'); @@ -22,14 +24,17 @@ const httpsAgent = axios.create({ ca: fs.readFileSync(config.get('CERT_PATH') + "/ca_cert.pem"), cert: fs.readFileSync(config.get('CERT_PATH') + "/client_cert.pem"), key: fs.readFileSync(config.get('CERT_PATH') + "/client_key.pem"), - rejectUnauthorized: true + host: host, + port: port, + requestCert: true, + rejectUnauthorized: false }) }); async function request(method, path, params) { try { let response; - const gatewayAddress = "https://localhost:5000"; + const gatewayAddress = `https://${host}:${port}`; if (method === "get") { response = await httpsAgent.get(gatewayAddress + path, {params: params}); } else { // post @@ -38,7 +43,7 @@ async function request(method, path, params) { } return response.data; } catch (err) { - // console.log(`${path} - ${err}`) + console.log(`${path} - ${err}`) } } From f4f2545a18e65bf75ed4573dc86d452a8dfc4775 Mon Sep 17 00:00:00 2001 From: vic-en Date: Sat, 7 Aug 2021 00:29:39 +0100 Subject: [PATCH 12/43] add more logging to uniswap v2 test script --- tests/scripts/uniswap.v2.test.js | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index 6ec7bee..ca41e3e 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -53,6 +53,7 @@ async function ethTests() { assert.exists(privateKey, "Pls include PRIVATE_KEY in conf file"); // call / + console.log("Checking status of gateway server..."); const result = await request("get", "/", {}); // confirm expected response console.log(result) @@ -60,51 +61,64 @@ async function ethTests() { // call /balances + console.log("Checking balances...") const balancesResponse = await request("post", "/eth/balances", {tokenList: JSON.stringify(tokens)}); // confirm and save balances - // console.log(balancesResponse) const balances = balancesResponse.balances; + console.log(balances); assert.isAbove(parseFloat(balances.ETH), 0, "Pls ensure there is some native token"); // call /balances with invalid token symbol // confirm expected error message + console.log("calling balances with invalid token symbols ABC and XYZ...") const balancesResponse1 = await request("post", "/eth/balances", {tokenList: JSON.stringify(["ABC", "XYZ"])}); + console.log(balancesResponse1.balances); assert.isNaN(parseFloat(balancesResponse1.balances.ABC), "ABC is a valid token."); assert.isNaN(parseFloat(balancesResponse1.balances.XYZ), "XYZ is a valid token."); // call /allowances // confirm and save allowances + console.log("checking allowances...") const allowancesResponse1 = await request("post", "/eth/allowances", {tokenList: JSON.stringify(tokens), connector: "uniswap"}); - // console.log(allowancesResponse1); let allowances = allowancesResponse1.approvals; + console.log(allowances); for (let token of tokens){ if (parseFloat(allowances[token]) < 1000.0) { // call /approve on each token + console.log(`Approving 5000 ${token}...`); let approve1 = await request("post", "/eth/approve", {token: token, connector: "uniswap", amount: '5000'}); console.log(approve1); while (allowances[token] !== approve1.amount) { console.log("Waiting for atleast 1 block time to give time for approval to be mined."); await sleep(13000); // confirm that allowance changed correctly + console.log("Rechecking allowances to confirm approval..."); let allowancesResponse2 = await request("post", "/eth/allowances", {tokenList: JSON.stringify(tokens), connector: "uniswap"}); allowances = allowancesResponse2.approvals; + console.log(allowances); } } } // call /approve with invalid spender address + console.log("Trying to approve for invalid contract..."); const approve3 = await request("post", "/eth/approve", {token: tokens[0], connector: "nill"}); + console.log(approve3); // confirm expected error message assert.notExists(approve3); // call /approve with invalid token symbol + console.log("Trying to approve invalid token ABC..."); const approve4 = await request("post", "/eth/approve", {token: "ABC", connector: "uniswap"}); + console.log(approve4); // confirm expected error message assert.notExists(approve4); // call /approve with invalid amount + console.log("Trying to approve invalid amount..."); const approve5 = await request("post", "/eth/approve", {token: tokens[0], connector: "uniswap", amount: 'number'}); + console.log(approve5); // confirm expected error message assert.notExists(approve5); } @@ -112,19 +126,29 @@ async function ethTests() { async function unitTests() { // call /start let pair = `${tokens[0]}-${tokens[1]}`; + console.log(`Starting Uniswap v2 on pair ${pair}...`); const start = await request("get", "/eth/uniswap/start", {pairs: JSON.stringify([pair])}); + console.log(start); + // call /gas-limit + console.log("Calling uniswap v2 gas-limit endpoint..."); const gasLimit = await request("post", "/eth/uniswap/gas-limit", {}); + console.log(gasLimit); // price buy + console.log(`Checking buy price for ${pair}...`); const buyPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: 'buy'}); + console.log(`Buy price: ${buyPrice.price}`); // price sell + console.log(`Checking sell price for ${pair}...`); const sellPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: 'sell'}); + console.log(`Sell price: ${sellPrice.price}`); // trade buy + console.log(`Executing buy trade on ${pair} with 0.01 amount...`); const buy = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: 'buy', limitPrice: buyPrice.price}); assert.hasAnyKeys(buy, ['txHash'], "Buy trade failed."); @@ -143,6 +167,7 @@ async function unitTests() { // trade sell + console.log(`Executing sell trade on ${pair} with 0.01 amount...`); const sell = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: 'sell', limitPrice: sellPrice.price}); assert.hasAnyKeys(sell, ['txHash'], "Sell trade failed."); @@ -157,10 +182,12 @@ async function unitTests() { // add tests for extreme values of limitPrice - buy and sell + console.log("Testing for failure with extreme values of buy limitPrice..."); assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: 'buy', limitPrice: buyPrice.price / 1000})); // add tests for extreme values of minimumSlippage + console.log("Testing for failure with extreme values of sell limitPrice..."); assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: 'sell', limitPrice: sellPrice.price * 1000})); From 661eff37d836112de1bb1a84123ee23cd4a7ef20 Mon Sep 17 00:00:00 2001 From: vic-en Date: Sat, 7 Aug 2021 00:31:41 +0100 Subject: [PATCH 13/43] fix lint --- src/services/fees.js | 4 +- src/services/terra.ts | 4 +- ...swap_V3_postman_collection_16_07_2021.json | 1467 ++++++++--------- tests/scripts/uniswap.v2.test.js | 283 ++-- 4 files changed, 860 insertions(+), 898 deletions(-) diff --git a/src/services/fees.js b/src/services/fees.js index af9c417..d298988 100644 --- a/src/services/fees.js +++ b/src/services/fees.js @@ -9,7 +9,9 @@ const globalConfig = const ethGasStationEnabled = globalConfig.getConfig('ETH_GAS_STATION_ENABLE') || false; const ethGasStationApiKey = globalConfig.getConfig('ETH_GAS_STATION_API_KEY'); -const ethManualGasPrice = parseInt(globalConfig.getConfig('ETH_MANUAL_GAS_PRICE')); +const ethManualGasPrice = parseInt( + globalConfig.getConfig('ETH_MANUAL_GAS_PRICE') +); const ethGasStationURL = ethGasStationHost + '/api/ethgasAPI.json?api-key=' + ethGasStationApiKey; const defaultRefreshInterval = 120; diff --git a/src/services/terra.ts b/src/services/terra.ts index 972f55e..4ff6d72 100644 --- a/src/services/terra.ts +++ b/src/services/terra.ts @@ -257,7 +257,7 @@ export default class Terra { gasAdjustment: number, secret: string ): Promise { - let txResult_; + let txResult_; try { let wallet; try { @@ -322,7 +322,7 @@ export default class Terra { .createAndSignTx(txOptions) .then((tx: StdTx) => this.lcd.tx.broadcast(tx)) .then((txResult: BlockTxBroadcastResult) => { - txResult_ = txResult; + txResult_ = txResult; if (!isTxError(txResult)) { tokenSwap.txSuccess = true; } else { diff --git a/test/postman/Uniswap_V3_postman_collection_16_07_2021.json b/test/postman/Uniswap_V3_postman_collection_16_07_2021.json index a8a7e8d..cda9e0d 100644 --- a/test/postman/Uniswap_V3_postman_collection_16_07_2021.json +++ b/test/postman/Uniswap_V3_postman_collection_16_07_2021.json @@ -1,788 +1,681 @@ { - "info": { - "_postman_id": "5de36bfa-027e-46e3-810d-219e42c75314", - "name": "Uniswap V3", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "uniswap v3 endpoints", - "item": [ - { - "name": "eth/uniswap/v3", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/start", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "", - "value": "", - "type": "text" - } - ], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "pairs", - "value": "[\"COIN1-COIN3\"]", - "type": "text", - "disabled": true - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/start?pairs=[\"COIN1-COIN3\"]", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "start" - ], - "query": [ - { - "key": "pairs", - "value": "[\"COIN1-COIN3\"]" - }, - { - "key": null, - "value": "[\"WETH-USDC\", \"DAI-USDT\", \"BAT-WBTC\"]", - "disabled": true - }, - { - "key": null, - "value": "[\"COIN1-COIN3\"]", - "disabled": true - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/gas-limit", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "gas-limit" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/result", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "logs", - "value": "[\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x3D2097889B97A9eF23B3eA8FC10c626fbda29099\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000008ac7230489e80000\",\n \"logIndex\": 115,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x809F5A762e7b0CC75C42cd76098b85CB7BD2BA64\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 116,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x7C0a35c75cb73ef794546Bb8C5F7F0912A3d0b29\",\n \"topics\": [\n \"0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde\",\n \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88\",\n \"0x0000000000000000000000000000000000000000000000000000000000000f78\",\n \"0x0000000000000000000000000000000000000000000000000000000000001b30\"\n ],\n \"data\": \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 117,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x\",\n \"logIndex\": 118,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 119,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n }\n ]", - "type": "text" - }, - { - "key": "pair", - "value": "COIN1-COIN3", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/result", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "result" - ], - "query": [ - { - "key": "", - "value": "", - "disabled": true - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(current price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "amount", - "value": "0.1", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "price" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(historical price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tier", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "seconds", - "value": "1", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "price" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "amount", - "value": "0.1", - "type": "text" - }, - { - "key": "limitPrice", - "value": "0", - "type": "text", - "disabled": true - }, - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/trade", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "trade" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenId", - "value": "3883", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/position", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "position" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/add-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "token0", - "value": "COIN3", - "type": "text" - }, - { - "key": "token1", - "value": "COIN1", - "type": "text" - }, - { - "key": "fee", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "lowerPrice", - "value": "0.1", - "type": "text" - }, - { - "key": "upperPrice", - "value": "1.4", - "type": "text" - }, - { - "key": "amount0", - "value": "0.00000001", - "type": "text" - }, - { - "key": "amount1", - "value": "0.001", - "type": "text" - }, - { - "key": "tokenId", - "value": "3709", - "type": "text", - "disabled": true - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/add-position", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "add-position" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/collect-fees", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "3414", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3//collect-fees", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "", - "collect-fees" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/remove-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "3883", - "type": "text" - }, - { - "key": "reducePercent", - "value": "100", - "type": "text" - }, - { - "key": "getFee", - "value": "True", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/remove-position", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "v3", - "remove-position" - ] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "ethereum", - "item": [ - { - "name": "eth", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth" - ] - } - }, - "response": [] - }, - { - "name": "eth/balances", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"COIN1\", \"COIN2\"]", - "description": "[\"COIN1\", \"COIN2\"]", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balances", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balances" - ] - } - }, - "response": [] - }, - { - "name": "eth/allowances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"COIN1\", \"COIN2\"]", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/allowances", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "allowances" - ] - } - }, - "response": [] - }, - { - "name": "eth/approve", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "token", - "value": "WETH", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "amount", - "value": "0", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/approve", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "approve" - ] - } - }, - "response": [] - }, - { - "name": "eth/poll", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "txHash", - "value": "0xaeba03944a5df71a1888a85473939bd2da31f2f6325d3c3a36a673158dfd9324", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/poll", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "poll" - ] - } - }, - "response": [] - } - ] - } - ] -} \ No newline at end of file + "info": { + "_postman_id": "5de36bfa-027e-46e3-810d-219e42c75314", + "name": "Uniswap V3", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "uniswap v3 endpoints", + "item": [ + { + "name": "eth/uniswap/v3", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/start", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [ + { + "key": "", + "value": "", + "type": "text" + } + ], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "pairs", + "value": "[\"COIN1-COIN3\"]", + "type": "text", + "disabled": true + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/start?pairs=[\"COIN1-COIN3\"]", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "start"], + "query": [ + { + "key": "pairs", + "value": "[\"COIN1-COIN3\"]" + }, + { + "key": null, + "value": "[\"WETH-USDC\", \"DAI-USDT\", \"BAT-WBTC\"]", + "disabled": true + }, + { + "key": null, + "value": "[\"COIN1-COIN3\"]", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/gas-limit", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/gas-limit", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "gas-limit"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/result", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "logs", + "value": "[\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x3D2097889B97A9eF23B3eA8FC10c626fbda29099\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000008ac7230489e80000\",\n \"logIndex\": 115,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x809F5A762e7b0CC75C42cd76098b85CB7BD2BA64\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 116,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x7C0a35c75cb73ef794546Bb8C5F7F0912A3d0b29\",\n \"topics\": [\n \"0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde\",\n \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88\",\n \"0x0000000000000000000000000000000000000000000000000000000000000f78\",\n \"0x0000000000000000000000000000000000000000000000000000000000001b30\"\n ],\n \"data\": \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 117,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x\",\n \"logIndex\": 118,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 119,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n }\n ]", + "type": "text" + }, + { + "key": "pair", + "value": "COIN1-COIN3", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/result", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "result"], + "query": [ + { + "key": "", + "value": "", + "disabled": true + } + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/price(current price)", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "COIN3", + "type": "text" + }, + { + "key": "quote", + "value": "COIN1", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "amount", + "value": "0.1", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "price"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/price(historical price)", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "COIN3", + "type": "text" + }, + { + "key": "quote", + "value": "COIN1", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tier", + "value": "MEDIUM", + "type": "text" + }, + { + "key": "seconds", + "value": "1", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "price"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/trade", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "COIN3", + "type": "text" + }, + { + "key": "quote", + "value": "COIN1", + "type": "text" + }, + { + "key": "amount", + "value": "0.1", + "type": "text" + }, + { + "key": "limitPrice", + "value": "0", + "type": "text", + "disabled": true + }, + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/trade", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "trade"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenId", + "value": "3883", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/position", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "position"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/add-position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "token0", + "value": "COIN3", + "type": "text" + }, + { + "key": "token1", + "value": "COIN1", + "type": "text" + }, + { + "key": "fee", + "value": "MEDIUM", + "type": "text" + }, + { + "key": "lowerPrice", + "value": "0.1", + "type": "text" + }, + { + "key": "upperPrice", + "value": "1.4", + "type": "text" + }, + { + "key": "amount0", + "value": "0.00000001", + "type": "text" + }, + { + "key": "amount1", + "value": "0.001", + "type": "text" + }, + { + "key": "tokenId", + "value": "3709", + "type": "text", + "disabled": true + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/add-position", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "add-position"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/collect-fees", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tokenId", + "value": "3414", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3//collect-fees", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "", "collect-fees"] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/remove-position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tokenId", + "value": "3883", + "type": "text" + }, + { + "key": "reducePercent", + "value": "100", + "type": "text" + }, + { + "key": "getFee", + "value": "True", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/remove-position", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "uniswap", "v3", "remove-position"] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [""] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [""] + } + } + ] + }, + { + "name": "ethereum", + "item": [ + { + "name": "eth", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth"] + } + }, + "response": [] + }, + { + "name": "eth/balances", + "event": [ + { + "listen": "test", + "script": { + "exec": [""], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"COIN1\", \"COIN2\"]", + "description": "[\"COIN1\", \"COIN2\"]", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balances", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "balances"] + } + }, + "response": [] + }, + { + "name": "eth/allowances", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"COIN1\", \"COIN2\"]", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/allowances", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "allowances"] + } + }, + "response": [] + }, + { + "name": "eth/approve", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "token", + "value": "WETH", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + }, + { + "key": "amount", + "value": "0", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/approve", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "approve"] + } + }, + "response": [] + }, + { + "name": "eth/poll", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "txHash", + "value": "0xaeba03944a5df71a1888a85473939bd2da31f2f6325d3c3a36a673158dfd9324", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/poll", + "protocol": "https", + "host": ["localhost"], + "port": "{{port}}", + "path": ["eth", "poll"] + } + }, + "response": [] + } + ] + } + ] +} diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index ca41e3e..88456ac 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -9,116 +9,153 @@ const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); const config = YAML.parseDocument(file); -const host = "localhost"; +const host = 'localhost'; const port = 5000; -const tokens = ["WETH", "DAI"]; +const tokens = ['WETH', 'DAI']; const privateKey = config.get('PRIVATE_KEY'); - function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } const httpsAgent = axios.create({ httpsAgent: new https.Agent({ - ca: fs.readFileSync(config.get('CERT_PATH') + "/ca_cert.pem"), - cert: fs.readFileSync(config.get('CERT_PATH') + "/client_cert.pem"), - key: fs.readFileSync(config.get('CERT_PATH') + "/client_key.pem"), - host: host, - port: port, + ca: fs.readFileSync(config.get('CERT_PATH') + '/ca_cert.pem'), + cert: fs.readFileSync(config.get('CERT_PATH') + '/client_cert.pem'), + key: fs.readFileSync(config.get('CERT_PATH') + '/client_key.pem'), + host: host, + port: port, requestCert: true, - rejectUnauthorized: false - }) + rejectUnauthorized: false, + }), }); async function request(method, path, params) { try { let response; const gatewayAddress = `https://${host}:${port}`; - if (method === "get") { - response = await httpsAgent.get(gatewayAddress + path, {params: params}); - } else { // post - params["privateKey"] = privateKey; + if (method === 'get') { + response = await httpsAgent.get(gatewayAddress + path, { + params: params, + }); + } else { + // post + params['privateKey'] = privateKey; response = await httpsAgent.post(gatewayAddress + path, params); } return response.data; } catch (err) { - console.log(`${path} - ${err}`) + console.log(`${path} - ${err}`); } } async function ethTests() { console.log(tokens); - assert.isAtLeast(tokens.length, 2, "Pls provise atlease 2 tokens"); - assert.exists(privateKey, "Pls include PRIVATE_KEY in conf file"); + assert.isAtLeast(tokens.length, 2, 'Pls provise atlease 2 tokens'); + assert.exists(privateKey, 'Pls include PRIVATE_KEY in conf file'); // call / - console.log("Checking status of gateway server..."); - const result = await request("get", "/", {}); + console.log('Checking status of gateway server...'); + const result = await request('get', '/', {}); // confirm expected response - console.log(result) - assert.equal(result, "ok") - + console.log(result); + assert.equal(result, 'ok'); // call /balances - console.log("Checking balances...") - const balancesResponse = await request("post", "/eth/balances", {tokenList: JSON.stringify(tokens)}); + console.log('Checking balances...'); + const balancesResponse = await request('post', '/eth/balances', { + tokenList: JSON.stringify(tokens), + }); // confirm and save balances const balances = balancesResponse.balances; - console.log(balances); - assert.isAbove(parseFloat(balances.ETH), 0, "Pls ensure there is some native token"); + console.log(balances); + assert.isAbove( + parseFloat(balances.ETH), + 0, + 'Pls ensure there is some native token' + ); // call /balances with invalid token symbol // confirm expected error message - console.log("calling balances with invalid token symbols ABC and XYZ...") - const balancesResponse1 = await request("post", "/eth/balances", {tokenList: JSON.stringify(["ABC", "XYZ"])}); - console.log(balancesResponse1.balances); - assert.isNaN(parseFloat(balancesResponse1.balances.ABC), "ABC is a valid token."); - assert.isNaN(parseFloat(balancesResponse1.balances.XYZ), "XYZ is a valid token."); + console.log('calling balances with invalid token symbols ABC and XYZ...'); + const balancesResponse1 = await request('post', '/eth/balances', { + tokenList: JSON.stringify(['ABC', 'XYZ']), + }); + console.log(balancesResponse1.balances); + assert.isNaN( + parseFloat(balancesResponse1.balances.ABC), + 'ABC is a valid token.' + ); + assert.isNaN( + parseFloat(balancesResponse1.balances.XYZ), + 'XYZ is a valid token.' + ); // call /allowances // confirm and save allowances - console.log("checking allowances...") - const allowancesResponse1 = await request("post", "/eth/allowances", {tokenList: JSON.stringify(tokens), connector: "uniswap"}); + console.log('checking allowances...'); + const allowancesResponse1 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), + connector: 'uniswap', + }); let allowances = allowancesResponse1.approvals; - console.log(allowances); - - for (let token of tokens){ - if (parseFloat(allowances[token]) < 1000.0) { - // call /approve on each token - console.log(`Approving 5000 ${token}...`); - let approve1 = await request("post", "/eth/approve", {token: token, connector: "uniswap", amount: '5000'}); - console.log(approve1); - while (allowances[token] !== approve1.amount) { - console.log("Waiting for atleast 1 block time to give time for approval to be mined."); - await sleep(13000); - // confirm that allowance changed correctly - console.log("Rechecking allowances to confirm approval..."); - let allowancesResponse2 = await request("post", "/eth/allowances", {tokenList: JSON.stringify(tokens), connector: "uniswap"}); - allowances = allowancesResponse2.approvals; - console.log(allowances); - } - } + console.log(allowances); + + for (let token of tokens) { + if (parseFloat(allowances[token]) < 1000.0) { + // call /approve on each token + console.log(`Approving 5000 ${token}...`); + let approve1 = await request('post', '/eth/approve', { + token: token, + connector: 'uniswap', + amount: '5000', + }); + console.log(approve1); + while (allowances[token] !== approve1.amount) { + console.log( + 'Waiting for atleast 1 block time to give time for approval to be mined.' + ); + await sleep(13000); + // confirm that allowance changed correctly + console.log('Rechecking allowances to confirm approval...'); + let allowancesResponse2 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), + connector: 'uniswap', + }); + allowances = allowancesResponse2.approvals; + console.log(allowances); + } + } } // call /approve with invalid spender address - console.log("Trying to approve for invalid contract..."); - const approve3 = await request("post", "/eth/approve", {token: tokens[0], connector: "nill"}); - console.log(approve3); + console.log('Trying to approve for invalid contract...'); + const approve3 = await request('post', '/eth/approve', { + token: tokens[0], + connector: 'nill', + }); + console.log(approve3); // confirm expected error message assert.notExists(approve3); // call /approve with invalid token symbol - console.log("Trying to approve invalid token ABC..."); - const approve4 = await request("post", "/eth/approve", {token: "ABC", connector: "uniswap"}); - console.log(approve4); + console.log('Trying to approve invalid token ABC...'); + const approve4 = await request('post', '/eth/approve', { + token: 'ABC', + connector: 'uniswap', + }); + console.log(approve4); // confirm expected error message assert.notExists(approve4); // call /approve with invalid amount - console.log("Trying to approve invalid amount..."); - const approve5 = await request("post", "/eth/approve", {token: tokens[0], connector: "uniswap", amount: 'number'}); - console.log(approve5); + console.log('Trying to approve invalid amount...'); + const approve5 = await request('post', '/eth/approve', { + token: tokens[0], + connector: 'uniswap', + amount: 'number', + }); + console.log(approve5); // confirm expected error message assert.notExists(approve5); } @@ -126,75 +163,105 @@ async function ethTests() { async function unitTests() { // call /start let pair = `${tokens[0]}-${tokens[1]}`; - console.log(`Starting Uniswap v2 on pair ${pair}...`); - const start = await request("get", "/eth/uniswap/start", {pairs: JSON.stringify([pair])}); - console.log(start); + console.log(`Starting Uniswap v2 on pair ${pair}...`); + const start = await request('get', '/eth/uniswap/start', { + pairs: JSON.stringify([pair]), + }); + console.log(start); // call /gas-limit - console.log("Calling uniswap v2 gas-limit endpoint..."); - const gasLimit = await request("post", "/eth/uniswap/gas-limit", {}); - console.log(gasLimit); + console.log('Calling uniswap v2 gas-limit endpoint...'); + const gasLimit = await request('post', '/eth/uniswap/gas-limit', {}); + console.log(gasLimit); // price buy - console.log(`Checking buy price for ${pair}...`); - const buyPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: - 'buy'}); - console.log(`Buy price: ${buyPrice.price}`); + console.log(`Checking buy price for ${pair}...`); + const buyPrice = await request('post', '/eth/uniswap/price', { + base: tokens[0], + quote: tokens[1], + amount: '1', + side: 'buy', + }); + console.log(`Buy price: ${buyPrice.price}`); // price sell - console.log(`Checking sell price for ${pair}...`); - const sellPrice = await request("post", "/eth/uniswap/price", {base: tokens[0], quote: tokens[1], amount: '1', side: - 'sell'}); - console.log(`Sell price: ${sellPrice.price}`); + console.log(`Checking sell price for ${pair}...`); + const sellPrice = await request('post', '/eth/uniswap/price', { + base: tokens[0], + quote: tokens[1], + amount: '1', + side: 'sell', + }); + console.log(`Sell price: ${sellPrice.price}`); // trade buy - console.log(`Executing buy trade on ${pair} with 0.01 amount...`); - const buy = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: - 'buy', limitPrice: buyPrice.price}); - assert.hasAnyKeys(buy, ['txHash'], "Buy trade failed."); + console.log(`Executing buy trade on ${pair} with 0.01 amount...`); + const buy = await request('post', '/eth/uniswap/trade', { + base: tokens[0], + quote: tokens[1], + amount: '0.01', + side: 'buy', + limitPrice: buyPrice.price, + }); + assert.hasAnyKeys(buy, ['txHash'], 'Buy trade failed.'); console.log(`Buy hash - ${buy.txHash}`); - await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction + await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction let done = false; let tx1, tx2; - while ( !done ) { - tx1 = await request("post", "/eth/poll", {txHash: buy.txHash}); - console.log(tx1); - done = tx1.confirmed; + while (!done) { + tx1 = await request('post', '/eth/poll', { txHash: buy.txHash }); + console.log(tx1); + done = tx1.confirmed; } - assert.equal(tx1.receipt.status, 1, "Buy trade reverted."); + assert.equal(tx1.receipt.status, 1, 'Buy trade reverted.'); done = false; - // trade sell - console.log(`Executing sell trade on ${pair} with 0.01 amount...`); - const sell = await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '0.01', side: - 'sell', limitPrice: sellPrice.price}); - assert.hasAnyKeys(sell, ['txHash'], "Sell trade failed."); + console.log(`Executing sell trade on ${pair} with 0.01 amount...`); + const sell = await request('post', '/eth/uniswap/trade', { + base: tokens[0], + quote: tokens[1], + amount: '0.01', + side: 'sell', + limitPrice: sellPrice.price, + }); + assert.hasAnyKeys(sell, ['txHash'], 'Sell trade failed.'); console.log(`Buy hash - ${sell.txHash}`); - await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction - while ( !done ) { - tx2 = await request("post", "/eth/poll", {txHash: sell.txHash}); - console.log(tx2); - done = tx2.confirmed; + await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction + while (!done) { + tx2 = await request('post', '/eth/poll', { txHash: sell.txHash }); + console.log(tx2); + done = tx2.confirmed; } - assert.equal(tx2.receipt.status, 1, "Sell trade reverted."); - + assert.equal(tx2.receipt.status, 1, 'Sell trade reverted.'); // add tests for extreme values of limitPrice - buy and sell - console.log("Testing for failure with extreme values of buy limitPrice..."); - assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: - 'buy', limitPrice: buyPrice.price / 1000})); + console.log('Testing for failure with extreme values of buy limitPrice...'); + assert.notExists( + await request('post', '/eth/uniswap/trade', { + base: tokens[0], + quote: tokens[1], + amount: '1', + side: 'buy', + limitPrice: buyPrice.price / 1000, + }) + ); // add tests for extreme values of minimumSlippage - console.log("Testing for failure with extreme values of sell limitPrice..."); - assert.notExists(await request("post", "/eth/uniswap/trade", {base: tokens[0], quote: tokens[1], amount: '1', side: - 'sell', limitPrice: sellPrice.price * 1000})); - + console.log('Testing for failure with extreme values of sell limitPrice...'); + assert.notExists( + await request('post', '/eth/uniswap/trade', { + base: tokens[0], + quote: tokens[1], + amount: '1', + side: 'sell', + limitPrice: sellPrice.price * 1000, + }) + ); } - -(async() => { - await ethTests(); - await unitTests(); +(async () => { + await ethTests(); + await unitTests(); })(); From 022e7dd92d8abb86b9f8da028ea96bb468520cd4 Mon Sep 17 00:00:00 2001 From: vic-en Date: Sat, 7 Aug 2021 00:34:41 +0100 Subject: [PATCH 14/43] update scripts readme --- tests/{scripts => }/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/{scripts => }/README.md (94%) diff --git a/tests/scripts/README.md b/tests/README.md similarity index 94% rename from tests/scripts/README.md rename to tests/README.md index 20a5de2..d349c88 100644 --- a/tests/scripts/README.md +++ b/tests/README.md @@ -20,5 +20,5 @@ PRIVATE_KEY: "********" - Simply run `node -r esm NAME_OF_SCRIPT` .i.e. to run `uniswap.v2.test.js`, run: ```bash -node -r esm uniswap.v2.test.js +node -r esm ./scripts/uniswap.v2.test.js ``` From 26d41c18db6a9175e6c854c8c0cbf225eb937ad7 Mon Sep 17 00:00:00 2001 From: vic-en Date: Mon, 9 Aug 2021 13:06:11 +0100 Subject: [PATCH 15/43] update uniswap v3 test script --- tests/scripts/uniswap.v3.test.js | 271 +++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 tests/scripts/uniswap.v3.test.js diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js new file mode 100644 index 0000000..b95936f --- /dev/null +++ b/tests/scripts/uniswap.v3.test.js @@ -0,0 +1,271 @@ +// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts +import YAML from 'yaml'; +import fs from 'fs'; +import axios from 'axios'; +import https from 'https'; +import { assert } from 'chai'; + +const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir +const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); +const config = YAML.parseDocument(file); + +const host = 'localhost'; +const port = 5000; +let tokens = ['WETH', 'DAI']; +const tier = 'MEDIUM'; +const privateKey = config.get('PRIVATE_KEY'); + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +const httpsAgent = axios.create({ + httpsAgent: new https.Agent({ + ca: fs.readFileSync(config.get('CERT_PATH') + '/ca_cert.pem'), + cert: fs.readFileSync(config.get('CERT_PATH') + '/client_cert.pem'), + key: fs.readFileSync(config.get('CERT_PATH') + '/client_key.pem'), + host: host, + port: port, + requestCert: true, + rejectUnauthorized: false, + }), +}); + +async function request(method, path, params) { + try { + let response; + const gatewayAddress = `https://${host}:${port}`; + if (method === 'get') { + response = await httpsAgent.get(gatewayAddress + path, { + params: params, + }); + } else { + // post + params['privateKey'] = privateKey; + response = await httpsAgent.post(gatewayAddress + path, params); + } + return response.data; + } catch (err) { + console.log(`${path} - ${err}`); + } +} + +async function ethTests() { + console.log(tokens); + assert.isAtLeast(tokens.length, 2, 'Pls provise atlease 2 tokens'); + assert.exists(privateKey, 'Pls include PRIVATE_KEY in conf file'); + + // call / + console.log('Checking status of gateway server...'); + const result = await request('get', '/', {}); + // confirm expected response + console.log(result); + assert.equal(result, 'ok'); + + // call /balances + console.log('Checking balances...'); + const balancesResponse = await request('post', '/eth/balances', { + tokenList: JSON.stringify(tokens), + }); + // confirm and save balances + const balances = balancesResponse.balances; + console.log(balances); + assert.isAbove( + parseFloat(balances.ETH), + 0, + 'Pls ensure there is some native token' + ); + + // call /balances with invalid token symbol + // confirm expected error message + console.log('calling balances with invalid token symbols ABC and XYZ...'); + const balancesResponse1 = await request('post', '/eth/balances', { + tokenList: JSON.stringify(['ABC', 'XYZ']), + }); + console.log(balancesResponse1.balances); + assert.isNaN( + parseFloat(balancesResponse1.balances.ABC), + 'ABC is a valid token.' + ); + assert.isNaN( + parseFloat(balancesResponse1.balances.XYZ), + 'XYZ is a valid token.' + ); + + // call /allowances + // confirm and save allowances + console.log('checking allowances...'); + const allowancesResponse1 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), + connector: 'uniswapV3NFTManager', + }); + let allowances = allowancesResponse1.approvals; + console.log(allowances); + + for (let token of tokens) { + if (parseFloat(allowances[token]) < 1000.0) { + // call /approve on each token + console.log(`Approving 5000 ${token}...`); + let approve1 = await request('post', '/eth/approve', { + token: token, + connector: 'uniswapV3NFTManager', + amount: '5000', + }); + console.log(approve1); + while (allowances[token] !== approve1.amount) { + console.log( + 'Waiting for atleast 1 block time to give time for approval to be mined.' + ); + await sleep(13000); + // confirm that allowance changed correctly + console.log('Rechecking allowances to confirm approval...'); + let allowancesResponse2 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), + connector: 'uniswapV3NFTManager', + }); + allowances = allowancesResponse2.approvals; + console.log(allowances); + } + } + } + + // call /approve with invalid spender address + console.log('Trying to approve for invalid contract...'); + const approve3 = await request('post', '/eth/approve', { + token: tokens[0], + connector: 'nill', + }); + console.log(approve3); + // confirm expected error message + assert.notExists(approve3); + + // call /approve with invalid token symbol + console.log('Trying to approve invalid token ABC...'); + const approve4 = await request('post', '/eth/approve', { + token: 'ABC', + connector: 'uniswapV3NFTManager', + }); + console.log(approve4); + // confirm expected error message + assert.notExists(approve4); + + // call /approve with invalid amount + console.log('Trying to approve invalid amount...'); + const approve5 = await request('post', '/eth/approve', { + token: tokens[0], + connector: 'uniswapV3NFTManager', + amount: 'number', + }); + console.log(approve5); + // confirm expected error message + assert.notExists(approve5); +} + +async function unitTests() { + // call /start + let pair = `${tokens[0]}-${tokens[1]}`; + console.log(`Starting Uniswap v3 on pair ${pair}...`); + const start = await request('get', '/eth/uniswap/v3/start', { + pairs: JSON.stringify([pair]), + }); + console.log(start); + pair = start.pairs[0]; + tokens = pair.split('-'); + + // call /gas-limit + console.log('Calling uniswap v3 gas-limit endpoint...'); + const gasLimit = await request('post', '/eth/uniswap/v3/gas-limit', {}); + console.log(gasLimit); + + // mid price + console.log(`Checking mid price for ${pair} on the ${tier} fee tier...`); + const midPrice = await request('post', '/eth/uniswap/v3/price', { + base: tokens[0], + quote: tokens[1], + seconds: '1', + tier: tier, + }); + console.log(`Mid price: ${midPrice.prices[0]}`); + + // add position + console.log(`Adding position on ${tier} fee tier for ${pair}...`); + const pid = await request('post', '/eth/uniswap/v3/add-position', { + token0: tokens[0], + token1: tokens[1], + lowerPrice: midPrice.prices[0], + upperPrice: parseFloat(midPrice.prices[0]) + 1, + amount0: '0.01', + amount1: '0.01', + fee: tier, + }); + assert.hasAnyKeys(pid, ['txHash'], 'Add position failed.'); + console.log(`PId hash - ${pid.txHash}`); + await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction + let done = false; + let tx1, tx2, tid; + while (!done) { + tx1 = await request('post', '/eth/poll', { txHash: pid.txHash }); + console.log(tx1); + done = tx1.confirmed; + } + if (done) { + // parse transaction log - /eth/uniswap/v3/result + const parsedLog = await request('post', '/eth/uniswap/v3/result', { + logs: JSON.stringify(tx1.receipt.logs), + pair: pair, + }); + for (let inf of parsedLog.info) { + if (inf.name === 'IncreaseLiquidity') { + for (let evt of inf.events) { + if (evt.name === 'tokenId') { + tid = evt.value; + console.log(`New lp order id: ${tid}`) + } + } + } + } + } + assert.equal(tx1.receipt.status, 1, 'Position transaction reverted.'); + + done = false; + + // trade sell + console.log(`Closing position with id ${tid}...`); + const closePid = await request('post', '/eth/uniswap/trade', { + tokenId: tid, + }); + assert.hasAnyKeys(closePid, ['txHash'], 'Close position transaction failed.'); + console.log(`closePId hash - ${sell.txHash}`); + await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction + while (!done) { + tx2 = await request('post', '/eth/poll', { txHash: closePid.txHash }); + console.log(tx2); + done = tx2.confirmed; + } + if (done) { + // parse transaction log - /eth/uniswap/v3/result + const parsedLog2 = await request('post', '/eth/uniswap/v3/result', { + logs: JSON.stringify(tx2.receipt.logs), + pair: pair, + }); + console.log(parsedLog2); + /* + for (let inf of parsedLog2.info) { + if (inf.name === 'DecreaseLiquidity') { + for (let evt of inf.events) { + if (evt.name === 'tokenId') { + tid = evt.value; + console.log(`Lp order with id ${tid} removed.`); + } + } + } + } + */ + } + assert.equal(tx2.receipt.status, 1, 'Close position transaction reverted.'); +} + +(async () => { + await ethTests(); + await unitTests(); +})(); From 3dc32829cc5cedc53935baf40e3a16b351903522 Mon Sep 17 00:00:00 2001 From: vic-en Date: Mon, 9 Aug 2021 13:40:29 +0100 Subject: [PATCH 16/43] final update for uniswap v3 test script --- tests/scripts/uniswap.v3.test.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js index b95936f..3252800 100644 --- a/tests/scripts/uniswap.v3.test.js +++ b/tests/scripts/uniswap.v3.test.js @@ -11,7 +11,7 @@ const config = YAML.parseDocument(file); const host = 'localhost'; const port = 5000; -let tokens = ['WETH', 'DAI']; +let tokens = ['COIN1', 'COIN3']; const tier = 'MEDIUM'; const privateKey = config.get('PRIVATE_KEY'); @@ -198,13 +198,13 @@ async function unitTests() { amount1: '0.01', fee: tier, }); - assert.hasAnyKeys(pid, ['txHash'], 'Add position failed.'); - console.log(`PId hash - ${pid.txHash}`); + assert.hasAnyKeys(pid, ['hash'], 'Add position failed.'); + console.log(`New position transaction hash - ${pid.hash}`); await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction let done = false; let tx1, tx2, tid; while (!done) { - tx1 = await request('post', '/eth/poll', { txHash: pid.txHash }); + tx1 = await request('post', '/eth/poll', { txHash: pid.hash }); console.log(tx1); done = tx1.confirmed; } @@ -229,16 +229,17 @@ async function unitTests() { done = false; - // trade sell + // close position console.log(`Closing position with id ${tid}...`); - const closePid = await request('post', '/eth/uniswap/trade', { + const closePid = await request('post', '/eth/uniswap/v3/remove-position', { tokenId: tid, + getFee: 'false', }); - assert.hasAnyKeys(closePid, ['txHash'], 'Close position transaction failed.'); - console.log(`closePId hash - ${sell.txHash}`); + assert.hasAnyKeys(closePid, ['hash'], 'Close position transaction failed.'); + console.log(`close position transaction hash - ${closePid.hash}`); await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction while (!done) { - tx2 = await request('post', '/eth/poll', { txHash: closePid.txHash }); + tx2 = await request('post', '/eth/poll', { txHash: closePid.hash }); console.log(tx2); done = tx2.confirmed; } @@ -248,19 +249,16 @@ async function unitTests() { logs: JSON.stringify(tx2.receipt.logs), pair: pair, }); - console.log(parsedLog2); - /* for (let inf of parsedLog2.info) { if (inf.name === 'DecreaseLiquidity') { for (let evt of inf.events) { if (evt.name === 'tokenId') { - tid = evt.value; + assert.equal(evt.value, tid); console.log(`Lp order with id ${tid} removed.`); } } } } - */ } assert.equal(tx2.receipt.status, 1, 'Close position transaction reverted.'); } From 573b063dfd1849531ed778e2e8644406f9c5f952 Mon Sep 17 00:00:00 2001 From: vic-en Date: Mon, 9 Aug 2021 13:59:53 +0100 Subject: [PATCH 17/43] comment out price related function in uniswap v3 --- src/routes/uniswap_v3.ts | 10 ++++++---- src/services/uniswap_v3.js | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/routes/uniswap_v3.ts b/src/routes/uniswap_v3.ts index 6e20ddd..6c79e06 100644 --- a/src/routes/uniswap_v3.ts +++ b/src/routes/uniswap_v3.ts @@ -171,8 +171,8 @@ router.get('/start', async (req, res) => { } }); -router.post('/trade', async (req: Request, res: Response) => { - /* +/*router.post('/trade', async (req: Request, res: Response) => { + POST: /trade x-www-form-urlencoded: { "quote":"BAT" @@ -184,7 +184,7 @@ router.post('/trade', async (req: Request, res: Response) => { "privateKey":{{privateKey}} "side":{buy|sell} } -*/ + const initTime = Date.now(); // params: privateKey (required), base (required), quote (required), amount (required), maxPrice (required), gasPrice (required) const privateKey = req.body.privateKey; @@ -318,7 +318,7 @@ router.post('/trade', async (req: Request, res: Response) => { }); } }); - +*/ router.post('/price', async (req: Request, res: Response) => { /* POST: /price @@ -350,6 +350,7 @@ router.post('/price', async (req: Request, res: Response) => { // fetch pools for all tiers let priceResult, price; if (req.body.amount) { + /* // get price at this depth const amount = req.body.amount; const side = req.body.side.toUpperCase(); @@ -378,6 +379,7 @@ router.post('/price', async (req: Request, res: Response) => { expectedAmount: parseFloat(expectedAmount.toSignificant(8)), }; } + */ } else { // get mid price for all tiers priceResult = await uniswap.currentPrice( diff --git a/src/services/uniswap_v3.js b/src/services/uniswap_v3.js index 414d88a..2297f1a 100644 --- a/src/services/uniswap_v3.js +++ b/src/services/uniswap_v3.js @@ -182,7 +182,7 @@ This swap section of this code is a duplicate of Uniswap v2 with little modifica Note that extending the uniswap v2 code may be possible in the future if uniswap v2 is updated to use the new uniswap/sdk-core library. */ /////////////////////////////////////////////////////// Swap section - +/* async get_pairs(firstToken, secondToken) { let poolDataRequests = []; let pools = []; @@ -284,7 +284,7 @@ Note that extending the uniswap v2 code may be possible in the future if uniswap } /////////////////////////////////////////////////// End of Swap section - +*/ //////////////////////////////////////////////////////////// LP section async getPosition(wallet, tokenId, eth, isRaw = false) { From 6ca67b8baf66a874a2a836e4334467f9da379f60 Mon Sep 17 00:00:00 2001 From: vic-en Date: Mon, 16 Aug 2021 15:28:07 +0100 Subject: [PATCH 18/43] remove alpine related commands --- Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index d2b9585..a8d197c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,4 @@ -FROM node:12.13.0-alpine - -# Add timezone database -RUN apk add --no-cache tzdata +FROM node:12.13.0 # Set labels LABEL application="gateway-api" From 41343aff6ab10682cc7b4a8d726b4036ae4b7cc1 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Tue, 17 Aug 2021 10:59:56 -0700 Subject: [PATCH 19/43] MF edits --- test/command.md | 3 -- test/conf/ca.cnf | 25 --------- test/conf/client.cnf | 13 ----- test/conf/server.cnf | 13 ----- test/index.js | 1 - test/ssl-scripts.sh | 54 ------------------- tests/README.md | 4 +- ...eway-Ethereum-Base.postman_collection.json | 0 .../Gateway-Terra.postman_collection.json | 0 .../postman/PERPFI.postman_collection.json | 0 .../Uniswap_V3_postman_collection.json | 0 ...swap_V3_postman_collection_16_07_2021.json | 0 .../postman/terra.postman_environment.json | 0 .../v2/Gateway.postman_collection.json | 0 .../v2/Gateway.postman_environment.json | 0 tests/scripts/uniswap.v2.test.js | 16 ++++-- 16 files changed, 13 insertions(+), 116 deletions(-) delete mode 100644 test/command.md delete mode 100644 test/conf/ca.cnf delete mode 100644 test/conf/client.cnf delete mode 100644 test/conf/server.cnf delete mode 100644 test/index.js delete mode 100755 test/ssl-scripts.sh rename {test => tests}/postman/Gateway-Ethereum-Base.postman_collection.json (100%) rename {test => tests}/postman/Gateway-Terra.postman_collection.json (100%) rename {test => tests}/postman/PERPFI.postman_collection.json (100%) rename {test => tests}/postman/Uniswap_V3_postman_collection.json (100%) rename {test => tests}/postman/Uniswap_V3_postman_collection_16_07_2021.json (100%) rename {test => tests}/postman/terra.postman_environment.json (100%) rename {test => tests}/postman/v2/Gateway.postman_collection.json (100%) rename {test => tests}/postman/v2/Gateway.postman_environment.json (100%) diff --git a/test/command.md b/test/command.md deleted file mode 100644 index 7ddb10c..0000000 --- a/test/command.md +++ /dev/null @@ -1,3 +0,0 @@ - -# test endpoint -curl --insecure --key /home/dev/bots/hbot_files/hummingbot_certs/client_key.pem --cert /home/dev/bots/hbot_files/hummingbot_certs/client_cert.pem https://localhost:5000/api diff --git a/test/conf/ca.cnf b/test/conf/ca.cnf deleted file mode 100644 index d415734..0000000 --- a/test/conf/ca.cnf +++ /dev/null @@ -1,25 +0,0 @@ -[ ca ] -default_ca = CA_default - -[ CA_default ] -serial = ca-serial -crl = ca-crl.pem -database = ca-database.txt -name_opt = CA_default -cert_opt = CA_default -default_crl_days = 365 -default_md = md5 - -[ req ] -default_bits = 4096 -days = 365 -distinguished_name = req_distinguished_name -attributes = req_attributes -prompt = no -output_password = password - -[ req_distinguished_name ] -CN = ca - -[ req_attributes ] -challengePassword = test diff --git a/test/conf/client.cnf b/test/conf/client.cnf deleted file mode 100644 index 4bf4921..0000000 --- a/test/conf/client.cnf +++ /dev/null @@ -1,13 +0,0 @@ -[ req ] -default_bits = 4096 -days = 365 -distinguished_name = req_distinguished_name -attributes = req_attributes -prompt = no - -[ req_distinguished_name ] -O = Hummingbot -CN = client - -[ req_attributes ] -challengePassword = password diff --git a/test/conf/server.cnf b/test/conf/server.cnf deleted file mode 100644 index 0dd2c3a..0000000 --- a/test/conf/server.cnf +++ /dev/null @@ -1,13 +0,0 @@ -[ req ] -default_bits = 4096 -days = 365 -distinguished_name = req_distinguished_name -attributes = req_attributes -prompt = no - -[ req_distinguished_name ] -O = Hummingbot -CN = localhost - -[ req_attributes ] -challengePassword = password diff --git a/test/index.js b/test/index.js deleted file mode 100644 index ff7bd09..0000000 --- a/test/index.js +++ /dev/null @@ -1 +0,0 @@ -// placeholder diff --git a/test/ssl-scripts.sh b/test/ssl-scripts.sh deleted file mode 100755 index 316f2ae..0000000 --- a/test/ssl-scripts.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -##### Server Ceritification Creation ##### -########################################## - -# CA configuration file: ca.cnf - -# create a new certificate authority using this configuration. -# we now have our certificate authority in ca_key.pem and ca_cert.pem -openssl req -new -x509 -days 9999 -config ./conf/ca.cnf -keyout ../certs/ca_key.pem -out ../certs/ca_cert.pem - -# generate a private key for the server. -openssl genrsa -out ../certs/server_key.pem 4096 - -# generate a certificate signing request -openssl req -new -config ./conf/server.cnf -key ../certs/server_key.pem -out ../certs/server_csr.pem - -# sign the request. -openssl x509 -req -extfile ./conf/server.cnf -days 999 -passin "pass:password" -in ../certs/server_csr.pem -CA ../certs/ca_cert.pem -CAkey ../certs/ca_key.pem -CAcreateserial -out ../certs/server_cert.pem - - -##### Client Ceritification Creation ##### -########################################## - -# create client key -openssl genrsa -out ../certs/client_key.pem 4096 - -# create certificate signing requests. -openssl req -new -config ./conf/client.cnf -key ../certs/client_key.pem -out ../certs/client_csr.pem - -# sign new client certs. -openssl x509 -req -extfile ./conf/client.cnf -days 999 -passin "pass:password" -in ../certs/client_csr.pem -CA ../certs/ca_cert.pem -CAkey ../certs/ca_key.pem -CAcreateserial -out ../certs/client_cert.pem - -# verify our certs -echo -echo "verifying server certs" -echo -openssl verify -CAfile ../certs/ca_cert.pem ../certs/server_cert.pem -echo -echo "verifying client certs" -openssl verify -CAfile ../certs/ca_cert.pem ../certs/client_cert.pem -echo - - -echo -echo "note: restart node server to load new certs" -echo - -# test after restarting node server -# use -v to see details in verbose mode -# curl --insecure --key ../certs/client_key.pem --cert ../certs/client_cert.pem https://localhost:5000/api -# curl --insecure --key ../certs/client_key.pem --cert ../certs/client_cert.pem https://localhost:5000/terra -# curl --insecure --key ../certs/client_key.pem --cert ../certs/client_cert.pem https://localhost:5000/balancer - diff --git a/tests/README.md b/tests/README.md index d349c88..35d0d74 100644 --- a/tests/README.md +++ b/tests/README.md @@ -17,8 +17,8 @@ PRIVATE_KEY: "********" ## How to run test scripts -- Simply run `node -r esm NAME_OF_SCRIPT` .i.e. to run `uniswap.v2.test.js`, run: +From the root directory, run `node -r esm PATH_TO_SCRIPT` .i.e. to run `uniswap.v2.test.js`, run: ```bash -node -r esm ./scripts/uniswap.v2.test.js +node -r esm ./tests/scripts/uniswap.v2.test.js ``` diff --git a/test/postman/Gateway-Ethereum-Base.postman_collection.json b/tests/postman/Gateway-Ethereum-Base.postman_collection.json similarity index 100% rename from test/postman/Gateway-Ethereum-Base.postman_collection.json rename to tests/postman/Gateway-Ethereum-Base.postman_collection.json diff --git a/test/postman/Gateway-Terra.postman_collection.json b/tests/postman/Gateway-Terra.postman_collection.json similarity index 100% rename from test/postman/Gateway-Terra.postman_collection.json rename to tests/postman/Gateway-Terra.postman_collection.json diff --git a/test/postman/PERPFI.postman_collection.json b/tests/postman/PERPFI.postman_collection.json similarity index 100% rename from test/postman/PERPFI.postman_collection.json rename to tests/postman/PERPFI.postman_collection.json diff --git a/test/postman/Uniswap_V3_postman_collection.json b/tests/postman/Uniswap_V3_postman_collection.json similarity index 100% rename from test/postman/Uniswap_V3_postman_collection.json rename to tests/postman/Uniswap_V3_postman_collection.json diff --git a/test/postman/Uniswap_V3_postman_collection_16_07_2021.json b/tests/postman/Uniswap_V3_postman_collection_16_07_2021.json similarity index 100% rename from test/postman/Uniswap_V3_postman_collection_16_07_2021.json rename to tests/postman/Uniswap_V3_postman_collection_16_07_2021.json diff --git a/test/postman/terra.postman_environment.json b/tests/postman/terra.postman_environment.json similarity index 100% rename from test/postman/terra.postman_environment.json rename to tests/postman/terra.postman_environment.json diff --git a/test/postman/v2/Gateway.postman_collection.json b/tests/postman/v2/Gateway.postman_collection.json similarity index 100% rename from test/postman/v2/Gateway.postman_collection.json rename to tests/postman/v2/Gateway.postman_collection.json diff --git a/test/postman/v2/Gateway.postman_environment.json b/tests/postman/v2/Gateway.postman_environment.json similarity index 100% rename from test/postman/v2/Gateway.postman_environment.json rename to tests/postman/v2/Gateway.postman_environment.json diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index 88456ac..12beed5 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -50,9 +50,11 @@ async function request(method, path, params) { } async function ethTests() { - console.log(tokens); - assert.isAtLeast(tokens.length, 2, 'Pls provise atlease 2 tokens'); - assert.exists(privateKey, 'Pls include PRIVATE_KEY in conf file'); + console.log('\nStarting ETH tests'); + console.log('***************************************************'); + console.log('Token symbols used in tests: ', tokens); + assert.isAtLeast(tokens.length, 2, 'Pls provide at least 2 tokens'); + assert.exists(privateKey, 'Pls include PRIVATE_KEY in global_conf file'); // call / console.log('Checking status of gateway server...'); @@ -161,6 +163,8 @@ async function ethTests() { } async function unitTests() { + console.log('\nStarting Uniswap tests'); + console.log('***************************************************'); // call /start let pair = `${tokens[0]}-${tokens[1]}`; console.log(`Starting Uniswap v2 on pair ${pair}...`); @@ -205,9 +209,10 @@ async function unitTests() { }); assert.hasAnyKeys(buy, ['txHash'], 'Buy trade failed.'); console.log(`Buy hash - ${buy.txHash}`); - await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction + await sleep(60000); // sleep for 60 seconds to give some time for provider to see transaction let done = false; let tx1, tx2; + console.log(`Polling...`); while (!done) { tx1 = await request('post', '/eth/poll', { txHash: buy.txHash }); console.log(tx1); @@ -228,7 +233,8 @@ async function unitTests() { }); assert.hasAnyKeys(sell, ['txHash'], 'Sell trade failed.'); console.log(`Buy hash - ${sell.txHash}`); - await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction + await sleep(1000); // sleep for 1 second to give some time for provider to see transaction + console.log(`Polling...`); while (!done) { tx2 = await request('post', '/eth/poll', { txHash: sell.txHash }); console.log(tx2); From 7bd6a9f3819e305c37675037a6d070a49f6f1018 Mon Sep 17 00:00:00 2001 From: vic-en Date: Wed, 18 Aug 2021 20:41:29 +0100 Subject: [PATCH 20/43] fix poll response when transaction is yet to be indexed --- src/services/ethereum.ts | 29 +++++++++++++++++------------ tests/scripts/uniswap.v2.test.js | 2 -- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/services/ethereum.ts b/src/services/ethereum.ts index af01d77..adf1d5b 100644 --- a/src/services/ethereum.ts +++ b/src/services/ethereum.ts @@ -262,19 +262,24 @@ export class EthereumService { async getTransactionReceipt(txHash: string): Promise { const transaction = await this.provider.getTransactionReceipt(txHash); - let gasUsed; - if (transaction.gasUsed) { - gasUsed = transaction.gasUsed.toNumber(); - } else { - gasUsed = 0; + if (transaction) { + return { + gasUsed: transaction.gasUsed.toNumber() || 0, + blockNumber: transaction.blockNumber, + confirmations: transaction.confirmations, + status: transaction.status || 0, + logs: transaction.logs, + }; + } else { // transaction is yet to be indexed + return { + gasUsed: 0, + blockNumber: 0, + confirmations: 0, + status: 0, + logs: [], + }; } - return { - gasUsed: gasUsed, - blockNumber: transaction.blockNumber, - confirmations: transaction.confirmations, - status: transaction.status || 0, - logs: transaction.logs, - }; + } } diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index 12beed5..ebd1190 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -209,7 +209,6 @@ async function unitTests() { }); assert.hasAnyKeys(buy, ['txHash'], 'Buy trade failed.'); console.log(`Buy hash - ${buy.txHash}`); - await sleep(60000); // sleep for 60 seconds to give some time for provider to see transaction let done = false; let tx1, tx2; console.log(`Polling...`); @@ -233,7 +232,6 @@ async function unitTests() { }); assert.hasAnyKeys(sell, ['txHash'], 'Sell trade failed.'); console.log(`Buy hash - ${sell.txHash}`); - await sleep(1000); // sleep for 1 second to give some time for provider to see transaction console.log(`Polling...`); while (!done) { tx2 = await request('post', '/eth/poll', { txHash: sell.txHash }); From a90dd873339d59bacd0eb939c73f6704cecf1ee6 Mon Sep 17 00:00:00 2001 From: vic-en Date: Wed, 18 Aug 2021 20:48:20 +0100 Subject: [PATCH 21/43] modify test script to reset allowances on every run --- tests/scripts/uniswap.v2.test.js | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index ebd1190..f06b225 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -95,7 +95,7 @@ async function ethTests() { // call /allowances // confirm and save allowances - console.log('checking allowances...'); + console.log('checking initial allowances...'); const allowancesResponse1 = await request('post', '/eth/allowances', { tokenList: JSON.stringify(tokens), connector: 'uniswap', @@ -104,29 +104,27 @@ async function ethTests() { console.log(allowances); for (let token of tokens) { - if (parseFloat(allowances[token]) < 1000.0) { - // call /approve on each token - console.log(`Approving 5000 ${token}...`); - let approve1 = await request('post', '/eth/approve', { - token: token, + // call /approve on each token + console.log(`Resetting allowance for ${token} to 5000...`); + let approve1 = await request('post', '/eth/approve', { + token: token, + connector: 'uniswap', + amount: '5000', + }); + console.log(approve1); + while (allowances[token] !== approve1.amount) { + console.log( + 'Waiting for atleast 1 block time (i.e 13 secs) to give time for approval to be mined.' + ); + await sleep(13000); + // confirm that allowance changed correctly + console.log('Rechecking allowances to confirm approval...'); + let allowancesResponse2 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), connector: 'uniswap', - amount: '5000', }); - console.log(approve1); - while (allowances[token] !== approve1.amount) { - console.log( - 'Waiting for atleast 1 block time to give time for approval to be mined.' - ); - await sleep(13000); - // confirm that allowance changed correctly - console.log('Rechecking allowances to confirm approval...'); - let allowancesResponse2 = await request('post', '/eth/allowances', { - tokenList: JSON.stringify(tokens), - connector: 'uniswap', - }); - allowances = allowancesResponse2.approvals; - console.log(allowances); - } + allowances = allowancesResponse2.approvals; + console.log(allowances); } } From 464743e99bc68654c466aac2dc63b7b4bcf1e962 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Wed, 18 Aug 2021 14:18:49 -0700 Subject: [PATCH 22/43] fix linting --- src/services/ethereum.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/services/ethereum.ts b/src/services/ethereum.ts index adf1d5b..bf0b833 100644 --- a/src/services/ethereum.ts +++ b/src/services/ethereum.ts @@ -270,7 +270,8 @@ export class EthereumService { status: transaction.status || 0, logs: transaction.logs, }; - } else { // transaction is yet to be indexed + } else { + // transaction is yet to be indexed return { gasUsed: 0, blockNumber: 0, @@ -279,7 +280,5 @@ export class EthereumService { logs: [], }; } - - } } From aef4aba5e59a84246b5a9febc8a15ca5df8105f5 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Wed, 18 Aug 2021 15:43:02 -0700 Subject: [PATCH 23/43] removed types from ethreceipt and deleted toNumber() --- src/services/ethereum.ts | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/services/ethereum.ts b/src/services/ethereum.ts index bf0b833..5feed38 100644 --- a/src/services/ethereum.ts +++ b/src/services/ethereum.ts @@ -3,6 +3,7 @@ import abi from '../assets/abi.json'; import { BigNumber, Contract, providers, Wallet } from 'ethers'; import { EthereumConfigService } from './ethereum_config'; import { default as kovanErc20TokenList } from '../assets/erc20_tokens_kovan.json'; +import { logger } from '../services/logger'; export enum GasStationLevel { FAST = 'fast', @@ -21,13 +22,13 @@ export enum Network { ROPSTEN = 'ropsten', } -export interface EthTransactionReceipt { - gasUsed: number; - blockNumber: number; - confirmations: number; - status: number; - logs: Array; -} +// export interface EthTransactionReceipt { +// gasUsed: number; +// blockNumber: number; +// confirmations: number; +// status: number; +// logs: Array; +// } export interface TokenERC20Info { symbol: string; @@ -40,12 +41,12 @@ export interface ERC20TokensList { tokens: TokenERC20Info[]; } -export interface EthTransactionReceipt { - gasUsed: number; - blockNumber: number; - confirmations: number; - status: number; -} +// export interface EthTransactionReceipt { +// gasUsed: number; +// blockNumber: number; +// confirmations: number; +// status: number; +// } const stringInsert = (str: string, val: string, index: number) => { if (index > 0) { @@ -259,12 +260,12 @@ export class EthereumService { * @param {string} txHash * @return {Promise} */ - async getTransactionReceipt(txHash: string): Promise { + async getTransactionReceipt(txHash: string): Promise { const transaction = await this.provider.getTransactionReceipt(txHash); - + logger.info(transaction); if (transaction) { return { - gasUsed: transaction.gasUsed.toNumber() || 0, + gasUsed: transaction.gasUsed || 0, blockNumber: transaction.blockNumber, confirmations: transaction.confirmations, status: transaction.status || 0, From 81a65d858c4e00f5a6c544522447d3b28e6c79e3 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Wed, 18 Aug 2021 16:30:57 -0700 Subject: [PATCH 24/43] increase default uniswap gas limit --- src/services/ethereum.ts | 2 +- src/services/uniswap.js | 2 +- tests/scripts/uniswap.v2.test.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/ethereum.ts b/src/services/ethereum.ts index 5feed38..c3bace3 100644 --- a/src/services/ethereum.ts +++ b/src/services/ethereum.ts @@ -258,7 +258,7 @@ export class EthereumService { /** * Get transaction receipt for a transaction hash. * @param {string} txHash - * @return {Promise} + * @return {Promise} */ async getTransactionReceipt(txHash: string): Promise { const transaction = await this.provider.getTransactionReceipt(txHash); diff --git a/src/services/uniswap.js b/src/services/uniswap.js index 1f7bc00..307e54f 100644 --- a/src/services/uniswap.js +++ b/src/services/uniswap.js @@ -11,7 +11,7 @@ const globalConfig = // constants const ROUTER = globalConfig.getConfig('UNISWAP_ROUTER'); -const GAS_LIMIT = globalConfig.getConfig('UNISWAP_GAS_LIMIT') || 150688; +const GAS_LIMIT = globalConfig.getConfig('UNISWAP_GAS_LIMIT') || 200688; const TTL = globalConfig.getConfig('UNISWAP_TTL') || 300; const UPDATE_PERIOD = globalConfig.getConfig('UNISWAP_UPDATE_PERIOD') || 300000; // stop updating pair after 5 minutes from last request diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index f06b225..b924742 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -264,6 +264,6 @@ async function unitTests() { } (async () => { - await ethTests(); + // await ethTests(); await unitTests(); })(); From c1dc6f0736b622dd5d1aa239a7fadbf6b8f6b64a Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Wed, 18 Aug 2021 17:13:20 -0700 Subject: [PATCH 25/43] revert merge to development --- Dockerfile | 5 +- package.json | 1 - src/assets/erc20_tokens_kovan.json | 39 ++--- src/routes/ethereum.ts | 79 +++++---- src/routes/uniswap.ts | 237 ++++++++++++++++++--------- src/routes/uniswap_v3.ts | 14 +- src/services/ethereum.ts | 24 +-- src/services/ethereum_gas.ts | 2 +- src/services/uniswap.js | 226 +++++++++++++++++++++---- src/services/uniswap_v3.js | 10 +- src/static/uniswap_route_tokens.json | 8 +- tests/example-test.js | 63 ------- 12 files changed, 446 insertions(+), 262 deletions(-) delete mode 100644 tests/example-test.js diff --git a/Dockerfile b/Dockerfile index a8d197c..d2b9585 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,7 @@ -FROM node:12.13.0 +FROM node:12.13.0-alpine + +# Add timezone database +RUN apk add --no-cache tzdata # Set labels LABEL application="gateway-api" diff --git a/package.json b/package.json index e4ee14c..08e9968 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "main": "index.js", "license": "Apache 2", "repository": "https://github.com/coinalpha/gateway-api", - "type": "module", "scripts": { "prebuild": "rimraf dist && mkdir dist", "build": "tsc --project ./", diff --git a/src/assets/erc20_tokens_kovan.json b/src/assets/erc20_tokens_kovan.json index 7f6c96e..44bd5d7 100644 --- a/src/assets/erc20_tokens_kovan.json +++ b/src/assets/erc20_tokens_kovan.json @@ -4,80 +4,67 @@ { "symbol": "BAT", "address": "0x1f1f156E0317167c11Aa412E3d1435ea29Dc3cCE", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "WETH", "address": "0xd0A1E359811322d97991E03f863a0C30C2cF029C", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "DAI", "address": "0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "MKR", "address": "0xef13C0c8abcaf5767160018d268f9697aE4f5375", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "USDC", "address": "0x2F375e94FC336Cdec2Dc0cCB5277FE59CBf1cAe5", - "decimals": 6, - "chainId": 42 + "decimals": 6 }, { "symbol": "REP", "address": "0x8c9e6c40d3402480ACE624730524fACC5482798c", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "WBTC", "address": "0xe0C9275E44Ea80eF17579d33c55136b7DA269aEb", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "SNX", "address": "0x86436BcE20258a6DcfE48C9512d4d49A30C4d8c4", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "ANT", "address": "0x37f03a12241E9FD3658ad6777d289c3fb8512Bc9", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "ZRX", "address": "0xccb0F4Cf5D3F97f4a55bb5f5cA321C3ED033f244", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "COIN1", "address": "0x809F5A762e7b0CC75C42cd76098b85CB7BD2BA64", - "decimals": 18, - "chainId": 42 + "decimals": 18 }, { "symbol": "COIN2", "address": "0x9866c4043bc6cf47eaf845c56f6ab221c204e0df", - "decimals": 8, - "chainId": 42 + "decimals": 8 }, { "symbol": "COIN3", "address": "0x3D2097889B97A9eF23B3eA8FC10c626fbda29099", - "decimals": 18, - "chainId": 42 + "decimals": 18 } ] } diff --git a/src/routes/ethereum.ts b/src/routes/ethereum.ts index 1764dc8..f1a2fd6 100644 --- a/src/routes/ethereum.ts +++ b/src/routes/ethereum.ts @@ -39,24 +39,34 @@ router.post('/balances', async (req: Request, res: Response) => { // Trying connect to Wallet try { - const wallet = ethereumService.getWallet(req.body.privateKey); + const wallet: ethers.Wallet = ethereumService.getWallet( + req.body.privateKey || '' + ); // Populate token contract info using token symbol list - const tokenList: Record = {}; + const tokenContractList: Record = {}; + for (const symbol of JSON.parse(req.body.tokenList)) { - const token = ethereumService.getERC20Token(symbol) as TokenERC20Info; - tokenList[symbol] = token; + const tokenContractInfo = ethereumService.getERC20TokenAddress(symbol); + if (!tokenContractInfo) { + continue; + } + + tokenContractList[symbol] = tokenContractInfo; } + // Getting user balancers const balances: Record = {}; balances.ETH = await ethereumService.getETHBalance(wallet); await Promise.all( - Object.keys(tokenList).map(async (symbol) => { - if (tokenList[symbol] !== undefined) { + Object.keys(tokenContractList).map(async (symbol) => { + if (tokenContractList[symbol] !== undefined) { + const address = tokenContractList[symbol].address; + const decimals = tokenContractList[symbol].decimals; balances[symbol] = await ethereumService.getERC20Balance( wallet, - tokenList[symbol].address, - tokenList[symbol].decimals + address, + decimals ); } else { logger.error(`Token contract info for ${symbol} not found`); @@ -84,26 +94,30 @@ router.post('/allowances', async (req: Request, res: Response) => { res.status(500).send('Wrong connector'); } - // Trying connect to Wallet + // Getting Wallet try { const wallet = ethereumService.getWallet(req.body.privateKey); - // Populate token contract info using token symbol list - const tokenList: Record = {}; + const tokenContractList: Record = {}; for (const symbol of JSON.parse(req.body.tokenList)) { - const token = ethereumService.getERC20Token(symbol) as TokenERC20Info; - tokenList[symbol] = token; - } + const tokenContractInfo = ethereumService.getERC20TokenAddress(symbol); + if (!tokenContractInfo) { + continue; + } + tokenContractList[symbol] = tokenContractInfo; + } const approvals: Record = {}; await Promise.all( - Object.keys(tokenList).map(async (symbol) => { + Object.keys(tokenContractList).map(async (symbol) => { + const address = tokenContractList[symbol].address; + const decimals = tokenContractList[symbol].decimals; try { approvals[symbol] = await ethereumService.getERC20Allowance( wallet, spender, - tokenList[symbol].address, - tokenList[symbol].decimals + address, + decimals ); } catch (err) { logger.error(err); @@ -139,21 +153,33 @@ router.post('/approve', async (req: Request, res: Response) => { const wallet = ethereumService.getWallet(req.body.privateKey); // Getting token info - const token = ethereumService.getERC20Token(req.body.token); + const tokenContractInfo = ethereumService.getERC20TokenAddress( + req.body.token + ); - if (!token) { + if (!tokenContractInfo) { res.status(500).send(`Token "${req.body.token}" is not supported`); } else { - const amount = ethers.utils.parseUnits(req.body.amount, token.decimals); + const tokenAddress = tokenContractInfo.address; + // const gasPrice = req.body.gasPrice || ethereumGasService.getGasPrice(); + const gasPrice = req.body.gasPrice || fees.ethGasPrice; + + let amount = ethers.constants.MaxUint256; + if (req.body.amount) { + amount = ethers.utils.parseUnits( + req.body.amount, + tokenContractInfo.decimals + ); + } // call approve function let approval; try { approval = await ethereumService.approveERC20( wallet, spender, - token.address, + tokenAddress, amount, - fees.ethGasPrice as number + gasPrice ); } catch (err) { approval = err; @@ -163,9 +189,9 @@ router.post('/approve', async (req: Request, res: Response) => { network: config.networkName, timestamp: initTime, latency: latency(initTime, Date.now()), - tokenAddress: token.address, + tokenAddress: tokenAddress, spender: spender, - amount: bigNumberWithDecimalToStr(amount, token.decimals), + amount: bigNumberWithDecimalToStr(amount, tokenContractInfo.decimals), approval: approval, }); } @@ -190,9 +216,4 @@ router.post('/poll', async (req: Request, res: Response) => { }); }); -router.post('/token', async (req: Request, res: Response) => { - const token = await ethereumService.getERC20Token(req.body.symbol); - res.status(200).json(token); -}); - export default router; diff --git a/src/routes/uniswap.ts b/src/routes/uniswap.ts index 0980ae2..07c400c 100644 --- a/src/routes/uniswap.ts +++ b/src/routes/uniswap.ts @@ -9,18 +9,28 @@ import { EthereumService } from '../services/ethereum'; import { EthereumConfigService } from '../services/ethereum_config'; import Uniswap from '../services/uniswap'; -import { EthereumGasService } from '../services/ethereum_gas'; +import Fees from '../services/fees'; const debug = require('debug')('router'); const router = express.Router(); +const globalConfig = + require('../services/configuration_manager').configManagerInstance; + const ethConfig = new EthereumConfigService(); const eth = new EthereumService(ethConfig); -const uniswap = new Uniswap(); -const fees = new EthereumGasService(ethConfig); + +const uniswap = new Uniswap(globalConfig.getConfig('ETHEREUM_CHAIN')); +uniswap.generate_tokens(); +setTimeout(uniswap.update_pairs.bind(uniswap), 2000); +const fees = new Fees(); const swapMoreThanMaxPriceError = 'Price too high'; const swapLessThanMaxPriceError = 'Price too low'; +const estimateGasLimit = () => { + return uniswap.gasLimit; +}; + const getErrorMessage = (err: string) => { /* [WIP] Custom error message based-on string match @@ -51,15 +61,29 @@ router.post('/', async (_req: Request, res: Response) => { }); }); -router.post('/gas-limit', async (_req: Request, res: Response) => { +router.post('/gas-limit', async (req: Request, res: Response) => { /* POST: /gas-limit */ - res.status(200).json({ - network: uniswap.network, - gasLimit: uniswap.gasLimit, - timestamp: Date.now(), - }); + const gasLimit = estimateGasLimit(); + + try { + res.status(200).json({ + network: uniswap.network, + gasLimit: gasLimit, + timestamp: Date.now(), + }); + } catch (err) { + logger.error(req.originalUrl, { message: err }); + let reason; + err.reason + ? (reason = err.reason) + : (reason = statusMessages.operation_error); + res.status(500).json({ + error: reason, + message: err, + }); + } }); router.get('/start', async (req: Request, res: Response) => { @@ -68,35 +92,63 @@ router.get('/start', async (req: Request, res: Response) => { */ const initTime = Date.now(); - // get token contract address and cache paths - const pairs = JSON.parse(req.query.pairs as string); - for (let pair of pairs) { - pair = pair.split('-'); - const baseToken = eth.getERC20Token(pair[0]); - const quoteToken = eth.getERC20Token(pair[1]); + if (typeof req.query.pairs === 'string') { + const pairs = JSON.parse(req.query.pairs); + let gasPrice; + if (typeof req.query.gasPrice === 'string') { + gasPrice = parseFloat(req.query.gasPrice); + } else { + gasPrice = fees.ethGasPrice; + } - // check for valid token symbols - if (baseToken === undefined || quoteToken === undefined) { - const undefinedToken = baseToken === undefined ? pair[0] : pair[1]; - res.status(500).json({ - error: `Token ${undefinedToken} contract address not found`, - message: `Token contract address not found for ${undefinedToken}. Check token list source`, - }); - return; + // get token contract address and cache paths + for (let pair of pairs) { + pair = pair.split('-'); + const baseTokenSymbol = pair[0]; + const quoteTokenSymbol = pair[1]; + const baseTokenContractInfo = eth.getERC20TokenAddress(baseTokenSymbol); + const quoteTokenContractInfo = eth.getERC20TokenAddress(quoteTokenSymbol); + + // check for valid token symbols + if ( + baseTokenContractInfo === undefined || + quoteTokenContractInfo === undefined + ) { + const undefinedToken = + baseTokenContractInfo === undefined + ? baseTokenSymbol + : quoteTokenSymbol; + res.status(500).json({ + error: `Token ${undefinedToken} contract address not found`, + message: `Token contract address not found for ${undefinedToken}. Check token list source`, + }); + return; + } + await Promise.allSettled([ + uniswap.extend_update_pairs([ + baseTokenContractInfo.address, + quoteTokenContractInfo.address, + ]), + ]); } + + const gasLimit = estimateGasLimit(); + const gasCost = await fees.getGasCost(gasPrice, gasLimit); + + const result = { + network: eth.networkName, + timestamp: initTime, + latency: latency(initTime, Date.now()), + success: true, + pairs: pairs, + gasPrice: gasPrice, + gasLimit: gasLimit, + gasCost: gasCost, + }; + res.status(200).json(result); + } else { + res.status(500).json({ err: 'error in pair type' }); } - const gasCost = await fees.getGasCost(uniswap.gasLimit); - const result = { - network: eth.networkName, - timestamp: initTime, - latency: latency(initTime, Date.now()), - success: true, - pairs: pairs, - gasPrice: fees.getGasPrice(), - gasLimit: uniswap.gasLimit, - gasCost: gasCost, - }; - res.status(200).json(result); }); router.post('/trade', async (req: Request, res: Response) => { @@ -106,62 +158,78 @@ router.post('/trade', async (req: Request, res: Response) => { "quote":"BAT" "base":"DAI" "amount":0.1 - "limitPrice?":1 + "limitPrice":1 + "gasPrice":10 "privateKey":{{privateKey}} "side":{buy|sell} } */ const initTime = Date.now(); + // params: privateKey (required), base (required), quote (required), amount (required), maxPrice (required), gasPrice (required) const privateKey = req.body.privateKey; const wallet = new ethers.Wallet(privateKey, uniswap.provider); const amount = req.body.amount; - const baseToken = eth.getERC20Token(req.body.base); - const quoteToken = eth.getERC20Token(req.body.quote); + const baseTokenContractInfo = eth.getERC20TokenAddress(req.body.base); + const quoteTokenContractInfo = eth.getERC20TokenAddress(req.body.quote); - if (baseToken && quoteToken) { + if (baseTokenContractInfo && quoteTokenContractInfo) { + const baseTokenAddress = baseTokenContractInfo.address; + const quoteTokenAddress = quoteTokenContractInfo.address; const side = req.body.side.toUpperCase(); - const limitPrice = req.body.limitPrice || null; - const gasCost = await fees.getGasCost(uniswap.gasLimit); + + let limitPrice; + if (req.body.limitPrice) { + limitPrice = parseFloat(req.body.limitPrice); + } + let gasPrice; + if (req.body.gasPrice) { + gasPrice = parseFloat(req.body.gasPrice); + } else { + gasPrice = fees.ethGasPrice; + } + const gasLimit = estimateGasLimit(); + const gasCost = await fees.getGasCost(gasPrice, gasLimit); + try { // fetch the optimal pool mix from uniswap const result: any = side === 'BUY' ? await uniswap.priceSwapOut( - quoteToken, // tokenIn is quote asset - baseToken, // tokenOut is base asset + quoteTokenAddress, // tokenIn is quote asset + baseTokenAddress, // tokenOut is base asset amount ) : await uniswap.priceSwapIn( - baseToken, // tokenIn is base asset - quoteToken, // tokenOut is quote asset + baseTokenAddress, // tokenIn is base asset + quoteTokenAddress, // tokenOut is quote asset amount ); if (result && result.trade && result.expectedAmount) { const trade = result.trade; const expectedAmount = result.expectedAmount; if (side === 'BUY') { - const price = trade.executionPrice.invert().toFixed(8); + const price = trade.executionPrice.invert().toSignificant(8); if (!limitPrice || price <= limitPrice) { // pass swaps to exchange-proxy to complete trade const tx = await uniswap.swapExactOut( wallet, trade, - baseToken.address, - fees.getGasPrice() + baseTokenAddress, + gasPrice ); // submit response res.status(200).json({ network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), - base: baseToken.address, - quote: quoteToken.address, + base: baseTokenAddress, + quote: quoteTokenAddress, amount: amount, - expectedIn: expectedAmount.toFixed(8), + expectedIn: expectedAmount.toSignificant(8), price: price, - gasPrice: fees.getGasPrice(), - gasLimit: uniswap.gasLimit, + gasPrice: gasPrice, + gasLimit, gasCost, txHash: tx.hash, }); @@ -176,28 +244,28 @@ router.post('/trade', async (req: Request, res: Response) => { } } else { // sell - const price = trade.executionPrice.toFixed(8); + const price = trade.executionPrice.toSignificant(8); logger.info(`Price: ${price.toString()}`); if (!limitPrice || price >= limitPrice) { // pass swaps to exchange-proxy to complete trade const tx = await uniswap.swapExactIn( wallet, trade, - baseToken.address, - fees.getGasPrice() + baseTokenAddress, + gasPrice ); // submit response res.status(200).json({ network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), - base: baseToken.address, - quote: quoteToken.address, + base: baseTokenAddress, + quote: quoteTokenAddress, amount: parseFloat(req.body.amount), - expectedOut: expectedAmount.toFixed(8), + expectedOut: expectedAmount.toSignificant(8), price: parseFloat(price), - gasPrice: fees.getGasPrice(), - gasLimit: uniswap.gasLimit, + gasPrice: gasPrice, + gasLimit, gasCost: gasCost, txHash: tx.hash, }); @@ -241,28 +309,39 @@ router.post('/price', async (req: Request, res: Response) => { "quote":"BAT" "base":"DAI" "amount":1 - "side":"buy" } */ const initTime = Date.now(); + // params: base (required), quote (required), amount (required) const amount = req.body.amount; - const baseToken = eth.getERC20Token(req.body.base); - const quoteToken = eth.getERC20Token(req.body.quote); - if (baseToken && quoteToken) { + + const baseTokenContractInfo = eth.getERC20TokenAddress(req.body.base); + const quoteTokenContractInfo = eth.getERC20TokenAddress(req.body.quote); + if (baseTokenContractInfo && quoteTokenContractInfo) { + const baseTokenAddress = baseTokenContractInfo.address; + const quoteTokenAddress = quoteTokenContractInfo.address; const side = req.body.side.toUpperCase(); - const gasCost = await fees.getGasCost(uniswap.gasLimit); + let gasPrice; + if (req.body.gasPrice) { + gasPrice = parseFloat(req.body.gasPrice); + } else { + gasPrice = fees.ethGasPrice; + } + const gasLimit = estimateGasLimit(); + const gasCost = await fees.getGasCost(gasPrice, gasLimit); try { + // fetch the optimal pool mix from uniswap const result: any = side === 'BUY' ? await uniswap.priceSwapOut( - quoteToken, // tokenIn is quote asset - baseToken, // tokenOut is base asset + quoteTokenAddress, // tokenIn is quote asset + baseTokenAddress, // tokenOut is base asset amount ) : await uniswap.priceSwapIn( - baseToken, // tokenIn is base asset - quoteToken, // tokenOut is quote asset + baseTokenAddress, // tokenIn is base asset + quoteTokenAddress, // tokenOut is quote asset amount ); if (result && result.trade && result.expectedAmount) { @@ -272,29 +351,31 @@ router.post('/price', async (req: Request, res: Response) => { if (trade !== null && expectedAmount !== null) { const price = side === 'BUY' - ? trade.executionPrice.invert().toFixed(8) - : trade.executionPrice.toFixed(8); + ? trade.executionPrice.invert().toSignificant(8) + : trade.executionPrice.toSignificant(8); const tradeAmount = parseFloat(amount); - const expectedTradeAmount = parseFloat(expectedAmount.toFixed(8)); + const expectedTradeAmount = parseFloat( + expectedAmount.toSignificant(8) + ); const tradePrice = parseFloat(price); const result = { network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), - base: baseToken.address, - quote: quoteToken.address, + base: baseTokenAddress, + quote: quoteTokenAddress, amount: tradeAmount, expectedAmount: expectedTradeAmount, price: tradePrice, - gasPrice: fees.getGasPrice(), - gasLimit: uniswap.gasLimit, + gasPrice: gasPrice, + gasLimit: gasLimit, gasCost: gasCost, trade: trade, }; debug( - `Price ${side} ${baseToken.symbol}-${quoteToken.symbol} | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${uniswap.gasLimit} estimated fee:${gasCost} ETH` + `Price ${side} ${baseTokenContractInfo.symbol}-${quoteTokenContractInfo.symbol} | amount:${amount} (rate:${tradePrice}) - gasPrice:${gasPrice} gasLimit:${gasLimit} estimated fee:${gasCost} ETH` ); res.status(200).json(result); } else { diff --git a/src/routes/uniswap_v3.ts b/src/routes/uniswap_v3.ts index b421534..3d8c723 100644 --- a/src/routes/uniswap_v3.ts +++ b/src/routes/uniswap_v3.ts @@ -250,7 +250,7 @@ router.post('/trade', async (req: Request, res: Response) => { ); if (side === 'BUY') { - const price = trade.executionPrice.invert().toFixed(8); + const price = trade.executionPrice.invert().toSignificant(8); logger.info(`uniswap.route - Price: ${price.toString()}`); if (!limitPrice || price <= limitPrice) { // pass swaps to exchange-proxy to complete trade @@ -268,7 +268,7 @@ router.post('/trade', async (req: Request, res: Response) => { base: baseTokenAddress, quote: quoteTokenAddress, amount: amount, - expectedIn: expectedAmount.toFixed(8), + expectedIn: expectedAmount.toSignificant(8), price: price, gasPrice: gasPrice, gasLimit, @@ -286,7 +286,7 @@ router.post('/trade', async (req: Request, res: Response) => { } } else { // sell - const price = trade.executionPrice.toFixed(8); + const price = trade.executionPrice.toSignificant(8); logger.info(`Price: ${price.toString()}`); if (!limitPrice || price >= limitPrice) { // pass swaps to exchange-proxy to complete trade @@ -304,7 +304,7 @@ router.post('/trade', async (req: Request, res: Response) => { base: baseTokenAddress, quote: quoteTokenAddress, amount: parseFloat(req.body.amount), - expectedOut: expectedAmount.toFixed(8), + expectedOut: expectedAmount.toSignificant(8), price: parseFloat(price), gasPrice: gasPrice, gasLimit, @@ -389,13 +389,13 @@ router.post('/price', async (req: Request, res: Response) => { if (trade !== null && expectedAmount !== null) { price = side === 'BUY' - ? trade.executionPrice.invert().toFixed(8) - : trade.executionPrice.toFixed(8); + ? trade.executionPrice.invert().toSignificant(8) + : trade.executionPrice.toSignificant(8); priceResult = { price: parseFloat(price), amount: parseFloat(amount), - expectedAmount: parseFloat(expectedAmount.toFixed(8)), + expectedAmount: parseFloat(expectedAmount.toSignificant(8)), }; } } else { diff --git a/src/services/ethereum.ts b/src/services/ethereum.ts index 94d0a00..c3bace3 100644 --- a/src/services/ethereum.ts +++ b/src/services/ethereum.ts @@ -34,7 +34,6 @@ export interface TokenERC20Info { symbol: string; address: string; decimals: number; - chainId: number; } export interface ERC20TokensList { @@ -74,20 +73,21 @@ export const bigNumberWithDecimalToStr = (n: BigNumber, d: number): string => { export class EthereumService { private readonly provider = new providers.JsonRpcProvider(this.config.rpcUrl); - private chainId = 1; private erc20TokenList: ERC20TokensList | null = null; constructor(private readonly config: EthereumConfigService) { switch (this.config.networkName) { case Network.KOVAN: - this.chainId = 42; this.erc20TokenList = kovanErc20TokenList; break; - default: // MAINNET + + case Network.MAINNET: { (async () => { const { data } = await axios.get(this.config.tokenListUrl); this.erc20TokenList = data; })(); + break; + } } } @@ -214,22 +214,6 @@ export class EthereumService { } } - /** - * Get ERC20 token - * @param {string} tokenSymbol - * @return {TokenERC20Info} | null - */ - getERC20Token(symbol: string): TokenERC20Info | undefined { - if (this.erc20TokenList) { - const token = this.erc20TokenList.tokens.find( - (obj) => - obj.symbol === symbol.toUpperCase() && obj.chainId === this.chainId - ); - return token; - } - return; - } - /** * Get ERC20 token address * @param {string} tokenSymbol diff --git a/src/services/ethereum_gas.ts b/src/services/ethereum_gas.ts index 8fff24e..631d278 100644 --- a/src/services/ethereum_gas.ts +++ b/src/services/ethereum_gas.ts @@ -91,7 +91,7 @@ export class EthereumGasService { getGasCost(gasLimit: number, inGwei = false): ethers.BigNumber { const cost = ethers.BigNumber.from(this.gasPrice * gasLimit); - const denom = ethers.BigNumber.from('1000000000'); + const denom = ethers.BigNumber.from(BigInt('1e+9')); return inGwei ? cost : cost.div(denom); } diff --git a/src/services/uniswap.js b/src/services/uniswap.js index 4b59185..307e54f 100644 --- a/src/services/uniswap.js +++ b/src/services/uniswap.js @@ -1,21 +1,22 @@ -import { unit } from 'mathjs'; -import { debug } from 'winston'; import { logger } from './logger'; +const debug = require('debug')('router'); const math = require('mathjs'); const uni = require('@uniswap/sdk'); const ethers = require('ethers'); const proxyArtifact = require('../static/uniswap_v2_router_abi.json'); +const routeTokens = require('../static/uniswap_route_tokens.json'); const globalConfig = require('../services/configuration_manager').configManagerInstance; // constants -const ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; -const GAS_LIMIT = 200688; -const TTL = 300; +const ROUTER = globalConfig.getConfig('UNISWAP_ROUTER'); +const GAS_LIMIT = globalConfig.getConfig('UNISWAP_GAS_LIMIT') || 200688; +const TTL = globalConfig.getConfig('UNISWAP_TTL') || 300; +const UPDATE_PERIOD = globalConfig.getConfig('UNISWAP_UPDATE_PERIOD') || 300000; // stop updating pair after 5 minutes from last request export default class Uniswap { - constructor() { + constructor(network = 'mainnet') { this.providerUrl = globalConfig.getConfig('ETHEREUM_RPC_URL'); this.network = globalConfig.getConfig('ETHEREUM_CHAIN'); this.provider = new ethers.providers.JsonRpcProvider(this.providerUrl); @@ -27,38 +28,203 @@ export default class Uniswap { this.slippage.n, this.slippage.d * 100 ); + this.pairsCacheTime = globalConfig.getConfig('UNISWAP_PAIRS_CACHE_TIME'); this.gasLimit = GAS_LIMIT; + this.expireTokenPairUpdate = UPDATE_PERIOD; + this.zeroReserveCheckInterval = globalConfig.getConfig( + 'UNISWAP_NO_RESERVE_CHECK_INTERVAL' + ); + this.zeroReservePairs = {}; // No reserve pairs + this.tokenList = {}; + this.pairs = []; + this.tokenSwapList = {}; + this.cachedRoutes = {}; + + switch (network) { + case 'mainnet': + this.chainID = uni.ChainId.MAINNET; + break; + case 'kovan': + this.chainID = uni.ChainId.KOVAN; + break; + default: { + const err = `Invalid network ${network}`; + logger.error(err); + throw Error(err); + } + } + } + + async fetch_route(tIn, tOut) { + var route, pair; + + try { + pair = await uni.Fetcher.fetchPairData(tIn, tOut); + route = new uni.Route([pair], tIn, tOut); + } catch (err) { + logger.error(err); + } + return route; + } + + generate_tokens() { + for (let token of routeTokens[this.network]) { + this.tokenList[token['address']] = new uni.Token( + this.chainID, + token['address'], + token['decimals'], + token['symbol'], + token['name'] + ); + } + } + + async extend_update_pairs(tokens = []) { + for (let token of tokens) { + if (!Object.prototype.hasOwnProperty.call(this.tokenList, token)) { + this.tokenList[token] = await uni.Fetcher.fetchTokenData( + this.chainID, + token + ); + } + this.tokenSwapList[token] = Date.now() + this.expireTokenPairUpdate; + } } - getUniswapToken = (token) => - new uni.Token(token.chainId, token.address, token.decimals); + async update_pairs() { + // Remove banned pairs after ban period + if (Object.keys(this.zeroReservePairs).length > 0) { + for (let pair in this.zeroReservePairs) { + if (this.zeroReservePairs[pair] <= Date.now()) { + delete this.zeroReservePairs[pair]; + // delete this.tokenList[token]; + } + } + } + // Generate all possible pair combinations of tokens + // This is done by generating an upper triangular matrix or right triangular matrix + if (Object.keys(this.tokenSwapList).length > 0) { + for (let token in this.tokenSwapList) { + if (this.tokenSwapList[token] <= Date.now()) { + delete this.tokenSwapList[token]; + // delete this.tokenList[token]; + } + } + + let tokens = Object.keys(this.tokenList); + var firstToken, secondToken, position; + let length = tokens.length; + let pairs = []; + let pairAddressRequests = []; + let pairAddressResponses = []; + for (firstToken = 0; firstToken < length; firstToken++) { + for ( + secondToken = firstToken + 1; + secondToken < length; + secondToken++ + ) { + try { + let pairString = + this.tokenList[tokens[firstToken]].address + + '-' + + this.tokenList[tokens[secondToken]].address; + if ( + !Object.prototype.hasOwnProperty.call( + this.zeroReservePairs, + pairString + ) + ) { + pairs.push(pairString); + pairAddressRequests.push( + uni.Fetcher.fetchPairData( + this.tokenList[tokens[firstToken]], + this.tokenList[tokens[secondToken]] + ) + ); + } + } catch (err) { + logger.error(err); + } + } + } + + await Promise.allSettled(pairAddressRequests).then((values) => { + for (position = 0; position < pairAddressRequests.length; position++) { + if (values[position].status === 'fulfilled') { + pairAddressResponses.push(values[position].value); + } else { + this.zeroReservePairs[pairs[position]] = + Date.now() + this.zeroReserveCheckInterval; + } + } + }); + this.pairs = pairAddressResponses; + } + setTimeout(this.update_pairs.bind(this), 1000); + } - async priceSwapIn(tIn, tOut, tokenInAmount) { - const tokenIn = this.getUniswapToken(tIn); - const tokenOut = this.getUniswapToken(tOut); - const amountIn = new uni.TokenAmount( - tokenIn, - ethers.utils.parseUnits(tokenInAmount, tokenIn.decimals) + async priceSwapIn(tokenIn, tokenOut, tokenInAmount) { + await this.extend_update_pairs([tokenIn, tokenOut]); + const tIn = this.tokenList[tokenIn]; + const tOut = this.tokenList[tokenOut]; + const tokenAmountIn = new uni.TokenAmount( + tIn, + ethers.utils.parseUnits(tokenInAmount, tIn.decimals) ); - const pair = await uni.Fetcher.fetchPairData(tokenIn, tokenOut); - const route = new uni.Route([pair], tokenIn); - const trade = new uni.Trade(route, amountIn, uni.TradeType.EXACT_INPUT); - logger.info(`Trade: ${trade}`); + if (this.pairs.length === 0) { + const route = await this.fetch_route(tIn, tOut); + const trade = uni.Trade.exactIn(route, tokenAmountIn); + if (trade !== undefined) { + const expectedAmount = trade.minimumAmountOut(this.allowedSlippage); + this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; + return { trade, expectedAmount }; + } + return "Can't find route to swap, kindly update "; + } + let trade = uni.Trade.bestTradeExactIn( + this.pairs, + tokenAmountIn, + this.tokenList[tokenOut], + { maxHops: 5 } + )[0]; + if (trade === undefined) { + trade = this.cachedRoutes[tIn.symbol + tOut.Symbol]; + } else { + this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; + } const expectedAmount = trade.minimumAmountOut(this.allowedSlippage); return { trade, expectedAmount }; } - async priceSwapOut(tIn, tOut, tokenOutAmount) { - const tokenIn = this.getUniswapToken(tIn); - const tokenOut = this.getUniswapToken(tOut); - const amountOut = new uni.TokenAmount( - tokenOut, - ethers.utils.parseUnits(tokenOutAmount, tokenOut.decimals) + async priceSwapOut(tokenIn, tokenOut, tokenOutAmount) { + await this.extend_update_pairs([tokenIn, tokenOut]); + const tOut = this.tokenList[tokenOut]; + const tIn = this.tokenList[tokenIn]; + const tokenAmountOut = new uni.TokenAmount( + tOut, + ethers.utils.parseUnits(tokenOutAmount, tOut.decimals) ); - const pair = await uni.Fetcher.fetchPairData(tokenIn, tokenOut); - const route = new uni.Route([pair], tokenIn); - const trade = new uni.Trade(route, amountOut, uni.TradeType.EXACT_OUTPUT); - logger.info(`Trade: ${trade}`); + if (this.pairs.length === 0) { + const route = await this.fetch_route(tIn, tOut); + const trade = uni.Trade.exactOut(route, tokenAmountOut); + if (trade !== undefined) { + const expectedAmount = trade.maximumAmountIn(this.allowedSlippage); + this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; + return { trade, expectedAmount }; + } + return; + } + let trade = uni.Trade.bestTradeExactOut( + this.pairs, + this.tokenList[tokenIn], + tokenAmountOut, + { maxHops: 5 } + )[0]; + if (trade === undefined) { + trade = this.cachedRoutes[tIn.symbol + tOut.Symbol]; + } else { + this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; + } const expectedAmount = trade.maximumAmountIn(this.allowedSlippage); return { trade, expectedAmount }; } @@ -81,7 +247,7 @@ export default class Uniswap { value: result.value, }); - logger.info(`Tx Hash: ${tx.hash}`); + debug(`Tx Hash: ${tx.hash}`); return tx; } @@ -103,7 +269,7 @@ export default class Uniswap { value: result.value, }); - logger.info(`Tx Hash: ${tx.hash}`); + debug(`Tx Hash: ${tx.hash}`); return tx; } } diff --git a/src/services/uniswap_v3.js b/src/services/uniswap_v3.js index 207861d..b2df4b2 100644 --- a/src/services/uniswap_v3.js +++ b/src/services/uniswap_v3.js @@ -178,7 +178,7 @@ export default class UniswapV3 { request[twap].value.tickCumulatives[0].toNumber() ) ) - .toFixed(8) + .toSignificant(8) ); } } @@ -418,10 +418,10 @@ Note that extending the uniswap v2 code may be possible in the future if uniswap fee: Object.keys(FeeAmount).find( (key) => FeeAmount[key] === position.fee ), - lowerPrice: positionInst.token0PriceLower.toFixed(8), - upperPrice: positionInst.token0PriceUpper.toFixed(8), - amount0: positionInst.amount0.toFixed(8), - amount1: positionInst.amount1.toFixed(8), + lowerPrice: positionInst.token0PriceLower.toSignificant(8), + upperPrice: positionInst.token0PriceUpper.toSignificant(8), + amount0: positionInst.amount0.toSignificant(8), + amount1: positionInst.amount1.toSignificant(8), unclaimedToken0: ethers.utils.formatUnits( feeInfo.amount0.toString(), token0.decimals diff --git a/src/static/uniswap_route_tokens.json b/src/static/uniswap_route_tokens.json index 958244e..8a2d5e2 100644 --- a/src/static/uniswap_route_tokens.json +++ b/src/static/uniswap_route_tokens.json @@ -51,7 +51,13 @@ "decimals": 18 }, { - "address": "0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa", + "address": "0xe0C9275E44Ea80eF17579d33c55136b7DA269aEb", + "name": "WrappedBTC", + "symbol": "WBTC", + "decimals": 8 + }, + { + "address": "0x1528F3FCc26d13F7079325Fb78D9442607781c8C", "name": "DaiStablecoin", "symbol": "DAI", "decimals": 18 diff --git a/tests/example-test.js b/tests/example-test.js deleted file mode 100644 index c4dfef0..0000000 --- a/tests/example-test.js +++ /dev/null @@ -1,63 +0,0 @@ -// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts -import YAML from 'yaml'; -import fs from 'fs'; - -const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir -const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); -const config = YAML.parseDocument(file); - -const tokens = ['WETH', 'DAI', 'MKR', 'USDC']; -const privateKey = config.get('PRIVATE_KEY'); - -async function ethTests() { - console.log(tokens); - console.log(privateKey); - - // call / - // confirm expected response - - // call /balances - // confirm and save balances - const balances = {}; - - // call /balances with invalid token symbol - // confirm expected error message - - // call /allowances - // confirm and save allowances - const allowances = {}; - - // call /balances with invalid token symbol - // confirm expected error message - - // call /approve on each token - // confirm that allowance changed correctly - - // call /approve with invalid spender address - // confirm expected error message - - // call /approve with invalid token symbol - // confirm expected error message - - // call /approve with invalid amount - // confirm expected error message -} - -async function uniTests() { - // call /start - // call /gas-limit - - // call with different combinations of tokens: - // price buy - // price sell - // trade buy - // trade sell - - // add tests for extreme values of limitPrice - buy and sell - - // add tests for extreme values of minimumSlippage - -} - -ethTests(); -uniTests(); From 3b045bcde84080162931436f5016deeb865e54c1 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Wed, 18 Aug 2021 17:25:02 -0700 Subject: [PATCH 26/43] Revert "revert merge to development" This reverts commit c1dc6f0736b622dd5d1aa239a7fadbf6b8f6b64a. --- Dockerfile | 5 +- package.json | 1 + src/assets/erc20_tokens_kovan.json | 39 +++-- src/routes/ethereum.ts | 79 ++++----- src/routes/uniswap.ts | 237 +++++++++------------------ src/routes/uniswap_v3.ts | 14 +- src/services/ethereum.ts | 24 ++- src/services/ethereum_gas.ts | 2 +- src/services/uniswap.js | 226 ++++--------------------- src/services/uniswap_v3.js | 10 +- src/static/uniswap_route_tokens.json | 8 +- tests/example-test.js | 63 +++++++ 12 files changed, 262 insertions(+), 446 deletions(-) create mode 100644 tests/example-test.js diff --git a/Dockerfile b/Dockerfile index d2b9585..a8d197c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,4 @@ -FROM node:12.13.0-alpine - -# Add timezone database -RUN apk add --no-cache tzdata +FROM node:12.13.0 # Set labels LABEL application="gateway-api" diff --git a/package.json b/package.json index 08e9968..e4ee14c 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "license": "Apache 2", "repository": "https://github.com/coinalpha/gateway-api", + "type": "module", "scripts": { "prebuild": "rimraf dist && mkdir dist", "build": "tsc --project ./", diff --git a/src/assets/erc20_tokens_kovan.json b/src/assets/erc20_tokens_kovan.json index 44bd5d7..7f6c96e 100644 --- a/src/assets/erc20_tokens_kovan.json +++ b/src/assets/erc20_tokens_kovan.json @@ -4,67 +4,80 @@ { "symbol": "BAT", "address": "0x1f1f156E0317167c11Aa412E3d1435ea29Dc3cCE", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "WETH", "address": "0xd0A1E359811322d97991E03f863a0C30C2cF029C", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "DAI", "address": "0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "MKR", "address": "0xef13C0c8abcaf5767160018d268f9697aE4f5375", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "USDC", "address": "0x2F375e94FC336Cdec2Dc0cCB5277FE59CBf1cAe5", - "decimals": 6 + "decimals": 6, + "chainId": 42 }, { "symbol": "REP", "address": "0x8c9e6c40d3402480ACE624730524fACC5482798c", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "WBTC", "address": "0xe0C9275E44Ea80eF17579d33c55136b7DA269aEb", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "SNX", "address": "0x86436BcE20258a6DcfE48C9512d4d49A30C4d8c4", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "ANT", "address": "0x37f03a12241E9FD3658ad6777d289c3fb8512Bc9", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "ZRX", "address": "0xccb0F4Cf5D3F97f4a55bb5f5cA321C3ED033f244", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "COIN1", "address": "0x809F5A762e7b0CC75C42cd76098b85CB7BD2BA64", - "decimals": 18 + "decimals": 18, + "chainId": 42 }, { "symbol": "COIN2", "address": "0x9866c4043bc6cf47eaf845c56f6ab221c204e0df", - "decimals": 8 + "decimals": 8, + "chainId": 42 }, { "symbol": "COIN3", "address": "0x3D2097889B97A9eF23B3eA8FC10c626fbda29099", - "decimals": 18 + "decimals": 18, + "chainId": 42 } ] } diff --git a/src/routes/ethereum.ts b/src/routes/ethereum.ts index f1a2fd6..1764dc8 100644 --- a/src/routes/ethereum.ts +++ b/src/routes/ethereum.ts @@ -39,34 +39,24 @@ router.post('/balances', async (req: Request, res: Response) => { // Trying connect to Wallet try { - const wallet: ethers.Wallet = ethereumService.getWallet( - req.body.privateKey || '' - ); + const wallet = ethereumService.getWallet(req.body.privateKey); // Populate token contract info using token symbol list - const tokenContractList: Record = {}; - + const tokenList: Record = {}; for (const symbol of JSON.parse(req.body.tokenList)) { - const tokenContractInfo = ethereumService.getERC20TokenAddress(symbol); - if (!tokenContractInfo) { - continue; - } - - tokenContractList[symbol] = tokenContractInfo; + const token = ethereumService.getERC20Token(symbol) as TokenERC20Info; + tokenList[symbol] = token; } - // Getting user balancers const balances: Record = {}; balances.ETH = await ethereumService.getETHBalance(wallet); await Promise.all( - Object.keys(tokenContractList).map(async (symbol) => { - if (tokenContractList[symbol] !== undefined) { - const address = tokenContractList[symbol].address; - const decimals = tokenContractList[symbol].decimals; + Object.keys(tokenList).map(async (symbol) => { + if (tokenList[symbol] !== undefined) { balances[symbol] = await ethereumService.getERC20Balance( wallet, - address, - decimals + tokenList[symbol].address, + tokenList[symbol].decimals ); } else { logger.error(`Token contract info for ${symbol} not found`); @@ -94,30 +84,26 @@ router.post('/allowances', async (req: Request, res: Response) => { res.status(500).send('Wrong connector'); } - // Getting Wallet + // Trying connect to Wallet try { const wallet = ethereumService.getWallet(req.body.privateKey); + // Populate token contract info using token symbol list - const tokenContractList: Record = {}; + const tokenList: Record = {}; for (const symbol of JSON.parse(req.body.tokenList)) { - const tokenContractInfo = ethereumService.getERC20TokenAddress(symbol); - if (!tokenContractInfo) { - continue; - } - - tokenContractList[symbol] = tokenContractInfo; + const token = ethereumService.getERC20Token(symbol) as TokenERC20Info; + tokenList[symbol] = token; } + const approvals: Record = {}; await Promise.all( - Object.keys(tokenContractList).map(async (symbol) => { - const address = tokenContractList[symbol].address; - const decimals = tokenContractList[symbol].decimals; + Object.keys(tokenList).map(async (symbol) => { try { approvals[symbol] = await ethereumService.getERC20Allowance( wallet, spender, - address, - decimals + tokenList[symbol].address, + tokenList[symbol].decimals ); } catch (err) { logger.error(err); @@ -153,33 +139,21 @@ router.post('/approve', async (req: Request, res: Response) => { const wallet = ethereumService.getWallet(req.body.privateKey); // Getting token info - const tokenContractInfo = ethereumService.getERC20TokenAddress( - req.body.token - ); + const token = ethereumService.getERC20Token(req.body.token); - if (!tokenContractInfo) { + if (!token) { res.status(500).send(`Token "${req.body.token}" is not supported`); } else { - const tokenAddress = tokenContractInfo.address; - // const gasPrice = req.body.gasPrice || ethereumGasService.getGasPrice(); - const gasPrice = req.body.gasPrice || fees.ethGasPrice; - - let amount = ethers.constants.MaxUint256; - if (req.body.amount) { - amount = ethers.utils.parseUnits( - req.body.amount, - tokenContractInfo.decimals - ); - } + const amount = ethers.utils.parseUnits(req.body.amount, token.decimals); // call approve function let approval; try { approval = await ethereumService.approveERC20( wallet, spender, - tokenAddress, + token.address, amount, - gasPrice + fees.ethGasPrice as number ); } catch (err) { approval = err; @@ -189,9 +163,9 @@ router.post('/approve', async (req: Request, res: Response) => { network: config.networkName, timestamp: initTime, latency: latency(initTime, Date.now()), - tokenAddress: tokenAddress, + tokenAddress: token.address, spender: spender, - amount: bigNumberWithDecimalToStr(amount, tokenContractInfo.decimals), + amount: bigNumberWithDecimalToStr(amount, token.decimals), approval: approval, }); } @@ -216,4 +190,9 @@ router.post('/poll', async (req: Request, res: Response) => { }); }); +router.post('/token', async (req: Request, res: Response) => { + const token = await ethereumService.getERC20Token(req.body.symbol); + res.status(200).json(token); +}); + export default router; diff --git a/src/routes/uniswap.ts b/src/routes/uniswap.ts index 07c400c..0980ae2 100644 --- a/src/routes/uniswap.ts +++ b/src/routes/uniswap.ts @@ -9,28 +9,18 @@ import { EthereumService } from '../services/ethereum'; import { EthereumConfigService } from '../services/ethereum_config'; import Uniswap from '../services/uniswap'; -import Fees from '../services/fees'; +import { EthereumGasService } from '../services/ethereum_gas'; const debug = require('debug')('router'); const router = express.Router(); -const globalConfig = - require('../services/configuration_manager').configManagerInstance; - const ethConfig = new EthereumConfigService(); const eth = new EthereumService(ethConfig); - -const uniswap = new Uniswap(globalConfig.getConfig('ETHEREUM_CHAIN')); -uniswap.generate_tokens(); -setTimeout(uniswap.update_pairs.bind(uniswap), 2000); -const fees = new Fees(); +const uniswap = new Uniswap(); +const fees = new EthereumGasService(ethConfig); const swapMoreThanMaxPriceError = 'Price too high'; const swapLessThanMaxPriceError = 'Price too low'; -const estimateGasLimit = () => { - return uniswap.gasLimit; -}; - const getErrorMessage = (err: string) => { /* [WIP] Custom error message based-on string match @@ -61,29 +51,15 @@ router.post('/', async (_req: Request, res: Response) => { }); }); -router.post('/gas-limit', async (req: Request, res: Response) => { +router.post('/gas-limit', async (_req: Request, res: Response) => { /* POST: /gas-limit */ - const gasLimit = estimateGasLimit(); - - try { - res.status(200).json({ - network: uniswap.network, - gasLimit: gasLimit, - timestamp: Date.now(), - }); - } catch (err) { - logger.error(req.originalUrl, { message: err }); - let reason; - err.reason - ? (reason = err.reason) - : (reason = statusMessages.operation_error); - res.status(500).json({ - error: reason, - message: err, - }); - } + res.status(200).json({ + network: uniswap.network, + gasLimit: uniswap.gasLimit, + timestamp: Date.now(), + }); }); router.get('/start', async (req: Request, res: Response) => { @@ -92,63 +68,35 @@ router.get('/start', async (req: Request, res: Response) => { */ const initTime = Date.now(); - if (typeof req.query.pairs === 'string') { - const pairs = JSON.parse(req.query.pairs); - let gasPrice; - if (typeof req.query.gasPrice === 'string') { - gasPrice = parseFloat(req.query.gasPrice); - } else { - gasPrice = fees.ethGasPrice; - } - - // get token contract address and cache paths - for (let pair of pairs) { - pair = pair.split('-'); - const baseTokenSymbol = pair[0]; - const quoteTokenSymbol = pair[1]; - const baseTokenContractInfo = eth.getERC20TokenAddress(baseTokenSymbol); - const quoteTokenContractInfo = eth.getERC20TokenAddress(quoteTokenSymbol); + // get token contract address and cache paths + const pairs = JSON.parse(req.query.pairs as string); + for (let pair of pairs) { + pair = pair.split('-'); + const baseToken = eth.getERC20Token(pair[0]); + const quoteToken = eth.getERC20Token(pair[1]); - // check for valid token symbols - if ( - baseTokenContractInfo === undefined || - quoteTokenContractInfo === undefined - ) { - const undefinedToken = - baseTokenContractInfo === undefined - ? baseTokenSymbol - : quoteTokenSymbol; - res.status(500).json({ - error: `Token ${undefinedToken} contract address not found`, - message: `Token contract address not found for ${undefinedToken}. Check token list source`, - }); - return; - } - await Promise.allSettled([ - uniswap.extend_update_pairs([ - baseTokenContractInfo.address, - quoteTokenContractInfo.address, - ]), - ]); + // check for valid token symbols + if (baseToken === undefined || quoteToken === undefined) { + const undefinedToken = baseToken === undefined ? pair[0] : pair[1]; + res.status(500).json({ + error: `Token ${undefinedToken} contract address not found`, + message: `Token contract address not found for ${undefinedToken}. Check token list source`, + }); + return; } - - const gasLimit = estimateGasLimit(); - const gasCost = await fees.getGasCost(gasPrice, gasLimit); - - const result = { - network: eth.networkName, - timestamp: initTime, - latency: latency(initTime, Date.now()), - success: true, - pairs: pairs, - gasPrice: gasPrice, - gasLimit: gasLimit, - gasCost: gasCost, - }; - res.status(200).json(result); - } else { - res.status(500).json({ err: 'error in pair type' }); } + const gasCost = await fees.getGasCost(uniswap.gasLimit); + const result = { + network: eth.networkName, + timestamp: initTime, + latency: latency(initTime, Date.now()), + success: true, + pairs: pairs, + gasPrice: fees.getGasPrice(), + gasLimit: uniswap.gasLimit, + gasCost: gasCost, + }; + res.status(200).json(result); }); router.post('/trade', async (req: Request, res: Response) => { @@ -158,78 +106,62 @@ router.post('/trade', async (req: Request, res: Response) => { "quote":"BAT" "base":"DAI" "amount":0.1 - "limitPrice":1 - "gasPrice":10 + "limitPrice?":1 "privateKey":{{privateKey}} "side":{buy|sell} } */ const initTime = Date.now(); - // params: privateKey (required), base (required), quote (required), amount (required), maxPrice (required), gasPrice (required) const privateKey = req.body.privateKey; const wallet = new ethers.Wallet(privateKey, uniswap.provider); const amount = req.body.amount; - const baseTokenContractInfo = eth.getERC20TokenAddress(req.body.base); - const quoteTokenContractInfo = eth.getERC20TokenAddress(req.body.quote); + const baseToken = eth.getERC20Token(req.body.base); + const quoteToken = eth.getERC20Token(req.body.quote); - if (baseTokenContractInfo && quoteTokenContractInfo) { - const baseTokenAddress = baseTokenContractInfo.address; - const quoteTokenAddress = quoteTokenContractInfo.address; + if (baseToken && quoteToken) { const side = req.body.side.toUpperCase(); - - let limitPrice; - if (req.body.limitPrice) { - limitPrice = parseFloat(req.body.limitPrice); - } - let gasPrice; - if (req.body.gasPrice) { - gasPrice = parseFloat(req.body.gasPrice); - } else { - gasPrice = fees.ethGasPrice; - } - const gasLimit = estimateGasLimit(); - const gasCost = await fees.getGasCost(gasPrice, gasLimit); - + const limitPrice = req.body.limitPrice || null; + const gasCost = await fees.getGasCost(uniswap.gasLimit); try { // fetch the optimal pool mix from uniswap const result: any = side === 'BUY' ? await uniswap.priceSwapOut( - quoteTokenAddress, // tokenIn is quote asset - baseTokenAddress, // tokenOut is base asset + quoteToken, // tokenIn is quote asset + baseToken, // tokenOut is base asset amount ) : await uniswap.priceSwapIn( - baseTokenAddress, // tokenIn is base asset - quoteTokenAddress, // tokenOut is quote asset + baseToken, // tokenIn is base asset + quoteToken, // tokenOut is quote asset amount ); if (result && result.trade && result.expectedAmount) { const trade = result.trade; const expectedAmount = result.expectedAmount; if (side === 'BUY') { - const price = trade.executionPrice.invert().toSignificant(8); + const price = trade.executionPrice.invert().toFixed(8); if (!limitPrice || price <= limitPrice) { // pass swaps to exchange-proxy to complete trade const tx = await uniswap.swapExactOut( wallet, trade, - baseTokenAddress, - gasPrice + baseToken.address, + fees.getGasPrice() ); // submit response res.status(200).json({ network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), - base: baseTokenAddress, - quote: quoteTokenAddress, + base: baseToken.address, + quote: quoteToken.address, amount: amount, - expectedIn: expectedAmount.toSignificant(8), + expectedIn: expectedAmount.toFixed(8), price: price, - gasPrice: gasPrice, - gasLimit, + gasPrice: fees.getGasPrice(), + gasLimit: uniswap.gasLimit, gasCost, txHash: tx.hash, }); @@ -244,28 +176,28 @@ router.post('/trade', async (req: Request, res: Response) => { } } else { // sell - const price = trade.executionPrice.toSignificant(8); + const price = trade.executionPrice.toFixed(8); logger.info(`Price: ${price.toString()}`); if (!limitPrice || price >= limitPrice) { // pass swaps to exchange-proxy to complete trade const tx = await uniswap.swapExactIn( wallet, trade, - baseTokenAddress, - gasPrice + baseToken.address, + fees.getGasPrice() ); // submit response res.status(200).json({ network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), - base: baseTokenAddress, - quote: quoteTokenAddress, + base: baseToken.address, + quote: quoteToken.address, amount: parseFloat(req.body.amount), - expectedOut: expectedAmount.toSignificant(8), + expectedOut: expectedAmount.toFixed(8), price: parseFloat(price), - gasPrice: gasPrice, - gasLimit, + gasPrice: fees.getGasPrice(), + gasLimit: uniswap.gasLimit, gasCost: gasCost, txHash: tx.hash, }); @@ -309,39 +241,28 @@ router.post('/price', async (req: Request, res: Response) => { "quote":"BAT" "base":"DAI" "amount":1 + "side":"buy" } */ const initTime = Date.now(); - // params: base (required), quote (required), amount (required) const amount = req.body.amount; - - const baseTokenContractInfo = eth.getERC20TokenAddress(req.body.base); - const quoteTokenContractInfo = eth.getERC20TokenAddress(req.body.quote); - if (baseTokenContractInfo && quoteTokenContractInfo) { - const baseTokenAddress = baseTokenContractInfo.address; - const quoteTokenAddress = quoteTokenContractInfo.address; + const baseToken = eth.getERC20Token(req.body.base); + const quoteToken = eth.getERC20Token(req.body.quote); + if (baseToken && quoteToken) { const side = req.body.side.toUpperCase(); - let gasPrice; - if (req.body.gasPrice) { - gasPrice = parseFloat(req.body.gasPrice); - } else { - gasPrice = fees.ethGasPrice; - } - const gasLimit = estimateGasLimit(); - const gasCost = await fees.getGasCost(gasPrice, gasLimit); + const gasCost = await fees.getGasCost(uniswap.gasLimit); try { - // fetch the optimal pool mix from uniswap const result: any = side === 'BUY' ? await uniswap.priceSwapOut( - quoteTokenAddress, // tokenIn is quote asset - baseTokenAddress, // tokenOut is base asset + quoteToken, // tokenIn is quote asset + baseToken, // tokenOut is base asset amount ) : await uniswap.priceSwapIn( - baseTokenAddress, // tokenIn is base asset - quoteTokenAddress, // tokenOut is quote asset + baseToken, // tokenIn is base asset + quoteToken, // tokenOut is quote asset amount ); if (result && result.trade && result.expectedAmount) { @@ -351,31 +272,29 @@ router.post('/price', async (req: Request, res: Response) => { if (trade !== null && expectedAmount !== null) { const price = side === 'BUY' - ? trade.executionPrice.invert().toSignificant(8) - : trade.executionPrice.toSignificant(8); + ? trade.executionPrice.invert().toFixed(8) + : trade.executionPrice.toFixed(8); const tradeAmount = parseFloat(amount); - const expectedTradeAmount = parseFloat( - expectedAmount.toSignificant(8) - ); + const expectedTradeAmount = parseFloat(expectedAmount.toFixed(8)); const tradePrice = parseFloat(price); const result = { network: uniswap.network, timestamp: initTime, latency: latency(initTime, Date.now()), - base: baseTokenAddress, - quote: quoteTokenAddress, + base: baseToken.address, + quote: quoteToken.address, amount: tradeAmount, expectedAmount: expectedTradeAmount, price: tradePrice, - gasPrice: gasPrice, - gasLimit: gasLimit, + gasPrice: fees.getGasPrice(), + gasLimit: uniswap.gasLimit, gasCost: gasCost, trade: trade, }; debug( - `Price ${side} ${baseTokenContractInfo.symbol}-${quoteTokenContractInfo.symbol} | amount:${amount} (rate:${tradePrice}) - gasPrice:${gasPrice} gasLimit:${gasLimit} estimated fee:${gasCost} ETH` + `Price ${side} ${baseToken.symbol}-${quoteToken.symbol} | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${uniswap.gasLimit} estimated fee:${gasCost} ETH` ); res.status(200).json(result); } else { diff --git a/src/routes/uniswap_v3.ts b/src/routes/uniswap_v3.ts index 3d8c723..b421534 100644 --- a/src/routes/uniswap_v3.ts +++ b/src/routes/uniswap_v3.ts @@ -250,7 +250,7 @@ router.post('/trade', async (req: Request, res: Response) => { ); if (side === 'BUY') { - const price = trade.executionPrice.invert().toSignificant(8); + const price = trade.executionPrice.invert().toFixed(8); logger.info(`uniswap.route - Price: ${price.toString()}`); if (!limitPrice || price <= limitPrice) { // pass swaps to exchange-proxy to complete trade @@ -268,7 +268,7 @@ router.post('/trade', async (req: Request, res: Response) => { base: baseTokenAddress, quote: quoteTokenAddress, amount: amount, - expectedIn: expectedAmount.toSignificant(8), + expectedIn: expectedAmount.toFixed(8), price: price, gasPrice: gasPrice, gasLimit, @@ -286,7 +286,7 @@ router.post('/trade', async (req: Request, res: Response) => { } } else { // sell - const price = trade.executionPrice.toSignificant(8); + const price = trade.executionPrice.toFixed(8); logger.info(`Price: ${price.toString()}`); if (!limitPrice || price >= limitPrice) { // pass swaps to exchange-proxy to complete trade @@ -304,7 +304,7 @@ router.post('/trade', async (req: Request, res: Response) => { base: baseTokenAddress, quote: quoteTokenAddress, amount: parseFloat(req.body.amount), - expectedOut: expectedAmount.toSignificant(8), + expectedOut: expectedAmount.toFixed(8), price: parseFloat(price), gasPrice: gasPrice, gasLimit, @@ -389,13 +389,13 @@ router.post('/price', async (req: Request, res: Response) => { if (trade !== null && expectedAmount !== null) { price = side === 'BUY' - ? trade.executionPrice.invert().toSignificant(8) - : trade.executionPrice.toSignificant(8); + ? trade.executionPrice.invert().toFixed(8) + : trade.executionPrice.toFixed(8); priceResult = { price: parseFloat(price), amount: parseFloat(amount), - expectedAmount: parseFloat(expectedAmount.toSignificant(8)), + expectedAmount: parseFloat(expectedAmount.toFixed(8)), }; } } else { diff --git a/src/services/ethereum.ts b/src/services/ethereum.ts index c3bace3..94d0a00 100644 --- a/src/services/ethereum.ts +++ b/src/services/ethereum.ts @@ -34,6 +34,7 @@ export interface TokenERC20Info { symbol: string; address: string; decimals: number; + chainId: number; } export interface ERC20TokensList { @@ -73,21 +74,20 @@ export const bigNumberWithDecimalToStr = (n: BigNumber, d: number): string => { export class EthereumService { private readonly provider = new providers.JsonRpcProvider(this.config.rpcUrl); + private chainId = 1; private erc20TokenList: ERC20TokensList | null = null; constructor(private readonly config: EthereumConfigService) { switch (this.config.networkName) { case Network.KOVAN: + this.chainId = 42; this.erc20TokenList = kovanErc20TokenList; break; - - case Network.MAINNET: { + default: // MAINNET (async () => { const { data } = await axios.get(this.config.tokenListUrl); this.erc20TokenList = data; })(); - break; - } } } @@ -214,6 +214,22 @@ export class EthereumService { } } + /** + * Get ERC20 token + * @param {string} tokenSymbol + * @return {TokenERC20Info} | null + */ + getERC20Token(symbol: string): TokenERC20Info | undefined { + if (this.erc20TokenList) { + const token = this.erc20TokenList.tokens.find( + (obj) => + obj.symbol === symbol.toUpperCase() && obj.chainId === this.chainId + ); + return token; + } + return; + } + /** * Get ERC20 token address * @param {string} tokenSymbol diff --git a/src/services/ethereum_gas.ts b/src/services/ethereum_gas.ts index 631d278..8fff24e 100644 --- a/src/services/ethereum_gas.ts +++ b/src/services/ethereum_gas.ts @@ -91,7 +91,7 @@ export class EthereumGasService { getGasCost(gasLimit: number, inGwei = false): ethers.BigNumber { const cost = ethers.BigNumber.from(this.gasPrice * gasLimit); - const denom = ethers.BigNumber.from(BigInt('1e+9')); + const denom = ethers.BigNumber.from('1000000000'); return inGwei ? cost : cost.div(denom); } diff --git a/src/services/uniswap.js b/src/services/uniswap.js index 307e54f..4b59185 100644 --- a/src/services/uniswap.js +++ b/src/services/uniswap.js @@ -1,22 +1,21 @@ +import { unit } from 'mathjs'; +import { debug } from 'winston'; import { logger } from './logger'; -const debug = require('debug')('router'); const math = require('mathjs'); const uni = require('@uniswap/sdk'); const ethers = require('ethers'); const proxyArtifact = require('../static/uniswap_v2_router_abi.json'); -const routeTokens = require('../static/uniswap_route_tokens.json'); const globalConfig = require('../services/configuration_manager').configManagerInstance; // constants -const ROUTER = globalConfig.getConfig('UNISWAP_ROUTER'); -const GAS_LIMIT = globalConfig.getConfig('UNISWAP_GAS_LIMIT') || 200688; -const TTL = globalConfig.getConfig('UNISWAP_TTL') || 300; -const UPDATE_PERIOD = globalConfig.getConfig('UNISWAP_UPDATE_PERIOD') || 300000; // stop updating pair after 5 minutes from last request +const ROUTER = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'; +const GAS_LIMIT = 200688; +const TTL = 300; export default class Uniswap { - constructor(network = 'mainnet') { + constructor() { this.providerUrl = globalConfig.getConfig('ETHEREUM_RPC_URL'); this.network = globalConfig.getConfig('ETHEREUM_CHAIN'); this.provider = new ethers.providers.JsonRpcProvider(this.providerUrl); @@ -28,203 +27,38 @@ export default class Uniswap { this.slippage.n, this.slippage.d * 100 ); - this.pairsCacheTime = globalConfig.getConfig('UNISWAP_PAIRS_CACHE_TIME'); this.gasLimit = GAS_LIMIT; - this.expireTokenPairUpdate = UPDATE_PERIOD; - this.zeroReserveCheckInterval = globalConfig.getConfig( - 'UNISWAP_NO_RESERVE_CHECK_INTERVAL' - ); - this.zeroReservePairs = {}; // No reserve pairs - this.tokenList = {}; - this.pairs = []; - this.tokenSwapList = {}; - this.cachedRoutes = {}; - - switch (network) { - case 'mainnet': - this.chainID = uni.ChainId.MAINNET; - break; - case 'kovan': - this.chainID = uni.ChainId.KOVAN; - break; - default: { - const err = `Invalid network ${network}`; - logger.error(err); - throw Error(err); - } - } - } - - async fetch_route(tIn, tOut) { - var route, pair; - - try { - pair = await uni.Fetcher.fetchPairData(tIn, tOut); - route = new uni.Route([pair], tIn, tOut); - } catch (err) { - logger.error(err); - } - return route; - } - - generate_tokens() { - for (let token of routeTokens[this.network]) { - this.tokenList[token['address']] = new uni.Token( - this.chainID, - token['address'], - token['decimals'], - token['symbol'], - token['name'] - ); - } - } - - async extend_update_pairs(tokens = []) { - for (let token of tokens) { - if (!Object.prototype.hasOwnProperty.call(this.tokenList, token)) { - this.tokenList[token] = await uni.Fetcher.fetchTokenData( - this.chainID, - token - ); - } - this.tokenSwapList[token] = Date.now() + this.expireTokenPairUpdate; - } } - async update_pairs() { - // Remove banned pairs after ban period - if (Object.keys(this.zeroReservePairs).length > 0) { - for (let pair in this.zeroReservePairs) { - if (this.zeroReservePairs[pair] <= Date.now()) { - delete this.zeroReservePairs[pair]; - // delete this.tokenList[token]; - } - } - } - // Generate all possible pair combinations of tokens - // This is done by generating an upper triangular matrix or right triangular matrix - if (Object.keys(this.tokenSwapList).length > 0) { - for (let token in this.tokenSwapList) { - if (this.tokenSwapList[token] <= Date.now()) { - delete this.tokenSwapList[token]; - // delete this.tokenList[token]; - } - } - - let tokens = Object.keys(this.tokenList); - var firstToken, secondToken, position; - let length = tokens.length; - let pairs = []; - let pairAddressRequests = []; - let pairAddressResponses = []; - for (firstToken = 0; firstToken < length; firstToken++) { - for ( - secondToken = firstToken + 1; - secondToken < length; - secondToken++ - ) { - try { - let pairString = - this.tokenList[tokens[firstToken]].address + - '-' + - this.tokenList[tokens[secondToken]].address; - if ( - !Object.prototype.hasOwnProperty.call( - this.zeroReservePairs, - pairString - ) - ) { - pairs.push(pairString); - pairAddressRequests.push( - uni.Fetcher.fetchPairData( - this.tokenList[tokens[firstToken]], - this.tokenList[tokens[secondToken]] - ) - ); - } - } catch (err) { - logger.error(err); - } - } - } - - await Promise.allSettled(pairAddressRequests).then((values) => { - for (position = 0; position < pairAddressRequests.length; position++) { - if (values[position].status === 'fulfilled') { - pairAddressResponses.push(values[position].value); - } else { - this.zeroReservePairs[pairs[position]] = - Date.now() + this.zeroReserveCheckInterval; - } - } - }); - this.pairs = pairAddressResponses; - } - setTimeout(this.update_pairs.bind(this), 1000); - } + getUniswapToken = (token) => + new uni.Token(token.chainId, token.address, token.decimals); - async priceSwapIn(tokenIn, tokenOut, tokenInAmount) { - await this.extend_update_pairs([tokenIn, tokenOut]); - const tIn = this.tokenList[tokenIn]; - const tOut = this.tokenList[tokenOut]; - const tokenAmountIn = new uni.TokenAmount( - tIn, - ethers.utils.parseUnits(tokenInAmount, tIn.decimals) + async priceSwapIn(tIn, tOut, tokenInAmount) { + const tokenIn = this.getUniswapToken(tIn); + const tokenOut = this.getUniswapToken(tOut); + const amountIn = new uni.TokenAmount( + tokenIn, + ethers.utils.parseUnits(tokenInAmount, tokenIn.decimals) ); - if (this.pairs.length === 0) { - const route = await this.fetch_route(tIn, tOut); - const trade = uni.Trade.exactIn(route, tokenAmountIn); - if (trade !== undefined) { - const expectedAmount = trade.minimumAmountOut(this.allowedSlippage); - this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; - return { trade, expectedAmount }; - } - return "Can't find route to swap, kindly update "; - } - let trade = uni.Trade.bestTradeExactIn( - this.pairs, - tokenAmountIn, - this.tokenList[tokenOut], - { maxHops: 5 } - )[0]; - if (trade === undefined) { - trade = this.cachedRoutes[tIn.symbol + tOut.Symbol]; - } else { - this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; - } + const pair = await uni.Fetcher.fetchPairData(tokenIn, tokenOut); + const route = new uni.Route([pair], tokenIn); + const trade = new uni.Trade(route, amountIn, uni.TradeType.EXACT_INPUT); + logger.info(`Trade: ${trade}`); const expectedAmount = trade.minimumAmountOut(this.allowedSlippage); return { trade, expectedAmount }; } - async priceSwapOut(tokenIn, tokenOut, tokenOutAmount) { - await this.extend_update_pairs([tokenIn, tokenOut]); - const tOut = this.tokenList[tokenOut]; - const tIn = this.tokenList[tokenIn]; - const tokenAmountOut = new uni.TokenAmount( - tOut, - ethers.utils.parseUnits(tokenOutAmount, tOut.decimals) + async priceSwapOut(tIn, tOut, tokenOutAmount) { + const tokenIn = this.getUniswapToken(tIn); + const tokenOut = this.getUniswapToken(tOut); + const amountOut = new uni.TokenAmount( + tokenOut, + ethers.utils.parseUnits(tokenOutAmount, tokenOut.decimals) ); - if (this.pairs.length === 0) { - const route = await this.fetch_route(tIn, tOut); - const trade = uni.Trade.exactOut(route, tokenAmountOut); - if (trade !== undefined) { - const expectedAmount = trade.maximumAmountIn(this.allowedSlippage); - this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; - return { trade, expectedAmount }; - } - return; - } - let trade = uni.Trade.bestTradeExactOut( - this.pairs, - this.tokenList[tokenIn], - tokenAmountOut, - { maxHops: 5 } - )[0]; - if (trade === undefined) { - trade = this.cachedRoutes[tIn.symbol + tOut.Symbol]; - } else { - this.cachedRoutes[tIn.symbol + tOut.Symbol] = trade; - } + const pair = await uni.Fetcher.fetchPairData(tokenIn, tokenOut); + const route = new uni.Route([pair], tokenIn); + const trade = new uni.Trade(route, amountOut, uni.TradeType.EXACT_OUTPUT); + logger.info(`Trade: ${trade}`); const expectedAmount = trade.maximumAmountIn(this.allowedSlippage); return { trade, expectedAmount }; } @@ -247,7 +81,7 @@ export default class Uniswap { value: result.value, }); - debug(`Tx Hash: ${tx.hash}`); + logger.info(`Tx Hash: ${tx.hash}`); return tx; } @@ -269,7 +103,7 @@ export default class Uniswap { value: result.value, }); - debug(`Tx Hash: ${tx.hash}`); + logger.info(`Tx Hash: ${tx.hash}`); return tx; } } diff --git a/src/services/uniswap_v3.js b/src/services/uniswap_v3.js index b2df4b2..207861d 100644 --- a/src/services/uniswap_v3.js +++ b/src/services/uniswap_v3.js @@ -178,7 +178,7 @@ export default class UniswapV3 { request[twap].value.tickCumulatives[0].toNumber() ) ) - .toSignificant(8) + .toFixed(8) ); } } @@ -418,10 +418,10 @@ Note that extending the uniswap v2 code may be possible in the future if uniswap fee: Object.keys(FeeAmount).find( (key) => FeeAmount[key] === position.fee ), - lowerPrice: positionInst.token0PriceLower.toSignificant(8), - upperPrice: positionInst.token0PriceUpper.toSignificant(8), - amount0: positionInst.amount0.toSignificant(8), - amount1: positionInst.amount1.toSignificant(8), + lowerPrice: positionInst.token0PriceLower.toFixed(8), + upperPrice: positionInst.token0PriceUpper.toFixed(8), + amount0: positionInst.amount0.toFixed(8), + amount1: positionInst.amount1.toFixed(8), unclaimedToken0: ethers.utils.formatUnits( feeInfo.amount0.toString(), token0.decimals diff --git a/src/static/uniswap_route_tokens.json b/src/static/uniswap_route_tokens.json index 8a2d5e2..958244e 100644 --- a/src/static/uniswap_route_tokens.json +++ b/src/static/uniswap_route_tokens.json @@ -51,13 +51,7 @@ "decimals": 18 }, { - "address": "0xe0C9275E44Ea80eF17579d33c55136b7DA269aEb", - "name": "WrappedBTC", - "symbol": "WBTC", - "decimals": 8 - }, - { - "address": "0x1528F3FCc26d13F7079325Fb78D9442607781c8C", + "address": "0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa", "name": "DaiStablecoin", "symbol": "DAI", "decimals": 18 diff --git a/tests/example-test.js b/tests/example-test.js new file mode 100644 index 0000000..c4dfef0 --- /dev/null +++ b/tests/example-test.js @@ -0,0 +1,63 @@ +// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts +import YAML from 'yaml'; +import fs from 'fs'; + +const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir +const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); +const config = YAML.parseDocument(file); + +const tokens = ['WETH', 'DAI', 'MKR', 'USDC']; +const privateKey = config.get('PRIVATE_KEY'); + +async function ethTests() { + console.log(tokens); + console.log(privateKey); + + // call / + // confirm expected response + + // call /balances + // confirm and save balances + const balances = {}; + + // call /balances with invalid token symbol + // confirm expected error message + + // call /allowances + // confirm and save allowances + const allowances = {}; + + // call /balances with invalid token symbol + // confirm expected error message + + // call /approve on each token + // confirm that allowance changed correctly + + // call /approve with invalid spender address + // confirm expected error message + + // call /approve with invalid token symbol + // confirm expected error message + + // call /approve with invalid amount + // confirm expected error message +} + +async function uniTests() { + // call /start + // call /gas-limit + + // call with different combinations of tokens: + // price buy + // price sell + // trade buy + // trade sell + + // add tests for extreme values of limitPrice - buy and sell + + // add tests for extreme values of minimumSlippage + +} + +ethTests(); +uniTests(); From fd7d897c85234690c7e6c5950c000fac1cde1f6d Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Wed, 18 Aug 2021 17:26:14 -0700 Subject: [PATCH 27/43] (fix) remove type module in package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index e4ee14c..08e9968 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "main": "index.js", "license": "Apache 2", "repository": "https://github.com/coinalpha/gateway-api", - "type": "module", "scripts": { "prebuild": "rimraf dist && mkdir dist", "build": "tsc --project ./", From 71569a86922483b0083b4073f3f25adf37c0832c Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Fri, 20 Aug 2021 16:54:26 -0700 Subject: [PATCH 28/43] (fix) revert to use old fees for gas cost --- src/routes/uniswap.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/routes/uniswap.ts b/src/routes/uniswap.ts index 0980ae2..42a82c1 100644 --- a/src/routes/uniswap.ts +++ b/src/routes/uniswap.ts @@ -10,6 +10,7 @@ import { EthereumConfigService } from '../services/ethereum_config'; import Uniswap from '../services/uniswap'; import { EthereumGasService } from '../services/ethereum_gas'; +import Fees from '../services/fees'; const debug = require('debug')('router'); const router = express.Router(); @@ -17,6 +18,7 @@ const ethConfig = new EthereumConfigService(); const eth = new EthereumService(ethConfig); const uniswap = new Uniswap(); const fees = new EthereumGasService(ethConfig); +const feesOld = new Fees(); const swapMoreThanMaxPriceError = 'Price too high'; const swapLessThanMaxPriceError = 'Price too low'; @@ -85,7 +87,7 @@ router.get('/start', async (req: Request, res: Response) => { return; } } - const gasCost = await fees.getGasCost(uniswap.gasLimit); + const gasCost = await feesOld.getGasCost(fees.getGasPrice(), uniswap.gasLimit); const result = { network: eth.networkName, timestamp: initTime, @@ -122,7 +124,7 @@ router.post('/trade', async (req: Request, res: Response) => { if (baseToken && quoteToken) { const side = req.body.side.toUpperCase(); const limitPrice = req.body.limitPrice || null; - const gasCost = await fees.getGasCost(uniswap.gasLimit); + const gasCost = await feesOld.getGasCost(fees.getGasPrice(), uniswap.gasLimit); try { // fetch the optimal pool mix from uniswap const result: any = @@ -250,7 +252,7 @@ router.post('/price', async (req: Request, res: Response) => { const quoteToken = eth.getERC20Token(req.body.quote); if (baseToken && quoteToken) { const side = req.body.side.toUpperCase(); - const gasCost = await fees.getGasCost(uniswap.gasLimit); + const gasCost = await feesOld.getGasCost(fees.getGasPrice(), uniswap.gasLimit); try { const result: any = From 6e5e33ce87151679aada2be5e562cba39eafd7fc Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Fri, 20 Aug 2021 17:37:39 -0700 Subject: [PATCH 29/43] (fix) gasUsed poll bug --- src/routes/ethereum.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/routes/ethereum.ts b/src/routes/ethereum.ts index 1764dc8..360f5ee 100644 --- a/src/routes/ethereum.ts +++ b/src/routes/ethereum.ts @@ -179,6 +179,9 @@ router.post('/poll', async (req: Request, res: Response) => { const initTime = Date.now(); const receipt = await ethereumService.getTransactionReceipt(req.body.txHash); const confirmed = receipt && receipt.blockNumber ? true : false; + if (receipt.gasUsed) { + receipt.gasUsed = receipt.gasUsed.toNumber(); + } res.status(200).json({ network: config.networkName, From b42c55cec33e4dd0563be3d8799eefe84d680ac5 Mon Sep 17 00:00:00 2001 From: vic-en Date: Tue, 24 Aug 2021 19:05:31 +0100 Subject: [PATCH 30/43] alway approve on every run --- tests/scripts/uniswap.v3.test.js | 40 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js index 3252800..67351d0 100644 --- a/tests/scripts/uniswap.v3.test.js +++ b/tests/scripts/uniswap.v3.test.js @@ -103,29 +103,27 @@ async function ethTests() { console.log(allowances); for (let token of tokens) { - if (parseFloat(allowances[token]) < 1000.0) { - // call /approve on each token - console.log(`Approving 5000 ${token}...`); - let approve1 = await request('post', '/eth/approve', { - token: token, + // call /approve on each token + console.log(`Approving 5000 ${token}...`); + let approve1 = await request('post', '/eth/approve', { + token: token, + connector: 'uniswapV3NFTManager', + amount: '5000', + }); + console.log(approve1); + while (allowances[token] !== approve1.amount) { + console.log( + 'Waiting for atleast 1 block time to give time for approval to be mined.' + ); + await sleep(13000); + // confirm that allowance changed correctly + console.log('Rechecking allowances to confirm approval...'); + let allowancesResponse2 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), connector: 'uniswapV3NFTManager', - amount: '5000', }); - console.log(approve1); - while (allowances[token] !== approve1.amount) { - console.log( - 'Waiting for atleast 1 block time to give time for approval to be mined.' - ); - await sleep(13000); - // confirm that allowance changed correctly - console.log('Rechecking allowances to confirm approval...'); - let allowancesResponse2 = await request('post', '/eth/allowances', { - tokenList: JSON.stringify(tokens), - connector: 'uniswapV3NFTManager', - }); - allowances = allowancesResponse2.approvals; - console.log(allowances); - } + allowances = allowancesResponse2.approvals; + console.log(allowances); } } From 1aabde5be0520acdd716ce5d39935ce3e2f443fe Mon Sep 17 00:00:00 2001 From: vic-en Date: Tue, 24 Aug 2021 19:14:36 +0100 Subject: [PATCH 31/43] remove sleep statements right after approvals --- tests/scripts/uniswap.v3.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js index 67351d0..cac834d 100644 --- a/tests/scripts/uniswap.v3.test.js +++ b/tests/scripts/uniswap.v3.test.js @@ -198,7 +198,6 @@ async function unitTests() { }); assert.hasAnyKeys(pid, ['hash'], 'Add position failed.'); console.log(`New position transaction hash - ${pid.hash}`); - await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction let done = false; let tx1, tx2, tid; while (!done) { @@ -235,7 +234,6 @@ async function unitTests() { }); assert.hasAnyKeys(closePid, ['hash'], 'Close position transaction failed.'); console.log(`close position transaction hash - ${closePid.hash}`); - await sleep(60000); // sleep for 1 minute to give some time for provider to see transaction while (!done) { tx2 = await request('post', '/eth/poll', { txHash: closePid.hash }); console.log(tx2); From 9ceaab78b1cb9ebcea723ec6a23bbd4505d2621d Mon Sep 17 00:00:00 2001 From: vic-en Date: Thu, 26 Aug 2021 10:38:07 +0100 Subject: [PATCH 32/43] separate eth tests --- tests/scripts/ethereum.test.js | 160 ++++++++++++++++++++++++++++++ tests/scripts/uniswap.v2.test.js | 161 +------------------------------ tests/scripts/uniswap.v3.test.js | 159 +----------------------------- 3 files changed, 164 insertions(+), 316 deletions(-) create mode 100644 tests/scripts/ethereum.test.js diff --git a/tests/scripts/ethereum.test.js b/tests/scripts/ethereum.test.js new file mode 100644 index 0000000..78c51bf --- /dev/null +++ b/tests/scripts/ethereum.test.js @@ -0,0 +1,160 @@ +// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts +import YAML from 'yaml'; +import fs from 'fs'; +import axios from 'axios'; +import https from 'https'; +import { assert } from 'chai'; + +const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir +const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); +const config = YAML.parseDocument(file); + +const host = 'localhost'; +const port = 5000; +const privateKey = config.get('PRIVATE_KEY'); + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +const httpsAgent = axios.create({ + httpsAgent: new https.Agent({ + ca: fs.readFileSync(config.get('CERT_PATH') + '/ca_cert.pem'), + cert: fs.readFileSync(config.get('CERT_PATH') + '/client_cert.pem'), + key: fs.readFileSync(config.get('CERT_PATH') + '/client_key.pem'), + host: host, + port: port, + requestCert: true, + rejectUnauthorized: false, + }), +}); + +export async function request(method, path, params) { + try { + let response; + const gatewayAddress = `https://${host}:${port}`; + if (method === 'get') { + response = await httpsAgent.get(gatewayAddress + path, { + params: params, + }); + } else { + // post + params['privateKey'] = privateKey; + response = await httpsAgent.post(gatewayAddress + path, params); + } + return response.data; + } catch (err) { + console.log(`${path} - ${err}`); + } +} + +export async function ethTests( connector = null, tokens = [] ) { + console.log('\nStarting ETH tests'); + console.log('***************************************************'); + console.log('Token symbols used in tests: ', tokens); + assert.isAtLeast(tokens.length, 2, 'Pls provide at least 2 tokens'); + assert.exists(privateKey, 'Pls include PRIVATE_KEY in global_conf file'); + + // call / + console.log('Checking status of gateway server...'); + const result = await request('get', '/', {}); + // confirm expected response + console.log(result); + assert.equal(result, 'ok'); + + // call /balances + console.log('Checking balances...'); + const balancesResponse = await request('post', '/eth/balances', { + tokenList: JSON.stringify(tokens), + }); + // confirm and save balances + const balances = balancesResponse.balances; + console.log(balances); + assert.isAbove( + parseFloat(balances.ETH), + 0, + 'Pls ensure there is some native token' + ); + + // call /balances with invalid token symbol + // confirm expected error message + console.log('calling balances with invalid token symbols ABC and XYZ...'); + const balancesResponse1 = await request('post', '/eth/balances', { + tokenList: JSON.stringify(['ABC', 'XYZ']), + }); + console.log(balancesResponse1.balances); + assert.isNaN( + parseFloat(balancesResponse1.balances.ABC), + 'ABC is a valid token.' + ); + assert.isNaN( + parseFloat(balancesResponse1.balances.XYZ), + 'XYZ is a valid token.' + ); + + // call /allowances + // confirm and save allowances + console.log('checking initial allowances...'); + const allowancesResponse1 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), + connector: connector, + }); + let allowances = allowancesResponse1.approvals; + console.log(allowances); + + for (let token of tokens) { + // call /approve on each token + console.log(`Resetting allowance for ${token} to 5000...`); + let approve1 = await request('post', '/eth/approve', { + token: token, + connector: connector, + amount: '5000', + }); + console.log(approve1); + while (allowances[token] !== approve1.amount) { + console.log( + 'Waiting for atleast 1 block time (i.e 13 secs) to give time for approval to be mined.' + ); + await sleep(13000); + // confirm that allowance changed correctly + console.log('Rechecking allowances to confirm approval...'); + let allowancesResponse2 = await request('post', '/eth/allowances', { + tokenList: JSON.stringify(tokens), + connector: connector, + }); + allowances = allowancesResponse2.approvals; + console.log(allowances); + } + } + + // call /approve with invalid spender address + console.log('Trying to approve for invalid contract...'); + const approve3 = await request('post', '/eth/approve', { + token: tokens[0], + connector: 'nill', + }); + console.log(approve3); + // confirm expected error message + assert.notExists(approve3); + + // call /approve with invalid token symbol + console.log('Trying to approve invalid token ABC...'); + const approve4 = await request('post', '/eth/approve', { + token: 'ABC', + connector: connector, + }); + console.log(approve4); + // confirm expected error message + assert.notExists(approve4); + + // call /approve with invalid amount + console.log('Trying to approve invalid amount...'); + const approve5 = await request('post', '/eth/approve', { + token: tokens[0], + connector: connector, + amount: 'number', + }); + console.log(approve5); + // confirm expected error message + assert.notExists(approve5); +} diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index b924742..3ae4c31 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -1,164 +1,7 @@ -// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts -import YAML from 'yaml'; -import fs from 'fs'; -import axios from 'axios'; -import https from 'https'; import { assert } from 'chai'; +import { request, ethTests } from './ethereum.test' -const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir -const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); -const config = YAML.parseDocument(file); - -const host = 'localhost'; -const port = 5000; const tokens = ['WETH', 'DAI']; -const privateKey = config.get('PRIVATE_KEY'); - -function sleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -const httpsAgent = axios.create({ - httpsAgent: new https.Agent({ - ca: fs.readFileSync(config.get('CERT_PATH') + '/ca_cert.pem'), - cert: fs.readFileSync(config.get('CERT_PATH') + '/client_cert.pem'), - key: fs.readFileSync(config.get('CERT_PATH') + '/client_key.pem'), - host: host, - port: port, - requestCert: true, - rejectUnauthorized: false, - }), -}); - -async function request(method, path, params) { - try { - let response; - const gatewayAddress = `https://${host}:${port}`; - if (method === 'get') { - response = await httpsAgent.get(gatewayAddress + path, { - params: params, - }); - } else { - // post - params['privateKey'] = privateKey; - response = await httpsAgent.post(gatewayAddress + path, params); - } - return response.data; - } catch (err) { - console.log(`${path} - ${err}`); - } -} - -async function ethTests() { - console.log('\nStarting ETH tests'); - console.log('***************************************************'); - console.log('Token symbols used in tests: ', tokens); - assert.isAtLeast(tokens.length, 2, 'Pls provide at least 2 tokens'); - assert.exists(privateKey, 'Pls include PRIVATE_KEY in global_conf file'); - - // call / - console.log('Checking status of gateway server...'); - const result = await request('get', '/', {}); - // confirm expected response - console.log(result); - assert.equal(result, 'ok'); - - // call /balances - console.log('Checking balances...'); - const balancesResponse = await request('post', '/eth/balances', { - tokenList: JSON.stringify(tokens), - }); - // confirm and save balances - const balances = balancesResponse.balances; - console.log(balances); - assert.isAbove( - parseFloat(balances.ETH), - 0, - 'Pls ensure there is some native token' - ); - - // call /balances with invalid token symbol - // confirm expected error message - console.log('calling balances with invalid token symbols ABC and XYZ...'); - const balancesResponse1 = await request('post', '/eth/balances', { - tokenList: JSON.stringify(['ABC', 'XYZ']), - }); - console.log(balancesResponse1.balances); - assert.isNaN( - parseFloat(balancesResponse1.balances.ABC), - 'ABC is a valid token.' - ); - assert.isNaN( - parseFloat(balancesResponse1.balances.XYZ), - 'XYZ is a valid token.' - ); - - // call /allowances - // confirm and save allowances - console.log('checking initial allowances...'); - const allowancesResponse1 = await request('post', '/eth/allowances', { - tokenList: JSON.stringify(tokens), - connector: 'uniswap', - }); - let allowances = allowancesResponse1.approvals; - console.log(allowances); - - for (let token of tokens) { - // call /approve on each token - console.log(`Resetting allowance for ${token} to 5000...`); - let approve1 = await request('post', '/eth/approve', { - token: token, - connector: 'uniswap', - amount: '5000', - }); - console.log(approve1); - while (allowances[token] !== approve1.amount) { - console.log( - 'Waiting for atleast 1 block time (i.e 13 secs) to give time for approval to be mined.' - ); - await sleep(13000); - // confirm that allowance changed correctly - console.log('Rechecking allowances to confirm approval...'); - let allowancesResponse2 = await request('post', '/eth/allowances', { - tokenList: JSON.stringify(tokens), - connector: 'uniswap', - }); - allowances = allowancesResponse2.approvals; - console.log(allowances); - } - } - - // call /approve with invalid spender address - console.log('Trying to approve for invalid contract...'); - const approve3 = await request('post', '/eth/approve', { - token: tokens[0], - connector: 'nill', - }); - console.log(approve3); - // confirm expected error message - assert.notExists(approve3); - - // call /approve with invalid token symbol - console.log('Trying to approve invalid token ABC...'); - const approve4 = await request('post', '/eth/approve', { - token: 'ABC', - connector: 'uniswap', - }); - console.log(approve4); - // confirm expected error message - assert.notExists(approve4); - - // call /approve with invalid amount - console.log('Trying to approve invalid amount...'); - const approve5 = await request('post', '/eth/approve', { - token: tokens[0], - connector: 'uniswap', - amount: 'number', - }); - console.log(approve5); - // confirm expected error message - assert.notExists(approve5); -} async function unitTests() { console.log('\nStarting Uniswap tests'); @@ -264,6 +107,6 @@ async function unitTests() { } (async () => { - // await ethTests(); + await ethTests('uniswap', tokens); await unitTests(); })(); diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js index cac834d..e6b16cf 100644 --- a/tests/scripts/uniswap.v3.test.js +++ b/tests/scripts/uniswap.v3.test.js @@ -1,163 +1,8 @@ -// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts -import YAML from 'yaml'; -import fs from 'fs'; -import axios from 'axios'; -import https from 'https'; import { assert } from 'chai'; +import { request, ethTests } from './ethereum.test' -const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir -const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); -const config = YAML.parseDocument(file); - -const host = 'localhost'; -const port = 5000; let tokens = ['COIN1', 'COIN3']; const tier = 'MEDIUM'; -const privateKey = config.get('PRIVATE_KEY'); - -function sleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -const httpsAgent = axios.create({ - httpsAgent: new https.Agent({ - ca: fs.readFileSync(config.get('CERT_PATH') + '/ca_cert.pem'), - cert: fs.readFileSync(config.get('CERT_PATH') + '/client_cert.pem'), - key: fs.readFileSync(config.get('CERT_PATH') + '/client_key.pem'), - host: host, - port: port, - requestCert: true, - rejectUnauthorized: false, - }), -}); - -async function request(method, path, params) { - try { - let response; - const gatewayAddress = `https://${host}:${port}`; - if (method === 'get') { - response = await httpsAgent.get(gatewayAddress + path, { - params: params, - }); - } else { - // post - params['privateKey'] = privateKey; - response = await httpsAgent.post(gatewayAddress + path, params); - } - return response.data; - } catch (err) { - console.log(`${path} - ${err}`); - } -} - -async function ethTests() { - console.log(tokens); - assert.isAtLeast(tokens.length, 2, 'Pls provise atlease 2 tokens'); - assert.exists(privateKey, 'Pls include PRIVATE_KEY in conf file'); - - // call / - console.log('Checking status of gateway server...'); - const result = await request('get', '/', {}); - // confirm expected response - console.log(result); - assert.equal(result, 'ok'); - - // call /balances - console.log('Checking balances...'); - const balancesResponse = await request('post', '/eth/balances', { - tokenList: JSON.stringify(tokens), - }); - // confirm and save balances - const balances = balancesResponse.balances; - console.log(balances); - assert.isAbove( - parseFloat(balances.ETH), - 0, - 'Pls ensure there is some native token' - ); - - // call /balances with invalid token symbol - // confirm expected error message - console.log('calling balances with invalid token symbols ABC and XYZ...'); - const balancesResponse1 = await request('post', '/eth/balances', { - tokenList: JSON.stringify(['ABC', 'XYZ']), - }); - console.log(balancesResponse1.balances); - assert.isNaN( - parseFloat(balancesResponse1.balances.ABC), - 'ABC is a valid token.' - ); - assert.isNaN( - parseFloat(balancesResponse1.balances.XYZ), - 'XYZ is a valid token.' - ); - - // call /allowances - // confirm and save allowances - console.log('checking allowances...'); - const allowancesResponse1 = await request('post', '/eth/allowances', { - tokenList: JSON.stringify(tokens), - connector: 'uniswapV3NFTManager', - }); - let allowances = allowancesResponse1.approvals; - console.log(allowances); - - for (let token of tokens) { - // call /approve on each token - console.log(`Approving 5000 ${token}...`); - let approve1 = await request('post', '/eth/approve', { - token: token, - connector: 'uniswapV3NFTManager', - amount: '5000', - }); - console.log(approve1); - while (allowances[token] !== approve1.amount) { - console.log( - 'Waiting for atleast 1 block time to give time for approval to be mined.' - ); - await sleep(13000); - // confirm that allowance changed correctly - console.log('Rechecking allowances to confirm approval...'); - let allowancesResponse2 = await request('post', '/eth/allowances', { - tokenList: JSON.stringify(tokens), - connector: 'uniswapV3NFTManager', - }); - allowances = allowancesResponse2.approvals; - console.log(allowances); - } - } - - // call /approve with invalid spender address - console.log('Trying to approve for invalid contract...'); - const approve3 = await request('post', '/eth/approve', { - token: tokens[0], - connector: 'nill', - }); - console.log(approve3); - // confirm expected error message - assert.notExists(approve3); - - // call /approve with invalid token symbol - console.log('Trying to approve invalid token ABC...'); - const approve4 = await request('post', '/eth/approve', { - token: 'ABC', - connector: 'uniswapV3NFTManager', - }); - console.log(approve4); - // confirm expected error message - assert.notExists(approve4); - - // call /approve with invalid amount - console.log('Trying to approve invalid amount...'); - const approve5 = await request('post', '/eth/approve', { - token: tokens[0], - connector: 'uniswapV3NFTManager', - amount: 'number', - }); - console.log(approve5); - // confirm expected error message - assert.notExists(approve5); -} async function unitTests() { // call /start @@ -260,6 +105,6 @@ async function unitTests() { } (async () => { - await ethTests(); + await ethTests('uniswapV3NFTManager', tokens); await unitTests(); })(); From b4ab83a8f74974e44c04ddb0870560243a8cce52 Mon Sep 17 00:00:00 2001 From: vic-en Date: Thu, 26 Aug 2021 11:36:51 +0100 Subject: [PATCH 33/43] add nonce manages to approve endpoint --- src/routes/ethereum.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/routes/ethereum.ts b/src/routes/ethereum.ts index 360f5ee..a1b1f5c 100644 --- a/src/routes/ethereum.ts +++ b/src/routes/ethereum.ts @@ -7,6 +7,8 @@ import { EthereumConfigService } from '../services/ethereum_config'; // import { EthereumGasService } from '../services/ethereum_gas'; import Fees from '../services/fees'; +import { getNonceManager } from '../services/utils'; + import { logger } from '../services/logger'; import { Router, Request, Response } from 'express'; import { ethers } from 'ethers'; @@ -136,7 +138,9 @@ router.post('/approve', async (req: Request, res: Response) => { } // Getting Wallet try { - const wallet = ethereumService.getWallet(req.body.privateKey); + const wallet = await getNonceManager( + ethereumService.getWallet(req.body.privateKey) + ); // Getting token info const token = ethereumService.getERC20Token(req.body.token); From 7027cfaa6d4129aa7583fd2d9eb0653f59bca316 Mon Sep 17 00:00:00 2001 From: vic-en Date: Thu, 26 Aug 2021 11:44:14 +0100 Subject: [PATCH 34/43] fix lint --- package.json | 2 +- src/routes/uniswap.ts | 21 +++++++++-- src/services/ethereum.ts | 3 +- tests/example-test.js | 63 -------------------------------- tests/scripts/ethereum.test.js | 2 +- tests/scripts/uniswap.v2.test.js | 2 +- tests/scripts/uniswap.v3.test.js | 10 ++--- 7 files changed, 27 insertions(+), 76 deletions(-) delete mode 100644 tests/example-test.js diff --git a/package.json b/package.json index 08e9968..9e175b1 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "prebuild": "rimraf dist && mkdir dist", "build": "tsc --project ./", "format": "prettier . --write", - "lint": "eslint src test --format table --fix", + "lint": "eslint src tests --format table --fix", "debug": "DEBUG=*router nodemon --ext 'ts,js,json' --exec 'ts-node' src/index.ts", "start": "pm2 start dist/index.js --no-daemon", "status": "pm2 monit", diff --git a/src/routes/uniswap.ts b/src/routes/uniswap.ts index 42a82c1..4561659 100644 --- a/src/routes/uniswap.ts +++ b/src/routes/uniswap.ts @@ -87,7 +87,10 @@ router.get('/start', async (req: Request, res: Response) => { return; } } - const gasCost = await feesOld.getGasCost(fees.getGasPrice(), uniswap.gasLimit); + const gasCost = await feesOld.getGasCost( + fees.getGasPrice(), + uniswap.gasLimit + ); const result = { network: eth.networkName, timestamp: initTime, @@ -124,7 +127,10 @@ router.post('/trade', async (req: Request, res: Response) => { if (baseToken && quoteToken) { const side = req.body.side.toUpperCase(); const limitPrice = req.body.limitPrice || null; - const gasCost = await feesOld.getGasCost(fees.getGasPrice(), uniswap.gasLimit); + const gasCost = await feesOld.getGasCost( + fees.getGasPrice(), + uniswap.gasLimit + ); try { // fetch the optimal pool mix from uniswap const result: any = @@ -252,7 +258,10 @@ router.post('/price', async (req: Request, res: Response) => { const quoteToken = eth.getERC20Token(req.body.quote); if (baseToken && quoteToken) { const side = req.body.side.toUpperCase(); - const gasCost = await feesOld.getGasCost(fees.getGasPrice(), uniswap.gasLimit); + const gasCost = await feesOld.getGasCost( + fees.getGasPrice(), + uniswap.gasLimit + ); try { const result: any = @@ -296,7 +305,11 @@ router.post('/price', async (req: Request, res: Response) => { trade: trade, }; debug( - `Price ${side} ${baseToken.symbol}-${quoteToken.symbol} | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${uniswap.gasLimit} estimated fee:${gasCost} ETH` + `Price ${side} ${baseToken.symbol}-${ + quoteToken.symbol + } | amount:${amount} (rate:${tradePrice}) - gasPrice:${fees.getGasPrice()} gasLimit:${ + uniswap.gasLimit + } estimated fee:${gasCost} ETH` ); res.status(200).json(result); } else { diff --git a/src/services/ethereum.ts b/src/services/ethereum.ts index 94d0a00..71caa93 100644 --- a/src/services/ethereum.ts +++ b/src/services/ethereum.ts @@ -83,7 +83,8 @@ export class EthereumService { this.chainId = 42; this.erc20TokenList = kovanErc20TokenList; break; - default: // MAINNET + default: + // MAINNET (async () => { const { data } = await axios.get(this.config.tokenListUrl); this.erc20TokenList = data; diff --git a/tests/example-test.js b/tests/example-test.js deleted file mode 100644 index c4dfef0..0000000 --- a/tests/example-test.js +++ /dev/null @@ -1,63 +0,0 @@ -// Example: https://github.com/balancer-labs/balancer-sor/blob/master/test/multihop-sor.spec.ts -import YAML from 'yaml'; -import fs from 'fs'; - -const GlobalConfigFilePath = 'conf/global_conf.yml'; // assume run from root dir -const file = fs.readFileSync(GlobalConfigFilePath, 'utf8'); -const config = YAML.parseDocument(file); - -const tokens = ['WETH', 'DAI', 'MKR', 'USDC']; -const privateKey = config.get('PRIVATE_KEY'); - -async function ethTests() { - console.log(tokens); - console.log(privateKey); - - // call / - // confirm expected response - - // call /balances - // confirm and save balances - const balances = {}; - - // call /balances with invalid token symbol - // confirm expected error message - - // call /allowances - // confirm and save allowances - const allowances = {}; - - // call /balances with invalid token symbol - // confirm expected error message - - // call /approve on each token - // confirm that allowance changed correctly - - // call /approve with invalid spender address - // confirm expected error message - - // call /approve with invalid token symbol - // confirm expected error message - - // call /approve with invalid amount - // confirm expected error message -} - -async function uniTests() { - // call /start - // call /gas-limit - - // call with different combinations of tokens: - // price buy - // price sell - // trade buy - // trade sell - - // add tests for extreme values of limitPrice - buy and sell - - // add tests for extreme values of minimumSlippage - -} - -ethTests(); -uniTests(); diff --git a/tests/scripts/ethereum.test.js b/tests/scripts/ethereum.test.js index 78c51bf..1701c5e 100644 --- a/tests/scripts/ethereum.test.js +++ b/tests/scripts/ethereum.test.js @@ -48,7 +48,7 @@ export async function request(method, path, params) { } } -export async function ethTests( connector = null, tokens = [] ) { +export async function ethTests(connector = null, tokens = []) { console.log('\nStarting ETH tests'); console.log('***************************************************'); console.log('Token symbols used in tests: ', tokens); diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index 3ae4c31..32a1554 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -1,5 +1,5 @@ import { assert } from 'chai'; -import { request, ethTests } from './ethereum.test' +import { request, ethTests } from './ethereum.test'; const tokens = ['WETH', 'DAI']; diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js index e6b16cf..8954061 100644 --- a/tests/scripts/uniswap.v3.test.js +++ b/tests/scripts/uniswap.v3.test.js @@ -1,5 +1,5 @@ import { assert } from 'chai'; -import { request, ethTests } from './ethereum.test' +import { request, ethTests } from './ethereum.test'; let tokens = ['COIN1', 'COIN3']; const tier = 'MEDIUM'; @@ -36,7 +36,7 @@ async function unitTests() { token0: tokens[0], token1: tokens[1], lowerPrice: midPrice.prices[0], - upperPrice: parseFloat(midPrice.prices[0]) + 1, + upperPrice: parseFloat(midPrice.prices[0]) + 1, amount0: '0.01', amount1: '0.01', fee: tier, @@ -56,12 +56,12 @@ async function unitTests() { logs: JSON.stringify(tx1.receipt.logs), pair: pair, }); - for (let inf of parsedLog.info) { + for (let inf of parsedLog.info) { if (inf.name === 'IncreaseLiquidity') { for (let evt of inf.events) { if (evt.name === 'tokenId') { tid = evt.value; - console.log(`New lp order id: ${tid}`) + console.log(`New lp order id: ${tid}`); } } } @@ -90,7 +90,7 @@ async function unitTests() { logs: JSON.stringify(tx2.receipt.logs), pair: pair, }); - for (let inf of parsedLog2.info) { + for (let inf of parsedLog2.info) { if (inf.name === 'DecreaseLiquidity') { for (let evt of inf.events) { if (evt.name === 'tokenId') { From a55c65399d740de7bbb161090a67980242d15ea3 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Thu, 26 Aug 2021 14:59:20 -0700 Subject: [PATCH 35/43] (test) add constants --- tests/scripts/ethereum.test.js | 7 +++-- tests/scripts/uniswap.v2.test.js | 54 +++++++++++++++++--------------- tests/scripts/uniswap.v3.test.js | 24 +++++++------- 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/tests/scripts/ethereum.test.js b/tests/scripts/ethereum.test.js index 1701c5e..f9ecacd 100644 --- a/tests/scripts/ethereum.test.js +++ b/tests/scripts/ethereum.test.js @@ -13,6 +13,9 @@ const host = 'localhost'; const port = 5000; const privateKey = config.get('PRIVATE_KEY'); +// constants +const ALLOWANCE = 5000000; + function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } @@ -104,11 +107,11 @@ export async function ethTests(connector = null, tokens = []) { for (let token of tokens) { // call /approve on each token - console.log(`Resetting allowance for ${token} to 5000...`); + console.log(`Resetting allowance for ${token} to ${ALLOWANCE}...`); let approve1 = await request('post', '/eth/approve', { token: token, connector: connector, - amount: '5000', + amount: ALLOWANCE.toString(), }); console.log(approve1); while (allowances[token] !== approve1.amount) { diff --git a/tests/scripts/uniswap.v2.test.js b/tests/scripts/uniswap.v2.test.js index 32a1554..3312319 100644 --- a/tests/scripts/uniswap.v2.test.js +++ b/tests/scripts/uniswap.v2.test.js @@ -1,13 +1,17 @@ import { assert } from 'chai'; import { request, ethTests } from './ethereum.test'; -const tokens = ['WETH', 'DAI']; +// constants +const TOKENS = ['WETH', 'DAI']; +const AMOUNT_PRICE = 1; +const AMOUNT_TRADE = 0.01; +const SCALE_FACTOR = 1000; async function unitTests() { console.log('\nStarting Uniswap tests'); console.log('***************************************************'); // call /start - let pair = `${tokens[0]}-${tokens[1]}`; + let pair = `${TOKENS[0]}-${TOKENS[1]}`; console.log(`Starting Uniswap v2 on pair ${pair}...`); const start = await request('get', '/eth/uniswap/start', { pairs: JSON.stringify([pair]), @@ -22,9 +26,9 @@ async function unitTests() { // price buy console.log(`Checking buy price for ${pair}...`); const buyPrice = await request('post', '/eth/uniswap/price', { - base: tokens[0], - quote: tokens[1], - amount: '1', + base: TOKENS[0], + quote: TOKENS[1], + amount: AMOUNT_PRICE.toString(), side: 'buy', }); console.log(`Buy price: ${buyPrice.price}`); @@ -32,19 +36,19 @@ async function unitTests() { // price sell console.log(`Checking sell price for ${pair}...`); const sellPrice = await request('post', '/eth/uniswap/price', { - base: tokens[0], - quote: tokens[1], - amount: '1', + base: TOKENS[0], + quote: TOKENS[1], + amount: AMOUNT_PRICE.toString(), side: 'sell', }); console.log(`Sell price: ${sellPrice.price}`); // trade buy - console.log(`Executing buy trade on ${pair} with 0.01 amount...`); + console.log(`Executing buy trade on ${pair} with ${AMOUNT_TRADE} amount...`); const buy = await request('post', '/eth/uniswap/trade', { - base: tokens[0], - quote: tokens[1], - amount: '0.01', + base: TOKENS[0], + quote: TOKENS[1], + amount: AMOUNT_TRADE.toString(), side: 'buy', limitPrice: buyPrice.price, }); @@ -63,11 +67,11 @@ async function unitTests() { done = false; // trade sell - console.log(`Executing sell trade on ${pair} with 0.01 amount...`); + console.log(`Executing sell trade on ${pair} with ${AMOUNT_TRADE} amount...`); const sell = await request('post', '/eth/uniswap/trade', { - base: tokens[0], - quote: tokens[1], - amount: '0.01', + base: TOKENS[0], + quote: TOKENS[1], + amount: AMOUNT_TRADE.toString(), side: 'sell', limitPrice: sellPrice.price, }); @@ -82,31 +86,31 @@ async function unitTests() { assert.equal(tx2.receipt.status, 1, 'Sell trade reverted.'); // add tests for extreme values of limitPrice - buy and sell - console.log('Testing for failure with extreme values of buy limitPrice...'); + console.log(`Testing for failure with ${buyPrice.price / SCALE_FACTOR} buy limitPrice...`); assert.notExists( await request('post', '/eth/uniswap/trade', { - base: tokens[0], - quote: tokens[1], + base: TOKENS[0], + quote: TOKENS[1], amount: '1', side: 'buy', - limitPrice: buyPrice.price / 1000, + limitPrice: buyPrice.price / SCALE_FACTOR, }) ); // add tests for extreme values of minimumSlippage - console.log('Testing for failure with extreme values of sell limitPrice...'); + console.log(`Testing for failure with ${sellPrice.price * SCALE_FACTOR} sell limitPrice...`); assert.notExists( await request('post', '/eth/uniswap/trade', { - base: tokens[0], - quote: tokens[1], + base: TOKENS[0], + quote: TOKENS[1], amount: '1', side: 'sell', - limitPrice: sellPrice.price * 1000, + limitPrice: sellPrice.price * SCALE_FACTOR, }) ); } (async () => { - await ethTests('uniswap', tokens); + await ethTests('uniswap', TOKENS); await unitTests(); })(); diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js index 8954061..8ea52bc 100644 --- a/tests/scripts/uniswap.v3.test.js +++ b/tests/scripts/uniswap.v3.test.js @@ -1,19 +1,21 @@ import { assert } from 'chai'; import { request, ethTests } from './ethereum.test'; -let tokens = ['COIN1', 'COIN3']; -const tier = 'MEDIUM'; +// constants +const TOKENS = ['COIN1', 'COIN3']; +const AMOUNTS = [0.01, 0.01]; +const TIER = 'MEDIUM'; async function unitTests() { // call /start - let pair = `${tokens[0]}-${tokens[1]}`; + let pair = `${TOKENS[0]}-${TOKENS[1]}`; console.log(`Starting Uniswap v3 on pair ${pair}...`); const start = await request('get', '/eth/uniswap/v3/start', { pairs: JSON.stringify([pair]), }); console.log(start); pair = start.pairs[0]; - tokens = pair.split('-'); + let tokens = pair.split('-'); // call /gas-limit console.log('Calling uniswap v3 gas-limit endpoint...'); @@ -21,25 +23,25 @@ async function unitTests() { console.log(gasLimit); // mid price - console.log(`Checking mid price for ${pair} on the ${tier} fee tier...`); + console.log(`Checking mid price for ${pair} on the ${TIER} fee tier...`); const midPrice = await request('post', '/eth/uniswap/v3/price', { base: tokens[0], quote: tokens[1], seconds: '1', - tier: tier, + tier: TIER, }); console.log(`Mid price: ${midPrice.prices[0]}`); // add position - console.log(`Adding position on ${tier} fee tier for ${pair}...`); + console.log(`Adding position on ${TIER} fee tier for ${pair}...`); const pid = await request('post', '/eth/uniswap/v3/add-position', { token0: tokens[0], token1: tokens[1], lowerPrice: midPrice.prices[0], upperPrice: parseFloat(midPrice.prices[0]) + 1, - amount0: '0.01', - amount1: '0.01', - fee: tier, + amount0: AMOUNTS[0].toString(), + amount1: AMOUNTS[1].toString(), + fee: TIER, }); assert.hasAnyKeys(pid, ['hash'], 'Add position failed.'); console.log(`New position transaction hash - ${pid.hash}`); @@ -105,6 +107,6 @@ async function unitTests() { } (async () => { - await ethTests('uniswapV3NFTManager', tokens); + await ethTests('uniswapV3NFTManager', TOKENS); await unitTests(); })(); From 6f22786fdbb0d3863f48c75d4e0955e235f3eef2 Mon Sep 17 00:00:00 2001 From: vic-en Date: Fri, 27 Aug 2021 16:35:39 +0100 Subject: [PATCH 36/43] update uniswap v3 --- src/routes/uniswap_v3.ts | 6 +++--- src/services/uniswap_v3.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/routes/uniswap_v3.ts b/src/routes/uniswap_v3.ts index f2ffda4..4025e6b 100644 --- a/src/routes/uniswap_v3.ts +++ b/src/routes/uniswap_v3.ts @@ -26,8 +26,8 @@ const uniswap = new UniswapV3(globalConfig.getConfig('ETHEREUM_CHAIN')); const fees = new Fees(); -const swapMoreThanMaxPriceError = 'Price too high'; -const swapLessThanMaxPriceError = 'Price too low'; +// const swapMoreThanMaxPriceError = 'Price too high'; +// const swapLessThanMaxPriceError = 'Price too low'; const estimateGasLimit = () => { return uniswap.gasLimit; @@ -348,7 +348,7 @@ router.post('/price', async (req: Request, res: Response) => { const gasCost = await fees.getGasCost(gasPrice, gasLimit); try { // fetch pools for all tiers - let priceResult, price; + let priceResult; // , price; if (req.body.amount) { /* // get price at this depth diff --git a/src/services/uniswap_v3.js b/src/services/uniswap_v3.js index a8a880e..59b2f16 100644 --- a/src/services/uniswap_v3.js +++ b/src/services/uniswap_v3.js @@ -347,7 +347,7 @@ Note that extending the uniswap v2 code may be possible in the future if uniswap liquidityPercentage: this.get_percent(percent), slippageTolerance: this.get_slippage(), deadline: this.get_ttl(), - burnToken: percent == 100 ? true : false, + burnToken: false, // percent == 100 ? true : false, collectOptions: { expectedCurrencyOwed0: new uni.CurrencyAmount.fromRawAmount( token0, From 67d0a54211d5b7911502354bb0e172a4ff52e4a4 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Fri, 27 Aug 2021 13:42:00 -0700 Subject: [PATCH 37/43] (fix) updated ethereum base collection --- ...eway-Ethereum-Base.postman_collection.json | 1733 ++++++----------- 1 file changed, 595 insertions(+), 1138 deletions(-) diff --git a/tests/postman/Gateway-Ethereum-Base.postman_collection.json b/tests/postman/Gateway-Ethereum-Base.postman_collection.json index b73fe32..e54b3ca 100644 --- a/tests/postman/Gateway-Ethereum-Base.postman_collection.json +++ b/tests/postman/Gateway-Ethereum-Base.postman_collection.json @@ -1,1139 +1,596 @@ { - "info": { - "_postman_id": "e39af94e-6095-479e-8ba0-66930b12e364", - "name": "Gateway-Ethereum-Base", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "ethereum", - "item": [ - { - "name": "eth/balances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenAddressList", - "value": "{ \"{{WETH}}\": 18, \"{{DAI}}\": 18}", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balances", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balances"] - } - }, - "response": [] - }, - { - "name": "eth/allowances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenAddressList", - "value": "{ \"{{BAT}}\": 18, \"{{DAI}}\": 18 }", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/allowances", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "allowances"] - } - }, - "response": [] - }, - { - "name": "eth/approve", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenAddress", - "value": "{{WETH}}", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "gasPrice", - "value": "23", - "type": "text" - }, - { - "key": "decimals", - "value": "18", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "amount", - "value": "999999", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/approve", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "approve"] - } - }, - "response": [] - }, - { - "name": "eth/get-receipt", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "txHash", - "value": "{{txHash}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/get-receipt", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "get-receipt"] - } - }, - "response": [] - } - ], - "protocolProfileBehavior": {} - }, - { - "name": "balancer", - "item": [ - { - "name": "balancer", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/balancer", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["balancer"] - } - }, - "response": [] - }, - { - "name": "balancer/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "maxSwaps", - "value": "3", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/balancer/gas-limit", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["balancer", "gas-limit"] - } - }, - "response": [] - }, - { - "name": "balancer/buy-price/", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "{{BAT}}", - "type": "text" - }, - { - "key": "quote", - "value": "{{DAI}}", - "type": "text" - }, - { - "key": "amount", - "value": "10", - "type": "text" - }, - { - "key": "maxSwaps", - "value": "4", - "type": "text" - }, - { - "key": "base_decimals", - "value": "18", - "type": "text" - }, - { - "key": "quote_decimals", - "value": "18", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/balancer/buy-price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["balancer", "buy-price"] - } - }, - "response": [ - { - "name": "{network}/quote", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "http://localhost:5000/{{network}}/quote/trading_pair/{{celo-cusd}}/amount/1", - "protocol": "http", - "host": ["localhost"], - "port": "5000", - "path": [ - "{{network}}", - "quote", - "trading_pair", - "{{celo-cusd}}", - "amount", - "1" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Security-Policy", - "value": "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests" - }, - { - "key": "X-DNS-Prefetch-Control", - "value": "off" - }, - { - "key": "Expect-CT", - "value": "max-age=0" - }, - { - "key": "X-Frame-Options", - "value": "SAMEORIGIN" - }, - { - "key": "Strict-Transport-Security", - "value": "max-age=15552000; includeSubDomains" - }, - { - "key": "X-Download-Options", - "value": "noopen" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "none" - }, - { - "key": "Referrer-Policy", - "value": "no-referrer" - }, - { - "key": "X-XSS-Protection", - "value": "0" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "97" - }, - { - "key": "ETag", - "value": "W/\"61-Wemp9YmP9g/CsUFMa7Y5zK6SoLQ\"" - }, - { - "key": "Date", - "value": "Wed, 23 Sep 2020 18:07:26 GMT" - }, - { - "key": "Connection", - "value": "keep-alive" - } - ], - "cookie": [], - "body": "{\n \"timestamp\": 1600884444051,\n \"latency\": 2.542,\n \"trading_pair\": \"CELO-CUSD\",\n \"price\": 2.5435604641582747\n}" - } - ] - }, - { - "name": "balancer/sell-price/", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "{{BAT}}", - "type": "text" - }, - { - "key": "quote", - "value": "{{DAI}}", - "type": "text" - }, - { - "key": "amount", - "value": "10", - "type": "text" - }, - { - "key": "maxSwaps", - "value": "4", - "type": "text" - }, - { - "key": "base_decimals", - "value": "18", - "type": "text" - }, - { - "key": "quote_decimals", - "value": "18", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/balancer/sell-price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["balancer", "sell-price"] - } - }, - "response": [ - { - "name": "{network}/quote", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "http://localhost:5000/{{network}}/quote/trading_pair/{{celo-cusd}}/amount/1", - "protocol": "http", - "host": ["localhost"], - "port": "5000", - "path": [ - "{{network}}", - "quote", - "trading_pair", - "{{celo-cusd}}", - "amount", - "1" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Security-Policy", - "value": "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests" - }, - { - "key": "X-DNS-Prefetch-Control", - "value": "off" - }, - { - "key": "Expect-CT", - "value": "max-age=0" - }, - { - "key": "X-Frame-Options", - "value": "SAMEORIGIN" - }, - { - "key": "Strict-Transport-Security", - "value": "max-age=15552000; includeSubDomains" - }, - { - "key": "X-Download-Options", - "value": "noopen" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "none" - }, - { - "key": "Referrer-Policy", - "value": "no-referrer" - }, - { - "key": "X-XSS-Protection", - "value": "0" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "97" - }, - { - "key": "ETag", - "value": "W/\"61-Wemp9YmP9g/CsUFMa7Y5zK6SoLQ\"" - }, - { - "key": "Date", - "value": "Wed, 23 Sep 2020 18:07:26 GMT" - }, - { - "key": "Connection", - "value": "keep-alive" - } - ], - "cookie": [], - "body": "{\n \"timestamp\": 1600884444051,\n \"latency\": 2.542,\n \"trading_pair\": \"CELO-CUSD\",\n \"price\": 2.5435604641582747\n}" - } - ] - }, - { - "name": "balancer/buy", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "{{BAT}}", - "type": "text" - }, - { - "key": "quote", - "value": "{{DAI}}", - "type": "text" - }, - { - "key": "amount", - "value": "1", - "type": "text" - }, - { - "key": "maxSwaps", - "value": "4", - "type": "text" - }, - { - "key": "maxPrice", - "value": "0.19767217120251", - "type": "text" - }, - { - "key": "gasPrice", - "value": "37", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "base_decimals", - "value": "18", - "type": "text" - }, - { - "key": "quote_decimals", - "value": "18", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/balancer/buy", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["balancer", "buy"] - } - }, - "response": [ - { - "name": "{network}/quote", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "http://localhost:5000/{{network}}/quote/trading_pair/{{celo-cusd}}/amount/1", - "protocol": "http", - "host": ["localhost"], - "port": "5000", - "path": [ - "{{network}}", - "quote", - "trading_pair", - "{{celo-cusd}}", - "amount", - "1" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Security-Policy", - "value": "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests" - }, - { - "key": "X-DNS-Prefetch-Control", - "value": "off" - }, - { - "key": "Expect-CT", - "value": "max-age=0" - }, - { - "key": "X-Frame-Options", - "value": "SAMEORIGIN" - }, - { - "key": "Strict-Transport-Security", - "value": "max-age=15552000; includeSubDomains" - }, - { - "key": "X-Download-Options", - "value": "noopen" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "none" - }, - { - "key": "Referrer-Policy", - "value": "no-referrer" - }, - { - "key": "X-XSS-Protection", - "value": "0" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "97" - }, - { - "key": "ETag", - "value": "W/\"61-Wemp9YmP9g/CsUFMa7Y5zK6SoLQ\"" - }, - { - "key": "Date", - "value": "Wed, 23 Sep 2020 18:07:26 GMT" - }, - { - "key": "Connection", - "value": "keep-alive" - } - ], - "cookie": [], - "body": "{\n \"timestamp\": 1600884444051,\n \"latency\": 2.542,\n \"trading_pair\": \"CELO-CUSD\",\n \"price\": 2.5435604641582747\n}" - } - ] - }, - { - "name": "balancer/sell", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "{{BAT}}", - "type": "text" - }, - { - "key": "quote", - "value": "{{DAI}}", - "type": "text" - }, - { - "key": "amount", - "value": "0.1", - "type": "text" - }, - { - "key": "maxSwaps", - "value": "4", - "type": "text" - }, - { - "key": "maxPrice", - "value": "0.2685681573104575", - "type": "text" - }, - { - "key": "gasPrice", - "value": "37", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "base_decimals", - "value": "18", - "type": "text" - }, - { - "key": "quote_decimals", - "value": "18", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/balancer/sell", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["balancer", "sell"] - } - }, - "response": [ - { - "name": "{network}/quote", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "http://localhost:5000/{{network}}/quote/trading_pair/{{celo-cusd}}/amount/1", - "protocol": "http", - "host": ["localhost"], - "port": "5000", - "path": [ - "{{network}}", - "quote", - "trading_pair", - "{{celo-cusd}}", - "amount", - "1" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Security-Policy", - "value": "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests" - }, - { - "key": "X-DNS-Prefetch-Control", - "value": "off" - }, - { - "key": "Expect-CT", - "value": "max-age=0" - }, - { - "key": "X-Frame-Options", - "value": "SAMEORIGIN" - }, - { - "key": "Strict-Transport-Security", - "value": "max-age=15552000; includeSubDomains" - }, - { - "key": "X-Download-Options", - "value": "noopen" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "none" - }, - { - "key": "Referrer-Policy", - "value": "no-referrer" - }, - { - "key": "X-XSS-Protection", - "value": "0" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "97" - }, - { - "key": "ETag", - "value": "W/\"61-Wemp9YmP9g/CsUFMa7Y5zK6SoLQ\"" - }, - { - "key": "Date", - "value": "Wed, 23 Sep 2020 18:07:26 GMT" - }, - { - "key": "Connection", - "value": "keep-alive" - } - ], - "cookie": [], - "body": "{\n \"timestamp\": 1600884444051,\n \"latency\": 2.542,\n \"trading_pair\": \"CELO-CUSD\",\n \"price\": 2.5435604641582747\n}" - } - ] - } - ], - "protocolProfileBehavior": {} - }, - { - "name": "uniswap", - "item": [ - { - "name": "uniswap", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/uniswap", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["uniswap"] - } - }, - "response": [] - }, - { - "name": "uniswap/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/uniswap/gas-limit", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["uniswap", "gas-limit"] - } - }, - "response": [] - }, - { - "name": "uniswap/buy-price/", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "{{BAT}}", - "type": "text" - }, - { - "key": "quote", - "value": "{{DAI}}", - "type": "text" - }, - { - "key": "amount", - "value": "10", - "type": "text" - }, - { - "key": "base_decimals", - "value": "18", - "type": "text" - }, - { - "key": "quote_decimals", - "value": "18", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/uniswap/buy-price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["uniswap", "buy-price"] - } - }, - "response": [ - { - "name": "{network}/quote", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "http://localhost:5000/{{network}}/quote/trading_pair/{{celo-cusd}}/amount/1", - "protocol": "http", - "host": ["localhost"], - "port": "5000", - "path": [ - "{{network}}", - "quote", - "trading_pair", - "{{celo-cusd}}", - "amount", - "1" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Security-Policy", - "value": "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests" - }, - { - "key": "X-DNS-Prefetch-Control", - "value": "off" - }, - { - "key": "Expect-CT", - "value": "max-age=0" - }, - { - "key": "X-Frame-Options", - "value": "SAMEORIGIN" - }, - { - "key": "Strict-Transport-Security", - "value": "max-age=15552000; includeSubDomains" - }, - { - "key": "X-Download-Options", - "value": "noopen" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "none" - }, - { - "key": "Referrer-Policy", - "value": "no-referrer" - }, - { - "key": "X-XSS-Protection", - "value": "0" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "97" - }, - { - "key": "ETag", - "value": "W/\"61-Wemp9YmP9g/CsUFMa7Y5zK6SoLQ\"" - }, - { - "key": "Date", - "value": "Wed, 23 Sep 2020 18:07:26 GMT" - }, - { - "key": "Connection", - "value": "keep-alive" - } - ], - "cookie": [], - "body": "{\n \"timestamp\": 1600884444051,\n \"latency\": 2.542,\n \"trading_pair\": \"CELO-CUSD\",\n \"price\": 2.5435604641582747\n}" - } - ] - }, - { - "name": "uniswap/sell-price/", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "{{BAT}}", - "type": "text" - }, - { - "key": "quote", - "value": "{{DAI}}", - "type": "text" - }, - { - "key": "amount", - "value": "10", - "type": "text" - }, - { - "key": "base_decimals", - "value": "18", - "type": "text" - }, - { - "key": "quote_decimals", - "value": "18", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/uniswap/sell-price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["uniswap", "sell-price"] - } - }, - "response": [ - { - "name": "{network}/quote", - "originalRequest": { - "method": "GET", - "header": [], - "url": { - "raw": "http://localhost:5000/{{network}}/quote/trading_pair/{{celo-cusd}}/amount/1", - "protocol": "http", - "host": ["localhost"], - "port": "5000", - "path": [ - "{{network}}", - "quote", - "trading_pair", - "{{celo-cusd}}", - "amount", - "1" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Content-Security-Policy", - "value": "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests" - }, - { - "key": "X-DNS-Prefetch-Control", - "value": "off" - }, - { - "key": "Expect-CT", - "value": "max-age=0" - }, - { - "key": "X-Frame-Options", - "value": "SAMEORIGIN" - }, - { - "key": "Strict-Transport-Security", - "value": "max-age=15552000; includeSubDomains" - }, - { - "key": "X-Download-Options", - "value": "noopen" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "none" - }, - { - "key": "Referrer-Policy", - "value": "no-referrer" - }, - { - "key": "X-XSS-Protection", - "value": "0" - }, - { - "key": "Content-Type", - "value": "application/json; charset=utf-8" - }, - { - "key": "Content-Length", - "value": "97" - }, - { - "key": "ETag", - "value": "W/\"61-Wemp9YmP9g/CsUFMa7Y5zK6SoLQ\"" - }, - { - "key": "Date", - "value": "Wed, 23 Sep 2020 18:07:26 GMT" - }, - { - "key": "Connection", - "value": "keep-alive" - } - ], - "cookie": [], - "body": "{\n \"timestamp\": 1600884444051,\n \"latency\": 2.542,\n \"trading_pair\": \"CELO-CUSD\",\n \"price\": 2.5435604641582747\n}" - } - ] - } - ], - "protocolProfileBehavior": {} - } - ], - "protocolProfileBehavior": {} -} + "info": { + "_postman_id": "56ee6c33-d41f-40d2-b248-eaf472c38eb0", + "name": "Gateway-Ethereum-Base", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "ethereum", + "item": [ + { + "name": "eth/balances", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"WETH\", \"DAI\"]", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balances", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balances" + ] + } + }, + "response": [] + }, + { + "name": "eth/allowances", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"WETH\", \"DAI\"]", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/allowances", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "allowances" + ] + } + }, + "response": [] + }, + { + "name": "eth/approve", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "token", + "value": "WETH", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + }, + { + "key": "amount", + "value": "999999", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/approve", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "approve" + ] + } + }, + "response": [] + }, + { + "name": "eth/poll", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "txHash", + "value": "0x8e070298f624a0c65f938cb5a6c1635e8021ba25382f474304e8261e1363dbe3", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/poll", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "poll" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "balancer", + "item": [ + { + "name": "eth/balancer", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "" + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/start", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/start?pairs=[\"WETH-DAI\"]", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "start" + ], + "query": [ + { + "key": "pairs", + "value": "[\"WETH-DAI\"]" + } + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/gas-limit", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "maxSwaps", + "value": "1", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/gas-limit", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "gas-limit" + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/price/", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + }, + { + "key": "limitPrice", + "value": "", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "price" + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/trade", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "price" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "uniswap", + "item": [ + { + "name": "eth/uniswap", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/start", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/start?pairs=[\"WETH-DAI\"]", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "start" + ], + "query": [ + { + "key": "pairs", + "value": "[\"WETH-DAI\"]" + } + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/gas-limit", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/gas-limit", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "gas-limit" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/price", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + }, + { + "key": "", + "value": "", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "price" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/trade", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + }, + { + "key": "limitPrice", + "value": "", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/trade", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "trade" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file From f6ec35116fa590489c388f23e609d12c52938547 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Fri, 27 Aug 2021 14:42:50 -0700 Subject: [PATCH 38/43] (fix) reorganized postman dir and updated uniswap-v3 collection --- ...eway-Ethereum-Base.postman_collection.json | 596 ------------- .../Uniswap_V3_postman_collection.json | 465 ---------- ...swap_V3_postman_collection_16_07_2021.json | 681 --------------- .../Balancer.postman_collection.json | 216 +++++ .../Ethereum.postman_collection.json | 169 ++++ .../PerpFi.postman_collection.json} | 0 .../Terra.postman_collection.json} | 0 .../Uniswap-V2.postman_collection.json | 214 +++++ .../Uniswap-V3.postman_collection.json | 444 ++++++++++ .../Gateway.postman_environment.json | 0 tests/postman/terra.postman_environment.json | 29 - .../v2/Gateway.postman_collection.json | 819 ------------------ 12 files changed, 1043 insertions(+), 2590 deletions(-) delete mode 100644 tests/postman/Gateway-Ethereum-Base.postman_collection.json delete mode 100644 tests/postman/Uniswap_V3_postman_collection.json delete mode 100644 tests/postman/Uniswap_V3_postman_collection_16_07_2021.json create mode 100644 tests/postman/collections/Balancer.postman_collection.json create mode 100644 tests/postman/collections/Ethereum.postman_collection.json rename tests/postman/{PERPFI.postman_collection.json => collections/PerpFi.postman_collection.json} (100%) rename tests/postman/{Gateway-Terra.postman_collection.json => collections/Terra.postman_collection.json} (100%) create mode 100644 tests/postman/collections/Uniswap-V2.postman_collection.json create mode 100644 tests/postman/collections/Uniswap-V3.postman_collection.json rename tests/postman/{v2 => environments}/Gateway.postman_environment.json (100%) delete mode 100644 tests/postman/terra.postman_environment.json delete mode 100644 tests/postman/v2/Gateway.postman_collection.json diff --git a/tests/postman/Gateway-Ethereum-Base.postman_collection.json b/tests/postman/Gateway-Ethereum-Base.postman_collection.json deleted file mode 100644 index e54b3ca..0000000 --- a/tests/postman/Gateway-Ethereum-Base.postman_collection.json +++ /dev/null @@ -1,596 +0,0 @@ -{ - "info": { - "_postman_id": "56ee6c33-d41f-40d2-b248-eaf472c38eb0", - "name": "Gateway-Ethereum-Base", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "ethereum", - "item": [ - { - "name": "eth/balances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"WETH\", \"DAI\"]", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balances", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balances" - ] - } - }, - "response": [] - }, - { - "name": "eth/allowances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"WETH\", \"DAI\"]", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/allowances", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "allowances" - ] - } - }, - "response": [] - }, - { - "name": "eth/approve", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "token", - "value": "WETH", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "amount", - "value": "999999", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/approve", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "approve" - ] - } - }, - "response": [] - }, - { - "name": "eth/poll", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "txHash", - "value": "0x8e070298f624a0c65f938cb5a6c1635e8021ba25382f474304e8261e1363dbe3", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/poll", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "poll" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "balancer", - "item": [ - { - "name": "eth/balancer", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balancer", - "" - ] - } - }, - "response": [] - }, - { - "name": "eth/balancer/start", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/start?pairs=[\"WETH-DAI\"]", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balancer", - "start" - ], - "query": [ - { - "key": "pairs", - "value": "[\"WETH-DAI\"]" - } - ] - } - }, - "response": [] - }, - { - "name": "eth/balancer/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "maxSwaps", - "value": "1", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/gas-limit", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balancer", - "gas-limit" - ] - } - }, - "response": [] - }, - { - "name": "eth/balancer/price/", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "WETH", - "type": "text" - }, - { - "key": "quote", - "value": "DAI", - "type": "text" - }, - { - "key": "amount", - "value": "0.01", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - }, - { - "key": "limitPrice", - "value": "", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/price", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balancer", - "price" - ] - } - }, - "response": [] - }, - { - "name": "eth/balancer/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "WETH", - "type": "text" - }, - { - "key": "quote", - "value": "DAI", - "type": "text" - }, - { - "key": "amount", - "value": "0.01", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/price", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "balancer", - "price" - ] - } - }, - "response": [] - } - ] - }, - { - "name": "uniswap", - "item": [ - { - "name": "eth/uniswap", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/start", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/start?pairs=[\"WETH-DAI\"]", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "start" - ], - "query": [ - { - "key": "pairs", - "value": "[\"WETH-DAI\"]" - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/gas-limit", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "gas-limit" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/price", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "WETH", - "type": "text" - }, - { - "key": "quote", - "value": "DAI", - "type": "text" - }, - { - "key": "amount", - "value": "0.01", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - }, - { - "key": "", - "value": "", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/price", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "price" - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "WETH", - "type": "text" - }, - { - "key": "quote", - "value": "DAI", - "type": "text" - }, - { - "key": "amount", - "value": "0.01", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - }, - { - "key": "limitPrice", - "value": "", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/trade", - "protocol": "https", - "host": [ - "localhost" - ], - "port": "{{port}}", - "path": [ - "eth", - "uniswap", - "trade" - ] - } - }, - "response": [] - } - ] - } - ] -} \ No newline at end of file diff --git a/tests/postman/Uniswap_V3_postman_collection.json b/tests/postman/Uniswap_V3_postman_collection.json deleted file mode 100644 index 556acd5..0000000 --- a/tests/postman/Uniswap_V3_postman_collection.json +++ /dev/null @@ -1,465 +0,0 @@ -{ - "info": { - "_postman_id": "5de36bfa-027e-46e3-810d-219e42c75314", - "name": "Uniswap V3", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "uniswap v3 endpoints", - "item": [ - { - "name": "eth/uniswap/v3", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/start", - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/start", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "start"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/gas-limit", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "gas-limit"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/result", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/result?logs=§ion=lp", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "result"], - "query": [ - { - "key": "logs", - "value": "" - }, - { - "key": "section", - "value": "lp" - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(current price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "WETH", - "type": "text" - }, - { - "key": "quote", - "value": "USDC", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tier", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "amount", - "value": "0.0001", - "type": "text", - "disabled": true - }, - { - "key": "side", - "value": "buy", - "type": "text", - "disabled": true - }, - { - "key": "seconds", - "value": "10", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "price"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(historical price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "WETH", - "type": "text" - }, - { - "key": "quote", - "value": "USDC", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tier", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "seconds", - "value": "10", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "price"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "amount", - "value": "0.5", - "type": "text" - }, - { - "key": "limitPrice", - "value": "", - "type": "text" - }, - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "side", - "value": "sell", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/trade", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "trade"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenId", - "value": "3413", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/position", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "position"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/add-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "token0", - "value": "COIN1", - "type": "text" - }, - { - "key": "token1", - "value": "COIN3", - "type": "text" - }, - { - "key": "fee", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "lowerPrice", - "value": "0.1", - "type": "text" - }, - { - "key": "upperPrice", - "value": "5", - "type": "text" - }, - { - "key": "amount0", - "value": "10", - "type": "text" - }, - { - "key": "amount1", - "value": "10", - "type": "text" - }, - { - "key": "tokenId", - "value": "3413", - "type": "text", - "disabled": true - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/add-position", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "add-position"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/collect-fees", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "44", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3//collect-fees", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "", "collect-fees"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/remove-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "3413", - "type": "text" - }, - { - "key": "reducePercent", - "value": "50", - "type": "text", - "disabled": true - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/remove-position", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "remove-position"] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [""] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [""] - } - } - ] - } - ] -} diff --git a/tests/postman/Uniswap_V3_postman_collection_16_07_2021.json b/tests/postman/Uniswap_V3_postman_collection_16_07_2021.json deleted file mode 100644 index cda9e0d..0000000 --- a/tests/postman/Uniswap_V3_postman_collection_16_07_2021.json +++ /dev/null @@ -1,681 +0,0 @@ -{ - "info": { - "_postman_id": "5de36bfa-027e-46e3-810d-219e42c75314", - "name": "Uniswap V3", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "uniswap v3 endpoints", - "item": [ - { - "name": "eth/uniswap/v3", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/start", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [ - { - "key": "", - "value": "", - "type": "text" - } - ], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "pairs", - "value": "[\"COIN1-COIN3\"]", - "type": "text", - "disabled": true - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/start?pairs=[\"COIN1-COIN3\"]", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "start"], - "query": [ - { - "key": "pairs", - "value": "[\"COIN1-COIN3\"]" - }, - { - "key": null, - "value": "[\"WETH-USDC\", \"DAI-USDT\", \"BAT-WBTC\"]", - "disabled": true - }, - { - "key": null, - "value": "[\"COIN1-COIN3\"]", - "disabled": true - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/gas-limit", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "gas-limit"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/result", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "logs", - "value": "[\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x3D2097889B97A9eF23B3eA8FC10c626fbda29099\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000008ac7230489e80000\",\n \"logIndex\": 115,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x809F5A762e7b0CC75C42cd76098b85CB7BD2BA64\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000007c0a35c75cb73ef794546bb8c5f7f0912a3d0b29\"\n ],\n \"data\": \"0x0000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 116,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0x7C0a35c75cb73ef794546Bb8C5F7F0912A3d0b29\",\n \"topics\": [\n \"0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde\",\n \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88\",\n \"0x0000000000000000000000000000000000000000000000000000000000000f78\",\n \"0x0000000000000000000000000000000000000000000000000000000000001b30\"\n ],\n \"data\": \"0x000000000000000000000000c36442b4a4522e871399cd717abdd847ab11fe88000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 117,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\n \"0x0000000000000000000000000000000000000000000000000000000000000000\",\n \"0x000000000000000000000000efb7be8631d154d4c0ad8676fec0897b2894fe8f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x\",\n \"logIndex\": 118,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n },\n {\n \"transactionIndex\": 17,\n \"blockNumber\": 25841905,\n \"transactionHash\": \"0x4aaa93a519c346f35acc08456d4ae5985cb0f6a990abf79f062fc901f63b945a\",\n \"address\": \"0xC36442b4a4522E871399CD717aBDD847Ab11FE88\",\n \"topics\": [\n \"0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f\",\n \"0x0000000000000000000000000000000000000000000000000000000000000e7d\"\n ],\n \"data\": \"0x000000000000000000000000000000000000000000000004d669a338b49d21570000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000411d4322db58dc2\",\n \"logIndex\": 119,\n \"blockHash\": \"0xb5819ae17e43df1ea9759b8faf76745681982a2c90ee85edeb88892d809d0b91\"\n }\n ]", - "type": "text" - }, - { - "key": "pair", - "value": "COIN1-COIN3", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/result", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "result"], - "query": [ - { - "key": "", - "value": "", - "disabled": true - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(current price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "amount", - "value": "0.1", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "price"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/price(historical price)", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tier", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "seconds", - "value": "1", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "price"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "COIN3", - "type": "text" - }, - { - "key": "quote", - "value": "COIN1", - "type": "text" - }, - { - "key": "amount", - "value": "0.1", - "type": "text" - }, - { - "key": "limitPrice", - "value": "0", - "type": "text", - "disabled": true - }, - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/trade", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "trade"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenId", - "value": "3883", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/position", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "position"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/add-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "token0", - "value": "COIN3", - "type": "text" - }, - { - "key": "token1", - "value": "COIN1", - "type": "text" - }, - { - "key": "fee", - "value": "MEDIUM", - "type": "text" - }, - { - "key": "lowerPrice", - "value": "0.1", - "type": "text" - }, - { - "key": "upperPrice", - "value": "1.4", - "type": "text" - }, - { - "key": "amount0", - "value": "0.00000001", - "type": "text" - }, - { - "key": "amount1", - "value": "0.001", - "type": "text" - }, - { - "key": "tokenId", - "value": "3709", - "type": "text", - "disabled": true - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/add-position", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "add-position"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/collect-fees", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "3414", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3//collect-fees", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "", "collect-fees"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/v3/remove-position", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "gasPrice", - "value": "37", - "type": "text", - "disabled": true - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "tokenId", - "value": "3883", - "type": "text" - }, - { - "key": "reducePercent", - "value": "100", - "type": "text" - }, - { - "key": "getFee", - "value": "True", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/v3/remove-position", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "v3", "remove-position"] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [""] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [""] - } - } - ] - }, - { - "name": "ethereum", - "item": [ - { - "name": "eth", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth"] - } - }, - "response": [] - }, - { - "name": "eth/balances", - "event": [ - { - "listen": "test", - "script": { - "exec": [""], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"COIN1\", \"COIN2\"]", - "description": "[\"COIN1\", \"COIN2\"]", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balances", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balances"] - } - }, - "response": [] - }, - { - "name": "eth/allowances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"COIN1\", \"COIN2\"]", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/allowances", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "allowances"] - } - }, - "response": [] - }, - { - "name": "eth/approve", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "token", - "value": "WETH", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "amount", - "value": "0", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/approve", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "approve"] - } - }, - "response": [] - }, - { - "name": "eth/poll", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "txHash", - "value": "0xaeba03944a5df71a1888a85473939bd2da31f2f6325d3c3a36a673158dfd9324", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/poll", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "poll"] - } - }, - "response": [] - } - ] - } - ] -} diff --git a/tests/postman/collections/Balancer.postman_collection.json b/tests/postman/collections/Balancer.postman_collection.json new file mode 100644 index 0000000..d033e3e --- /dev/null +++ b/tests/postman/collections/Balancer.postman_collection.json @@ -0,0 +1,216 @@ +{ + "info": { + "_postman_id": "3c837b4c-d9ed-4ab8-baf4-6bc3af708e7a", + "name": "Balancer", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "eth/balancer", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "" + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/start", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/start?pairs=[\"WETH-DAI\"]", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "start" + ], + "query": [ + { + "key": "pairs", + "value": "[\"WETH-DAI\"]" + } + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/gas-limit", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "maxSwaps", + "value": "1", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/gas-limit", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "gas-limit" + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/trade", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "price" + ] + } + }, + "response": [] + }, + { + "name": "eth/balancer/price/", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + }, + { + "key": "limitPrice", + "value": "", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balancer/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balancer", + "price" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/tests/postman/collections/Ethereum.postman_collection.json b/tests/postman/collections/Ethereum.postman_collection.json new file mode 100644 index 0000000..dd25745 --- /dev/null +++ b/tests/postman/collections/Ethereum.postman_collection.json @@ -0,0 +1,169 @@ +{ + "info": { + "_postman_id": "97be3455-820f-44c1-bdda-7cfd06ae2841", + "name": "Ethereum", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "eth/balances", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"WETH\", \"DAI\"]", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/balances", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "balances" + ] + } + }, + "response": [] + }, + { + "name": "eth/allowances", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenList", + "value": "[\"WETH\", \"DAI\"]", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/allowances", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "allowances" + ] + } + }, + "response": [] + }, + { + "name": "eth/approve", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "token", + "value": "WETH", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "connector", + "value": "balancer", + "type": "text" + }, + { + "key": "amount", + "value": "999999", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/approve", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "approve" + ] + } + }, + "response": [] + }, + { + "name": "eth/poll", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "txHash", + "value": "0x8e070298f624a0c65f938cb5a6c1635e8021ba25382f474304e8261e1363dbe3", + "type": "text" + } + ], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/poll", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "poll" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/tests/postman/PERPFI.postman_collection.json b/tests/postman/collections/PerpFi.postman_collection.json similarity index 100% rename from tests/postman/PERPFI.postman_collection.json rename to tests/postman/collections/PerpFi.postman_collection.json diff --git a/tests/postman/Gateway-Terra.postman_collection.json b/tests/postman/collections/Terra.postman_collection.json similarity index 100% rename from tests/postman/Gateway-Terra.postman_collection.json rename to tests/postman/collections/Terra.postman_collection.json diff --git a/tests/postman/collections/Uniswap-V2.postman_collection.json b/tests/postman/collections/Uniswap-V2.postman_collection.json new file mode 100644 index 0000000..32c2302 --- /dev/null +++ b/tests/postman/collections/Uniswap-V2.postman_collection.json @@ -0,0 +1,214 @@ +{ + "info": { + "_postman_id": "9a81deca-3553-42d9-bfbf-590de6f901a2", + "name": "Uniswap-V2", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "eth/uniswap", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/start", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/start?pairs=[\"WETH-DAI\"]", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "start" + ], + "query": [ + { + "key": "pairs", + "value": "[\"WETH-DAI\"]" + } + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/gas-limit", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/gas-limit", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "gas-limit" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/price", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + }, + { + "key": "", + "value": "", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "price" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/trade", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "WETH", + "type": "text" + }, + { + "key": "quote", + "value": "DAI", + "type": "text" + }, + { + "key": "amount", + "value": "0.01", + "type": "text" + }, + { + "key": "side", + "value": "buy", + "type": "text" + }, + { + "key": "limitPrice", + "value": "", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/trade", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "trade" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/tests/postman/collections/Uniswap-V3.postman_collection.json b/tests/postman/collections/Uniswap-V3.postman_collection.json new file mode 100644 index 0000000..63a732c --- /dev/null +++ b/tests/postman/collections/Uniswap-V3.postman_collection.json @@ -0,0 +1,444 @@ +{ + "info": { + "_postman_id": "28f0dee4-0afc-4bee-b41f-60db8087c35e", + "name": "Uniswap-V3", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "eth/uniswap/v3", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/start", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/start?pairs=[\"WETH-DAI\"]", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "start" + ], + "query": [ + { + "key": "pairs", + "value": "[\"WETH-DAI\"]" + } + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/gas-limit", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [], + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/gas-limit", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "gas-limit" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/result", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "logs", + "value": "[]", + "type": "text" + }, + { + "key": "pair", + "value": "WETH-DAI", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/result", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "result" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/price", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "DAI", + "type": "text" + }, + { + "key": "quote", + "value": "WETH", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tier", + "value": "LOW", + "type": "text" + }, + { + "key": "seconds", + "value": "1", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/price", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "price" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/trade", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "base", + "value": "DAI", + "type": "text" + }, + { + "key": "quote", + "value": "WETH", + "type": "text" + }, + { + "key": "amount", + "value": "100", + "type": "text" + }, + { + "key": "side", + "value": "sell", + "type": "text" + }, + { + "key": "limitPrice", + "value": "", + "type": "text" + }, + { + "key": "tier", + "value": "LOW", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/trade", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "trade" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "tokenId", + "value": "6498", + "type": "text" + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/position", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "position" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/add-position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "gasPrice", + "value": "37", + "type": "text", + "disabled": true + }, + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "token0", + "value": "DAI", + "type": "text" + }, + { + "key": "token1", + "value": "WETH", + "type": "text" + }, + { + "key": "fee", + "value": "LOW", + "type": "text" + }, + { + "key": "lowerPrice", + "value": "0.0003", + "type": "text" + }, + { + "key": "upperPrice", + "value": "0.0005", + "type": "text" + }, + { + "key": "amount0", + "value": "100", + "type": "text" + }, + { + "key": "amount1", + "value": "0.05", + "type": "text" + }, + { + "key": "tokenId", + "value": "3413", + "type": "text", + "disabled": true + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/add-position", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "add-position" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/remove-position", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tokenId", + "value": "6498", + "type": "text" + }, + { + "key": "getFee", + "value": "FALSE", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/remove-position", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "remove-position" + ] + } + }, + "response": [] + }, + { + "name": "eth/uniswap/v3/collect-fees", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "urlencoded", + "urlencoded": [ + { + "key": "privateKey", + "value": "{{privateKey}}", + "type": "text" + }, + { + "key": "tokenId", + "value": "6498", + "type": "text" + } + ] + }, + "url": { + "raw": "https://localhost:{{port}}/eth/uniswap/v3/collect-fees", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "{{port}}", + "path": [ + "eth", + "uniswap", + "v3", + "collect-fees" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/tests/postman/v2/Gateway.postman_environment.json b/tests/postman/environments/Gateway.postman_environment.json similarity index 100% rename from tests/postman/v2/Gateway.postman_environment.json rename to tests/postman/environments/Gateway.postman_environment.json diff --git a/tests/postman/terra.postman_environment.json b/tests/postman/terra.postman_environment.json deleted file mode 100644 index eb95c30..0000000 --- a/tests/postman/terra.postman_environment.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "id": "aebe7d1f-0e85-4441-8679-2ddc38d74350", - "name": "terra", - "values": [ - { - "key": "protocol", - "value": "terra", - "enabled": true - }, - { - "key": "port", - "value": "5000", - "enabled": true - }, - { - "key": "address", - "value": "myaddresss", - "enabled": true - }, - { - "key": "secret", - "value": "mysupersecret", - "enabled": true - } - ], - "_postman_variable_scope": "environment", - "_postman_exported_at": "2020-11-13T06:00:14.142Z", - "_postman_exported_using": "Postman/7.35.0" -} diff --git a/tests/postman/v2/Gateway.postman_collection.json b/tests/postman/v2/Gateway.postman_collection.json deleted file mode 100644 index 63baa2a..0000000 --- a/tests/postman/v2/Gateway.postman_collection.json +++ /dev/null @@ -1,819 +0,0 @@ -{ - "info": { - "_postman_id": "c7985e75-fb04-4b2e-96b9-d62561f160d0", - "name": "Gateway", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "v2", - "item": [ - { - "name": "ethereum", - "item": [ - { - "name": "eth", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth"] - } - }, - "response": [] - }, - { - "name": "eth/balances", - "event": [ - { - "listen": "test", - "script": { - "exec": [""], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"BAT\",\"USDC\",\"DAI\",\"WETH\",\"ZRX\"]", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balances", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balances"] - } - }, - "response": [] - }, - { - "name": "eth/allowances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "tokenList", - "value": "[\"BAT\",\"USDC\",\"DAI\",\"WETH\",\"ZRX\"]", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/allowances", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "allowances"] - } - }, - "response": [] - }, - { - "name": "eth/approve", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "token", - "value": "ZRX", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "gasPrice", - "value": "23", - "type": "text" - }, - { - "key": "connector", - "value": "balancer", - "type": "text" - }, - { - "key": "amount", - "value": "999", - "type": "text", - "disabled": true - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/approve", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "approve"] - } - }, - "response": [] - }, - { - "name": "eth/poll", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "txHash", - "value": "{{txHash}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/poll", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "poll"] - } - }, - "response": [] - } - ] - }, - { - "name": "balancer", - "item": [ - { - "name": "eth/balancer", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balancer"] - } - }, - "response": [] - }, - { - "name": "eth/balancer/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/gas-limit", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balancer", "gas-limit"] - } - }, - "response": [] - }, - { - "name": "eth/balancer/start", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/start?pairs=[\"BAT-DAI\"]&gasPrice=30", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balancer", "start"], - "query": [ - { - "key": "pairs", - "value": "[\"BAT-DAI\"]", - "description": ";" - }, - { - "key": "gasPrice", - "value": "30" - } - ] - } - }, - "response": [] - }, - { - "name": "eth/balancer/price", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "BAT", - "type": "text" - }, - { - "key": "quote", - "value": "dai", - "type": "text" - }, - { - "key": "amount", - "value": "10", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balancer", "price"] - } - }, - "response": [] - }, - { - "name": "eth/balancer/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "BAT", - "type": "text" - }, - { - "key": "quote", - "value": "USDC", - "type": "text" - }, - { - "key": "amount", - "value": "1", - "type": "text" - }, - { - "key": "limitPrice", - "value": "0.19767217120251", - "type": "text" - }, - { - "key": "gasPrice", - "value": "37", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "side", - "value": "sell", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/balancer/trade", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "balancer", "trade"] - } - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [""] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [""] - } - } - ] - }, - { - "name": "uniswap", - "item": [ - { - "name": "eth/uniswap", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/gas-limit", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/gas-limit", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "gas-limit"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/start", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/start?pairs=[\"WETH-USDC\"]&gasPrice=30", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "start"], - "query": [ - { - "key": "pairs", - "value": "[\"WETH-USDC\"]" - }, - { - "key": "gasPrice", - "value": "30" - } - ] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/price", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "WETH", - "type": "text" - }, - { - "key": "quote", - "value": "DAI", - "type": "text" - }, - { - "key": "amount", - "value": "1", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "price"] - } - }, - "response": [] - }, - { - "name": "eth/uniswap/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "BAT", - "type": "text" - }, - { - "key": "quote", - "value": "DAI", - "type": "text" - }, - { - "key": "amount", - "value": "1", - "type": "text" - }, - { - "key": "limitPrice", - "value": "0.19767217120251", - "type": "text" - }, - { - "key": "gasPrice", - "value": "37", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{privateKey}}", - "type": "text" - }, - { - "key": "side", - "value": "sell", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/eth/uniswap/trade", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["eth", "uniswap", "trade"] - } - }, - "response": [] - } - ] - }, - { - "name": "terra", - "item": [ - { - "name": "terra", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "address", - "value": "{{address}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/terra", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["terra"] - } - }, - "response": [] - }, - { - "name": "terra/balances", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "address", - "value": "{{terraWalletAddress}}", - "type": "text" - } - ], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/terra/balances", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["terra", "balances"] - } - }, - "response": [] - }, - { - "name": "terra/start", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "LUNA", - "type": "text" - }, - { - "key": "quote", - "value": "UST", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/terra/start", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["terra", "start"] - } - }, - "response": [] - }, - { - "name": "terra/price", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "UST", - "type": "text" - }, - { - "key": "quote", - "value": "KRT", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - }, - { - "key": "amount", - "value": "1", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/terra/price", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["terra", "price"] - } - }, - "response": [] - }, - { - "name": "terra/trade", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "base", - "value": "UST", - "type": "text" - }, - { - "key": "quote", - "value": "KRT", - "type": "text" - }, - { - "key": "side", - "value": "buy", - "type": "text" - }, - { - "key": "amount", - "value": "10", - "type": "text" - }, - { - "key": "privateKey", - "value": "{{terraSeeds}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://localhost:{{port}}/terra/trade", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["terra", "trade"] - } - }, - "response": [] - } - ] - } - ] - }, - { - "name": "/api", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/api", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": ["api"] - } - }, - "response": [] - }, - { - "name": "/", - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [], - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://localhost:{{port}}/", - "protocol": "https", - "host": ["localhost"], - "port": "{{port}}", - "path": [""] - } - }, - "response": [] - } - ] -} From 2fb49a45e09f968a9aef6fbda63903115eb727ba Mon Sep 17 00:00:00 2001 From: vic-en Date: Fri, 27 Aug 2021 23:10:14 +0100 Subject: [PATCH 39/43] add tests for other pools of tested pair --- tests/scripts/uniswap.v3.test.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/scripts/uniswap.v3.test.js b/tests/scripts/uniswap.v3.test.js index 8954061..117f2a0 100644 --- a/tests/scripts/uniswap.v3.test.js +++ b/tests/scripts/uniswap.v3.test.js @@ -1,7 +1,7 @@ import { assert } from 'chai'; import { request, ethTests } from './ethereum.test'; -let tokens = ['COIN1', 'COIN3']; +let tokens = ['WETH', 'DAI']; const tier = 'MEDIUM'; async function unitTests() { @@ -30,6 +30,21 @@ async function unitTests() { }); console.log(`Mid price: ${midPrice.prices[0]}`); + // check if pool exists on other 2 tiers + let tiers = [ "LOW", "MEDIUM", "HIGH" ]; + tiers.pop(tiers.indexOf(tier) - 1); + for (let tr of tiers) { + console.log(`Checking mid price for ${pair} on the ${tr} fee tier...`); + let checkPrice = await request('post', '/eth/uniswap/v3/price', { + base: tokens[0], + quote: tokens[1], + seconds: '1', + tier: tr, + }); + console.log(checkPrice) + } + + // add position console.log(`Adding position on ${tier} fee tier for ${pair}...`); const pid = await request('post', '/eth/uniswap/v3/add-position', { From 30ebd90c92eef2666ce50acee2cde1c69e0c13ab Mon Sep 17 00:00:00 2001 From: vic-en Date: Fri, 27 Aug 2021 23:10:41 +0100 Subject: [PATCH 40/43] assume private key is defined as an env variable --- tests/scripts/ethereum.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/ethereum.test.js b/tests/scripts/ethereum.test.js index 1701c5e..677b22d 100644 --- a/tests/scripts/ethereum.test.js +++ b/tests/scripts/ethereum.test.js @@ -11,7 +11,7 @@ const config = YAML.parseDocument(file); const host = 'localhost'; const port = 5000; -const privateKey = config.get('PRIVATE_KEY'); +const privateKey = process.env.PRIVATE_KEY; function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); From d58e6ca7ddcf61af3b0b4fb1bf3a2d4493fcefcb Mon Sep 17 00:00:00 2001 From: vic-en Date: Fri, 27 Aug 2021 23:13:43 +0100 Subject: [PATCH 41/43] update log when private key doesn't exist --- tests/scripts/ethereum.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/ethereum.test.js b/tests/scripts/ethereum.test.js index 7a70acd..d9f5d2b 100644 --- a/tests/scripts/ethereum.test.js +++ b/tests/scripts/ethereum.test.js @@ -56,7 +56,7 @@ export async function ethTests(connector = null, tokens = []) { console.log('***************************************************'); console.log('Token symbols used in tests: ', tokens); assert.isAtLeast(tokens.length, 2, 'Pls provide at least 2 tokens'); - assert.exists(privateKey, 'Pls include PRIVATE_KEY in global_conf file'); + assert.exists(privateKey, 'Pls set PRIVATE_KEY in environment variable'); // call / console.log('Checking status of gateway server...'); From 2a733882910f8bbe4054df25b09c7fe38d414214 Mon Sep 17 00:00:00 2001 From: Michael Feng Date: Fri, 27 Aug 2021 15:48:29 -0700 Subject: [PATCH 42/43] update README --- tests/README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/README.md b/tests/README.md index 35d0d74..d81a72f 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,23 +1,24 @@ ![Hummingbot](https://i.ibb.co/X5zNkKw/blacklogo-with-text.png) ----- - -The aim of Hummingbot Gateway Test scripts is to test endpoints related to supported decentralized protocols in an ideal order in each script. +Test scripts for endpoints used by different connectors in Hummingbot Gateway ## Requirements -- [Have gateway server properly configured and running](https://docs.hummingbot.io/gateway/installation/) -- Ensure you have the following line containing your private key in the gateway's `global_conf.yml` file: +- [Run the Gateway server](https://docs.hummingbot.io/gateway/installation/) ```bash -PRIVATE_KEY: "********" +yarn start ``` -*** Note that test scripts are expected to be run on thesame machine running the gateway server. *** +- Expose your Ethereum wallet private key as environment variable `PRIVATE_KEY` + +```bash +export PRIVATE_KEY = [your private key] +``` -## How to run test scripts +## How to run -From the root directory, run `node -r esm PATH_TO_SCRIPT` .i.e. to run `uniswap.v2.test.js`, run: +From the root Hummingbot directory, run `node -r esm PATH_TO_SCRIPT` .i.e. to run `uniswap.v2.test.js`, run: ```bash node -r esm ./tests/scripts/uniswap.v2.test.js From e31d2623df61c775b0534f8901dd11bd83573229 Mon Sep 17 00:00:00 2001 From: vic-en Date: Tue, 31 Aug 2021 14:08:50 +0100 Subject: [PATCH 43/43] allow approval when amount isn't sent from client --- src/routes/ethereum.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/routes/ethereum.ts b/src/routes/ethereum.ts index 360f5ee..5987cd9 100644 --- a/src/routes/ethereum.ts +++ b/src/routes/ethereum.ts @@ -144,7 +144,9 @@ router.post('/approve', async (req: Request, res: Response) => { if (!token) { res.status(500).send(`Token "${req.body.token}" is not supported`); } else { - const amount = ethers.utils.parseUnits(req.body.amount, token.decimals); + const amount = req.body.amount + ? ethers.utils.parseUnits(req.body.amount, token.decimals) + : ethers.constants.MaxUint256; // call approve function let approval; try {