From 99fcba7a030243b53fc24f375ca74bebd0ed3ea0 Mon Sep 17 00:00:00 2001 From: artemkolodko Date: Tue, 5 Sep 2023 18:20:45 +0100 Subject: [PATCH 1/9] update /stats --- package-lock.json | 796 +++++++++++++++++++++++++++- src/modules/schedule/exchangeApi.ts | 14 + src/modules/schedule/explorerApi.ts | 18 +- src/modules/schedule/index.ts | 58 +- 4 files changed, 831 insertions(+), 55 deletions(-) create mode 100644 src/modules/schedule/exchangeApi.ts diff --git a/package-lock.json b/package-lock.json index 1fae033b..91a5a17b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,6 +63,16 @@ "typescript": "^4.8.4" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@babel/runtime": { "version": "7.22.10", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz", @@ -83,7 +93,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -105,6 +115,66 @@ "resolved": "https://registry.npmjs.org/@deno/shim-deno-test/-/shim-deno-test-0.4.0.tgz", "integrity": "sha512-oYWcD7CpERZy/TXMTM9Tgh1HD/POHlbY9WpzmAk+5H8DohcxG415Qws8yLGlim3EaKBT2v3lJv01x4G0BosnaQ==" }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "peer": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "peer": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@ethereumjs/common": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.5.0.tgz", @@ -881,11 +951,47 @@ "resolved": "https://registry.npmjs.org/@grammyjs/types/-/types-3.1.2.tgz", "integrity": "sha512-AsSkTUfZCfSEIacUBOQ94qLbZZy3UofkschWv4uBJKEHjuEfGnjeZZgiwhDfTDjmpmW+MbcasvS+FEfD2jiSLw==" }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "peer": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true, + "peer": true + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6.0.0" } @@ -894,18 +1000,56 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "devOptional": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@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, + "peer": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@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, + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "peer": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -1083,25 +1227,25 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "devOptional": true }, "node_modules/@types/bn.js": { "version": "5.1.1", @@ -1769,7 +1913,7 @@ "version": "8.9.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -1777,11 +1921,21 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.0" } @@ -1869,7 +2023,14 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "peer": true }, "node_modules/array-flatten": { "version": "1.1.1", @@ -2282,6 +2443,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -2857,7 +3028,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "node_modules/cross-fetch": { "version": "3.1.8", @@ -3063,6 +3234,13 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "peer": true + }, "node_modules/defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", @@ -3113,7 +3291,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.3.1" } @@ -3132,6 +3310,19 @@ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==" }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "peer": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -3353,6 +3544,74 @@ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, + "node_modules/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, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "dev": true, + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint-config-prettier": { "version": "8.8.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", @@ -3365,6 +3624,100 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "peer": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "peer": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/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, + "peer": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -3648,6 +4001,13 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "peer": true + }, "node_modules/fast-redact": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.2.0.tgz", @@ -3661,6 +4021,29 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "peer": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/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, + "peer": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3711,6 +4094,45 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "dev": true, + "peer": true, + "dependencies": { + "flatted": "^3.2.7", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true, + "peer": true + }, "node_modules/follow-redirects": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", @@ -3905,6 +4327,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "peer": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/global": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", @@ -3914,6 +4349,22 @@ "process": "^0.11.10" } }, + "node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -3978,6 +4429,13 @@ "node": "^12.20.0 || >=14.13.1" } }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "peer": true + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -4266,6 +4724,33 @@ } ] }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/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, + "peer": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4432,6 +4917,16 @@ "node": ">=0.12.0" } }, + "node_modules/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, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-typed-array": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", @@ -4474,6 +4969,19 @@ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -4494,6 +5002,13 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "peer": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -4566,11 +5081,48 @@ "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==" }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "peer": true + }, "node_modules/lokijs": { "version": "1.5.12", "resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.5.12.tgz", @@ -4599,7 +5151,7 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, "node_modules/md5": { "version": "2.3.0", @@ -4864,6 +5416,13 @@ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "peer": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -5106,6 +5665,24 @@ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "peer": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/otpauth": { "version": "9.1.3", "resolved": "https://registry.npmjs.org/otpauth/-/otpauth-9.1.3.tgz", @@ -5125,6 +5702,38 @@ "node": ">=12.20" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "peer": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -5143,6 +5752,19 @@ "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "peer": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-headers": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", @@ -5534,6 +6156,16 @@ "node": ">=10" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "2.8.7", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", @@ -5656,6 +6288,27 @@ "node": ">=0.10.0" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, "node_modules/quick-format-unescaped": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", @@ -5868,6 +6521,16 @@ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -5895,11 +6558,38 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "peer": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rfc4648": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.2.tgz", "integrity": "sha512-tLOizhR6YGovrEBLatX1sdcuhoSCXddw3mqNVAcKxGJ+J0hFeJ+SjeWCv5UPA/WU3YzWPPuCVYgXBKZUPGpKtg==" }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -5925,6 +6615,30 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -6642,6 +7356,13 @@ "node": ">=10.0.0" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "peer": true + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -6735,7 +7456,7 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -6867,6 +7588,32 @@ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "peer": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -7132,7 +7879,7 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7250,7 +7997,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "devOptional": true }, "node_modules/varint": { "version": "5.0.2", @@ -7928,10 +8675,23 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/src/modules/schedule/exchangeApi.ts b/src/modules/schedule/exchangeApi.ts new file mode 100644 index 00000000..6fa113e8 --- /dev/null +++ b/src/modules/schedule/exchangeApi.ts @@ -0,0 +1,14 @@ +import axios from "axios"; + +interface CoinGeckoResponse { + harmony: { + usd: string; + }; +} + +export const getOneRate = async () => { + const { data } = await axios.get( + `https://api.coingecko.com/api/v3/simple/price?ids=harmony&vs_currencies=usd` + ); + return +data.harmony.usd; +} diff --git a/src/modules/schedule/explorerApi.ts b/src/modules/schedule/explorerApi.ts index 4f4a704e..84948b9a 100644 --- a/src/modules/schedule/explorerApi.ts +++ b/src/modules/schedule/explorerApi.ts @@ -2,6 +2,13 @@ import axios from 'axios' import config from "../../config"; import {abbreviateNumber, getPercentDiff} from "./utils"; +export interface MetricsDaily { + date: string + value: string +} + +const { explorerRestApiUrl: apiUrl, explorerRestApiKey: apiKey } = config.schedule + export enum MetricsDailyType { walletsCount = 'wallets_count', transactionsCount = 'transactions_count', @@ -10,14 +17,7 @@ export enum MetricsDailyType { totalFee = 'total_fee', } -export interface MetricsDaily { - date: string - value: string -} - -const { explorerRestApiUrl: apiUrl, explorerRestApiKey: apiKey } = config.schedule - -const getDailyMetrics = async (type: string, limit: number) => { +export const getDailyMetrics = async (type: MetricsDailyType, limit: number) => { const feesUrl = `${apiUrl}/v0/metrics?type=${type}&limit=${limit}` const { data } = await axios.get(feesUrl, { headers: { @@ -28,7 +28,7 @@ const getDailyMetrics = async (type: string, limit: number) => { } export const getFeeStats = async () => { - const metrics = await getDailyMetrics('total_fee', 14) + const metrics = await getDailyMetrics(MetricsDailyType.totalFee, 14) let feesWeek1 = 0, feesWeek2 = 0 diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index a6a919d4..8773b894 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -4,11 +4,12 @@ import cron from 'node-cron' import { LRUCache } from 'lru-cache' import config from '../../config' import {BotContext, OnMessageContext} from "../types"; -import {getFeeStats} from "./explorerApi"; +import {getDailyMetrics, getFeeStats, MetricsDailyType} from "./explorerApi"; import {getAddressBalance, getBotFee, getBotFeeStats} from "./harmonyApi"; import {getBridgeStats} from "./bridgeAPI"; import {statsService} from "../../database/services"; import {abbreviateNumber} from "./utils"; +import {getOneRate} from "./exchangeApi"; enum SupportedCommands { BOT_STATS = 'botstats', @@ -49,26 +50,8 @@ export class BotSchedule { private async prepareMetricsUpdate(refetchData = false) { try { - this.logger.info(`Start preparing stats`) - - const networkFeeStats = await getFeeStats() - const networkFeesReport = `*${networkFeeStats.value}* ONE (${networkFeeStats.change}%)` - - let bridgeStatsReport = this.cache.get('bridge_report') || '' - this.logger.info(`Bridge stats report from cache: "${bridgeStatsReport}"`) - if(refetchData || !bridgeStatsReport) { - const bridgeStats = await getBridgeStats() - bridgeStatsReport = `*${bridgeStats.value}* USD (${bridgeStats.change}%)` - this.cache.set('bridge_report', bridgeStatsReport) - } - - const botFeesReport = await this.getBotFeeReport(this.holderAddress); - - const reportMessage = - `\nNetwork fees (7-day growth): ${networkFeesReport}` + - `\nBridge flow: ${bridgeStatsReport}` + - `\nBot fees: ${botFeesReport}` - + this.logger.info(`Start preparing daily stats...`) + const reportMessage = await this.generateReport() this.logger.info(`Prepared message: "${reportMessage}"`) this.reportMessage = reportMessage return reportMessage @@ -94,7 +77,7 @@ export class BotSchedule { } private async runCronJob() { - cron.schedule('30 17 * * *', () => { + cron.schedule('55 17 * * *', () => { this.prepareMetricsUpdate(true) }, { scheduled: true, @@ -109,7 +92,7 @@ export class BotSchedule { timezone: "Europe/Lisbon" }); - await this.prepareMetricsUpdate() + // await this.prepareMetricsUpdate() // await this.postMetricsUpdate() } @@ -123,20 +106,39 @@ export class BotSchedule { } public async generateReport() { + this.logger.info(`Start generating report...`) const [ + networkFeesWeekly, + walletsCountWeekly, + oneRate, + balance, weeklyUsers, - totalSupportedMessages + dailyMessages ] = await Promise.all([ + getDailyMetrics(MetricsDailyType.totalFee, 7), + getDailyMetrics(MetricsDailyType.walletsCount, 7), + getOneRate(), + getAddressBalance(this.holderAddress), statsService.getActiveUsers(7), statsService.getTotalMessages(1, true) ]) - const report = `\nBot fees: *${abbreviateNumber(balance / Math.pow(10, 18))}* ONE` + - `\nWeekly active users: *${abbreviateNumber(weeklyUsers)}*` + - `\nDaily user engagement: *${abbreviateNumber(totalSupportedMessages)}*` - return report; + const networkFeesSum = networkFeesWeekly.reduce((sum, item) => sum + +item.value, 0) + const walletsCountSum = walletsCountWeekly.reduce((sum, item) => sum + +item.value, 0) + + const networkUsage = + `- Network 7-day fees, wallets, price: ` + + `${networkFeesSum}, ${walletsCountSum}, ${oneRate}` + + const oneBotMetrics = + `-Bot total earns, weekly users, daily messages:` + + `*${abbreviateNumber(balance / Math.pow(10, 18))}* ONE` + + `, *${abbreviateNumber(weeklyUsers)}*` + + `, *${abbreviateNumber(dailyMessages)}*` + + return `${networkUsage}\n${oneBotMetrics}`; } public async generateFullReport() { From 15ce8b575e5b7a3d30ae187cf5e917554c20204f Mon Sep 17 00:00:00 2001 From: artemkolodko Date: Tue, 5 Sep 2023 19:05:30 +0100 Subject: [PATCH 2/9] Complete network and bot metrics /stats --- src/modules/schedule/index.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index c974c530..70b3e13e 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -130,15 +130,18 @@ export class BotSchedule { const networkUsage = `- Network 7-day fees, wallets, price: ` + - `${networkFeesSum}, ${walletsCountSum}, ${oneRate}` + `*${abbreviateNumber(networkFeesSum)}* ONE, ${abbreviateNumber(walletsCountSum)}, $${oneRate.toFixed(4)}` + + const assetsUpdate = + `- Total assets, swaps, stakes: ` const oneBotMetrics = - `-Bot total earns, weekly users, daily messages:` + + `- Bot total earns, weekly users, daily messages: ` + `*${abbreviateNumber(balance / Math.pow(10, 18))}* ONE` + `, *${abbreviateNumber(weeklyUsers)}*` + `, *${abbreviateNumber(dailyMessages)}*` - return `${networkUsage}\n${oneBotMetrics}`; + return `${networkUsage}\n${assetsUpdate}\n${oneBotMetrics}`; } public async generateReportEngagementByCommand(days: number) { From 328db85f1c341e8c7ab2c9302066184198e22a5e Mon Sep 17 00:00:00 2001 From: artemkolodko Date: Tue, 5 Sep 2023 19:43:33 +0100 Subject: [PATCH 3/9] Remove bridge stats --- src/modules/schedule/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index 70b3e13e..66a573ec 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -141,7 +141,7 @@ export class BotSchedule { `, *${abbreviateNumber(weeklyUsers)}*` + `, *${abbreviateNumber(dailyMessages)}*` - return `${networkUsage}\n${assetsUpdate}\n${oneBotMetrics}`; + return `${networkUsage}\n${oneBotMetrics}`; } public async generateReportEngagementByCommand(days: number) { From 57966271b7fe2ec4db7267cb6e7ada9687f0deb0 Mon Sep 17 00:00:00 2001 From: Aishlia Date: Tue, 5 Sep 2023 17:06:31 -0700 Subject: [PATCH 4/9] Fix flag parsing --- src/modules/sd-images/api/helpers.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/sd-images/api/helpers.ts b/src/modules/sd-images/api/helpers.ts index d26f51ad..f0da6a8b 100644 --- a/src/modules/sd-images/api/helpers.ts +++ b/src/modules/sd-images/api/helpers.ts @@ -35,7 +35,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar let height = model.baseModel === 'SDXL 1.0' ? 1024 : 768; if (aspectRatioMatch) { - const aspectRatio = aspectRatioMatch[1]; + const aspectRatio = aspectRatioMatch[2]; const [aspectWidth, aspectHeight] = aspectRatio.split(':').map(Number); if (!isNaN(aspectWidth) && !isNaN(aspectHeight) && aspectHeight !== 0) { @@ -50,7 +50,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar const dimensionsMatch = prompt.match(/(--|\—)d\s+(\d+x\d+)/); if (dimensionsMatch) { - const dimensions = dimensionsMatch[1]; + const dimensions = dimensionsMatch[2]; [width, height] = dimensions.split('x').map(Number); @@ -62,7 +62,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar let cfgScale = 7.0; if (cfgScaleMatch) { - cfgScale = parseFloat(cfgScaleMatch[1]); + cfgScale = parseFloat(cfgScaleMatch[2]); prompt = prompt.replace(/(--|\—)cfg\s+(\d+(\.\d+)?)/, ''); } @@ -72,7 +72,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar let steps = 26; if (stepsMatch) { - steps = parseInt(stepsMatch[1]); + steps = parseInt(stepsMatch[2]); prompt = prompt.replace(/(--|\—)steps\s+(\d+)/, ''); } @@ -82,7 +82,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar let controlnetVersion = 1; if (controlnetVersionMatch) { - controlnetVersion = parseInt(controlnetVersionMatch[1]); + controlnetVersion = parseInt(controlnetVersionMatch[2]); prompt = prompt.replace(/(--|\—)c\s+(\d+)/, ''); } @@ -93,7 +93,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar const seedMatch = prompt.match(/(--|\—)seed\s+(\d+)/); if (seedMatch) { - seed = parseInt(seedMatch[1]); + seed = parseInt(seedMatch[2]); prompt = prompt.replace(/(--|\—)seed\s+(\d+)/, ''); } @@ -104,7 +104,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar const denoiseMatch = prompt.match(/(--|\—)denoise\s+(\d+\.\d+)/); if (denoiseMatch) { - denoise = Number(denoiseMatch[1]); + denoise = Number(denoiseMatch[2]); prompt = prompt.replace(/(--|\—)denoise\s+(\d+\.\d+)/, ''); } @@ -114,7 +114,7 @@ export const getParamsFromPrompt = (originalPrompt: string, model: IModel): IPar let negativePrompt = NEGATIVE_PROMPT; if (noMatch) { - negativePrompt = noMatch[1].trim(); + negativePrompt = noMatch[2].trim(); prompt = prompt.replace(/(--|\—)no\s+(.+?)(?=\s+--|$)/, ''); } From e8d9c514c8ce8306dbd9f001c19b4c5eacd71a44 Mon Sep 17 00:00:00 2001 From: Theo Fandrich Date: Tue, 5 Sep 2023 19:02:41 -0700 Subject: [PATCH 5/9] test edit --- src/database/chat.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database/chat.service.ts b/src/database/chat.service.ts index aa79733f..acd4ce58 100644 --- a/src/database/chat.service.ts +++ b/src/database/chat.service.ts @@ -64,7 +64,7 @@ export class ChatService { const newAmount = bn(chat.creditAmount).minus(bn(amount)) if(newAmount.lt(0)) { - throw new Error(`${accountId} Insufficient credits: cannot withdraw ${amount}, current balance ${chat.creditAmount}`) + throw new Error(`${accountId} Insufficient credits: can not withdraw ${amount}, current balance ${chat.creditAmount}`) } return chatRepository.update({ From 2c2e24f4d49dc67a81b7bd053939314936b42151 Mon Sep 17 00:00:00 2001 From: artemkolodko Date: Wed, 6 Sep 2023 14:37:01 +0100 Subject: [PATCH 6/9] Add bridge metrics --- src/bot.ts | 2 +- src/modules/schedule/bridgeAPI.ts | 16 ++++++++++++++++ src/modules/schedule/index.ts | 24 ++++++++++++++---------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/bot.ts b/src/bot.ts index 35d711e9..cc4733cb 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -442,7 +442,7 @@ bot.command('stop', (ctx) => { logger.info("/stop command"); ctx.session.openAi.chatGpt.chatConversation = []; ctx.session.openAi.chatGpt.usage = 0; - ctx.session.openAi.chatGpt.price = 0; + ctx.session.openAi.chatGpt.price = 0; ctx.session.translate.enable = false; ctx.session.translate.languages = [] ctx.session.oneCountry.lastDomain = "" diff --git a/src/modules/schedule/bridgeAPI.ts b/src/modules/schedule/bridgeAPI.ts index 62a099f9..121398f2 100644 --- a/src/modules/schedule/bridgeAPI.ts +++ b/src/modules/schedule/bridgeAPI.ts @@ -3,6 +3,7 @@ import moment from 'moment' import {abbreviateNumber, getPercentDiff} from "./utils"; const bridgeUrl = 'https://hmy-lz-api-token.fly.dev' +const stakeApiUrl = 'https://api.stake.hmny.io' interface BridgeOperation { id: number @@ -63,6 +64,11 @@ export const getTokensList = async (): Promise => { return data.content } +export const getStakingStats = async () => { + const { data } = await axios.get<{ "total-staking": string }>(`${stakeApiUrl}/networks/harmony/network_info_lite`) + return data +} + export const getBridgeStats = async () => { const daysCount = 7 const weekTimestamp = moment().subtract(daysCount - 1,'days').unix() @@ -129,3 +135,13 @@ export const getBridgeStats = async () => { change } } + +export const getTVL = async () => { + const tokens = await getTokensList() + return tokens.reduce((acc, item) => acc + +item.totalLockedUSD, 0) +} + +export const getTotalStakes = async () => { + const { "total-staking": totalStaking } = await getStakingStats() + return Math.round(+totalStaking / 10**18) +} diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index 66a573ec..67fa99aa 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -6,7 +6,7 @@ import config from '../../config' import {BotContext, OnMessageContext} from "../types"; import {getDailyMetrics, getFeeStats, MetricsDailyType} from "./explorerApi"; import {getAddressBalance, getBotFee, getBotFeeStats} from "./harmonyApi"; -import {getBridgeStats} from "./bridgeAPI"; +import {getBridgeStats, getTotalStakes, getTVL} from "./bridgeAPI"; import {statsService} from "../../database/services"; import {abbreviateNumber} from "./utils"; import {getOneRate} from "./exchangeApi"; @@ -48,7 +48,7 @@ export class BotSchedule { } - private async prepareMetricsUpdate(refetchData = false) { + private async prepareMetricsUpdate() { try { this.logger.info(`Start preparing daily stats...`) const reportMessage = await this.generateReport() @@ -57,7 +57,7 @@ export class BotSchedule { return reportMessage } catch (e) { console.log('### e', e); - this.logger.error(`Cannot get stats: ${(e as Error).message}`) + this.logger.error(`Cannot generate stats report: ${(e as Error).message}`) } } @@ -78,7 +78,7 @@ export class BotSchedule { private async runCronJob() { cron.schedule('55 17 * * *', () => { - this.prepareMetricsUpdate(true) + this.prepareMetricsUpdate() }, { scheduled: true, timezone: "Europe/Lisbon" @@ -91,9 +91,6 @@ export class BotSchedule { scheduled: true, timezone: "Europe/Lisbon" }); - - // await this.prepareMetricsUpdate() - // await this.postMetricsUpdate() } public isSupportedEvent(ctx: OnMessageContext) { @@ -106,12 +103,14 @@ export class BotSchedule { } public async generateReport() { - this.logger.info(`Start generating report...`) const [ networkFeesWeekly, walletsCountWeekly, oneRate, + bridgeTVL, + totalStakes, + balance, weeklyUsers, dailyMessages @@ -120,6 +119,9 @@ export class BotSchedule { getDailyMetrics(MetricsDailyType.walletsCount, 7), getOneRate(), + getTVL(), + getTotalStakes(), + getAddressBalance(this.holderAddress), statsService.getActiveUsers(7), statsService.getTotalMessages(1, true) @@ -132,8 +134,10 @@ export class BotSchedule { `- Network 7-day fees, wallets, price: ` + `*${abbreviateNumber(networkFeesSum)}* ONE, ${abbreviateNumber(walletsCountSum)}, $${oneRate.toFixed(4)}` + console.log('totalStakes', totalStakes) const assetsUpdate = - `- Total assets, swaps, stakes: ` + `- Total assets, swaps, stakes: ` + + `$${abbreviateNumber(bridgeTVL)}, - ,${abbreviateNumber(totalStakes)} ONE` const oneBotMetrics = `- Bot total earns, weekly users, daily messages: ` + @@ -141,7 +145,7 @@ export class BotSchedule { `, *${abbreviateNumber(weeklyUsers)}*` + `, *${abbreviateNumber(dailyMessages)}*` - return `${networkUsage}\n${oneBotMetrics}`; + return `${networkUsage}\n${assetsUpdate}\n${oneBotMetrics}`; } public async generateReportEngagementByCommand(days: number) { From 02d49a71e5e2dfc8a6efd255722c88c0beb9fe23 Mon Sep 17 00:00:00 2001 From: artemkolodko Date: Wed, 6 Sep 2023 14:38:04 +0100 Subject: [PATCH 7/9] Update formatting --- src/modules/schedule/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index 67fa99aa..3d869034 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -142,8 +142,8 @@ export class BotSchedule { const oneBotMetrics = `- Bot total earns, weekly users, daily messages: ` + `*${abbreviateNumber(balance / Math.pow(10, 18))}* ONE` + - `, *${abbreviateNumber(weeklyUsers)}*` + - `, *${abbreviateNumber(dailyMessages)}*` + `, ${abbreviateNumber(weeklyUsers)}` + + `, ${abbreviateNumber(dailyMessages)}` return `${networkUsage}\n${assetsUpdate}\n${oneBotMetrics}`; } From 7fa29ac8e6fe26757557b806c8bcb3aa28b4eb94 Mon Sep 17 00:00:00 2001 From: artemkolodko Date: Wed, 6 Sep 2023 19:55:48 +0100 Subject: [PATCH 8/9] Add swap.country data to /stats report --- src/modules/schedule/index.ts | 52 ++++++----------- src/modules/schedule/subgraphAPI.ts | 88 +++++------------------------ 2 files changed, 33 insertions(+), 107 deletions(-) diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index 3d869034..76b8d123 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -1,15 +1,15 @@ import pino from "pino"; import { Bot } from 'grammy' import cron from 'node-cron' -import { LRUCache } from 'lru-cache' import config from '../../config' import {BotContext, OnMessageContext} from "../types"; -import {getDailyMetrics, getFeeStats, MetricsDailyType} from "./explorerApi"; +import {getDailyMetrics, MetricsDailyType} from "./explorerApi"; import {getAddressBalance, getBotFee, getBotFeeStats} from "./harmonyApi"; -import {getBridgeStats, getTotalStakes, getTVL} from "./bridgeAPI"; +import {getTotalStakes, getTVL} from "./bridgeAPI"; import {statsService} from "../../database/services"; import {abbreviateNumber} from "./utils"; import {getOneRate} from "./exchangeApi"; +import {getTradingVolume} from "./subgraphAPI"; enum SupportedCommands { BOT_STATS = 'botstats', @@ -30,9 +30,6 @@ export class BotSchedule { } }) - private cache = new LRUCache({ max: 100, ttl: 1000 * 60 * 60 * 2 }) - private reportMessage = '' - constructor(bot: Bot) { this.bot = bot @@ -48,19 +45,6 @@ export class BotSchedule { } - private async prepareMetricsUpdate() { - try { - this.logger.info(`Start preparing daily stats...`) - const reportMessage = await this.generateReport() - this.logger.info(`Prepared message: "${reportMessage}"`) - this.reportMessage = reportMessage - return reportMessage - } catch (e) { - console.log('### e', e); - this.logger.error(`Cannot generate stats report: ${(e as Error).message}`) - } - } - private async postMetricsUpdate() { const scheduleChatId = config.schedule.chatId if(!scheduleChatId) { @@ -68,24 +52,20 @@ export class BotSchedule { return } - if(this.reportMessage) { - await this.bot.api.sendMessage(scheduleChatId, this.reportMessage, { + const reportMessage = await this.generateReport() + if(reportMessage) { + await this.bot.api.sendMessage(scheduleChatId, reportMessage, { parse_mode: "Markdown", }) - this.logger.info(`Daily metrics posted in chat ${scheduleChatId}: ${this.reportMessage}`) + this.logger.info(`Daily metrics posted in chat ${scheduleChatId}: ${reportMessage}`) + } else { + this.logger.error(`Cannot prepare daily /stats message`) } } private async runCronJob() { - cron.schedule('55 17 * * *', () => { - this.prepareMetricsUpdate() - }, { - scheduled: true, - timezone: "Europe/Lisbon" - }); - cron.schedule('00 18 * * *', () => { - this.logger.info('Posting daily metrics') + this.logger.info('Posting daily metrics...') this.postMetricsUpdate() }, { scheduled: true, @@ -110,6 +90,7 @@ export class BotSchedule { bridgeTVL, totalStakes, + swapTradingVolume, balance, weeklyUsers, @@ -121,6 +102,7 @@ export class BotSchedule { getTVL(), getTotalStakes(), + getTradingVolume(), getAddressBalance(this.holderAddress), statsService.getActiveUsers(7), @@ -129,15 +111,17 @@ export class BotSchedule { const networkFeesSum = networkFeesWeekly.reduce((sum, item) => sum + +item.value, 0) const walletsCountSum = walletsCountWeekly.reduce((sum, item) => sum + +item.value, 0) + const walletsCountAvg = Math.round(walletsCountSum / walletsCountWeekly.length) const networkUsage = `- Network 7-day fees, wallets, price: ` + - `*${abbreviateNumber(networkFeesSum)}* ONE, ${abbreviateNumber(walletsCountSum)}, $${oneRate.toFixed(4)}` + `*${abbreviateNumber(networkFeesSum)}* ONE, ${abbreviateNumber(walletsCountAvg)}, $${oneRate.toFixed(4)}` + + const swapTradingVolumeSum = swapTradingVolume.reduce((sum, item) => sum + Math.round(+item.volumeUSD), 0) - console.log('totalStakes', totalStakes) const assetsUpdate = `- Total assets, swaps, stakes: ` + - `$${abbreviateNumber(bridgeTVL)}, - ,${abbreviateNumber(totalStakes)} ONE` + `$${abbreviateNumber(bridgeTVL)}, $${abbreviateNumber(swapTradingVolumeSum)}, ${abbreviateNumber(totalStakes)} ONE` const oneBotMetrics = `- Bot total earns, weekly users, daily messages: ` + @@ -197,7 +181,7 @@ export class BotSchedule { const { message_id } = ctx.update.message if(ctx.hasCommand(SupportedCommands.BOT_STATS)) { - const report = await this.prepareMetricsUpdate() + const report = await this.generateReport() if(report) { await ctx.reply(report, { parse_mode: "Markdown", diff --git a/src/modules/schedule/subgraphAPI.ts b/src/modules/schedule/subgraphAPI.ts index 8c325e4a..ac8cc7df 100644 --- a/src/modules/schedule/subgraphAPI.ts +++ b/src/modules/schedule/subgraphAPI.ts @@ -3,94 +3,36 @@ import config from '../../config' import moment from "moment/moment"; import {getPercentDiff} from "./utils"; -interface SwapToken { - feesUSD: string -} - -interface Swap { - timestamp: string - token0: SwapToken - token1: SwapToken -} - -interface SubgraphData { - swaps: Swap[] +export interface TradingVolume { + id: string + volumeUSD: string + date: number } interface SubgraphResponse { - data: SubgraphData + data: { + uniswapDayDatas: TradingVolume[] + } } -const generateQuery = (timestamp: number, skip = 0, first = 100) => { +const generateTradingVolumeQuery = (first = 30) => { return ` query { - swaps(orderBy: timestamp, orderDirection: desc, where: { timestamp_gt: ${timestamp} }, skip: ${skip}, first: ${first}) { - timestamp - token0 { - feesUSD - }, - token1 { - feesUSD - } + uniswapDayDatas(orderBy: date, orderDirection: desc, first: ${first}) { + id, + volumeUSD, + date } } ` } -const getSubgraphData = async (timestamp: number, offset = 0, limit = 1000) => { +export const getTradingVolume = async (daysCount = 30): Promise => { const { data } = await axios.post( config.schedule.swapSubgraphApiUrl, { - query: generateQuery(timestamp, offset, limit), + query: generateTradingVolumeQuery(daysCount), }, ); - return data.data; -} - -export const getSwapFees = async() => { - const daysCount = 7 - const weekTimestamp = moment().subtract(daysCount,'days').unix() - const daysAmountMap: Record = {} - const chunkSize = 1000 - - for (let i = 0; i < 20; i++) { - const { swaps } = await getSubgraphData(weekTimestamp, 0, chunkSize) - swaps.forEach(swap => { - const { timestamp, token0, token1 } = swap - const date = moment(+timestamp * 1000).format('YYYYMMDD') - - const amountUsd = Number(token0.feesUSD) + Number(token1.feesUSD) - if(daysAmountMap[date]) { - daysAmountMap[date] += amountUsd - } else { - daysAmountMap[date] = amountUsd - } - }) - - if(swaps.length < chunkSize) { - break; - } - const lastSwap = swaps[swaps.length - 1] - if(lastSwap && +lastSwap.timestamp < weekTimestamp) { - break; - } - } - - const daysAmountList = Object.entries(daysAmountMap) - .sort(([a], [b]) => +b - +a) - .map(([_, value]) => Math.round(value)) - - const realDaysCount = daysAmountList.length - const value = daysAmountList[0] // Latest day - const valueTotal = daysAmountList.reduce((sum, item) => sum += item, 0) - const average = valueTotal / realDaysCount - let change = getPercentDiff(average, value).toFixed(1) - if(+change > 0) { - change = `+${change}` - } - - return { - value, - change - } + return data.data.uniswapDayDatas; } From 67cc8a94b1cba265e07a7c51d9ca11cca6d36cc3 Mon Sep 17 00:00:00 2001 From: artemkolodko Date: Wed, 6 Sep 2023 19:59:21 +0100 Subject: [PATCH 9/9] Count totalStakes in USD --- src/modules/schedule/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/schedule/index.ts b/src/modules/schedule/index.ts index 76b8d123..cdb20ac2 100644 --- a/src/modules/schedule/index.ts +++ b/src/modules/schedule/index.ts @@ -118,10 +118,11 @@ export class BotSchedule { `*${abbreviateNumber(networkFeesSum)}* ONE, ${abbreviateNumber(walletsCountAvg)}, $${oneRate.toFixed(4)}` const swapTradingVolumeSum = swapTradingVolume.reduce((sum, item) => sum + Math.round(+item.volumeUSD), 0) + const totalStakeUSD = Math.round(oneRate * totalStakes) const assetsUpdate = `- Total assets, swaps, stakes: ` + - `$${abbreviateNumber(bridgeTVL)}, $${abbreviateNumber(swapTradingVolumeSum)}, ${abbreviateNumber(totalStakes)} ONE` + `$${abbreviateNumber(bridgeTVL)}, $${abbreviateNumber(swapTradingVolumeSum)}, $${abbreviateNumber(totalStakeUSD)}` const oneBotMetrics = `- Bot total earns, weekly users, daily messages: ` +