diff --git a/.gitignore b/.gitignore index 2f54cb9..81080c9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,8 @@ node_modules/ config.json -/.idea \ No newline at end of file +/.idea + +/.db + +/test_db \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6a4a458 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## v0.0.1 - 2024-11-11 + +Initial release diff --git a/README.md b/README.md index 265a934..2e195b6 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ # Rapid Relayer + Rapid Relayer is a fast, scalable, stateful IBC Relayer optimized for interwoven rollups. -Rapid Relayer does not use the `tx_search` query of Hermes to handle packets from several blocks at once. Initia Labs has developed this IBC Relayer to replace Hermes, only using the necessary functions for packet handling. +Rapid Relayer does not use the `tx_search` query of Hermes to handle packets from several blocks at once. Initia Labs has developed this IBC Relayer to replace Hermes, only using the necessary functions for packet handling. + +## Problems We Faced -### Problems We Faced - Minitia L2s generate blocks extremely quick at 500ms per block. - Due to the interwoven nature of Initia, often many IBC packets are generated within blocks. Hermes can handle batches of packets but on a single block basis. - Hermes handles these IBC packets sequentially leading to unprocessed packets accumulating very quickly when having fast blocktimes. -- If Hermes stops, unprocessed packets will continue to pile up. +- If Hermes stops, unprocessed packets will continue to pile up. - When Hermes misses a packet, it finds them using `tx_search` query on every sequence, this can take minutes for just a few hundred packets. - We need something more rapid. -### How We Fix This +## How We Fix This + - We removed the `tx_search` query, and handle packets in parallel across several blocks at once. - Keep track of `synced_height` and `latest_height`. - Multi-threaded workers: packet handler and event feeder. The event feeder feeds the packet from new blocks to a cache and the packet handler fetches packets from it. This way, even if the packet handler stops, the event feeder will continue to operate. -- We remove the slow call of `tx_search`. - +- We remove the slow call of `tx_search`. ## Installation @@ -38,39 +40,58 @@ npm install ```json { - "port": 3000, + "$schema": "./config.schema.json", + "port": 7010, + "metricPort": 70001, "logLevel": "info", - "pairs": [ + "chains": [ { - "name": "chainA - chainB", // default chainA.chainId - chainB.chainId - "chainA": { - "bech32Prefix": "init", // bech 32 prefix - "chainId": "chain-1", // chainId - "gasPrice": "0.2uinit", // gas price - "lcdUri": "http://rest.chain-1.com", // lcd (rest) uri - "rpcUri": "http://rpc.chain-1.com", // rpc uri - "key": { - "type": "raw", // raw | mnemonic - "privateKey": "12af.." // for raw hex based private key, for mnemonic 12/24 words + "bech32Prefix": "init", + "chainId": "chain-1", + "gasPrice": "0.15gas", + "restUri": "https://rest.chain-1.com", + "rpcUri": "https://rpc.chain-1.com", + "wallets": [ + { + "key": { + "type": "raw", + "privateKey": "123..." + }, + "maxHandlePacket": 10, + "startHeight": 0 // if empty start from the latest height }, - "connectionId": "connection-1", // connection id to relay - "syncInfo": { - "height": 12345, // synced height - "txIndex": 30 // synced tx index - } // Optional, If a syncInfo file exists, this field is ignored. - }, - "chainB": { - "bech32Prefix": "init", - "chainId": "chain-2", - "gasPrice": "0umin", - "lcdUri": "http://rest.chain-2.com", - "rpcUri": "http://rpc.chain-2.com", - "key": { - "type": "mnemonic", - "privateKey": "bus ..." - }, - "connectionId": "connection-0" + { + "key": { + "type": "mnemonic", + "privateKey": "repair family apology column ..." + }, + "maxHandlePacket": 10, + "packetFilter": { + "connections": [{ "connectionId": "conneciton-1" }] + } + } + ], + "feeFilter": { + "recvFee": [{ "denom": "gas", "amount": 100 }], + "timeoutFee": [{ "denom": "gas", "amount": 200 }], + "ackFee": [{ "denom": "gas", "amount": 300 }] } + }, + { + "bech32Prefix": "init", + "chainId": "chain-2", + "gasPrice": "0umin", + "restUri": "https://rest.chain-2.com", + "rpcUri": "https://rpc.chain-2.com", + "wallets": [ + { + "key": { + "type": "raw", + "privateKey": "123..." + }, + "maxHandlePacket": 10 + } + ] } ] } @@ -81,17 +102,18 @@ npm install ```bash npm start ``` + ## Install via docker -```bash + +```bash docker build -t your-tag . ``` -mount a volume called '/config' which contains your config.json -and a /syncInfo volume which will contain the state + +mount a volume called '/config' which contains your config.json +and a /syncInfo volume which will contain the state + ```bash docker run -it -v/tmp/rr/config:/config -v/tmp/rr/syncInfo:/syncInfo -d rapid-relayer:latest ``` -this should start the relayer in a docker container using your config, and placing the state in a separate volume - -## SyncInfo -rapid-relayer checks events and stores processed information in `.syncInfo`. To move migrate relayer to other, please copy `.syncInfo` +this should start the relayer in a docker container using your config, and placing the state in a separate volume diff --git a/config.example.json b/config.example.json index 2f6d396..641fcb4 100644 --- a/config.example.json +++ b/config.example.json @@ -1,37 +1,56 @@ { - "port": 3000, + "$schema": "./config.schema.json", + "port": 7010, + "metricPort": 70001, "logLevel": "info", - "pairs": [ + "chains": [ { - "name": "chainA - chainB", - "chainA": { - "bech32Prefix": "init", - "chainId": "chain-1", - "gasPrice": "0.2uinit", - "lcdUri": "http://rest.chain-1.com", - "rpcUri": "http://rpc.chain-1.com", - "key": { - "type": "raw", - "privateKey": "12af.." + "bech32Prefix": "init", + "chainId": "chain-1", + "gasPrice": "0.15gas", + "restUri": "https://rest.chain-1.com", + "rpcUri": "https://rpc.chain-1.com", + "wallets": [ + { + "key": { + "type": "raw", + "privateKey": "123..." + }, + "maxHandlePacket": 10, + "startHeight": 0 // if empty start from the latest height }, - "connectionId": "connection-1", - "syncInfo": { - "height": 12345, - "txIndex": 30 + { + "key": { + "type": "mnemonic", + "privateKey": "repair family apology column ..." + }, + "maxHandlePacket": 10, + "packetFilter": { + "connections": [{ "connectionId": "conneciton-1" }] + } } - }, - "chainB": { - "bech32Prefix": "init", - "chainId": "chain-2", - "gasPrice": "0umin", - "lcdUri": "http://rest.chain-2.com", - "rpcUri": "http://rpc.chain-2.com", - "key": { - "type": "mnemonic", - "privateKey": "bus ..." - }, - "connectionId": "connection-0" + ], + "feeFilter": { + "recvFee": [{ "denom": "gas", "amount": 100 }], + "timeoutFee": [{ "denom": "gas", "amount": 200 }], + "ackFee": [{ "denom": "gas", "amount": 300 }] } + }, + { + "bech32Prefix": "init", + "chainId": "chain-2", + "gasPrice": "0umin", + "restUri": "https://rest.chain-2.com", + "rpcUri": "https://rpc.chain-2.com", + "wallets": [ + { + "key": { + "type": "raw", + "privateKey": "123..." + }, + "maxHandlePacket": 10 + } + ] } ] } diff --git a/config.schema.json b/config.schema.json new file mode 100644 index 0000000..769037c --- /dev/null +++ b/config.schema.json @@ -0,0 +1,145 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema", + "title": "Rapid Relayer Config", + "description": "Rapid Relayer config schema", + "type": "object", + "required": ["port", "metricPort", "logLevel", "chains"], + "properties": { + "$schema": { + "type": "string" + }, + "port": { + "type": "number" + }, + "dbPath": { + "type": "string" + }, + "metricPort": { + "type": "number" + }, + "logLevel": { + "type": "string" + }, + "chains": { + "type": "array", + "items": { + "$ref": "#/$defs/chain" + }, + "minContains": 2 + } + }, + "additionalProperties": false, + "$defs": { + "chain": { + "type": "object", + "required": [ + "bech32Prefix", + "chainId", + "gasPrice", + "restUri", + "rpcUri", + "wallets" + ], + "properties": { + "bech32Prefix": { + "type": "string", + "description": "bech32 prefix of chain" + }, + "chainId": { + "type": "string", + "description": "chain id" + }, + "gasPrice": { + "type": "string", + "description": "gas price in format 0.1denom" + }, + "restUri": { + "type": "string", + "description": "cosmos rest api uri" + }, + "rpcUri": { + "type": "string", + "description": "cosmos rest rpc uri" + }, + "wallets": { + "type": "array", + "items": { + "$ref": "#/$defs/wallet" + }, + "minContains": "1" + }, + "feeFilter": { + "type": "object", + "properties": { + "recvFee": { + "type": "array", + "items": { + "$ref": "#/$defs/coin" + }, + "minContains": "1" + }, + "ackFee": { + "type": "array", + "items": { + "$ref": "#/$defs/coin" + }, + "minContains": "1" + }, + "timeoutFee": { + "type": "array", + "items": { + "$ref": "#/$defs/coin" + }, + "minContains": "1" + } + } + } + } + }, + "wallet": { + "type": "object", + "required": ["key"], + "properties": { + "key": { + "type": "object", + "required": ["type", "privateKey"], + "properties": { + "type": { + "type": "string", + "enum": ["raw", "mnemonic", "env_raw", "env_mnemonic"] + }, + "privateKey": { + "type": "string" + }, + "options": { + "type": "object", + "properties": { + "account": { + "type": "number" + }, + "index": { + "type": "number" + }, + "coinType": { + "type": "number" + } + } + } + } + } + } + }, + "coin": { + "type": "object", + "required": ["denom", "amount"], + "properties": { + "denom": { + "type": "string" + }, + "amount": { + "type": "number" + } + } + } + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs index bdf3d4e..ea442eb 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,8 +1,7 @@ // @ts-check -import eslint from "@eslint/js"; -import tseslint from "typescript-eslint"; -import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; +import eslint from '@eslint/js' +import tseslint from 'typescript-eslint' export default tseslint.config( eslint.configs.recommended, @@ -12,17 +11,16 @@ export default tseslint.config( { languageOptions: { parserOptions: { - project: "./tsconfig.json", + project: './tsconfig.json', tsconfigRootDir: import.meta.dirname, }, }, }, { - files: ["**/*.js"], + files: ['**/*.js'], ...tseslint.configs.disableTypeChecked, }, - eslintPluginPrettierRecommended, { - ignores: ["dist/**/*", "**/*.config.mjs"], - }, -); + ignores: ['dist/**/*', '**/*.config.mjs'], + } +) diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..a90fbb3 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,11 @@ +// jest.config.js +module.exports = { + preset: 'ts-jest', + setupFilesAfterEnv: ['/src/test/testSetup.ts'], + testEnvironment: 'node', + testMatch: ['**/?(*.)spec.ts'], + moduleNameMapper: { + '^src/(.*)$': '/src/$1', + }, + maxWorkers: 1, +} diff --git a/package-lock.json b/package-lock.json index 531b03f..4af4d57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "ibc-relayer", + "name": "rapid-relayer", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "ibc-relayer", + "name": "rapid-relayer", "version": "0.0.1", "license": "ISC", "dependencies": { @@ -14,10 +14,11 @@ "@cosmjs/json-rpc": "^0.32.3", "@cosmjs/stargate": "^0.32.3", "@cosmjs/tendermint-rpc": "^0.32.3", - "@initia/initia.js": "^0.2.5", + "@initia/initia.js": "^0.2.20", "@initia/initia.proto": "^0.2.0", "axios": "^1.7.5", "bech32": "^2.0.0", + "better-sqlite3": "^11.3.0", "bluebird": "^3.7.2", "express": "^4.19.2", "http": "^0.0.1-security", @@ -26,1548 +27,4436 @@ "prom-client": "^15.1.2", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "^5.4.5", "winston": "^3.13.0" }, "devDependencies": { + "@types/better-sqlite3": "^7.6.11", "@types/bluebird": "^3.5.42", "@types/express": "^4.17.21", + "@types/jest": "^29.5.14", + "@types/node": "^22.5.4", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "husky": "^9.0.11", + "jest": "^29.7.0", + "msw": "^2.6.2", + "ts-jest": "^29.2.5", + "typescript": "^5.6.3", "typescript-eslint": "^7.16.0" } }, - "node_modules/@colors/colors": { - "version": "1.6.0", - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@confio/ics23": { - "version": "0.6.8", + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@noble/hashes": "^1.0.0", - "protobufjs": "^6.8.8" - } - }, - "node_modules/@confio/ics23/node_modules/long": { - "version": "4.0.0", - "license": "Apache-2.0" - }, - "node_modules/@confio/ics23/node_modules/protobufjs": { - "version": "6.11.4", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": ">=13.7.0", - "long": "^4.0.0" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, - "bin": { - "pbjs": "bin/pbjs", - "pbts": "bin/pbts" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@cosmjs/amino": { - "version": "0.32.3", - "license": "Apache-2.0", + "node_modules/@ampproject/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@cosmjs/crypto": "^0.32.3", - "@cosmjs/encoding": "^0.32.3", - "@cosmjs/math": "^0.32.3", - "@cosmjs/utils": "^0.32.3" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@cosmjs/crypto": { - "version": "0.32.3", - "license": "Apache-2.0", + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@cosmjs/encoding": "^0.32.3", - "@cosmjs/math": "^0.32.3", - "@cosmjs/utils": "^0.32.3", - "@noble/hashes": "^1", - "bn.js": "^5.2.0", - "elliptic": "^6.5.4", - "libsodium-wrappers-sumo": "^0.7.11" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@cosmjs/encoding": { - "version": "0.32.3", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" + "node_modules/@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@cosmjs/encoding/node_modules/bech32": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/@cosmjs/json-rpc": { - "version": "0.32.3", - "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.32.3.tgz", - "integrity": "sha512-JwFRWZa+Y95KrAG8CuEbPVOSnXO2uMSEBcaAB/FBU3Mo4jQnDoUjXvt3vwtFWxfAytrWCn1I4YDFaOAinnEG/Q==", + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dev": true, + "license": "MIT", "dependencies": { - "@cosmjs/stream": "^0.32.3", - "xstream": "^11.14.0" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@cosmjs/math": { - "version": "0.32.3", - "license": "Apache-2.0", + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", "dependencies": { - "bn.js": "^5.2.0" + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@cosmjs/proto-signing": { - "version": "0.32.3", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/amino": "^0.32.3", - "@cosmjs/crypto": "^0.32.3", - "@cosmjs/encoding": "^0.32.3", - "@cosmjs/math": "^0.32.3", - "@cosmjs/utils": "^0.32.3", - "cosmjs-types": "^0.9.0" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@cosmjs/socket": { - "version": "0.32.3", - "license": "Apache-2.0", + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "dev": true, + "license": "MIT", "dependencies": { - "@cosmjs/stream": "^0.32.3", - "isomorphic-ws": "^4.0.1", - "ws": "^7", - "xstream": "^11.14.0" + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@cosmjs/stargate": { - "version": "0.32.3", - "license": "Apache-2.0", + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@confio/ics23": "^0.6.8", - "@cosmjs/amino": "^0.32.3", - "@cosmjs/encoding": "^0.32.3", - "@cosmjs/math": "^0.32.3", - "@cosmjs/proto-signing": "^0.32.3", - "@cosmjs/stream": "^0.32.3", - "@cosmjs/tendermint-rpc": "^0.32.3", - "@cosmjs/utils": "^0.32.3", - "cosmjs-types": "^0.9.0", - "xstream": "^11.14.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@cosmjs/stream": { - "version": "0.32.3", - "license": "Apache-2.0", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "dev": true, + "license": "MIT", "dependencies": { - "xstream": "^11.14.0" + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@cosmjs/tendermint-rpc": { - "version": "0.32.3", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/crypto": "^0.32.3", - "@cosmjs/encoding": "^0.32.3", - "@cosmjs/json-rpc": "^0.32.3", - "@cosmjs/math": "^0.32.3", - "@cosmjs/socket": "^0.32.3", - "@cosmjs/stream": "^0.32.3", - "@cosmjs/utils": "^0.32.3", - "axios": "^1.6.0", - "readonly-date": "^1.0.0", - "xstream": "^11.14.0" + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@cosmjs/utils": { - "version": "0.32.3", - "license": "Apache-2.0" - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": ">=12" - } - }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "license": "MIT", - "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": 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" - }, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, + "license": "MIT", "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "@babel/types": "^7.26.0" }, - "engines": { - "node": ">=6.0" + "bin": { + "parser": "bin/babel-parser.js" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/@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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-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==", + "node_modules/@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, - "engines": { - "node": ">=12.22" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "node_modules/@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, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@improbable-eng/grpc-web": { - "version": "0.15.0", - "license": "Apache-2.0", + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", "dependencies": { - "browser-headers": "^0.4.1" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "google-protobuf": "^3.14.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@initia/initia.js": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@initia/initia.js/-/initia.js-0.2.5.tgz", - "integrity": "sha512-smK0h2MlroXJQCY8yR73bUKuIU3WRnB3vPzbIDnCQKZHcqIZ5A8Sl/qz6LQX9cWeAlvuyDYnFDyd+UgSqLOYqg==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "license": "MIT", "dependencies": { - "@initia/initia.proto": "^0.2.0", - "@initia/opinit.proto": "^0.0.8", - "@ledgerhq/hw-transport": "^6.27.12", - "@ledgerhq/hw-transport-webhid": "^6.27.12", - "@ledgerhq/hw-transport-webusb": "^6.27.12", - "@mysten/bcs": "^0.10.1", - "axios": "^1.6.5", - "bech32": "^2.0.0", - "bignumber.js": "^9.1.0", - "bip32": "^2.0.6", - "bip39": "^3.0.4", - "jscrypto": "^1.0.3", - "keccak256": "^1.0.6", - "long": "^5.2.0", - "ripemd160": "^2.0.2", - "secp256k1": "^5.0.0", - "tmp": "^0.2.1", - "ws": "^7.5.9" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { - "node": ">=14" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@initia/initia.proto": { - "version": "0.2.0", - "license": "Apache-2.0", + "node_modules/@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, + "license": "MIT", "dependencies": { - "@improbable-eng/grpc-web": "^0.15.0", - "google-protobuf": "^3.21.0", - "long": "^5.2.3", - "protobufjs": "^7.1.1" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@initia/opinit.proto": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@initia/opinit.proto/-/opinit.proto-0.0.8.tgz", - "integrity": "sha512-MddIGje1CX2lT+jezpWDQv7ex/wLbAK9qCHu+RM/kY13yOwzMeeD539Au2llVB4LWwPEkd0h71HwxJWE78IE1A==", + "node_modules/@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, + "license": "MIT", "dependencies": { - "@improbable-eng/grpc-web": "^0.15.0", - "google-protobuf": "^3.21.0", - "long": "^5.2.0", - "protobufjs": "^7.1.1" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", + "node_modules/@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, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ledgerhq/devices": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.3.0.tgz", - "integrity": "sha512-h5Scr+yIae8yjPOViCHLdMjpqn4oC2Whrsq8LinRxe48LEGMdPqSV1yY7+3Ch827wtzNpMv+/ilKnd8rY+rTlg==", + "node_modules/@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, + "license": "MIT", "dependencies": { - "@ledgerhq/errors": "^6.16.4", - "@ledgerhq/logs": "^6.12.0", - "rxjs": "^7.8.1", - "semver": "^7.3.5" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ledgerhq/errors": { - "version": "6.16.4", - "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.16.4.tgz", - "integrity": "sha512-M57yFaLYSN+fZCX0E0zUqOmrV6eipK+s5RhijHoUNlHUqrsvUz7iRQgpd5gRgHB5VkIjav7KdaZjKiWGcHovaQ==" - }, - "node_modules/@ledgerhq/hw-transport": { - "version": "6.30.6", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.30.6.tgz", - "integrity": "sha512-fT0Z4IywiuJuZrZE/+W0blkV5UCotDPFTYKLkKCLzYzuE6javva7D/ajRaIeR+hZ4kTmKF4EqnsmDCXwElez+w==", + "node_modules/@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, + "license": "MIT", "dependencies": { - "@ledgerhq/devices": "^8.3.0", - "@ledgerhq/errors": "^6.16.4", - "@ledgerhq/logs": "^6.12.0", - "events": "^3.3.0" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ledgerhq/hw-transport-webhid": { - "version": "6.28.6", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.28.6.tgz", - "integrity": "sha512-npU1mgL97KovpTUgcdORoOZ7eVFgwCA7zt0MpgUGUMRNJWDgCFsJslx7KrVXlCGOg87gLfDojreIre502I5pYg==", + "node_modules/@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, + "license": "MIT", "dependencies": { - "@ledgerhq/devices": "^8.3.0", - "@ledgerhq/errors": "^6.16.4", - "@ledgerhq/hw-transport": "^6.30.6", - "@ledgerhq/logs": "^6.12.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ledgerhq/hw-transport-webusb": { - "version": "6.28.6", - "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.28.6.tgz", - "integrity": "sha512-rzICsvhcFcL4wSAvRPe+b9EEWB8cxj6yWy3FZdfs7ufi/0muNpFXWckWv1TC34em55sGXu2cMcwMKXg/O/Lc0Q==", + "node_modules/@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, + "license": "MIT", "dependencies": { - "@ledgerhq/devices": "^8.3.0", - "@ledgerhq/errors": "^6.16.4", - "@ledgerhq/hw-transport": "^6.30.6", - "@ledgerhq/logs": "^6.12.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ledgerhq/logs": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.12.0.tgz", - "integrity": "sha512-ExDoj1QV5eC6TEbMdLUMMk9cfvNKhhv5gXol4SmULRVCx/3iyCPhJ74nsb3S0Vb+/f+XujBEj3vQn5+cwS0fNA==" - }, - "node_modules/@mysten/bcs": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@mysten/bcs/-/bcs-0.10.1.tgz", - "integrity": "sha512-cQDb7Rhz2J82ZqgVQiHykuwKUlgiLWS2bjoajPPW0uvXlb75qrgKuaxh1UzsaRhHy3egk/APc0xjiZoqdbzB4w==", + "node_modules/@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, + "license": "MIT", "dependencies": { - "bs58": "^5.0.0" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@noble/hashes": { - "version": "1.4.0", + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">= 16" + "node": ">=6.9.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, + "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, + "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, "engines": { - "node": ">=8.0.0" + "node": ">=6.9.0" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": ">=6.0" }, - "funding": { - "url": "https://opencollective.com/unts" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "license": "BSD-3-Clause" + "node_modules/@babel/traverse/node_modules/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, + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "license": "BSD-3-Clause" + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@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, + "license": "MIT" + }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", + "integrity": "sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cookie": "^0.7.2" + } + }, + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "statuses": "^2.0.1" + } + }, + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" + } + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@confio/ics23": { + "version": "0.6.8", + "license": "Apache-2.0", + "dependencies": { + "@noble/hashes": "^1.0.0", + "protobufjs": "^6.8.8" + } + }, + "node_modules/@confio/ics23/node_modules/long": { + "version": "4.0.0", + "license": "Apache-2.0" + }, + "node_modules/@confio/ics23/node_modules/protobufjs": { + "version": "6.11.4", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/@cosmjs/amino": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/utils": "^0.32.3" + } + }, + "node_modules/@cosmjs/crypto": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/utils": "^0.32.3", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers-sumo": "^0.7.11" + } + }, + "node_modules/@cosmjs/encoding": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/encoding/node_modules/bech32": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/@cosmjs/json-rpc": { + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.32.3.tgz", + "integrity": "sha512-JwFRWZa+Y95KrAG8CuEbPVOSnXO2uMSEBcaAB/FBU3Mo4jQnDoUjXvt3vwtFWxfAytrWCn1I4YDFaOAinnEG/Q==", + "dependencies": { + "@cosmjs/stream": "^0.32.3", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/math": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@cosmjs/proto-signing": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "^0.32.3", + "@cosmjs/crypto": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/utils": "^0.32.3", + "cosmjs-types": "^0.9.0" + } + }, + "node_modules/@cosmjs/socket": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.32.3", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stargate": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/proto-signing": "^0.32.3", + "@cosmjs/stream": "^0.32.3", + "@cosmjs/tendermint-rpc": "^0.32.3", + "@cosmjs/utils": "^0.32.3", + "cosmjs-types": "^0.9.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stream": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/tendermint-rpc": { + "version": "0.32.3", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/json-rpc": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/socket": "^0.32.3", + "@cosmjs/stream": "^0.32.3", + "@cosmjs/utils": "^0.32.3", + "axios": "^1.6.0", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/utils": { + "version": "0.32.3", + "license": "Apache-2.0" + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "license": "MIT", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "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, + "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.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": 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/eslintrc/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "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, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@improbable-eng/grpc-web": { + "version": "0.15.0", + "license": "Apache-2.0", + "dependencies": { + "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" + } + }, + "node_modules/@initia/initia.js": { + "version": "0.2.21", + "resolved": "https://registry.npmjs.org/@initia/initia.js/-/initia.js-0.2.21.tgz", + "integrity": "sha512-R5fTGXAu0sBwaPHEIoT5BFtvflyfJn54ZgVbzn0Olke5hHKDHHOkZiuF0ymN+4EvgHEnX4ZTjZmtf4gMD4ddhg==", + "license": "Apache-2.0", + "dependencies": { + "@initia/initia.proto": "^0.2.3", + "@initia/opinit.proto": "^0.0.10", + "@ledgerhq/hw-transport": "^6.27.12", + "@ledgerhq/hw-transport-webhid": "^6.27.12", + "@ledgerhq/hw-transport-webusb": "^6.27.12", + "@mysten/bcs": "^1.0.2", + "axios": "^1.7.4", + "bech32": "^2.0.0", + "bignumber.js": "^9.1.0", + "bip32": "^2.0.6", + "bip39": "^3.0.4", + "jscrypto": "^1.0.3", + "keccak256": "^1.0.6", + "long": "^5.2.0", + "ripemd160": "^2.0.2", + "secp256k1": "^5.0.0", + "semver": "^7.6.3", + "ws": "^7.5.10" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@initia/initia.proto": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@initia/initia.proto/-/initia.proto-0.2.3.tgz", + "integrity": "sha512-lmhRNFTzYBGIYZgtiy2DLXIf6VsOXf9/WDgtSPjl9wlFchhbEJrR+PHBxQFYhHen5JmXpXWzESmTSGPUILOXHw==", + "license": "Apache-2.0", + "dependencies": { + "@improbable-eng/grpc-web": "^0.15.0", + "google-protobuf": "^3.21.4", + "long": "^5.2.3", + "protobufjs": "^7.3.2" + } + }, + "node_modules/@initia/opinit.proto": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@initia/opinit.proto/-/opinit.proto-0.0.10.tgz", + "integrity": "sha512-AlLIAZMqeZSld1g0Fp/zXkVjQME19r8N3JEy9rISKqQpjKAIbgnZJ3ukR78nYGdr9TPpt8RBMdDWsjPnzD0xSQ==", + "license": "Apache-2.0", + "dependencies": { + "@improbable-eng/grpc-web": "^0.15.0", + "google-protobuf": "^3.21.4", + "long": "^5.2.3", + "protobufjs": "^7.3.2" + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.1.tgz", + "integrity": "sha512-6ycMm7k7NUApiMGfVc32yIPp28iPKxhGRMqoNDiUjq2RyTAkbs5Fx0TdzBqhabcKvniDdAAvHCmsRjnNfTsogw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.0.1", + "@inquirer/type": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.0.1.tgz", + "integrity": "sha512-KKTgjViBQUi3AAssqjUFMnMO3CM3qwCHvePV9EW+zTKGKafFGFF01sc1yOIYjLJ7QU52G/FbzKc+c01WLzXmVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.7", + "@inquirer/type": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.7.tgz", + "integrity": "sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.0.tgz", + "integrity": "sha512-YYykfbw/lefC7yKj7nanzQXILM7r3suIvyFlCcMskc99axmsSewXWkAfXKwMbgxL76iAFVmRwmYdwNZNc8gjog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@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==", + "dev": true, + "license": "ISC", + "dependencies": { + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/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, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/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, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/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, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/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, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@ledgerhq/devices": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-8.3.0.tgz", + "integrity": "sha512-h5Scr+yIae8yjPOViCHLdMjpqn4oC2Whrsq8LinRxe48LEGMdPqSV1yY7+3Ch827wtzNpMv+/ilKnd8rY+rTlg==", + "dependencies": { + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/logs": "^6.12.0", + "rxjs": "^7.8.1", + "semver": "^7.3.5" + } + }, + "node_modules/@ledgerhq/errors": { + "version": "6.16.4", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-6.16.4.tgz", + "integrity": "sha512-M57yFaLYSN+fZCX0E0zUqOmrV6eipK+s5RhijHoUNlHUqrsvUz7iRQgpd5gRgHB5VkIjav7KdaZjKiWGcHovaQ==" + }, + "node_modules/@ledgerhq/hw-transport": { + "version": "6.30.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-6.30.6.tgz", + "integrity": "sha512-fT0Z4IywiuJuZrZE/+W0blkV5UCotDPFTYKLkKCLzYzuE6javva7D/ajRaIeR+hZ4kTmKF4EqnsmDCXwElez+w==", + "dependencies": { + "@ledgerhq/devices": "^8.3.0", + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/logs": "^6.12.0", + "events": "^3.3.0" + } + }, + "node_modules/@ledgerhq/hw-transport-webhid": { + "version": "6.28.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webhid/-/hw-transport-webhid-6.28.6.tgz", + "integrity": "sha512-npU1mgL97KovpTUgcdORoOZ7eVFgwCA7zt0MpgUGUMRNJWDgCFsJslx7KrVXlCGOg87gLfDojreIre502I5pYg==", + "dependencies": { + "@ledgerhq/devices": "^8.3.0", + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/hw-transport": "^6.30.6", + "@ledgerhq/logs": "^6.12.0" + } + }, + "node_modules/@ledgerhq/hw-transport-webusb": { + "version": "6.28.6", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport-webusb/-/hw-transport-webusb-6.28.6.tgz", + "integrity": "sha512-rzICsvhcFcL4wSAvRPe+b9EEWB8cxj6yWy3FZdfs7ufi/0muNpFXWckWv1TC34em55sGXu2cMcwMKXg/O/Lc0Q==", + "dependencies": { + "@ledgerhq/devices": "^8.3.0", + "@ledgerhq/errors": "^6.16.4", + "@ledgerhq/hw-transport": "^6.30.6", + "@ledgerhq/logs": "^6.12.0" + } + }, + "node_modules/@ledgerhq/logs": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-6.12.0.tgz", + "integrity": "sha512-ExDoj1QV5eC6TEbMdLUMMk9cfvNKhhv5gXol4SmULRVCx/3iyCPhJ74nsb3S0Vb+/f+XujBEj3vQn5+cwS0fNA==" + }, + "node_modules/@mswjs/interceptors": { + "version": "0.36.10", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.36.10.tgz", + "integrity": "sha512-GXrJgakgJW3DWKueebkvtYgGKkxA7s0u5B0P5syJM5rvQUnrpLPigvci8Hukl7yEM+sU06l+er2Fgvx/gmiRgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@mysten/bcs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mysten/bcs/-/bcs-1.1.0.tgz", + "integrity": "sha512-yy9/1Y4d0FlRywS1+9ze/T7refCbrvwFwJIOKs9M3QBK1njbcHZp+LkVeLqBvIJA5eZ3ZCzmhQ1Xq4Sed5mEBA==", + "license": "Apache-2.0", + "dependencies": { + "bs58": "^6.0.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.4.0", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "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, + "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, + "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, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", - "license": "BSD-3-Clause" + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/better-sqlite3": { + "version": "7.6.11", + "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.11.tgz", + "integrity": "sha512-i8KcD3PgGtGBLl3+mMYA8PdKkButvPyARxA7IQAd6qeslht13qxb1zzO8dRCtE7U3IoJS782zDBAeoKiM695kg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bluebird": { + "version": "3.5.42", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.1.tgz", + "integrity": "sha512-ej0phymbFLoCB26dbbq5PGScsf2JAJ4IJHjG10LalgUV36XKTmA4GdA+PVllKvRk0sEKt64X8975qFnkSi0hqA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "22.5.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", + "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "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, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/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, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/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, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-styles/node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "license": "MIT" + }, + "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 + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", + "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@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-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/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 + }, + "node_modules/base-x": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.0.tgz", + "integrity": "sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bech32": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/better-sqlite3": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.3.0.tgz", + "integrity": "sha512-iHt9j8NPYF3oKCNOO5ZI4JwThjt3Z6J6XrcwG85VNMVzv1ByqrHWv5VILEbCMFWDsoHhXvQ7oC8vgRXFAKgl9w==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.5.0", + "prebuild-install": "^7.1.1" + } + }, + "node_modules/bignumber.js": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "engines": { + "node": "*" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bintrees": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" + }, + "node_modules/bip32": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", + "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", + "dependencies": { + "@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" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bip32/node_modules/@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" + }, + "node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "license": "MIT" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/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, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/browser-headers": { + "version": "0.4.1", + "license": "Apache-2.0" + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bs58": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", + "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", + "license": "MIT", + "dependencies": { + "base-x": "^5.0.0" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", + "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/bs58check/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bs58check/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/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, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001677", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz", + "integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "license": "BSD-3-Clause" + "node_modules/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, + "license": "MIT", + "engines": { + "node": ">=10" + } }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "license": "BSD-3-Clause", + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/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==", "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, - "node_modules/@protobufjs/float": { + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { "version": "1.0.2", - "license": "BSD-3-Clause" + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "license": "BSD-3-Clause" + "node_modules/color": { + "version": "3.2.1", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "license": "BSD-3-Clause" + "node_modules/color-convert": { + "version": "1.9.3", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "license": "BSD-3-Clause" + "node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "license": "BSD-3-Clause" + "node_modules/color-string": { + "version": "1.9.1", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", + "node_modules/colorspace": { + "version": "1.1.4", + "license": "MIT", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, "license": "MIT" }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cosmjs-types": { + "version": "0.9.0", + "license": "Apache-2.0" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/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==", + "dependencies": { + "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" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", "license": "MIT" }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", + "node_modules/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, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "license": "MIT" + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/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==", + "engines": { + "node": ">=4.0.0" + } }, - "node_modules/@types/bluebird": { - "version": "3.5.42", - "dev": true, - "license": "MIT" + "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 }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, + "node_modules/define-data-property": { + "version": "1.1.4", + "license": "MIT", "dependencies": { - "@types/node": "*" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, + "node_modules/define-properties": { + "version": "1.2.1", + "license": "MIT", "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.1.tgz", - "integrity": "sha512-ej0phymbFLoCB26dbbq5PGScsf2JAJ4IJHjG10LalgUV36XKTmA4GdA+PVllKvRk0sEKt64X8975qFnkSi0hqA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" } }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/@types/long": { - "version": "4.0.2", - "license": "MIT" + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } }, - "node_modules/@types/node": { - "version": "20.12.12", + "node_modules/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, "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" + "engines": { + "node": ">=8" } }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true + "node_modules/diff": { + "version": "4.0.2", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/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, "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "jake": "^10.8.5" }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" + "bin": { + "ejs": "bin/cli.js" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "node_modules/electron-to-chromium": { + "version": "1.5.51", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.51.tgz", + "integrity": "sha512-kKeWV57KSS8jH4alKt/jKnvHPmJgBxXzGUSbMd4eQF+iOsVPl7bz2KUmu6eo80eMP8wVioTfTyTzdMgM15WXNg==", "dev": true, + "license": "ISC" + }, + "node_modules/elliptic": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "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" } }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "license": "MIT" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, - "dependencies": { - "ms": "2.1.2" + "license": "MIT", + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/enabled": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.8" } }, - "node_modules/@typescript-eslint/parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/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==", + "dependencies": { + "once": "^1.4.0" + } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "node_modules/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, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "is-arrayish": "^0.2.1" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "get-intrinsic": "^1.2.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, + "license": "MIT", "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=6" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, - "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "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, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "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": "^18.18.0 || >=20.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "dependencies": { - "ms": "2.1.2" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" }, "engines": { - "node": ">=6.0" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { "optional": true } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "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, "dependencies": { - "brace-expansion": "^2.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, + "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, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "node_modules/eslint/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" + "ms": "2.1.2" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=6.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "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, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "bin": { - "acorn": "bin/acorn" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "engines": { - "node": ">=0.4.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "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==", + "node_modules/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, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.2", - "license": "MIT", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">=0.4.0" + "node": ">=4" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "estraverse": "^5.1.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/ansi-styles": { + "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4.0" } }, - "node_modules/ansi-styles/node_modules/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==", + "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, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=4.0" } }, - "node_modules/ansi-styles/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/arg": { - "version": "4.1.3", - "license": "MIT" - }, - "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 - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/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==", + "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, "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.5", - "license": "MIT" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "node": ">=0.10.0" } }, - "node_modules/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 - }, - "node_modules/base-x": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", - "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bech32": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { - "node": "*" + "node": ">= 0.6" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" } - }, - "node_modules/bintrees": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", - "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" - }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dependencies": { - "@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" + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "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" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/bip32/node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - }, - "node_modules/bip39": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", - "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", - "dependencies": { - "@noble/hashes": "^1.2.0" + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "license": "MIT" + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } }, - "node_modules/bn.js": { - "version": "5.2.1", - "license": "MIT" + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", "http-errors": "2.0.0", - "iconv-lite": "0.4.24", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">= 0.10.0" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/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 + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "fill-range": "^7.1.1" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/brorand": { - "version": "1.1.0", - "license": "MIT" + "node_modules/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 }, - "node_modules/browser-headers": { - "version": "0.4.1", - "license": "Apache-2.0" + "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 }, - "node_modules/bs58": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", - "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, "dependencies": { - "base-x": "^4.0.0" + "reusify": "^1.0.4" } }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" + "bser": "2.1.1" } }, - "node_modules/bs58check/node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "node_modules/fecha": { + "version": "4.2.3", + "license": "MIT" + }, + "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, "dependencies": { - "safe-buffer": "^5.0.1" + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/bs58check/node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "node_modules/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==" + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "base-x": "^3.0.2" + "minimatch": "^5.0.1" } }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "balanced-match": "^1.0.0" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "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, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/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==", + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/color": { - "version": "3.2.1", + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/fn.name": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "license": "MIT", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/color-convert": { - "version": "1.9.3", + "node_modules/form-data": { + "version": "4.0.0", "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/color-name": { - "version": "1.1.3", - "license": "MIT" + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/color-string": { - "version": "1.9.1", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "engines": { + "node": ">= 0.6" } }, - "node_modules/colorspace": { - "version": "1.1.4", + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/combined-stream": { - "version": "1.0.8", + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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, "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=6.9.0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "node_modules/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, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "license": "MIT", "dependencies": { - "safe-buffer": "5.2.1" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/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, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8.0.0" } }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "node_modules/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, + "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/cosmjs-types": { - "version": "0.9.0", - "license": "Apache-2.0" - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" }, - "node_modules/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==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { - "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" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/create-require": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "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, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 8" + "node": ">=10.13.0" } }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "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 + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/define-data-property": { - "version": "1.1.4", + "node_modules/globalthis": { + "version": "1.0.4", "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", + "define-properties": "^1.2.1", "gopd": "^1.0.1" }, "engines": { @@ -1577,1006 +4466,1136 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "license": "MIT", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", + "node_modules/google-protobuf": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.4.tgz", + "integrity": "sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==", + "license": "(BSD-3-Clause AND Apache-2.0)" + }, + "node_modules/gopd": { + "version": "1.0.1", "license": "MIT", - "engines": { - "node": ">=0.4.0" + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, - "node_modules/diff": { - "version": "4.0.2", - "license": "BSD-3-Clause", + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/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, - "dependencies": { - "path-type": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "es-define-property": "^1.0.0" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/elliptic": { - "version": "6.5.5", + "node_modules/has-proto": { + "version": "1.0.3", "license": "MIT", - "dependencies": { - "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" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" - }, - "node_modules/enabled": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/has-symbols": { + "version": "1.0.3", + "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "license": "MIT", + "node_modules/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==", "dependencies": { - "get-intrinsic": "^1.2.4" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/es-errors": { - "version": "1.3.0", + "node_modules/hash.js": { + "version": "1.1.7", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, "engines": { "node": ">= 0.4" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "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==", + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "MIT" + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "node_modules/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, + "license": "MIT" + }, + "node_modules/http": { + "version": "0.0.1-security" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "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" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 0.8" } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "node_modules/https": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/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, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" } }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "node_modules/husky": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "bin": { + "husky": "bin.mjs" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } + "url": "https://github.com/sponsors/typicode" } }, - "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, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=0.10.0" } }, - "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==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 4" } }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "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, "dependencies": { - "ms": "2.1.2" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=6.0" + "node": ">=6" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "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==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, + "license": "MIT", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, "engines": { - "node": ">=0.10" + "node": ">=0.8.19" } }, - "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==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "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, - "engines": { - "node": ">=4.0" - } + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" }, - "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, - "engines": { - "node": ">=0.10.0" - } + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/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==", "engines": { - "node": ">= 0.6" + "node": ">= 0.10" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } + "node_modules/is-arrayish": { + "version": "0.3.2", + "license": "MIT" }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "hasown": "^2.0.2" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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 - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, "engines": { - "node": ">=8.6.0" + "node": ">=0.10.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/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, - "dependencies": { - "is-glob": "^4.0.1" - }, + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/fast-json-stable-stringify": { + "node_modules/is-generator-fn": { "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 - }, - "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 + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "reusify": "^1.0.4" + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/fecha": { - "version": "4.2.3", + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true, "license": "MIT" }, - "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==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=0.12.0" } }, - "node_modules/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==" - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "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, - "dependencies": { - "to-regex-range": "^5.0.1" + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "license": "MIT", + "engines": { + "node": ">=8" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=8" } }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "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==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=10" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/fn.name": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, "engines": { - "node": ">=4.0" + "node": ">=6.0" }, "peerDependenciesMeta": { - "debug": { + "supports-color": { "optional": true } } }, - "node_modules/form-data": { - "version": "4.0.0", - "license": "MIT", + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.2", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "license": "MIT", + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" }, - "engines": { - "node": ">= 0.4" + "bin": { + "jake": "bin/cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "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==", + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, + "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/globalthis": { - "version": "1.0.4", + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, "license": "MIT", "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, + "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/google-protobuf": { - "version": "3.21.2", - "license": "(BSD-3-Clause AND Apache-2.0)" - }, - "node_modules/gopd": { - "version": "1.0.1", + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3" + "detect-newline": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-proto": { - "version": "1.0.3", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-symbols": { - "version": "1.0.3", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/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==", + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hash.js": { - "version": "1.1.7", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hasown": { - "version": "2.0.2", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "license": "MIT", "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/http": { - "version": "0.0.1-security" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/https": { - "version": "1.0.0", - "license": "ISC" - }, - "node_modules/husky": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", - "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, - "bin": { - "husky": "bin.mjs" - }, + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "peerDependencies": { + "jest-resolve": "*" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true } - ] + } }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, + "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, "engines": { - "node": ">=0.8.19" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/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==", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, "engines": { - "node": ">= 0.10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "license": "MIT" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-runtime/node_modules/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, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, + "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, "engines": { - "node": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "license": "MIT", - "peerDependencies": { - "ws": "*" + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2597,12 +5616,32 @@ "jscrypto": "bin/cli.js" } }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2658,10 +5697,30 @@ "json-buffer": "3.0.1" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/kuler": { "version": "2.0.0", "license": "MIT" }, + "node_modules/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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2686,6 +5745,13 @@ "libsodium-sumo": "^0.7.13" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2701,6 +5767,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2726,10 +5799,46 @@ "version": "5.2.3", "license": "Apache-2.0" }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/make-error": { "version": "1.3.6", "license": "ISC" }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -2744,14 +5853,26 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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, + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", @@ -2771,10 +5892,11 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -2787,6 +5909,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -2811,6 +5934,27 @@ "node": ">= 0.6" } }, + "node_modules/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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "license": "ISC" @@ -2838,15 +5982,100 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/ms": { "version": "2.1.3", "license": "MIT" }, + "node_modules/msw": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.6.2.tgz", + "integrity": "sha512-RdRgPvjfuzMIACkWv7VOVAeSRYMU3ofokLv1w0RsbFX960qnj/tFEyOFXY0G2GTUd9trA6rHuHciM/FKpBp6/A==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.1", + "@bundled-es-modules/statuses": "^1.0.1", + "@bundled-es-modules/tough-cookie": "^0.1.6", + "@inquirer/confirm": "^5.0.0", + "@mswjs/interceptors": "^0.36.5", + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.3", + "path-to-regexp": "^6.3.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.26.1", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.8.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/msw/node_modules/type-fest": { + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/nan": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz", "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==" }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "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", @@ -2861,6 +6090,17 @@ "node": ">= 0.6" } }, + "node_modules/node-abi": { + "version": "3.67.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.67.0.tgz", + "integrity": "sha512-bLn/fU/ALVBE9wj+p4Y21ZJWYFjUXLXPi/IewyLZkx3ApxKDNBWCKdReeKOtD8dWpOdDCeMyLh6ZewzcLsG2Nw==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -2876,10 +6116,51 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2895,6 +6176,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -2906,7 +6188,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -2918,6 +6199,22 @@ "fn.name": "1.x.x" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2935,6 +6232,13 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true, + "license": "MIT" + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2965,6 +6269,16 @@ "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", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2977,10 +6291,30 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -3012,10 +6346,18 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", @@ -3026,6 +6368,13 @@ "node": ">=8" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -3038,6 +6387,110 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/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, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/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, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/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, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/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, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/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, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3075,6 +6528,34 @@ "node": ">=6.0.0" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/prom-client": { "version": "15.1.2", "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-15.1.2.tgz", @@ -3087,8 +6568,24 @@ "node": "^16 || ^18 || >=20" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/protobufjs": { - "version": "7.3.0", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -3125,6 +6622,25 @@ "version": "1.1.0", "license": "MIT" }, + "node_modules/psl": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.10.0.tgz", + "integrity": "sha512-KSKHEbjAnpUuAUserOq0FxGXCUrzC3WniuSJhvdbs102rL55266ZcHBqLWOsG30spQMlPdpy7icATiAQehg/iA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3134,12 +6650,30 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -3148,6 +6682,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3172,6 +6713,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3180,6 +6722,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -3190,6 +6733,35 @@ "node": ">= 0.8" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, "node_modules/readable-stream": { "version": "3.6.2", "license": "MIT", @@ -3206,6 +6778,64 @@ "version": "1.0.0", "license": "Apache-2.0" }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3215,6 +6845,16 @@ "node": ">=4" } }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3309,20 +6949,22 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/secp256k1": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.0.tgz", - "integrity": "sha512-TKWX8xvoGHrxVdqbYeZM9w+izTF4b9z3NhSaDkdn81btvuh+ivbIMGT/zQvDtTFWhRlThpoz6LEYTr7n8A5GcA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-5.0.1.tgz", + "integrity": "sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA==", "hasInstallScript": true, + "license": "MIT", "dependencies": { - "elliptic": "^6.5.4", + "elliptic": "^6.5.7", "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/secp256k1/node_modules/node-addon-api": { @@ -3331,9 +6973,10 @@ "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -3342,9 +6985,10 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -3364,15 +7008,25 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -3382,6 +7036,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -3397,7 +7052,8 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/sha.js": { "version": "2.4.11", @@ -3436,6 +7092,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -3449,6 +7106,56 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/simple-swizzle": { "version": "0.2.2", "license": "MIT", @@ -3456,6 +7163,13 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3465,6 +7179,34 @@ "node": ">=8" } }, + "node_modules/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, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/stack-trace": { "version": "0.0.10", "license": "MIT", @@ -3472,14 +7214,45 @@ "node": "*" } }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true, + "license": "MIT" + }, "node_modules/string_decoder": { "version": "1.3.0", "license": "MIT", @@ -3487,6 +7260,35 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/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, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -3506,6 +7308,16 @@ "node": ">=4" } }, + "node_modules/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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3530,6 +7342,19 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/symbol-observable": { "version": "2.0.3", "license": "MIT", @@ -3553,6 +7378,32 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tdigest": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", @@ -3561,6 +7412,21 @@ "bintrees": "1.0.2" } }, + "node_modules/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, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/text-hex": { "version": "1.0.0", "license": "MIT" @@ -3592,13 +7458,12 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "engines": { - "node": ">=14.14" - } + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -3616,10 +7481,27 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/triple-beam": { "version": "1.4.1", "license": "MIT", @@ -3639,6 +7521,55 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-jest": { + "version": "29.2.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", + "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "^2.1.0", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.6.3", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, "node_modules/ts-node": { "version": "10.9.2", "license": "MIT", @@ -3697,6 +7628,17 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -3709,6 +7651,16 @@ "node": ">= 0.8.0" } }, + "node_modules/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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -3725,6 +7677,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -3739,7 +7692,9 @@ "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" }, "node_modules/typescript": { - "version": "5.4.5", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -3776,17 +7731,60 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "license": "MIT" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3796,6 +7794,17 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "license": "MIT" @@ -3812,6 +7821,32 @@ "version": "3.0.1", "license": "MIT" }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -3820,6 +7855,16 @@ "node": ">= 0.8" } }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3884,11 +7929,42 @@ "node": ">=0.10.0" } }, + "node_modules/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, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } }, "node_modules/ws": { "version": "7.5.10", @@ -3918,6 +7994,52 @@ "symbol-observable": "^2.0.3" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yn": { "version": "3.1.1", "license": "MIT", @@ -3936,6 +8058,19 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 6b4deac..c04e6ba 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { - "name": "ibc-relayer", + "name": "rapid-relayer", "version": "0.0.1", "description": "", "main": "index.js", "scripts": { "start": "node --stack_size=4096 --max-old-space-size=4096 -r ts-node/register/transpile-only -r tsconfig-paths/register src/index.ts", "lint": "npx eslint . --fix", - "prepare": "husky" + "prepare": "husky", + "test": "jest" }, "author": "", "license": "ISC", @@ -16,10 +17,11 @@ "@cosmjs/json-rpc": "^0.32.3", "@cosmjs/stargate": "^0.32.3", "@cosmjs/tendermint-rpc": "^0.32.3", - "@initia/initia.js": "^0.2.5", + "@initia/initia.js": "^0.2.20", "@initia/initia.proto": "^0.2.0", "axios": "^1.7.5", "bech32": "^2.0.0", + "better-sqlite3": "^11.3.0", "bluebird": "^3.7.2", "express": "^4.19.2", "http": "^0.0.1-security", @@ -28,16 +30,22 @@ "prom-client": "^15.1.2", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "^5.4.5", "winston": "^3.13.0" }, "devDependencies": { + "@types/better-sqlite3": "^7.6.11", "@types/bluebird": "^3.5.42", "@types/express": "^4.17.21", + "@types/jest": "^29.5.14", + "@types/node": "^22.5.4", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "husky": "^9.0.11", + "jest": "^29.7.0", + "msw": "^2.6.2", + "ts-jest": "^29.2.5", + "typescript": "^5.6.3", "typescript-eslint": "^7.16.0" }, "lint-staged": { diff --git a/src/chain/index.ts b/src/chain/index.ts index 089f9f1..e69de29 100644 --- a/src/chain/index.ts +++ b/src/chain/index.ts @@ -1,600 +0,0 @@ -import { - LCDClient, - Wallet, - Msg, - APIRequester, - ConnectionCounterparty, -} from '@initia/initia.js' -import { delay } from 'bluebird' -import { info, error, debug } from 'src/lib/logger' -import * as http from 'http' -import * as https from 'https' - -import * as fs from 'fs' -import { parseSendPacketEvent, parseWriteAckEvent } from 'src/lib/eventParser' -import { WalletManager } from './wallet' -import { - generateMsgUpdateClient, - generateCounterpartyChainMessages, - generateThisChainMessages, -} from 'src/msgs' -import { RPCClient } from 'src/lib/rpcClient' -import { - ChainConfig, - ChainStatus, - ClientState, - PacketEventWithIndex, - SendPacketEventWithIndex, - SyncInfo, - WriteAckEventWithIndex, -} from './types' -import { metrics } from 'src/lib/metric' -import { Counter } from 'prom-client' -import { syncInfoFile } from '../lib/config' - -export class Chain { - private syncInfo: { - height: number - txIndex: number - } - public latestHeight: number - private fedHeight: number - public latestTimestamp: number - private packetsToHandle: PacketEventWithIndex[] - private counterpartyChain: Chain - public clientId: string - // worker name => latest heartbeat - private workers: Record - - private constructor( - public lcd: LCDClient, - public rpc: RPCClient, - public wallet: WalletManager, - public connectionId: string - ) { - this.packetsToHandle = [] - this.workers = {} - } - - // initializer - - static async init(config: ChainConfig): Promise { - const lcd = new LCDClient( - config.lcdUri, - { - chainId: config.chainId, - gasPrices: config.gasPrice, - }, - new APIRequester(config.lcdUri, { - httpAgent: new http.Agent({ keepAlive: true }), - httpsAgent: new https.Agent({ keepAlive: true }), - timeout: 60000, - }) - ) - const rpc = new RPCClient(config.rpcUri) - const wallet = new Wallet(lcd, config.key) - const walletManager = new WalletManager(wallet, config.bech32Prefix) - - const chain = new Chain(lcd, rpc, walletManager, config.connectionId) - chain.clientId = (await lcd.ibc.connection(config.connectionId)).client_id - - await chain.updateLatestHeight() - const syncInfo = fs.existsSync(chain.syncFilePath()) - const dir = fs.existsSync(syncInfoFile) - if (!dir) { - fs.mkdirSync(syncInfoFile) - } - if (!syncInfo) { - chain.updatesyncInfo(config.syncInfo ?? { height: 1, txIndex: 0 }) - } - chain.syncInfo = JSON.parse( - fs.readFileSync(chain.syncFilePath()).toString() - ) as SyncInfo - chain.fedHeight = - chain.syncInfo.txIndex == -1 - ? chain.syncInfo.height - : chain.syncInfo.height - 1 - - return chain - } - - public async registerCounterpartyChain(counterpartyChain: Chain) { - if (this.counterpartyChain) { - throw Error('already has counterpartyChain') - } - - this.debug('register counterparty chain') - this.counterpartyChain = counterpartyChain - await this.validateConfig() - void this.latestHeightWorker() - void this.handlePackets() - void this.feedEvents() - } - - // workers - - private async handlePackets() { - // to prevent rerun - if ( - (this.workers['packet_handler'] ?? 0) > - new Date().valueOf() - 5 * 60 * 1000 - ) { - return - } - - this.debug('Activate packet handler') - - for (;;) { - try { - const packets = this.packetsToHandle.slice(0, 50) // TODO make this configurable - if (packets.length === 0) { - this.updatesyncInfo({ height: this.fedHeight, txIndex: -1 }) - continue - } - - // wait until next height - if (packets[packets.length - 1].height >= this.latestHeight) { - continue - } - - const syncInfo = { - height: packets[packets.length - 1].height, - txIndex: packets[packets.length - 1].txIndex, - } - - // filter packets - - // get send packet events - const sendPackets: SendPacketEventWithIndex[] = packets.filter( - (packet) => packet.type === 'send_packet' - ) as SendPacketEventWithIndex[] - - // get write acknowledgement events - const writeAcks: WriteAckEventWithIndex[] = packets.filter( - (packet) => packet.type === 'write_acknowledgement' - ) as WriteAckEventWithIndex[] - - this.info( - `Found events. Send packets - ${sendPackets.length}. Recv packets - ${writeAcks.length}` - ) - - // filter and split send packets - const { timeoutPackets, recvPackets } = - await this.splitSendPackets(sendPackets) - - // filter write ack - const acks = await this.filterAckPackets(writeAcks) - - this.info( - `Filtered events. Message to generate: timeout - ${timeoutPackets.length}. recvPacket - ${recvPackets.length}. ack - ${acks.length}` - ) - - // if nothing to do - if (timeoutPackets.length + recvPackets.length + acks.length === 0) { - this.updatesyncInfo(syncInfo) - this.packetsToHandle = this.packetsToHandle.slice(packets.length) - continue - } - - // generate msgs - - // counterparty msgs - const counterpartyMsgs: Msg[] = await generateCounterpartyChainMessages( - this, - this.counterpartyChain, - recvPackets, - acks - ) - - this.info( - `Request handle packet to wallet manager. This chain - ${ - timeoutPackets.length == 0 ? 0 : timeoutPackets.length + 1 - }. Counterparty chain - ${counterpartyMsgs.length}` - ) - - const [thisResult, counterpartyResult] = await Promise.all([ - this.delayedTimeout(timeoutPackets), - this.counterpartyChain.wallet.request(counterpartyMsgs), - ]) - - this.info( - `Packet Handled. This chain - ${thisResult.txhash} (code - ${thisResult.code}, rawLog - ${thisResult.rawLog}). Counterparty chain - ${counterpartyResult.txhash} (code - ${counterpartyResult.code} rawLog - ${counterpartyResult.rawLog})` - ) - - // All must succeed to update syncinfo or retry - if (thisResult.code === 0 && counterpartyResult.code === 0) { - this.updatesyncInfo(syncInfo) - this.packetsToHandle = this.packetsToHandle.slice(packets.length) - } - } catch (e) { - this.error(`Fail to handle packet. response - ${e}`) - } finally { - this.workers['packet_handler'] = new Date().valueOf() - await delay(1000) - } - } - } - - private async feedEvents() { - // to prevent rerun - if ( - (this.workers['event_feeder'] ?? 0) > - new Date().valueOf() - 5 * 60 * 1000 - ) { - return - } - - this.debug('Activate event feeder') - - for (;;) { - try { - if (this.packetsToHandle.length > 1000) continue - - // height to fetch - const heights = Array.from( - { length: 20 }, - (_, i) => i + this.fedHeight + 1 - ).filter((height) => height <= this.latestHeight) - - if (heights.length === 0) continue - - const blockResults = await Promise.all( - heights.map((height) => this.fetchBlockResult(height)) - ) - - this.debug( - `Fetched block results for heights (${JSON.stringify(heights)})` - ) - const results: PacketEventWithIndex[] = [] - - for (const events of blockResults) { - results.push(...events) - } - - this.debug(`push packets to packet to handle (${results.length})`) - this.packetsToHandle.push(...results) - this.fedHeight = heights[heights.length - 1] - } catch (e) { - this.error(`Fail to fetch block result. response - ${e}`) - } finally { - this.workers['event_feeder'] = new Date().valueOf() - await delay(100) - } - } - } - - private async latestHeightWorker() { - // to prevent rerun - if ( - (this.workers['latest_height_worker'] ?? 0) > - new Date().valueOf() - 5 * 60 * 1000 - ) { - return - } - - this.debug('Activate latest height worker') - - // TODO add websocket options - const MAX_RETRY = 10 - let retried = 0 - for (;;) { - try { - await this.updateLatestHeight() - this.debug( - `Set latest height. Height - ${this.latestHeight}, Timestamp - ${this.latestTimestamp}` - ) - const needUpdateClient = await this.checkTrustPeriod() - if (needUpdateClient) { - const { msg: msgUpdateClient } = await generateMsgUpdateClient( - this.counterpartyChain, - this - ) - const updateClientResult = await this.wallet.request([ - msgUpdateClient, - ]) - this.info( - `Client Updated. txhash - ${updateClientResult.txhash} (code - ${updateClientResult.code}).` - ) - } - retried = 0 - } catch (e) { - this.error( - `[latestHeightWorker] Got error while fetching latest height (${e})` - ) - retried++ - if (retried >= MAX_RETRY) { - throw Error( - `<${this.chainId()}> [latestHeightWorker] Max retry exceeded` - ) - } - } finally { - this.workers['latest_height_worker'] = new Date().valueOf() - await delay(1000) - } - } - } - - // filters - - // split and filter - private async splitSendPackets(packets: SendPacketEventWithIndex[]): Promise<{ - timeoutPackets: SendPacketEventWithIndex[] - recvPackets: SendPacketEventWithIndex[] - }> { - const cutoffHeight = this.counterpartyChain.latestHeight - const cutoffTime = this.counterpartyChain.latestTimestamp + 10000 - - // source path => packet - const timeoutPackets: Record = {} - const recvPackets: Record = {} - - for (const packet of packets) { - const path = `${packet.packetData.source_port}/${packet.packetData.source_channel}` - const heightTimeout = - packet.packetData.timeout_height !== undefined && - packet.packetData.timeout_height.revision_height != 0 && - packet.packetData.timeout_height.revision_number != 0 && - cutoffHeight >= packet.packetData.timeout_height.revision_height - - const timestampTimeout = - Number(packet.packetData.timeout_timestamp) != 0 && - cutoffTime * 1000000 >= Number(packet.packetData.timeout_timestamp) - - if (!heightTimeout && !timestampTimeout) { - if (recvPackets[path] === undefined) { - recvPackets[path] = [] - } - recvPackets[path].push(packet) - } else { - if (timeoutPackets[path] === undefined) { - timeoutPackets[path] = [] - } - timeoutPackets[path].push(packet) - } - } - - // filter timeout that already done. - // filter by unreceivedAcks - await Promise.all( - Object.keys(timeoutPackets).map(async (path) => { - if (timeoutPackets[path].length === 0) return - const unrecivedPackets = await this.lcd.ibc.unreceivedAcks( - timeoutPackets[path][0].packetData.source_port, - timeoutPackets[path][0].packetData.source_channel, - timeoutPackets[path].map((packet) => packet.packetData.sequence) - ) - - const unrecivedSequences = unrecivedPackets.sequences.map((sequence) => - Number(sequence) - ) - - timeoutPackets[path] = timeoutPackets[path].filter((packet) => - unrecivedSequences.includes(packet.packetData.sequence) - ) - }) - ) - - // filter by unreceivedPacket - await Promise.all( - Object.keys(timeoutPackets).map(async (path) => { - if (timeoutPackets[path].length === 0) return - const unrecivedPackets = - await this.counterpartyChain.lcd.ibc.unreceivedPackets( - timeoutPackets[path][0].packetData.destination_port, - timeoutPackets[path][0].packetData.destination_channel, - timeoutPackets[path].map((packet) => packet.packetData.sequence) - ) - - const unrecivedSequences = unrecivedPackets.sequences.map((sequence) => - Number(sequence) - ) - - timeoutPackets[path] = timeoutPackets[path].filter((packet) => - unrecivedSequences.includes(packet.packetData.sequence) - ) - }) - ) - - // filter recv packets that already done. - await Promise.all( - Object.keys(recvPackets).map(async (path) => { - if (recvPackets[path].length === 0) return - const unrecivedPackets = - await this.counterpartyChain.lcd.ibc.unreceivedPackets( - recvPackets[path][0].packetData.destination_port, - recvPackets[path][0].packetData.destination_channel, - recvPackets[path].map((packet) => packet.packetData.sequence) - ) - - const unrecivedSequences = unrecivedPackets.sequences.map((sequence) => - Number(sequence) - ) - - recvPackets[path] = recvPackets[path].filter((packet) => - unrecivedSequences.includes(packet.packetData.sequence) - ) - }) - ) - - return { - timeoutPackets: Object.values(timeoutPackets).flat(), - recvPackets: Object.values(recvPackets).flat(), - } - } - - private async delayedTimeout(timeoutPackets: SendPacketEventWithIndex[]) { - if (timeoutPackets.length === 0) { - return this.wallet.request([]) - } - - await delay(15000) - // chain msgs - const thisMsgs: Msg[] = await generateThisChainMessages( - this, - this.counterpartyChain, - timeoutPackets - ) - - return this.wallet.request(thisMsgs) - } - - private async filterAckPackets( - packets: WriteAckEventWithIndex[] - ): Promise { - const unrecivedSequences: number[] = [] - await Promise.all( - packets.map(async (packet) => { - const unrecivedPackets = - await this.counterpartyChain.lcd.ibc.unreceivedAcks( - packet.packetData.packet.source_port, - packet.packetData.packet.source_channel, - [packet.packetData.packet.sequence] - ) - - if (unrecivedPackets.sequences[0]) { - unrecivedSequences.push(Number(unrecivedPackets.sequences[0])) - } - }) - ) - return packets.filter((packet) => - unrecivedSequences.includes(packet.packetData.packet.sequence) - ) - } - - private async validateConfig() { - // check connection mapping - const counterpartyConnectionId = ( - (await this.lcd.ibc.connection(this.connectionId)) - .counterparty as ConnectionCounterparty - ).connection_id - - if (counterpartyConnectionId !== this.counterpartyChain.connectionId) { - throw Error( - `"${this.chainId()} - ${ - this.connectionId - }" is not connected with "${this.counterpartyChain.chainId()} - ${ - this.counterpartyChain.connectionId - }"` - ) - } - } - - // return true if it need update client - private async checkTrustPeriod(): Promise { - const state = await this.lcd.apiRequester.get( - `/ibc/core/client/v1/client_states/${this.clientId}` - ) - const trustingPeriod = - Number(state.client_state.trusting_period.replace('s', '')) * 1000 - const revisionHeight = Number( - state.client_state.latest_height.revision_height - ) - - const header = await this.counterpartyChain.rpc.header(revisionHeight) - const revisionTimestamp = new Date(header.header.time).valueOf() - const timeDiff = new Date().valueOf() - revisionTimestamp - return timeDiff >= trustingPeriod * 0.66 - } - - private updatesyncInfo(syncInfo: SyncInfo) { - fs.writeFileSync(this.syncFilePath(), JSON.stringify(syncInfo)) - this.syncInfo = syncInfo - } - - private async updateLatestHeight() { - const abciInfo = await this.rpc.abciInfo() - if (!abciInfo.lastBlockHeight) { - throw Error('Can not get last block height') - } - const height = abciInfo.lastBlockHeight - this.latestHeight = Number(height) - this.latestTimestamp = new Date().valueOf() // is it okay to use local timestamp? - - this.inc(metrics.chain.latestHeightWorker) - } - - private async fetchBlockResult( - height: number - ): Promise { - this.debug(`Fetch new block results (height - ${height})`) - const blockResult = await this.rpc.blockResults(height) - const txData = [...blockResult.results] - - const packetEvents: PacketEventWithIndex[] = [] - - txData.map((data, i) => { - for (const event of data.events) { - const sendPacket = parseSendPacketEvent(event, this.connectionId) - if (sendPacket) { - packetEvents.push({ - height, - txIndex: i, - type: 'send_packet', - packetData: sendPacket, - }) - - this.inc(metrics.chain.eventFeederWorker.sendPacket) - } - - const writeAck = parseWriteAckEvent(event, this.connectionId) - if (writeAck) { - packetEvents.push({ - height, - txIndex: i, - type: 'write_acknowledgement', - packetData: writeAck, - }) - - this.inc(metrics.chain.eventFeederWorker.writeAck) - } - } - }) - - return packetEvents - } - - private syncFilePath(): string { - return `${syncInfoFile}/${this.lcd.config.chainId}_${this.connectionId}.json` - } - - private chainId(): string { - return this.lcd.config.chainId as string - } - - public chainStatus(): ChainStatus { - return { - chainId: this.chainId(), - connectionId: this.connectionId, - latestHeightInfo: { - height: this.latestHeight, - timestamp: new Date(this.latestTimestamp), - }, - lastFeedHeight: this.fedHeight, - syncInfo: { ...this.syncInfo }, - } - } - // logs - - private info(log: string) { - info(`<${this.chainId()}/${this.connectionId}> ${log}`) - } - - private error(log: string) { - error(`<${this.chainId()}/${this.connectionId}> ${log}`) - } - - private debug(log: string) { - debug(`<${this.chainId()}/${this.connectionId}> ${log}`) - } - - // metrics - - public inc(counter: Counter, inc?: number) { - counter - .labels({ - chainId: this.chainId(), - connectionId: this.connectionId, - }) - .inc(inc) - } -} diff --git a/src/chain/types.ts b/src/chain/types.ts deleted file mode 100644 index ab10b10..0000000 --- a/src/chain/types.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Key, Packet } from '@initia/initia.js' -import { Ack } from 'src/msgs' - -export interface ChainConfig { - bech32Prefix: string - chainId: string - gasPrice: string - lcdUri: string - rpcUri: string - key: Key - connectionId: string - syncInfo?: { - height: number - txIndex: number - } -} - -export interface SyncInfo { - height: number - txIndex: number -} - -export type PacketEventWithIndex = - | SendPacketEventWithIndex - | WriteAckEventWithIndex - -export interface SendPacketEventWithIndex { - height: number - txIndex: number - type: 'send_packet' - packetData: Packet -} - -export interface WriteAckEventWithIndex { - height: number - txIndex: number - type: 'write_acknowledgement' - packetData: Ack -} - -export interface ChainStatus { - chainId: string - connectionId: string - latestHeightInfo: { - height: number - timestamp: Date - } - lastFeedHeight: number - syncInfo: SyncInfo -} - -export interface ClientState { - client_state: { - trusting_period: string - latest_height: { - revision_height: string - } - } -} diff --git a/src/chain/wallet.ts b/src/chain/wallet.ts deleted file mode 100644 index 8ac4114..0000000 --- a/src/chain/wallet.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { - Msg, - SyncTxBroadcastResult, - Wallet, - isTxError, -} from '@initia/initia.js' -import { bech32 } from 'bech32' -import { delay } from 'bluebird' -import { error, info, warn } from 'src/lib/logger' - -export class WalletManager { - private requests: Record< - number, - { msgs: Msg[]; result: SyncTxBroadcastResult | undefined } - > - private requestIndexInprogress: number - private requestIndex: number - private sequence: number - constructor( - private wallet: Wallet, - private bech32Prefix: string - ) { - this.requests = {} - this.requestIndex = 0 - this.requestIndexInprogress = 0 - void this.runRequestWorker() - } - - async init() { - const accountInfo = await this.wallet.lcd.auth.accountInfo(this.address()) - this.sequence = accountInfo.getSequenceNumber() - } - - async request(msgs: Msg[], executeDelay = 0): Promise { - await delay(executeDelay) - if (msgs.length === 0) { - return { - txhash: '', - code: 0, - } - } - const index = this.requestIndex++ - - this.requests[index] = { msgs, result: undefined } - - while (this.requests[index].result === undefined) { - await delay(500) - } - - const result = this.requests[index].result - // just for avoid lint error - if (result === undefined) { - throw Error('Result Not Found') - } - - delete this.requests[index] - // polling tx - - if (isTxError(result) && result.code !== 19) { - return { - txhash: result.txhash, - code: Number(result.code), - rawLog: result.raw_log, - } - } - - let retry = 0 - // TODO make this as config - while (retry < 120) { - const txResult = await this.wallet.lcd.tx - .txInfo(result.txhash) - .catch(() => undefined) - await delay(500) - retry++ - - if (txResult) { - return { - txhash: result.txhash, - code: txResult.code, - rawLog: txResult.code === 0 ? undefined : txResult.raw_log, - } - } - } - - return { - txhash: result.txhash, - code: -1, - rawLog: 'timeout', - } - } - - private async runRequestWorker() { - const MAX_RETRY = 10 - let retried = 0 - for (;;) { - const request = this.requests[this.requestIndexInprogress] - try { - if (!this.sequence) { - await this.init() - } - - if (!request) continue - - const signedTx = await this.wallet.createAndSignTx({ - msgs: request.msgs, - sequence: this.sequence, - }) - - const result = await this.wallet.lcd.tx.broadcastSync(signedTx) - request.result = result - - this.requestIndexInprogress++ - - if (result.raw_log.startsWith('account sequence mismatch')) { - try { - const expected = result.raw_log.split(', ')[1] - this.sequence = Number(expected.split(' ')[1]) - info(`update sequence`) - } catch (e) { - warn(`error to parse sequence`) - } - } - - if (!(isTxError(result) && result.code !== 19)) { - this.sequence++ - } - } catch (e) { - const errorMsg = e as { response?: { data: string } } - const errorContent = JSON.stringify(errorMsg?.response?.data ?? e) - if (errorContent.indexOf('account sequence mismatch') !== -1) { - const expected = errorContent - .slice(errorContent.indexOf('account sequence mismatch')) - .split(', ')[1] - this.sequence = Number(expected.split(' ')[1]) - info(`update sequence`) - } - - error( - `[runRequestWorker] (${JSON.stringify(errorMsg?.response?.data ?? error)})` - ) - retried++ - - // if fail to broadcast, return error result to make regenerate msgs - if (retried >= MAX_RETRY) { - this.requestIndexInprogress++ - error(`[runRequestWorker] Max retry exceeded`) - request.result = { - txhash: '', - height: -1, - code: -1, - raw_log: '[runRequestWorker] Max retry exceeded', - } - } - } finally { - await delay(1000) - } - } - } - - public address(): string { - const address = this.wallet.key.accAddress - return bech32.encode(this.bech32Prefix, bech32.decode(address).words) - } -} - -interface TxResult { - txhash: string - code?: number - rawLog?: string // only include in code is not zero -} diff --git a/src/db/constants.ts b/src/db/constants.ts new file mode 100644 index 0000000..373d562 --- /dev/null +++ b/src/db/constants.ts @@ -0,0 +1,3 @@ +// constants + +export const U64_MAX = 0xffffffffffffffffn diff --git a/src/db/controller/channel.spec.ts b/src/db/controller/channel.spec.ts new file mode 100644 index 0000000..d4f5811 --- /dev/null +++ b/src/db/controller/channel.spec.ts @@ -0,0 +1,315 @@ +import { + Bool, + ChannelOpenCloseEvent, + ChannelOpenCloseTable, + ChannelState, +} from 'src/types' +import { ChannelController } from './channel' +import { DB } from '..' +import { insert, select } from '../utils' +import { mockServers } from 'src/test/testSetup' + +describe('channel controller', () => { + test('channel open e2e', async () => { + const [mockServer1, mockServer2] = mockServers + // test channel_open_init + { + // create mock events + const events: ChannelOpenCloseEvent[] = [ + { + type: 'channel_open_init', + channelOpenCloseInfo: { + height: 100, + srcConnectionId: 'connection-1', + srcPortId: 'transfer', + srcChannelId: 'channel-1', + dstConnectionId: '', + dstPortId: '', + dstChannelId: '', + }, + }, + ] + + // create feed functions + const fns = await ChannelController.feedEvents( + mockServer1.rest.client(), + mockServer1.rest.chainId, + events + ) + + // execute feed functions + fns() + + // check db insertion + const res = select(DB, ChannelController.tableName) + const expectVal: ChannelOpenCloseTable[] = [ + { + id: 1, + in_progress: Bool.FALSE, + height: 100, + state: ChannelState.INIT, + chain_id: mockServer2.rest.chainId, // counterparty's chain id + connection_id: 'connection-2', + port_id: '', + channel_id: '', + counterparty_chain_id: mockServer1.rest.chainId, + counterparty_connection_id: 'connection-1', + counterparty_port_id: 'transfer', + counterparty_channel_id: 'channel-1', + }, + ] + expect(res).toEqual(expectVal) + } + + // test channel_open_try + { + // create mock events + const events: ChannelOpenCloseEvent[] = [ + { + type: 'channel_open_try', + channelOpenCloseInfo: { + height: 100, + srcConnectionId: 'connection-2', + srcPortId: 'transfer', + srcChannelId: 'channel-1', + dstConnectionId: 'connection-2', + dstPortId: 'transfer', + dstChannelId: 'channel-2', + }, + }, + ] + + // create feed functions + const fns = await ChannelController.feedEvents( + mockServer2.rest.client(), + mockServer2.rest.chainId, + events + ) + + // execute feed functions + fns() + + // check deletion and insertion + const res = select(DB, ChannelController.tableName) + // id 1 must be removed + const expectVal: ChannelOpenCloseTable[] = [ + { + id: 2, + in_progress: Bool.FALSE, + height: 100, + state: ChannelState.TRYOPEN, + chain_id: mockServer1.rest.chainId, // counterparty's chain id + connection_id: 'connection-1', + port_id: 'transfer', + channel_id: 'channel-1', + counterparty_chain_id: mockServer2.rest.chainId, + counterparty_connection_id: 'connection-2', + counterparty_port_id: 'transfer', + counterparty_channel_id: 'channel-2', + }, + ] + expect(res).toEqual(expectVal) + } + + // test channel_open_ack + { + // create mock events + const events: ChannelOpenCloseEvent[] = [ + { + type: 'channel_open_ack', + channelOpenCloseInfo: { + height: 100, + srcConnectionId: 'connection-1', + srcPortId: 'transfer', + srcChannelId: 'channel-1', + dstConnectionId: 'connection-2', + dstPortId: 'transfer', + dstChannelId: 'channel-2', + }, + }, + ] + + // to check deletion of open init, insert + insert(DB, ChannelController.tableName, { + id: 1, + in_progress: Bool.FALSE, + height: 100, + state: ChannelState.INIT, + chain_id: mockServer2.rest.chainId, // counterparty's chain id + connection_id: 'connection-2', + port_id: '', + channel_id: '', + counterparty_chain_id: mockServer1.rest.chainId, + counterparty_connection_id: 'connection-1', + counterparty_port_id: 'transfer', + counterparty_channel_id: 'channel-1', + }) + + // create feed functions + const fns = await ChannelController.feedEvents( + mockServer1.rest.client(), + mockServer1.rest.chainId, + events + ) + + // execute feed functions + fns() + + // check deletion and insertion + const res = select(DB, ChannelController.tableName) + // id 1 and 2 must be removed + const expectVal: ChannelOpenCloseTable[] = [ + { + id: 3, + in_progress: Bool.FALSE, + height: 100, + state: ChannelState.ACK, + chain_id: mockServer2.rest.chainId, // counterparty's chain id + connection_id: 'connection-2', + port_id: 'transfer', + channel_id: 'channel-2', + counterparty_chain_id: mockServer1.rest.chainId, + counterparty_connection_id: 'connection-1', + counterparty_port_id: 'transfer', + counterparty_channel_id: 'channel-1', + }, + ] + expect(res).toEqual(expectVal) + } + + // test channel_open_confirm + { + // create mock events + const events: ChannelOpenCloseEvent[] = [ + { + type: 'channel_open_confirm', + channelOpenCloseInfo: { + height: 100, + srcConnectionId: 'connection-1', + srcPortId: 'transfer', + srcChannelId: 'channel-1', + dstConnectionId: 'connection-2', + dstPortId: 'transfer', + dstChannelId: 'channel-2', + }, + }, + ] + + // to check deletion of open try_open, insert + insert(DB, ChannelController.tableName, { + id: 2, + in_progress: Bool.FALSE, + height: 100, + state: ChannelState.TRYOPEN, + chain_id: mockServer1.rest.chainId, // counterparty's chain id + connection_id: 'connection-1', + port_id: 'transfer', + channel_id: 'channel-1', + counterparty_chain_id: mockServer2.rest.chainId, + counterparty_connection_id: 'connection-2', + counterparty_port_id: 'transfer', + counterparty_channel_id: 'channel-2', + }) + + // create feed functions + const fns = await ChannelController.feedEvents( + mockServer2.rest.client(), + mockServer2.rest.chainId, + events + ) + + // execute feed functions + fns() + + // check deletions + const res = select(DB, ChannelController.tableName) + // id 2 and 3 must be removed and noting remain + const expectVal: ChannelOpenCloseTable[] = [] + expect(res).toEqual(expectVal) + } + }) + + test('channel close e2e', async () => { + const [mockServer1, mockServer2] = mockServers + { + // create mock events + const events: ChannelOpenCloseEvent[] = [ + { + type: 'channel_close', + channelOpenCloseInfo: { + height: 100, + srcConnectionId: 'connection-1', + srcPortId: 'transfer', + srcChannelId: 'channel-1', + dstConnectionId: 'connection-2', + dstPortId: 'transfer', + dstChannelId: 'channel-2', + }, + }, + ] + + // create feed functions + const fns = await ChannelController.feedEvents( + mockServer1.rest.client(), + mockServer1.rest.chainId, + events + ) + + // execute feed functions + fns() + + // check db insertion + const res = select(DB, ChannelController.tableName) + const expectVal: ChannelOpenCloseTable[] = [ + { + id: 4, + in_progress: Bool.FALSE, + height: 100, + state: ChannelState.CLOSE, + chain_id: mockServer2.rest.chainId, // counterparty's chain id + connection_id: 'connection-2', + port_id: 'transfer', + channel_id: 'channel-2', + counterparty_chain_id: mockServer1.rest.chainId, + counterparty_connection_id: 'connection-1', + counterparty_port_id: 'transfer', + counterparty_channel_id: 'channel-1', + }, + ] + expect(res).toEqual(expectVal) + } + + { + // create mock events + const events: ChannelOpenCloseEvent[] = [ + { + type: 'channel_close_confirm', + channelOpenCloseInfo: { + height: 100, + srcConnectionId: 'connection-1', + srcPortId: 'transfer', + srcChannelId: 'channel-1', + dstConnectionId: 'connection-2', + dstPortId: 'transfer', + dstChannelId: 'channel-2', + }, + }, + ] + + // create feed functions + const fns = await ChannelController.feedEvents( + mockServer2.rest.client(), + mockServer2.rest.chainId, + events + ) + + // execute feed functions + fns() + + // check db deletion + const res = select(DB, ChannelController.tableName) + const expectVal: ChannelOpenCloseTable[] = [] + expect(res).toEqual(expectVal) + } + }) +}) diff --git a/src/db/controller/channel.ts b/src/db/controller/channel.ts new file mode 100644 index 0000000..a9a9a28 --- /dev/null +++ b/src/db/controller/channel.ts @@ -0,0 +1,336 @@ +import { DB } from '..' +import { + Bool, + ChannelOpenCloseTable, + ChannelOpenCloseEvent, + ChannelState, +} from 'src/types' +import { In, WhereOptions, del, insert, select, update } from '../utils' +import { RESTClient } from 'src/lib/restClient' +import { ConnectionController } from './connection' +import { PacketController, PacketFilter } from './packet' +import { Database } from 'better-sqlite3' + +export class ChannelController { + static tableName = 'channel_open_close' + public static async feedEvents( + rest: RESTClient, + chainId: string, + events: ChannelOpenCloseEvent[] + ): Promise<() => void> { + const feedFns: (() => void)[] = [] + for (const event of events) { + switch (event.type) { + case 'channel_open_init': + feedFns.push( + await this.feedChannelOpenInitEvent(rest, chainId, event) + ) + break + case 'channel_open_try': + feedFns.push(await this.feedChannelOpenTryEvent(rest, chainId, event)) + break + case 'channel_open_ack': + feedFns.push(await this.feedChannelOpenAckEvent(rest, chainId, event)) + break + case 'channel_open_confirm': + feedFns.push( + await this.feedChannelOpenConfirmEvent(rest, chainId, event) + ) + break + case 'channel_close': + case 'channel_close_init': + feedFns.push( + await this.feedChannelCloseInitEvent(rest, chainId, event) + ) + break + case 'channel_close_confirm': + feedFns.push(this.feedChannelCloseConfirmEvent(rest, chainId, event)) + break + } + } + + return () => { + for (const fn of feedFns) { + fn() + } + } + } + + public static getOpenEvent( + chainId: string, + counterpartyChainIds: string[], + filter: PacketFilter = {}, + state?: ChannelState, + limit = 100 + ): ChannelOpenCloseTable[] { + const wheres: WhereOptions[] = [] + + if (filter.connections) { + for (const connectionFilter of filter.connections) { + if (connectionFilter.channels) continue + wheres.push({ + in_progress: Bool.FALSE, + state, + chain_id: chainId, + connection_id: connectionFilter.connectionId, + counterparty_chain_id: In(counterpartyChainIds), + }) + } + } else { + wheres.push({ + in_progress: Bool.FALSE, + state, + chain_id: chainId, + counterparty_chain_id: In(counterpartyChainIds), + }) + } + + return select( + DB, + this.tableName, + wheres, + { id: 'ASC' }, + limit + ) + } + + public static delOpenEvents(events: ChannelOpenCloseTable[]) { + if (events.filter((event) => event.id === undefined).length !== 0) { + throw new Error('id must be exists to remove channel on open') + } + + if (events.length === 0) return + + del( + DB, + this.tableName, + events.map((v) => ({ id: v.id as number })) + ) + } + + public static updateInProgress(id?: number, inProgress = true) { + update( + DB, + this.tableName, + { in_progress: inProgress ? Bool.TRUE : Bool.FALSE }, + [{ id }] + ) + } + + public static resetPacketInProgress(db?: Database) { + db = db ?? DB + update(db, this.tableName, { + in_progress: Bool.FALSE, + }) + } + + // executed on the src chain + private static async feedChannelOpenInitEvent( + rest: RESTClient, + chainId: string, + event: ChannelOpenCloseEvent + ): Promise<() => void> { + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.channelOpenCloseInfo.srcConnectionId + ) + + // add channel on open for dst chain + const channelOnOpen: ChannelOpenCloseTable = { + in_progress: Bool.FALSE, + height: event.channelOpenCloseInfo.height, + state: ChannelState.INIT, + chain_id: connection.counterparty_chain_id, + connection_id: connection.counterparty_connection_id, + port_id: event.channelOpenCloseInfo.dstPortId, + channel_id: event.channelOpenCloseInfo.dstChannelId, + counterparty_chain_id: chainId, + counterparty_connection_id: event.channelOpenCloseInfo.srcConnectionId, + counterparty_port_id: event.channelOpenCloseInfo.srcPortId, + counterparty_channel_id: event.channelOpenCloseInfo.srcChannelId, + } + + return () => { + insert(DB, this.tableName, channelOnOpen) // store INIT state to the dst chain + } + } + + // executed on the dst chain + private static async feedChannelOpenTryEvent( + rest: RESTClient, + chainId: string, + event: ChannelOpenCloseEvent + ): Promise<() => void> { + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.channelOpenCloseInfo.dstConnectionId + ) + + // add channel on open for src chain + const channelOnOpen: ChannelOpenCloseTable = { + in_progress: Bool.FALSE, + height: event.channelOpenCloseInfo.height, + state: ChannelState.TRYOPEN, + chain_id: connection.counterparty_chain_id, + connection_id: connection.counterparty_connection_id, + port_id: event.channelOpenCloseInfo.srcPortId, + channel_id: event.channelOpenCloseInfo.srcChannelId, + counterparty_chain_id: chainId, + counterparty_connection_id: event.channelOpenCloseInfo.dstConnectionId, + counterparty_port_id: event.channelOpenCloseInfo.dstPortId, + counterparty_channel_id: event.channelOpenCloseInfo.dstChannelId, + } + + return () => { + del(DB, this.tableName, [ + { + state: ChannelState.INIT, + counterparty_chain_id: connection.counterparty_chain_id, + counterparty_port_id: channelOnOpen.port_id, + counterparty_channel_id: channelOnOpen.channel_id, + }, + ]) // remove INIT from the dst chain + insert(DB, this.tableName, channelOnOpen) // store TRYOPEN state to the src chain + } + } + + // executed on the src chain + private static async feedChannelOpenAckEvent( + rest: RESTClient, + chainId: string, + event: ChannelOpenCloseEvent + ): Promise<() => void> { + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.channelOpenCloseInfo.srcConnectionId + ) + + // add channel on open for dst chain + const channelOnOpen: ChannelOpenCloseTable = { + in_progress: Bool.FALSE, + height: event.channelOpenCloseInfo.height, + state: ChannelState.ACK, + chain_id: connection.counterparty_chain_id, + connection_id: connection.counterparty_connection_id, + port_id: event.channelOpenCloseInfo.dstPortId, + channel_id: event.channelOpenCloseInfo.dstChannelId, + counterparty_chain_id: chainId, + counterparty_connection_id: event.channelOpenCloseInfo.srcConnectionId, + counterparty_port_id: event.channelOpenCloseInfo.srcPortId, + counterparty_channel_id: event.channelOpenCloseInfo.srcChannelId, + } + + return () => { + del(DB, this.tableName, [ + { + state: ChannelState.TRYOPEN, + counterparty_chain_id: channelOnOpen.chain_id, + counterparty_port_id: channelOnOpen.port_id, + counterparty_channel_id: channelOnOpen.channel_id, + }, + ]) // remove TRYOPEN from src chain + del(DB, this.tableName, [ + { + state: ChannelState.INIT, + counterparty_chain_id: chainId, + counterparty_port_id: channelOnOpen.counterparty_port_id, + counterparty_channel_id: channelOnOpen.counterparty_channel_id, + }, + ]) // remove INIT from dst chain + insert(DB, this.tableName, channelOnOpen) // store ACK state to the dst chain + } + } + + // executed on the dst chain + private static async feedChannelOpenConfirmEvent( + rest: RESTClient, + chainId: string, + event: ChannelOpenCloseEvent + ): Promise<() => void> { + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.channelOpenCloseInfo.dstConnectionId + ) + return () => { + del(DB, this.tableName, [ + { + state: ChannelState.TRYOPEN, + counterparty_chain_id: chainId, + counterparty_port_id: event.channelOpenCloseInfo.dstPortId, + counterparty_channel_id: event.channelOpenCloseInfo.dstChannelId, + }, + ]) // remove TRYOPEN from src chain + del(DB, this.tableName, [ + { + state: ChannelState.ACK, + counterparty_chain_id: connection.counterparty_chain_id, + counterparty_port_id: event.channelOpenCloseInfo.srcPortId, + counterparty_channel_id: event.channelOpenCloseInfo.srcChannelId, + }, + ]) // remove ACK from dst chain + } + } + + private static async feedChannelCloseInitEvent( + rest: RESTClient, + chainId: string, + event: ChannelOpenCloseEvent + ): Promise<() => void> { + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.channelOpenCloseInfo.srcConnectionId + ) + + // add channel on open for dst chain + const channelOnOpen: ChannelOpenCloseTable = { + in_progress: Bool.FALSE, + height: event.channelOpenCloseInfo.height, + state: ChannelState.CLOSE, + chain_id: connection.counterparty_chain_id, + connection_id: connection.counterparty_connection_id, + port_id: event.channelOpenCloseInfo.dstPortId, + channel_id: event.channelOpenCloseInfo.dstChannelId, + counterparty_chain_id: chainId, + counterparty_connection_id: event.channelOpenCloseInfo.srcConnectionId, + counterparty_port_id: event.channelOpenCloseInfo.srcPortId, + counterparty_channel_id: event.channelOpenCloseInfo.srcChannelId, + } + + return () => { + insert(DB, this.tableName, channelOnOpen) + + // Mark all packets as timed out + PacketController.updateTimeout( + chainId, + event.channelOpenCloseInfo.srcChannelId + ) + } + } + + private static feedChannelCloseConfirmEvent( + _rest: RESTClient, + chainId: string, + event: ChannelOpenCloseEvent + ): () => void { + return () => { + del(DB, this.tableName, [ + { + state: ChannelState.CLOSE, + chain_id: chainId, + port_id: event.channelOpenCloseInfo.dstPortId, + channel_id: event.channelOpenCloseInfo.dstChannelId, + }, + ]) + // Mark all packets as timed out + PacketController.updateTimeout( + chainId, + event.channelOpenCloseInfo.srcChannelId + ) + } + } +} diff --git a/src/db/controller/client.ts b/src/db/controller/client.ts new file mode 100644 index 0000000..cab0991 --- /dev/null +++ b/src/db/controller/client.ts @@ -0,0 +1,80 @@ +import { DB } from '..' +import { insert, selectOne } from '../utils' +import { Any } from 'cosmjs-types/google/protobuf/any' +import { UpdateClientEvent, ClientTable } from 'src/types' +import { Header } from 'cosmjs-types/ibc/lightclients/tendermint/v1/tendermint' +import { RESTClient } from 'src/lib/restClient' + +export class ClientController { + static tableName = 'client' + public static async addClient( + rest: RESTClient, + chainId: string, + clientId: string + ): Promise { + const state = await rest.ibc.getClientState(clientId) + + const client: ClientTable = { + chain_id: chainId, + client_id: clientId, + counterparty_chain_id: state.client_state.chain_id, + trusting_period: parseInt( + state.client_state.trusting_period.replace('s', '') + ), + revision_height: parseInt( + state.client_state.latest_height.revision_height + ), + last_update_time: 0, + } + + insert(DB, this.tableName, client) + + return client + } + + public static async feedUpdateClientEvent( + rest: RESTClient, + chainId: string, + event: UpdateClientEvent + ) { + // create key + const clientId = event.clientId + + // decode header + const msg = Any.decode( + new Uint8Array([...Buffer.from(event.header, 'hex')]) + ) + if (msg.typeUrl !== '/ibc.lightclients.tendermint.v1.Header') return + const header = Header.decode(msg.value) + + // get client + const client = await this.getClient(rest, chainId, clientId) + + // update client + client.revision_height = parseInt( + event.consensusHeights.split(',')[0].split('-')[1] + ) + + if (header.signedHeader?.header?.time.seconds) { + client.last_update_time = Number(header.signedHeader.header.time.seconds) + } + + insert(DB, this.tableName, client) + } + + public static async getClient( + rest: RESTClient, + chainId: string, + clientId: string + ): Promise { + // get client + const client = selectOne(DB, this.tableName, [ + { + chain_id: chainId, + client_id: clientId, + }, + ]) + + return client ?? this.addClient(rest, chainId, clientId) + } +} diff --git a/src/db/controller/connection.ts b/src/db/controller/connection.ts new file mode 100644 index 0000000..9eb9c36 --- /dev/null +++ b/src/db/controller/connection.ts @@ -0,0 +1,49 @@ +import { DB } from '..' +import { ConnectionTable } from 'src/types' +import { ClientController } from './client' +import { insert, selectOne } from '../utils' +import { RESTClient } from 'src/lib/restClient' + +export class ConnectionController { + static tableName = 'connection' + public static async addConnection( + rest: RESTClient, + chainId: string, + connectionId: string + ): Promise { + const connectionInfo = await rest.ibc.getConnection(connectionId) + const clientId = connectionInfo.connection.client_id + const client = await ClientController.getClient(rest, chainId, clientId) + + const connection: ConnectionTable = { + chain_id: chainId, + connection_id: connectionId, + client_id: client.client_id, + counterparty_chain_id: client.counterparty_chain_id, + counterparty_connection_id: + connectionInfo.connection.counterparty.connection_id, + counterparty_client_id: connectionInfo.connection.counterparty.client_id, + } + + insert(DB, this.tableName, connection) + + return connection + } + + // TODO: add connection_open_init event feeder + + public static async getConnection( + rest: RESTClient, + chainId: string, + connectionId: string + ): Promise { + const connection = selectOne(DB, this.tableName, [ + { + chain_id: chainId, + connection_id: connectionId, + }, + ]) + + return connection ?? this.addConnection(rest, chainId, connectionId) + } +} diff --git a/src/db/controller/packet.spec.ts b/src/db/controller/packet.spec.ts new file mode 100644 index 0000000..bbf158c --- /dev/null +++ b/src/db/controller/packet.spec.ts @@ -0,0 +1,108 @@ +import { FeeType, PacketFeeTable } from 'src/types' +import { DB } from '..' +import { select } from '../utils' +import { mockServers } from 'src/test/testSetup' +import { parsePacketFeeEvent } from 'src/lib/eventParser' +import { PacketFeeController } from './packetFee' + +describe('packet controler', () => { + test('packet send e2e', async () => { + const [mockServer1, _] = mockServers + + const event = parsePacketFeeEvent({ + type: 'incentivized_ibc_packet', + attributes: [ + { + key: 'port_id', + value: 'transfer', + }, + { + key: 'channel_id', + value: 'channel-1', + }, + { + key: 'packet_sequence', + value: '1', + }, + { + key: 'recv_fee', + value: '100tokena,200tokenb', + }, + { + key: 'ack_fee', + value: '200tokena,100tokenb', + }, + { + key: 'timeout_fee', + value: '300tokena,300tokenb', + }, + { + key: 'msg_index', + value: '0', + }, + ], + }) + + // create feed functions + const fns = PacketFeeController.feedEvents(mockServer1.rest.chainId, [ + event, + ]) + + // execute feed functions + fns() + + // check db insertion + const res = select(DB, PacketFeeController.tableName) + const expectVal: PacketFeeTable[] = [ + { + chain_id: mockServer1.rest.chainId, + channel_id: 'channel-1', + sequence: event.sequence, + fee_type: FeeType.RECV, + denom: 'tokena', + amount: 100, + }, + { + chain_id: mockServer1.rest.chainId, + channel_id: 'channel-1', + sequence: event.sequence, + fee_type: FeeType.RECV, + denom: 'tokenb', + amount: 200, + }, + { + chain_id: mockServer1.rest.chainId, + channel_id: 'channel-1', + sequence: event.sequence, + fee_type: FeeType.ACK, + denom: 'tokena', + amount: 200, + }, + { + chain_id: mockServer1.rest.chainId, + channel_id: 'channel-1', + sequence: event.sequence, + fee_type: FeeType.ACK, + denom: 'tokenb', + amount: 100, + }, + { + chain_id: mockServer1.rest.chainId, + channel_id: 'channel-1', + sequence: event.sequence, + fee_type: FeeType.TIMEOUT, + denom: 'tokena', + amount: 300, + }, + { + chain_id: mockServer1.rest.chainId, + channel_id: 'channel-1', + sequence: event.sequence, + fee_type: FeeType.TIMEOUT, + denom: 'tokenb', + amount: 300, + }, + ] + expect(res).toEqual(expectVal) + }) +}) diff --git a/src/db/controller/packet.ts b/src/db/controller/packet.ts new file mode 100644 index 0000000..e0eaa86 --- /dev/null +++ b/src/db/controller/packet.ts @@ -0,0 +1,622 @@ +import { + AcknowledgePacketEvent, + PacketEvent, + SendPacketEvent, + TimeoutPacketEvent, + WriteAckEvent, + PacketSendTable, + PacketTimeoutTable, + PacketWriteAckTable, + Bool, + FeeType, +} from 'src/types' +import { DB } from '..' +import { In, WhereOptions, del, insert, select, update } from '../utils' +import { ConnectionController } from './connection' +import { Database } from 'better-sqlite3' +import { RESTClient } from 'src/lib/restClient' +import { PacketFeeController } from './packetFee' +import { PacketFee } from 'src/lib/config' + +export class PacketController { + public static tableNamePacketSend = 'packet_send' + public static tableNamePacketTimeout = 'packet_timeout' + public static tableNamePacketWriteAck = 'packet_write_ack' + + public static async feedEvents( + rest: RESTClient, + chainId: string, + events: PacketEvent[] + ): Promise<() => void> { + const feedFns: (() => void)[] = [] + for (const event of events) { + switch (event.type) { + case 'send_packet': + feedFns.push(await this.feedSendPacketEvent(rest, chainId, event)) + break + case 'write_acknowledgement': + feedFns.push(await this.feedWriteAckEvent(rest, chainId, event)) + break + case 'acknowledge_packet': + feedFns.push( + await this.feedAcknowledgePacketEvent(rest, chainId, event) + ) + break + case 'timeout_packet': + feedFns.push(await this.feedTimeoutPacketEvent(rest, chainId, event)) + break + } + } + + return () => { + for (const fn of feedFns) { + fn() + } + } + } + + public static getSendPackets( + chainId: string, + height: number, + timestamp: number, + chainIdsWithFeeFilters: { chainId: string; feeFilter: PacketFee }[], + filter: PacketFilter = {}, + limit = 100 + ): PacketSendTable[] { + const res: PacketSendTable[] = [] + + // query for each chain id + for (const { + chainId: counterpartyChainId, + feeFilter, + } of chainIdsWithFeeFilters) { + const wheres: WhereOptions[] = [] + let custom = `(timeout_height > ${height} OR timeout_timestamp > ${timestamp})` // filter timeout packet + if (feeFilter.recvFee && feeFilter.recvFee.length !== 0) { + const conditions = feeFilter.recvFee.map( + (v) => + `((SELECT amount FROM packet_fee WHERE chain_id = packet_send.src_chain_id AND channel_id = packet_send.src_channel_id AND sequence = packet_send.sequence AND fee_type = ${FeeType.RECV} AND denom = '${v.denom}') >= ${v.amount})` + ) + custom += ` AND (${conditions.join(' OR ')})` + } + + if (filter.connections) { + // TODO: make this more efficientnet. filter connection by chain id + wheres.push( + ...filter.connections.map((conn) => ({ + in_progress: Bool.FALSE, + dst_chain_id: chainId, + dst_connection_id: conn.connectionId, + dst_channel_id: conn.channels ? In(conn.channels) : undefined, + src_chain_id: counterpartyChainId, + custom, + })) + ) + } else { + wheres.push({ + in_progress: Bool.FALSE, + dst_chain_id: chainId, + src_chain_id: counterpartyChainId, + custom, + }) + } + + res.push( + ...select( + DB, + this.tableNamePacketSend, + wheres, + { sequence: 'ASC' }, + limit - res.length + ) + ) + } + + return res + } + + public static getTimeoutPackets( + chainId: string, + height: number, + timestamp: number, + counterpartyChainIds: string[], + feeFilter: PacketFee, + filter: PacketFilter = {}, + limit = 100 + ): PacketTimeoutTable[] { + let custom = `((timeout_height < ${height} AND timeout_height != 0) OR timeout_timestamp < ${timestamp} AND timeout_timestamp != 0)` // filter timeout packet + + if (feeFilter.timeoutFee && feeFilter.timeoutFee.length !== 0) { + const conditions = feeFilter.timeoutFee.map( + (v) => + `((SELECT amount FROM packet_fee WHERE chain_id = packet_timeout.src_chain_id AND channel_id = packet_timeout.src_channel_id AND sequence = packet_timeout.sequence AND fee_type = ${FeeType.TIMEOUT} AND denom = '${v.denom}') >= ${v.amount})` + ) + custom += ` AND (${conditions.join(' OR ')})` + } + + const wheres: WhereOptions[] = [] + + if (filter.connections) { + // TODO: make this more efficientnet. filter connection by chain id + wheres.push( + ...filter.connections.map((conn) => ({ + in_progress: Bool.FALSE, + src_chain_id: chainId, + src_connection_id: conn.connectionId, + src_channel_id: conn.channels ? In(conn.channels) : undefined, + dst_chain_id: In(counterpartyChainIds), + custom, + })) + ) + } else { + wheres.push({ + in_progress: Bool.FALSE, + src_chain_id: chainId, + dst_chain_id: In(counterpartyChainIds), + custom, + }) + } + + return select( + DB, + this.tableNamePacketTimeout, + wheres, + { sequence: 'ASC' }, + limit + ) + } + + public static getWriteAckPackets( + chainId: string, + counterpartyChainIds: string[], + feeFilter: PacketFee, + filter: PacketFilter = {}, + limit = 100 + ): PacketWriteAckTable[] { + let custom = 'TRUE' + + if (feeFilter.ackFee && feeFilter.ackFee.length !== 0) { + const conditions = feeFilter.ackFee.map( + (v) => + `((SELECT amount FROM packet_fee WHERE chain_id = packet_write_ack.src_chain_id AND channel_id = packet_write_ack.src_channel_id AND sequence = packet_write_ack.sequence AND fee_type = ${FeeType.ACK} AND denom = '${v.denom}') >= ${v.amount})` + ) + custom += ` AND (${conditions.join(' OR ')})` + } + + const wheres: WhereOptions[] = [] + + if (filter.connections) { + wheres.push( + ...filter.connections.map((conn) => ({ + in_progress: Bool.FALSE, + src_chain_id: chainId, + src_connection_id: conn.connectionId, + src_channel_id: conn.channels ? In(conn.channels) : undefined, + dst_chain_id: In(counterpartyChainIds), // TODO: make this more efficientnet, like filter it on outside of this. + custom, + })) + ) + } else { + wheres.push({ + in_progress: Bool.FALSE, + src_chain_id: chainId, + dst_chain_id: In(counterpartyChainIds), + custom, + }) + } + + return select( + DB, + this.tableNamePacketWriteAck, + wheres, + { sequence: 'ASC' }, + limit + ) + } + + public static delSendPackets(packets: PacketSendTable[]) { + if (packets.length === 0) return + del( + DB, + this.tableNamePacketSend, + packets.map((packet) => ({ + dst_chain_id: packet.dst_chain_id, + dst_connection_id: packet.dst_connection_id, + dst_channel_id: packet.dst_channel_id, + sequence: packet.sequence, + })) + ) + } + + public static delTimeoutPackets(packets: PacketTimeoutTable[]) { + if (packets.length === 0) return + del( + DB, + this.tableNamePacketTimeout, + packets.map((packet) => ({ + src_chain_id: packet.src_chain_id, + src_connection_id: packet.src_connection_id, + src_channel_id: packet.src_channel_id, + sequence: packet.sequence, + })) + ) + } + + public static delWriteAckPackets(packets: PacketWriteAckTable[]) { + if (packets.length === 0) return + del( + DB, + this.tableNamePacketWriteAck, + packets.map((packet) => ({ + src_chain_id: packet.src_chain_id, + src_connection_id: packet.src_connection_id, + src_channel_id: packet.src_channel_id, + sequence: packet.sequence, + })) + ) + } + + public static updateSendPacketInProgress( + packet: PacketSendTable, + inProgress = true + ) { + update( + DB, + this.tableNamePacketSend, + { in_progress: inProgress ? Bool.TRUE : Bool.FALSE }, + [ + { + dst_chain_id: packet.dst_chain_id, + dst_connection_id: packet.dst_connection_id, + dst_channel_id: packet.dst_channel_id, + sequence: packet.sequence, + }, + ] + ) + } + + public static updateTimeoutPacketInProgress( + packet: PacketTimeoutTable, + inProgress = true + ) { + update( + DB, + this.tableNamePacketTimeout, + { in_progress: inProgress ? Bool.TRUE : Bool.FALSE }, + [ + { + src_chain_id: packet.src_chain_id, + src_connection_id: packet.src_connection_id, + src_channel_id: packet.src_channel_id, + sequence: packet.sequence, + }, + ] + ) + } + + public static updateWriteAckPacketInProgress( + packet: PacketWriteAckTable, + inProgress = true + ) { + update( + DB, + this.tableNamePacketWriteAck, + { in_progress: inProgress ? Bool.TRUE : Bool.FALSE }, + [ + { + src_chain_id: packet.src_chain_id, + src_connection_id: packet.src_connection_id, + src_channel_id: packet.src_channel_id, + sequence: packet.sequence, + }, + ] + ) + } + + public static resetPacketInProgress(db?: Database) { + db = db ?? DB + update(db, this.tableNamePacketSend, { + in_progress: Bool.FALSE, + }) + update(db, this.tableNamePacketTimeout, { + in_progress: Bool.FALSE, + }) + update(db, this.tableNamePacketWriteAck, { + in_progress: Bool.FALSE, + }) + } + + private static async feedSendPacketEvent( + rest: RESTClient, + chainId: string, + event: SendPacketEvent + ): Promise<() => void> { + // get counterparty's info + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.packetInfo.connectionId + ) + + // add pakcet send on dst chain + const packetSend: PacketSendTable = { + dst_chain_id: connection.counterparty_chain_id, + dst_connection_id: connection.counterparty_connection_id, + dst_channel_id: event.packetInfo.dstChannel, + sequence: Number(event.packetInfo.sequence), + in_progress: Bool.FALSE, + is_ordered: + 'ORDER_ORDERED' === event.packetInfo.ordering ? Bool.TRUE : Bool.FALSE, + height: event.packetInfo.height, + dst_port: event.packetInfo.dstPort, + src_chain_id: chainId, + src_connection_id: event.packetInfo.connectionId, + src_port: event.packetInfo.srcPort, + src_channel_id: event.packetInfo.srcChannel, + packet_data: event.packetInfo.data as string, + timeout_height: Number(event.packetInfo.timeoutHeight), + timeout_timestamp: Number(event.packetInfo.timeoutTimestamp), + timeout_height_raw: event.packetInfo.timeoutHeightRaw, + timeout_timestamp_raw: event.packetInfo.timeoutTimestampRaw, + } + + // add packet timeout on source chain + const packetTimeout: PacketTimeoutTable = { + src_chain_id: chainId, + src_connection_id: event.packetInfo.connectionId, + src_channel_id: event.packetInfo.srcChannel, + sequence: Number(event.packetInfo.sequence), + in_progress: Bool.FALSE, + is_ordered: + 'ORDER_ORDERED' === event.packetInfo.ordering ? Bool.TRUE : Bool.FALSE, + src_port: event.packetInfo.srcPort, + dst_chain_id: connection.counterparty_chain_id, + dst_connection_id: connection.counterparty_connection_id, + dst_port: event.packetInfo.dstPort, + dst_channel_id: event.packetInfo.dstChannel, + packet_data: event.packetInfo.data as string, + timeout_height: Number(event.packetInfo.timeoutHeight), + timeout_timestamp: Number(event.packetInfo.timeoutTimestamp), + timeout_height_raw: event.packetInfo.timeoutHeightRaw, + timeout_timestamp_raw: event.packetInfo.timeoutTimestampRaw, + } + + return () => { + insert(DB, this.tableNamePacketSend, packetSend) + insert(DB, this.tableNamePacketTimeout, packetTimeout) + + // if channel is ordered channel, update in progress for higher sequence + if (packetSend.is_ordered === Bool.TRUE) { + update( + DB, + this.tableNamePacketSend, + { in_progress: Bool.FALSE }, + [ + { + dst_chain_id: packetSend.dst_chain_id, + dst_channel_id: packetSend.dst_channel_id, + }, + ] + ) + } + } + } + + private static async feedWriteAckEvent( + rest: RESTClient, + chainId: string, + event: WriteAckEvent + ): Promise<() => void> { + // get counterparty's info + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.packetInfo.connectionId + ) + + // add packet write ack on src chain + const packetWriteAck: PacketWriteAckTable = { + src_chain_id: connection.counterparty_chain_id, + src_connection_id: connection.counterparty_connection_id, + src_channel_id: event.packetInfo.srcChannel, + sequence: Number(event.packetInfo.sequence), + in_progress: Bool.FALSE, + is_ordered: + 'ORDER_ORDERED' === event.packetInfo.ordering ? Bool.TRUE : Bool.FALSE, + height: event.packetInfo.height, + src_port: event.packetInfo.srcPort, + dst_chain_id: chainId, + dst_connection_id: event.packetInfo.connectionId, + dst_port: event.packetInfo.dstPort, + dst_channel_id: event.packetInfo.dstChannel, + packet_data: event.packetInfo.data as string, + ack: event.packetInfo.ack as string, + timeout_height: Number(event.packetInfo.timeoutHeight), + timeout_timestamp: Number(event.packetInfo.timeoutTimestamp), + timeout_height_raw: event.packetInfo.timeoutHeightRaw, + timeout_timestamp_raw: event.packetInfo.timeoutTimestampRaw, + } + return () => { + // remove pakcet send + del(DB, this.tableNamePacketSend, [ + { + dst_chain_id: chainId, + dst_channel_id: event.packetInfo.dstChannel, + sequence: Number(event.packetInfo.sequence), + }, + ]) + + // remove packet fees + PacketFeeController.removePacketFee( + packetWriteAck.src_chain_id, + packetWriteAck.src_channel_id, + packetWriteAck.sequence, + FeeType.RECV + ) + PacketFeeController.removePacketFee( + packetWriteAck.src_chain_id, + packetWriteAck.src_channel_id, + packetWriteAck.sequence, + FeeType.TIMEOUT + ) + + insert(DB, this.tableNamePacketWriteAck, packetWriteAck) + + // if channel is ordered channel, update in progress for higher sequence + if (packetWriteAck.is_ordered === Bool.TRUE) { + update( + DB, + this.tableNamePacketSend, + { in_progress: Bool.FALSE }, + [ + { + dst_chain_id: chainId, + dst_channel_id: event.packetInfo.dstChannel, + }, + ] + ) + } + } + } + + private static async feedAcknowledgePacketEvent( + rest: RESTClient, + chainId: string, + event: AcknowledgePacketEvent + ): Promise<() => void> { + // get counterparty's info + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.packetInfo.connectionId + ) + + return () => { + // remove pakcet send + del(DB, this.tableNamePacketSend, [ + { + dst_chain_id: connection.counterparty_chain_id, + dst_connection_id: connection.counterparty_connection_id, + dst_channel_id: event.packetInfo.dstChannel, + sequence: Number(event.packetInfo.sequence), + }, + ]) + + // remove packet timeout + del(DB, this.tableNamePacketSend, [ + { + src_chain_id: chainId, + src_connection_id: event.packetInfo.connectionId, + src_channel_id: event.packetInfo.srcChannel, + sequence: Number(event.packetInfo.sequence), + }, + ]) + + // remove packet write ack + del(DB, this.tableNamePacketSend, [ + { + src_chain_id: chainId, + src_connection_id: event.packetInfo.connectionId, + src_channel_id: event.packetInfo.srcChannel, + sequence: Number(event.packetInfo.sequence), + }, + ]) + + // remove packet fees + PacketFeeController.removePacketFee( + chainId, + event.packetInfo.srcChannel, + event.packetInfo.sequence, + FeeType.RECV + ) + PacketFeeController.removePacketFee( + chainId, + event.packetInfo.srcChannel, + event.packetInfo.sequence, + FeeType.TIMEOUT + ) + PacketFeeController.removePacketFee( + chainId, + event.packetInfo.srcChannel, + event.packetInfo.sequence, + FeeType.ACK + ) + } + } + + private static async feedTimeoutPacketEvent( + rest: RESTClient, + chainId: string, + event: TimeoutPacketEvent + ): Promise<() => void> { + // get counterparty's info + const connection = await ConnectionController.getConnection( + rest, + chainId, + event.packetInfo.connectionId + ) + return () => { + // remove pakcet send + del(DB, this.tableNamePacketSend, [ + { + dst_chain_id: connection.counterparty_chain_id, + dst_connection_id: connection.counterparty_connection_id, + dst_channel_id: event.packetInfo.dstChannel, + sequence: Number(event.packetInfo.sequence), + }, + ]) + + // remove packet timeout + del(DB, this.tableNamePacketSend, [ + { + src_chain_id: chainId, + src_connection_id: event.packetInfo.connectionId, + src_channel_id: event.packetInfo.srcChannel, + sequence: Number(event.packetInfo.sequence), + }, + ]) + + // remove packet fees + PacketFeeController.removePacketFee( + chainId, + event.packetInfo.srcChannel, + event.packetInfo.sequence, + FeeType.RECV + ) + PacketFeeController.removePacketFee( + chainId, + event.packetInfo.srcChannel, + event.packetInfo.sequence, + FeeType.TIMEOUT + ) + PacketFeeController.removePacketFee( + chainId, + event.packetInfo.srcChannel, + event.packetInfo.sequence, + FeeType.ACK + ) + } + } + + // update timeout timestamp to -1 to execute timeout closed channel + public static updateTimeout(chainId: string, channelId: string) { + update( + DB, + PacketController.tableNamePacketTimeout, + { timeout_timestamp: -1 }, + [ + { + dst_channel_id: channelId, + dst_chain_id: chainId, + }, + ] + ) + } +} + +export interface PacketFilter { + connections?: { + connectionId: string + channels?: string[] // if empty search all + }[] // if empty search all +} diff --git a/src/db/controller/packetFee.spec.ts b/src/db/controller/packetFee.spec.ts new file mode 100644 index 0000000..18b57bd --- /dev/null +++ b/src/db/controller/packetFee.spec.ts @@ -0,0 +1,69 @@ +import { Bool, PacketEvent, PacketSendTable } from 'src/types' +import { DB } from '..' +import { select } from '../utils' +import { PacketController } from './packet' +import { mockServers } from 'src/test/testSetup' + +describe('channel controler', () => { + test('packet send e2e', async () => { + const [mockServer1, _] = mockServers + // test send_packet + { + // create mock events + const events: PacketEvent[] = [ + { + type: 'send_packet', + packetInfo: { + height: 100, + sequence: 1, + connectionId: 'connection-1', + srcPort: 'transfer', + srcChannel: 'channel-1', + dstPort: 'transfer', + data: 'e2RhdGE6IG51bGx9', + dstChannel: 'channel-2', + timeoutHeight: 0, + timeoutTimestamp: 1731051545, + timeoutHeightRaw: '0-0', + timeoutTimestampRaw: '1731051545000000000', + }, + }, + ] + + // create feed functions + const fns = await PacketController.feedEvents( + mockServer1.rest.client(), + mockServer1.rest.chainId, + events + ) + + // execute feed functions + fns() + + // check db insertion + const res = select(DB, PacketController.tableNamePacketSend) + const expectVal: PacketSendTable[] = [ + { + dst_chain_id: 'chain-2', + dst_connection_id: 'connection-2', + dst_channel_id: 'channel-2', + sequence: 1, + in_progress: Bool.FALSE, + is_ordered: Bool.FALSE, + height: 100, + dst_port: 'transfer', + src_chain_id: 'chain-1', + src_connection_id: 'connection-1', + src_port: 'transfer', + src_channel_id: 'channel-1', + packet_data: 'e2RhdGE6IG51bGx9', + timeout_height: 0, + timeout_timestamp: 1731051545, + timeout_height_raw: '0-0', + timeout_timestamp_raw: '1731051545000000000', + }, + ] + expect(res).toEqual(expectVal) + } + }) +}) diff --git a/src/db/controller/packetFee.ts b/src/db/controller/packetFee.ts new file mode 100644 index 0000000..022a4c1 --- /dev/null +++ b/src/db/controller/packetFee.ts @@ -0,0 +1,59 @@ +import { DB } from '..' +import { FeeType, PacketFeeEvent, PacketFeeTable } from 'src/types' +import { del, insert } from '../utils' +import { Coin, Coins } from '@initia/initia.js' + +export class PacketFeeController { + static tableName = 'packet_fee' + + public static feedEvents( + chainId: string, + events: PacketFeeEvent[] + ): () => void { + const feedFns: (() => void)[] = [] + const toFn = ( + event: PacketFeeEvent, + coins: Coin[], + type: FeeType + ): (() => void) => { + return () => { + for (const coin of coins) { + const packetFee: PacketFeeTable = { + chain_id: chainId, + channel_id: event.channelId, + sequence: event.sequence, + fee_type: type, + denom: coin.denom, + amount: Number(coin.amount), + } + insert(DB, this.tableName, packetFee) + } + } + } + for (const event of events) { + const recvFee = new Coins(event.recvFee).toArray() + feedFns.push(toFn(event, recvFee, FeeType.RECV)) + const ackFee = new Coins(event.ackFee).toArray() + feedFns.push(toFn(event, ackFee, FeeType.ACK)) + const timeoutFee = new Coins(event.timeoutFee).toArray() + feedFns.push(toFn(event, timeoutFee, FeeType.TIMEOUT)) + } + + return () => { + for (const fn of feedFns) { + fn() + } + } + } + + public static removePacketFee( + chainId: string, + channelId: string, + sequence: number, + type: FeeType + ) { + del(DB, this.tableName, [ + { chain_id: chainId, channel_id: channelId, sequence, fee_type: type }, + ]) + } +} diff --git a/src/db/controller/syncInfo.ts b/src/db/controller/syncInfo.ts new file mode 100644 index 0000000..b95afff --- /dev/null +++ b/src/db/controller/syncInfo.ts @@ -0,0 +1,101 @@ +import { DB } from '..' +import { SyncInfoTable } from 'src/types' +import { del, insert, select, update } from '../utils' + +export class SyncInfoController { + private static tableName = 'sync_info' + public static init( + chainId: string, + startHeights: number[], + latestHeight: number + ): SyncInfoTable[] { + startHeights = startHeights.sort() + const syncInfos = this.getSyncInfos(chainId) + + if (syncInfos.length === 0) { + if (startHeights.length === 0) { + startHeights.push(latestHeight) + } + const startHeight = startHeights.pop() as number + + const syncInfo: SyncInfoTable = { + chain_id: chainId, + start_height: startHeight, + end_height: -1, + synced_height: startHeight - 1, + } + + insert(DB, this.tableName, syncInfo) + syncInfos.unshift(syncInfo) + } + + while (startHeights.length !== 0) { + const startHeight = startHeights.pop() as number + for (const syncInfo of syncInfos) { + if (syncInfo.start_height > startHeight) { + const newSyncInfo: SyncInfoTable = { + chain_id: chainId, + start_height: startHeight, + end_height: syncInfo.start_height - 1, + synced_height: startHeight - 1, + } + + syncInfos.unshift(newSyncInfo) + insert(DB, this.tableName, newSyncInfo) + } + + // TODO: split sync info when syncInfo.syncedHeight < startHeight < syncInfo.endHeight + break + } + } + + return syncInfos + } + + public static getSyncInfos(chainId: string): SyncInfoTable[] { + return select(DB, this.tableName, [{ chain_id: chainId }]) + } + + /** + * update `syncedHeight`. + * If `syncedHeight` reach to `endHeight`, merge syncInfo to next range and return true + * @param chainId + * @param startHeight + * @param endHeight + * @param syncedHeight + * @returns + */ + public static update( + chainId: string, + startHeight: number, + endHeight: number, + syncedHeight: number + ): boolean { + // check finish + if (syncedHeight === endHeight) { + del(DB, this.tableName, [ + { chain_id: chainId, start_height: startHeight }, + ]) + + update(DB, this.tableName, { start_height: startHeight }, [ + { + chain_id: chainId, + start_height: endHeight + 1, + }, + ]) + + console.log(select(DB, this.tableName)) + + return true + } + + update(DB, this.tableName, { synced_height: syncedHeight }, [ + { + chain_id: chainId, + start_height: startHeight, + }, + ]) + + return false + } +} diff --git a/src/db/index.ts b/src/db/index.ts new file mode 100644 index 0000000..68e565c --- /dev/null +++ b/src/db/index.ts @@ -0,0 +1,23 @@ +import DatabaseConstructor, { Database } from 'better-sqlite3' +import { migrate } from './migration' +import * as fs from 'fs' +import * as path from 'path' +import { config } from 'src/lib/config' + +export let DB: Database + +export function initDBConnection() { + const dbPath = config.dbPath ?? './' + + if (!fs.existsSync(path.join(dbPath, '.db'))) { + fs.mkdirSync(path.join(dbPath, '.db')) + } + const db = new DatabaseConstructor(path.join(dbPath, '.db/main.db')) + + DB = migrate(db) + + process.on('SIGINT', () => { + DB.close() + process.exit(0) + }) +} diff --git a/src/db/migration/0.0.1.sql b/src/db/migration/0.0.1.sql new file mode 100644 index 0000000..af0335b --- /dev/null +++ b/src/db/migration/0.0.1.sql @@ -0,0 +1,163 @@ +-- insert version +INSERT INTO version (id, version) VALUES (1, '0.0.1'); + +-- create sync info table +CREATE TABLE sync_info ( + chain_id TEXT NOT NULL, + start_height BIGINT NOT NULL, + end_height BIGINT, + synced_height BIGINT, + PRIMARY KEY (chain_id, start_height) +); + +-- create client table +CREATE TABLE client ( + chain_id TEXT NOT NULL, + client_id TEXT NOT NULL, + counterparty_chain_id TEXT NOT NULL, + trusting_period BIGINT NOT NULL, + revision_height BIGINT NOT NULL, + last_update_time BIGINT NOT NULL, -- in second + PRIMARY KEY (chain_id, client_id) +); + +-- create connection table +CREATE TABLE connection ( + chain_id TEXT NOT NULL, + connection_id TEXT NOT NULL, + client_id TEXT NOT NULL, + counterparty_chain_id TEXT NOT NULL, + counterparty_connection_id TEXT NOT NULL, + counterparty_client_id TEXT NOT NULL, + PRIMARY KEY (chain_id, connection_id) +); + +-- create packet tables + +-- create packet send table, table for execute packet_recv +-- store send_packet event +CREATE TABLE packet_send ( + -- pk + dst_chain_id TEXT NOT NULL, + dst_channel_id TEXT NOT NULL, + sequence BIGINT NOT NULL, + + -- in progress + in_progress BOOLEAN, + + -- order + is_ordered BOOLEAN, + + -- packet data + height BIGINT NOT NULL, + dst_connection_id TEXT NOT NULL, + dst_port TEXT NOT NULL, + src_chain_id TEXT NOT NULL, -- add this for filtering + src_connection_id TEXT NOT NULL, + src_port TEXT NOT NULL, + src_channel_id TEXT NOT NULL, + packet_data TEXT NOT NULL, + timeout_height BIGINT NOT NULL, + timeout_timestamp BIGINT NOT NULL, + timeout_height_raw TEXT NOT NULL, + timeout_timestamp_raw TEXT NOT NULL, + + PRIMARY KEY (dst_chain_id, dst_channel_id, sequence) +); + +-- create packet timeout table, table for execute timeout +-- store send_packet event +CREATE TABLE packet_timeout ( + -- pk + src_chain_id TEXT NOT NULL, + src_channel_id TEXT NOT NULL, + sequence BIGINT NOT NULL, + + -- in progress + in_progress BOOLEAN, + + -- order + is_ordered BOOLEAN, + + -- packet data + src_connection_id TEXT NOT NULL, + src_port TEXT NOT NULL, + dst_chain_id TEXT NOT NULL, -- add this for filtering + dst_connection_id TEXT NOT NULL, + dst_port TEXT NOT NULL, + dst_channel_id TEXT NOT NULL, + packet_data TEXT NOT NULL, + timeout_height BIGINT NOT NULL, + timeout_timestamp BIGINT NOT NULL, + timeout_height_raw TEXT NOT NULL, + timeout_timestamp_raw TEXT NOT NULL, + + PRIMARY KEY (src_chain_id, src_channel_id, sequence) +); + +-- create packet write ack table, table for execute ack +-- store write_acknowledgement event +CREATE TABLE packet_write_ack ( + -- pk + src_chain_id TEXT NOT NULL, + src_channel_id TEXT NOT NULL, + sequence BIGINT NOT NULL, + + -- in progress + in_progress BOOLEAN, + + -- order + is_ordered BOOLEAN, + + -- packet data + height BIGINT NOT NULL, + src_connection_id TEXT NOT NULL, + src_port TEXT NOT NULL, + dst_chain_id TEXT NOT NULL, -- add this for filtering + dst_connection_id TEXT NOT NULL, + dst_port TEXT NOT NULL, + dst_channel_id TEXT NOT NULL, + packet_data TEXT NOT NULL, + ack TEXT NOT NULL, + timeout_height BIGINT NOT NULL, + timeout_timestamp BIGINT NOT NULL, + timeout_height_raw TEXT NOT NULL, + timeout_timestamp_raw TEXT NOT NULL, + + PRIMARY KEY (src_chain_id, src_channel_id, sequence) +); + +-- create channel on open table +CREATE TABLE channel_open_close ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + -- in progress + in_progress BOOLEAN, + + -- channel data + height BIGINT NOT NULL, + state BIGINT NOT NULL, -- 1: INIT, 2: TRYOPEN, 3: ACK, 4: CLOSE (counter party state) + chain_id TEXT NOT NULL, -- chain_id that need to execute msg + connection_id TEXT NOT NULL, + port_id TEXT NOT NULL, + channel_id TEXT NOT NULL, + counterparty_chain_id TEXT NOT NULL, + counterparty_connection_id TEXT NOT NULL, + counterparty_port_id TEXT NOT NULL, + counterparty_channel_id TEXT NOT NULL +); + +-- create packet fee table +CREATE TABLE packet_fee ( + -- pk + chain_id TEXT NOT NULL, + channel_id TEXT NOT NULL, + sequence BIGINT NOT NULL, + fee_type BIGINT NOT NULL, -- 1: recv, 2: ack, 3: timeout + denom TEXT NOT NULL, + + -- fee data + amount BIGINT NOT NULL, + + PRIMARY KEY (chain_id, channel_id, sequence, fee_type, denom) +) \ No newline at end of file diff --git a/src/db/migration/index.ts b/src/db/migration/index.ts new file mode 100644 index 0000000..32e3e43 --- /dev/null +++ b/src/db/migration/index.ts @@ -0,0 +1,76 @@ +import { Database } from 'better-sqlite3' +import fs from 'fs' +import { VersionTable } from 'src/types' +import { PacketController } from '../controller/packet' +import { ChannelController } from '../controller/channel' + +export function migrate(db: Database): Database { + // create version table + db.exec(` + CREATE TABLE IF NOT EXISTS version ( + id INT PRIMARY KEY NOT NULL, + version TEXT NOT NULL + );`) + + // get version + const versions = db + .prepare(`SELECT * FROM version WHERE id = 1`) + .all() as VersionTable[] + const version = versions.length === 0 ? '0.0.0' : versions[0].version + + // get migrations + const migrations = fs + .readdirSync('./src/db/migration') + .filter((f) => f.endsWith('.sql')) + .map((f) => f.replace('.sql', '')) + + // get unapplied versions + const numberizedVersion = numberize(version) + + const unappliedVersions = migrations + .map(numberize) + .sort() + .filter((v) => v > numberizedVersion) + .map(versionize) + + // apply versions + for (const version of unappliedVersions) { + const sql = fs.readFileSync(`./src/db/migration/${version}.sql`).toString() + db.transaction(() => { + db.exec(sql) + })() + } + + // reset in progress + PacketController.resetPacketInProgress(db) + ChannelController.resetPacketInProgress(db) + return db +} + +function numberize(version: string): number { + const ns = version.split('.').map((n) => parseInt(n)) // '1.2.3' => [1,2,3] + if (ns.length !== 3) { + throw Error('invalid version') + } + return ns.reduce((p, c) => { + if (c > 255) { + throw Error('version numbering is too big') + } + + return (p << 8) + c + }) +} + +function versionize(num: number): string { + if (num > 16777215) { + throw Error('invalid numberized version') + } + + const ns = [] + for (let i = 0; i < 3; i++) { + ns.push(num % 256) + num = num >> 8 + } + + return ns.reverse().join('.') +} diff --git a/src/db/utils.ts b/src/db/utils.ts new file mode 100644 index 0000000..2cf1617 --- /dev/null +++ b/src/db/utils.ts @@ -0,0 +1,263 @@ +import { Database } from 'better-sqlite3' +import { + PacketSendTable, + PacketTimeoutTable, + PacketWriteAckTable, +} from 'src/types' +import { Height, Packet } from '@initia/initia.js' + +export function toBE(bigint: bigint, len = 8): Uint8Array { + const result = [] + while (bigint > 0) { + result.push(Number(bigint % BigInt(256))) + bigint = bigint / BigInt(256) + } + + // fill 0 + while (result.length < len) { + result.push(0) + } + + if (result.length !== len) { + throw Error('Number is too big to convert') + } + + return new Uint8Array(result.reverse()) +} + +export function fromBE(bytes: number[] | Buffer): bigint { + bytes = [...bytes] + let result = 0n + bytes = bytes.reverse() + while (bytes.length > 0) { + result = result * 256n + BigInt(bytes.pop() as number) + } + return result +} + +// type convert +export function packetTableToPacket( + packetTable: PacketSendTable | PacketWriteAckTable | PacketTimeoutTable +): Packet { + const height = new Height( + Number(packetTable.timeout_height_raw.split('-')[0]), + Number(packetTable.timeout_height_raw.split('-')[1]) + ) + return new Packet( + packetTable.sequence, + packetTable.src_port, + packetTable.src_channel_id, + packetTable.dst_port, + packetTable.dst_channel_id, + packetTable.packet_data, + height, + packetTable.timeout_timestamp_raw + ) +} + +// sql helper + +export function insert(db: Database, tableName: string, obj: T) { + const keys = Object.keys(obj as object) + const placeHolder = keys.map((key) => `$${key}`).join(',') + const prepare = db.prepare( + `INSERT INTO ${tableName} (${keys.join(',')}) VALUES (${placeHolder})` + ) + + prepare.run(obj) +} + +export function select( + db: Database, + tableName: string, + wheres?: WhereOptions[], + orders?: Order, + limit?: number +): T[] { + let sql = `SELECT * FROM ${tableName}` + const params: ParamType[] = [] + + if (wheres) { + const [whereSql, whereParams] = where(wheres) + sql += whereSql + params.push(...whereParams) + } + + if (orders) { + sql += order(orders) + } + + if (limit) { + sql += ' limit ?' + params.push(limit) + } + + return db.prepare(sql).all(params) +} + +export function selectOne( + db: Database, + tableName: string, + wheres?: WhereOptions[], + orders?: Order +): T | undefined { + const res = select(db, tableName, wheres, orders, 1) + if (res.length === 0) return undefined + + return res[0] +} + +export function del( + db: Database, + tableName: string, + wheres?: WhereOptions[] +) { + let sql = `DELETE from ${tableName}` + const params: ParamType[] = [] + if (wheres) { + const [whereSql, whereParams] = where(wheres) + sql += whereSql + params.push(...whereParams) + } + + db.prepare(sql).run(params) +} + +export function update( + db: Database, + tableName: string, + set: Partial, + wheres?: WhereOptions[] +) { + let sql = `UPDATE ${tableName} SET` + const params = [] + const keys = Object.keys(set as object) + const placeHolder = keys.map((key) => ` ${key} = $${key}`).join(',') + sql += placeHolder + + if (wheres) { + const [whereSql, whereParams] = where(wheres) + sql += whereSql + params.push(...whereParams) + } + + db.prepare(sql).run(params, set) +} + +function where(wheres: WhereOptions[]): [string, ParamType[]] { + let sql = '' + + const conditions = [] + const params: ParamType[] = [] + + for (const where of wheres) { + const condition = [] + const keys = Object.keys(where) as (keyof T)[] + for (const key of keys) { + const value = where[key] + if (typeof value === 'object' && value !== null) { + if ('in' in value) { + const vals = value.in as unknown[] + const placeHolder = vals.map(() => '?').join(',') + condition.push(`${String(key)} IN(${placeHolder})`) + params.push(...vals.map(toParamType)) + } else { + const rangeConditions: string[] = [] + + // if both gt and gte are given, use gt + if ('gte' in value && !('gt' in value)) { + rangeConditions.push(`${String(key)} >= ?`) + params.push(toParamType(value.gte)) + } + if ('gt' in value) { + rangeConditions.push(`${String(key)} > ?`) + params.push(toParamType(value.gt)) + } + + // if both lt and lte are given, use lt + if ('lte' in value && !('lt' in value)) { + rangeConditions.push(`${String(key)} <= ?`) + params.push(toParamType(value.lte)) + } + if ('lt' in value) { + rangeConditions.push(`${String(key)} < ?`) + params.push(toParamType(value.lt)) + } + + condition.push(`(${rangeConditions.join(' AND ')})`) + } + } else if (key === 'custom') { + condition.push(value) + } else if (typeof value === 'undefined') { + // do nothing + } else { + condition.push(`${String(key)} = ?`) + params.push(toParamType(value)) + } + } + if (condition.length !== 0) { + conditions.push(`(${condition.join(' AND ')})`) + } + } + + if (conditions.length !== 0) { + sql += ` WHERE ${conditions.join(' OR ')}` + } + + return [sql, params] +} + +function order(order: Order): string { + let sql = '' + + const orders: string[] = [] + const keys = Object.keys(where) as (keyof T)[] + for (const key of keys) { + orders.push(`${String(key)} ${order[key]}`) + } + + if (orders.length !== 0) { + sql = ` ORDER BY ${orders.join(', ')} ` + } + + return sql +} + +export type WhereOptions = { + [P in keyof T]?: T[P] | Range | In +} & { custom?: string } + +export type Order = { + [P in keyof T]?: 'ASC' | 'DESC' +} + +interface Range { + gt?: V + gte?: V + lt?: V + lte?: V +} + +interface In { + in: V[] +} + +export function In(array: T[]): In { + return { in: array } +} + +type ParamType = number | string | bigint | Buffer | null + +function toParamType(p: T): ParamType { + if ( + typeof p === 'number' || + typeof p === 'string' || + typeof p === 'bigint' || + p === null || + Buffer.isBuffer(p) + ) { + return p as number | string | bigint | Buffer | null + } + + return String(p) +} diff --git a/src/index.ts b/src/index.ts index a799385..e9d8394 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,35 +1,20 @@ -import { Chain } from './chain' import express from 'express' -import { runPair } from './lib/chainPair' -import { config } from './lib/config' -import { ChainStatus } from './chain/types' import { registry } from './lib/metric' import { info } from './lib/logger' -async function main() { - const pairs: Record = {} - await Promise.all( - config.pairs.map(async (config) => { - const pair = await runPair(config) - pairs[pair.name] = { chainA: pair.chainA, chainB: pair.chainB } - }) - ) +import { config } from './lib/config' +import { WorkerController } from './workers' +import { initDBConnection } from './db' +async function main() { + initDBConnection() + const workerController = new WorkerController() + await workerController.init(config) const app = express() app.get('/status', (req, res) => { - const result: Record = - {} - Object.keys(pairs).map((name) => { - result[name] = { - chainA: pairs[name].chainA.chainStatus(), - chainB: pairs[name].chainB.chainStatus(), - } - }) - - res.json(result) + res.json(workerController.getStatus()) }) - const metricApp = express() metricApp.get('/metrics', (req, res) => { @@ -42,6 +27,9 @@ async function main() { app.listen(config.port) info(`status app listen to port ${config.port}`) + info(`rapid relayer has been started`) + info(JSON.stringify(workerController.getStatus(), undefined, 2)) + metricApp.listen(config.metricPort) info(`metric app listen to port ${config.metricPort}`) } diff --git a/src/lib/chainPair.ts b/src/lib/chainPair.ts deleted file mode 100644 index d07ee59..0000000 --- a/src/lib/chainPair.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Key, MnemonicKey, RawKey } from '@initia/initia.js' -import { Chain } from 'src/chain' -import { SyncInfo } from 'src/chain/types' -import { env } from 'node:process' - -export async function runPair( - config: ConfigPair -): Promise<{ name: string; chainA: Chain; chainB: Chain }> { - const keyA = createKey(config.chainA.key) - const keyB = createKey(config.chainB.key) - - const chainA = await Chain.init({ - ...config.chainA, - key: keyA, - }) - - const chainB = await Chain.init({ - ...config.chainB, - key: keyB, - }) - - await chainA.registerCounterpartyChain(chainB) - await chainB.registerCounterpartyChain(chainA) - - return { - name: config.name ?? `${config.chainA.chainId} - ${config.chainB.chainId}`, - chainA, - chainB, - } -} - -function createKey(rawKey: ChainRawKeyConfig): Key { - let keyReturn - switch (rawKey.type) { - case 'mnemonic': { - const options = rawKey.options || {} - - keyReturn = new MnemonicKey({ mnemonic: rawKey.privateKey, ...options }) - break - } - case 'env_mnemonic': { - const key = env[rawKey.privateKey] - if (!key) { - throw Error(`missing environment ${rawKey.privateKey}`) - } - const options = rawKey.options || {} - - keyReturn = new MnemonicKey({ mnemonic: key, ...options }) - break - } - case 'raw': { - keyReturn = new RawKey(Buffer.from(rawKey.privateKey, 'hex')) - break - } - case 'env_raw': { - const key = env[rawKey.privateKey] - if (!key) { - throw Error(`missing environment ${rawKey.privateKey}`) - } - keyReturn = new RawKey(Buffer.from(key, 'hex')) - break - } - } - return keyReturn -} - -interface ChainRawKeyConfig { - type: 'raw' | 'mnemonic' | 'env_raw' | 'env_mnemonic' - privateKey: string - /** - * for mnemonic type keys only - */ - options?: { - account?: number - /** - * BIP44 index number - */ - index?: number - /** - * Coin type. Default is INIT, 118. - */ - coinType?: number - } -} - -interface ChainRawConfig { - bech32Prefix: string - chainId: string - gasPrice: string - lcdUri: string - rpcUri: string - key: ChainRawKeyConfig - connectionId: string - syncInfo?: SyncInfo // if syncInfo file exists, ignore start height -} - -export interface ConfigPair { - name?: string - chainA: ChainRawConfig - chainB: ChainRawConfig -} diff --git a/src/lib/config.ts b/src/lib/config.ts index 1edd34a..324a7d8 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -1,6 +1,6 @@ import * as fs from 'fs' -import { ConfigPair } from './chainPair' import { env } from 'node:process' +import { PacketFilter } from 'src/db/controller/packet' export const config: Config = JSON.parse( fs.readFileSync(env.CONFIGFILE || './config.json').toString() @@ -10,7 +10,53 @@ export interface Config { port: number metricPort: number logLevel: string - pairs: ConfigPair[] + dbPath?: string + chains: ChainConfig[] } -export const syncInfoFile = env.SYNC_INFO || './.syncInfo' +interface ChainConfig { + bech32Prefix: string + chainId: string + gasPrice: string + restUri: string + rpcUri: string + wallets: WalletConfig[] + feeFilter?: PacketFee +} + +interface WalletConfig { + key: KeyConfig + maxHandlePacket?: number // max packet amount that handle at once + packetFilter?: PacketFilter + startHeight?: number +} + +export interface PacketFee { + recvFee?: Coin[] + ackFee?: Coin[] + timeoutFee?: Coin[] +} + +interface Coin { + denom: string + amount: number +} + +export interface KeyConfig { + type: 'raw' | 'mnemonic' | 'env_raw' | 'env_mnemonic' + privateKey: string + /** + * for mnemonic type keys only + */ + options?: { + account?: number + /** + * BIP44 index number + */ + index?: number + /** + * Coin type. Default is INIT, 118. + */ + coinType?: number + } +} diff --git a/src/lib/eventParser.spec.ts b/src/lib/eventParser.spec.ts new file mode 100644 index 0000000..d84bf89 --- /dev/null +++ b/src/lib/eventParser.spec.ts @@ -0,0 +1,224 @@ +import { parsePacketEvent } from './eventParser' + +describe('event parser', () => { + test('packet parser', () => { + // test send packet + { + const packetInfo = parsePacketEvent(sendPacket, 123) + const expectValue = { + height: 123, + connectionId: 'connection-1559', + sequence: 293662, + srcPort: 'transfer', + srcChannel: 'channel-259', + dstPort: 'transfer', + dstChannel: 'channel-3', + data: 'eyJkZW5vbSI6InRyYW5zZmVyL2NoYW5uZWwtMjU5L3VrdWppIiwiYW1vdW50IjoiMTQ5NjY5MDEiLCJzZW5kZXIiOiJvc21vMTd5cDN5dmE3ZXhnMHJ1MnlsMndhZXdjZ2RzdzlhYzNmMm00M3VrZ2Q3ZDM5ZTA0NHlyNnF6d2t5ZDMiLCJyZWNlaXZlciI6Imt1amlyYTE1M3o5YTkwZjA5NzdwMnFkZTI4bTBjc3h1YXZxdXlhdGVmOXh0cCJ9', + timeoutHeight: 0, + timeoutTimestamp: 1730462659, + timeoutHeightRaw: '0-0', + timeoutTimestampRaw: '1730462659929766700', + ordering: 'ORDER_UNORDERED', + ack: undefined, + } + + expect(expectValue).toEqual(packetInfo) + } + + // test wirte ack + { + const packetInfo = parsePacketEvent(writeAck, 123) + const expectValue = { + height: 123, + connectionId: 'connection-2566', + sequence: 399171, + srcPort: 'transfer', + srcChannel: 'channel-2', + dstPort: 'transfer', + dstChannel: 'channel-19774', + data: 'eyJhbW91bnQiOiIzNzAwMDAwMDAwMDAwMDAwMDAwMCIsImRlbm9tIjoiYWR5bSIsIm1lbW8iOiJ7XCJ3YXNtXCI6e1wiY29udHJhY3RcIjpcIm9zbW8xZThwbGQ4ZnQ1cmMzcW03OGhjbGR5MnAwNXJqcmZ6YWVlYTUwbXAwenY1YzI5NHBsMnB5cWs1anJuZFwiLFwibXNnXCI6e1wic3dhcF9hbmRfYWN0aW9uXCI6e1widXNlcl9zd2FwXCI6e1wic3dhcF9leGFjdF9hc3NldF9pblwiOntcInN3YXBfdmVudWVfbmFtZVwiOlwib3Ntb3Npcy1wb29sbWFuYWdlclwiLFwib3BlcmF0aW9uc1wiOlt7XCJwb29sXCI6XCIxNDQ5XCIsXCJkZW5vbV9pblwiOlwiaWJjLzlBNzZDREYwQ0JDRUYzNzkyM0YzMjUxOEZBMTVFNURDOTJCOUY1NjEyODI5MkJDNEQ2M0M0QUVBNzZDQkIxMTBcIixcImRlbm9tX291dFwiOlwidW9zbW9cIn1dfX0sXCJtaW5fYXNzZXRcIjp7XCJuYXRpdmVcIjp7XCJkZW5vbVwiOlwidW9zbW9cIixcImFtb3VudFwiOlwiMTI5Mjc5MjY0XCJ9fSxcInRpbWVvdXRfdGltZXN0YW1wXCI6MTczMDQ2MjY1NDg5NzQxNjAyMCxcInBvc3Rfc3dhcF9hY3Rpb25cIjp7XCJ0cmFuc2ZlclwiOntcInRvX2FkZHJlc3NcIjpcIm9zbW8xdXl4ZHJxeWt0cWZ6Z3o0bWpyajg4ZWV3ZzUyOTh1NTQwZjAzN3hcIn19LFwiYWZmaWxpYXRlc1wiOlt7XCJiYXNpc19wb2ludHNfZmVlXCI6XCI2MFwiLFwiYWRkcmVzc1wiOlwib3NtbzFteTR0azQyMGdqbWhnZ3F3dnZoYTZleTkzOTBncXdmcmVlMnA0dVwifSx7XCJiYXNpc19wb2ludHNfZmVlXCI6XCIxNVwiLFwiYWRkcmVzc1wiOlwib3NtbzE0Z2Y2eHNsd2U5cGhuMno5NjV0NGRjdTd2Y2hodGhmZ3YybGh5eVwifV19fX19IiwicmVjZWl2ZXIiOiJvc21vMWU4cGxkOGZ0NXJjM3FtNzhoY2xkeTJwMDVyanJmemFlZWE1MG1wMHp2NWMyOTRwbDJweXFrNWpybmQiLCJzZW5kZXIiOiJkeW0xYXkyY2t4NHM4dm5oY3l2MzZoaDVxNnNxNDR2MDJ2aGNyYXdyYXYifQ==', + timeoutHeight: 23278545, + timeoutTimestamp: 0, + timeoutHeightRaw: '1-23278545', + timeoutTimestampRaw: '0', + ordering: 'ORDER_UNORDERED', + ack: 'eyJyZXN1bHQiOiJleUpqYjI1MGNtRmpkRjl5WlhOMWJIUWlPbTUxYkd3c0ltbGlZMTloWTJzaU9pSmxlVXA1V2xoT01XSklVV2xQYVVwQ1ZWUXdPVWx1TUQwaWZRPT0ifQ==', + } + + expect(expectValue).toEqual(packetInfo) + } + + // test send packet (base64 encoded events) + { + const packetInfo = parsePacketEvent(sendPacketBase64, 123) + const expectValue = { + height: 123, + connectionId: 'connection-61', + sequence: 15598, + srcPort: 'transfer', + srcChannel: 'channel-39', + dstPort: 'transfer', + dstChannel: 'channel-45', + data: 'eyJhbW91bnQiOiIzNDczMDAwMDAwIiwiZGVub20iOiJ1dXNkYyIsInJlY2VpdmVyIjoic2VpMWt3Z25lY3lzcTVxeGhnMmg4NmNwN2cwNWU2enN6dHJjZzAzOWg2Iiwic2VuZGVyIjoibm9ibGUxcGswYzB4MGxtdjVtbTgweXJtcmNtMno1eTgzZjN2bXV2dmNqNHgifQ==', + timeoutHeight: 14691118, + timeoutTimestamp: 0, + timeoutHeightRaw: '14691018-14691118', + timeoutTimestampRaw: '0', + ordering: 'ORDER_UNORDERED', + ack: undefined, + } + + expect(expectValue).toEqual(packetInfo) + } + + // test wirte ack (base64 encoded events) + { + const packetInfo = parsePacketEvent(writeAckBase64, 123) + const expectValue = { + height: 123, + connectionId: 'connection-34', + sequence: 30288, + srcPort: 'transfer', + srcChannel: 'channel-30', + dstPort: 'transfer', + dstChannel: 'channel-18', + data: 'eyJhbW91bnQiOiIyMDAzNDU4NTciLCJkZW5vbSI6InRyYW5zZmVyL2NoYW5uZWwtMzAvdXVzZGMiLCJyZWNlaXZlciI6Im5vYmxlMTZlbjlhdGVxNTU2NWM0bjI2ZWQwd3lrbW5xaGQwdGhwYzU3dG1oIiwic2VuZGVyIjoibmV1dHJvbjE2ZW45YXRlcTU1NjVjNG4yNmVkMHd5a21ucWhkMHRocDVnenBlNyJ9', + timeoutHeight: 0, + timeoutTimestamp: 1730467768, + timeoutHeightRaw: '0-0', + timeoutTimestampRaw: '1730467768229000000', + ordering: undefined, + ack: 'eyJyZXN1bHQiOiJBUT09In0=', + } + + expect(expectValue).toEqual(packetInfo) + } + }) +}) + +// Real data from chains for test +const sendPacketBase64 = { + type: 'send_packet', + attributes: [ + { + key: 'cGFja2V0X2RhdGE=', // packet data + value: + 'eyJhbW91bnQiOiIzNDczMDAwMDAwIiwiZGVub20iOiJ1dXNkYyIsInJlY2VpdmVyIjoic2VpMWt3Z25lY3lzcTVxeGhnMmg4NmNwN2cwNWU2enN6dHJjZzAzOWg2Iiwic2VuZGVyIjoibm9ibGUxcGswYzB4MGxtdjVtbTgweXJtcmNtMno1eTgzZjN2bXV2dmNqNHgifQ==', + }, // '{"amount":"3473000000","denom":"uusdc","receiver":"sei1kwgnecysq5qxhg2h86cp7g05e6zsztrcg039h6","sender":"noble1pk0c0x0lmv5mm80yrmrcm2z5y83f3vmuvvcj4x"}' + { + key: 'cGFja2V0X2RhdGFfaGV4', // packet data hex + value: + 'N2IyMjYxNmQ2Zjc1NmU3NDIyM2EyMjMzMzQzNzMzMzAzMDMwMzAzMDMwMjIyYzIyNjQ2NTZlNmY2ZDIyM2EyMjc1NzU3MzY0NjMyMjJjMjI3MjY1NjM2NTY5NzY2NTcyMjIzYTIyNzM2NTY5MzE2Yjc3Njc2ZTY1NjM3OTczNzEzNTcxNzg2ODY3MzI2ODM4MzY2MzcwMzc2NzMwMzU2NTM2N2E3MzdhNzQ3MjYzNjczMDMzMzk2ODM2MjIyYzIyNzM2NTZlNjQ2NTcyMjIzYTIyNmU2ZjYyNmM2NTMxNzA2YjMwNjMzMDc4MzA2YzZkNzYzNTZkNmQzODMwNzk3MjZkNzI2MzZkMzI3YTM1NzkzODMzNjYzMzc2NmQ3NTc2NzY2MzZhMzQ3ODIyN2Q=', + }, // '7b22616d6f756e74223a2233343733303030303030222c2264656e6f6d223a227575736463222c227265636569766572223a22736569316b77676e656379737135717868673268383663703767303565367a737a747263673033396836222c2273656e646572223a226e6f626c6531706b30633078306c6d76356d6d383079726d72636d327a357938336633766d757676636a3478227d + { + key: 'cGFja2V0X3RpbWVvdXRfaGVpZ2h0', // packet timeout height + value: 'MTQ2OTEwMTgtMTQ2OTExMTg=', // 14691018-14691118 ? + }, + { key: 'cGFja2V0X3RpbWVvdXRfdGltZXN0YW1w', value: 'MA==' }, // packet timeout, 0 + { key: 'cGFja2V0X3NlcXVlbmNl', value: 'MTU1OTg=' }, // packet sequence, 15598 + { key: 'cGFja2V0X3NyY19wb3J0', value: 'dHJhbnNmZXI=' }, // packet src port, transfer + { key: 'cGFja2V0X3NyY19jaGFubmVs', value: 'Y2hhbm5lbC0zOQ==' }, // packet src channel, channel-39 + { key: 'cGFja2V0X2RzdF9wb3J0', value: 'dHJhbnNmZXI=' }, // packet dst port, transfer + { key: 'cGFja2V0X2RzdF9jaGFubmVs', value: 'Y2hhbm5lbC00NQ==' }, // packet dst channel, channel-45 + { + key: 'cGFja2V0X2NoYW5uZWxfb3JkZXJpbmc=', // packet channel ordering + value: 'T1JERVJfVU5PUkRFUkVE', // , ORDER_UNORDERED + }, + { key: 'cGFja2V0X2Nvbm5lY3Rpb24=', value: 'Y29ubmVjdGlvbi02MQ==' }, // packet connection, connection-61 + ], +} +const writeAckBase64 = { + type: 'write_acknowledgement', + attributes: [ + { + key: 'cGFja2V0X2RhdGE=', // packet data + value: + 'eyJhbW91bnQiOiIyMDAzNDU4NTciLCJkZW5vbSI6InRyYW5zZmVyL2NoYW5uZWwtMzAvdXVzZGMiLCJyZWNlaXZlciI6Im5vYmxlMTZlbjlhdGVxNTU2NWM0bjI2ZWQwd3lrbW5xaGQwdGhwYzU3dG1oIiwic2VuZGVyIjoibmV1dHJvbjE2ZW45YXRlcTU1NjVjNG4yNmVkMHd5a21ucWhkMHRocDVnenBlNyJ9', + }, // {"amount":"200345857","denom":"transfer/channel-30/uusdc","receiver":"noble16en9ateq5565c4n26ed0wykmnqhd0thpc57tmh","sender":"neutron16en9ateq5565c4n26ed0wykmnqhd0thp5gzpe7"} + { + key: 'cGFja2V0X2RhdGFfaGV4', // packet data hex + value: + 'N2IyMjYxNmQ2Zjc1NmU3NDIyM2EyMjMyMzAzMDMzMzQzNTM4MzUzNzIyMmMyMjY0NjU2ZTZmNmQyMjNhMjI3NDcyNjE2ZTczNjY2NTcyMmY2MzY4NjE2ZTZlNjU2YzJkMzMzMDJmNzU3NTczNjQ2MzIyMmMyMjcyNjU2MzY1Njk3NjY1NzIyMjNhMjI2ZTZmNjI2YzY1MzEzNjY1NmUzOTYxNzQ2NTcxMzUzNTM2MzU2MzM0NmUzMjM2NjU2NDMwNzc3OTZiNmQ2ZTcxNjg2NDMwNzQ2ODcwNjMzNTM3NzQ2ZDY4MjIyYzIyNzM2NTZlNjQ2NTcyMjIzYTIyNmU2NTc1NzQ3MjZmNmUzMTM2NjU2ZTM5NjE3NDY1NzEzNTM1MzYzNTYzMzQ2ZTMyMzY2NTY0MzA3Nzc5NmI2ZDZlNzE2ODY0MzA3NDY4NzAzNTY3N2E3MDY1MzcyMjdk', + }, // 7b22616d6f756e74223a22323030333435383537222c2264656e6f6d223a227472616e736665722f6368616e6e656c2d33302f7575736463222c227265636569766572223a226e6f626c653136656e39617465713535363563346e323665643077796b6d6e71686430746870633537746d68222c2273656e646572223a226e657574726f6e3136656e39617465713535363563346e323665643077796b6d6e7168643074687035677a706537227d + { key: 'cGFja2V0X3RpbWVvdXRfaGVpZ2h0', value: 'MC0w' }, // packet timeout height, 0-0 + { + key: 'cGFja2V0X3RpbWVvdXRfdGltZXN0YW1w', // packet timeout timestamp + value: 'MTczMDQ2Nzc2ODIyOTAwMDAwMA==', // 1730467768229000000 + }, + { key: 'cGFja2V0X3NlcXVlbmNl', value: 'MzAyODg=' }, // packet sequence 30288 + { key: 'cGFja2V0X3NyY19wb3J0', value: 'dHJhbnNmZXI=' }, // packet src port, transfer + { key: 'cGFja2V0X3NyY19jaGFubmVs', value: 'Y2hhbm5lbC0zMA==' }, // packet src channel, channel-30 + { key: 'cGFja2V0X2RzdF9wb3J0', value: 'dHJhbnNmZXI=' }, // packet dst port, transfer + { key: 'cGFja2V0X2RzdF9jaGFubmVs', value: 'Y2hhbm5lbC0xOA==' }, // packet dst channel, channel-18 + { key: 'cGFja2V0X2Fjaw==', value: 'eyJyZXN1bHQiOiJBUT09In0=' }, // packet ack, {"result":"AQ=="} + { + key: 'cGFja2V0X2Fja19oZXg=', // packet ack hex + value: 'N2IyMjcyNjU3Mzc1NmM3NDIyM2EyMjQxNTEzZDNkMjI3ZA==', // 7b22726573756c74223a2241513d3d227d + }, + { key: 'cGFja2V0X2Nvbm5lY3Rpb24=', value: 'Y29ubmVjdGlvbi0zNA==' }, // packet connection, connection-34 + ], +} + +const sendPacket = { + type: 'send_packet', + attributes: [ + { key: 'connection_id', value: 'connection-1559' }, + { key: 'packet_channel_ordering', value: 'ORDER_UNORDERED' }, + { key: 'packet_connection', value: 'connection-1559' }, + { + key: 'packet_data', + value: + '{"denom":"transfer/channel-259/ukuji","amount":"14966901","sender":"osmo17yp3yva7exg0ru2yl2waewcgdsw9ac3f2m43ukgd7d39e044yr6qzwkyd3","receiver":"kujira153z9a90f0977p2qde28m0csxuavquyatef9xtp"}', + }, + { + key: 'packet_data_hex', + value: + '7b2264656e6f6d223a227472616e736665722f6368616e6e656c2d3235392f756b756a69222c22616d6f756e74223a223134393636393031222c2273656e646572223a226f736d6f31377970337976613765786730727532796c327761657763676473773961633366326d3433756b67643764333965303434797236717a776b796433222c227265636569766572223a226b756a6972613135337a396139306630393737703271646532386d306373787561767175796174656639787470227d', + }, + { key: 'packet_dst_channel', value: 'channel-3' }, + { key: 'packet_dst_port', value: 'transfer' }, + { key: 'packet_sequence', value: '293662' }, + { key: 'packet_src_channel', value: 'channel-259' }, + { key: 'packet_src_port', value: 'transfer' }, + { key: 'packet_timeout_height', value: '0-0' }, + { key: 'packet_timeout_timestamp', value: '1730462659929766700' }, + { key: 'msg_index', value: '1' }, + ], +} + +const writeAck = { + type: 'write_acknowledgement', + attributes: [ + { + key: 'packet_data', + value: + '{"amount":"37000000000000000000","denom":"adym","memo":"{\\"wasm\\":{\\"contract\\":\\"osmo1e8pld8ft5rc3qm78hcldy2p05rjrfzaeea50mp0zv5c294pl2pyqk5jrnd\\",\\"msg\\":{\\"swap_and_action\\":{\\"user_swap\\":{\\"swap_exact_asset_in\\":{\\"swap_venue_name\\":\\"osmosis-poolmanager\\",\\"operations\\":[{\\"pool\\":\\"1449\\",\\"denom_in\\":\\"ibc/9A76CDF0CBCEF37923F32518FA15E5DC92B9F56128292BC4D63C4AEA76CBB110\\",\\"denom_out\\":\\"uosmo\\"}]}},\\"min_asset\\":{\\"native\\":{\\"denom\\":\\"uosmo\\",\\"amount\\":\\"129279264\\"}},\\"timeout_timestamp\\":1730462654897416020,\\"post_swap_action\\":{\\"transfer\\":{\\"to_address\\":\\"osmo1uyxdrqyktqfzgz4mjrj88eewg5298u540f037x\\"}},\\"affiliates\\":[{\\"basis_points_fee\\":\\"60\\",\\"address\\":\\"osmo1my4tk420gjmhggqwvvha6ey9390gqwfree2p4u\\"},{\\"basis_points_fee\\":\\"15\\",\\"address\\":\\"osmo14gf6xslwe9phn2z965t4dcu7vchhthfgv2lhyy\\"}]}}}}","receiver":"osmo1e8pld8ft5rc3qm78hcldy2p05rjrfzaeea50mp0zv5c294pl2pyqk5jrnd","sender":"dym1ay2ckx4s8vnhcyv36hh5q6sq44v02vhcrawrav"}', + }, + { + key: 'packet_data_hex', + value: + '7b22616d6f756e74223a223337303030303030303030303030303030303030222c2264656e6f6d223a226164796d222c226d656d6f223a227b5c227761736d5c223a7b5c22636f6e74726163745c223a5c226f736d6f316538706c6438667435726333716d373868636c647932703035726a72667a6165656135306d70307a763563323934706c327079716b356a726e645c222c5c226d73675c223a7b5c22737761705f616e645f616374696f6e5c223a7b5c22757365725f737761705c223a7b5c22737761705f65786163745f61737365745f696e5c223a7b5c22737761705f76656e75655f6e616d655c223a5c226f736d6f7369732d706f6f6c6d616e616765725c222c5c226f7065726174696f6e735c223a5b7b5c22706f6f6c5c223a5c22313434395c222c5c2264656e6f6d5f696e5c223a5c226962632f394137364344463043424345463337393233463332353138464131354535444339324239463536313238323932424334443633433441454137364342423131305c222c5c2264656e6f6d5f6f75745c223a5c22756f736d6f5c227d5d7d7d2c5c226d696e5f61737365745c223a7b5c226e61746976655c223a7b5c2264656e6f6d5c223a5c22756f736d6f5c222c5c22616d6f756e745c223a5c223132393237393236345c227d7d2c5c2274696d656f75745f74696d657374616d705c223a313733303436323635343839373431363032302c5c22706f73745f737761705f616374696f6e5c223a7b5c227472616e736665725c223a7b5c22746f5f616464726573735c223a5c226f736d6f31757978647271796b7471667a677a346d6a726a383865657767353239387535343066303337785c227d7d2c5c22616666696c69617465735c223a5b7b5c2262617369735f706f696e74735f6665655c223a5c2236305c222c5c22616464726573735c223a5c226f736d6f316d7934746b343230676a6d6867677177767668613665793933393067717766726565327034755c227d2c7b5c2262617369735f706f696e74735f6665655c223a5c2231355c222c5c22616464726573735c223a5c226f736d6f313467663678736c77653970686e327a393635743464637537766368687468666776326c6879795c227d5d7d7d7d7d222c227265636569766572223a226f736d6f316538706c6438667435726333716d373868636c647932703035726a72667a6165656135306d70307a763563323934706c327079716b356a726e64222c2273656e646572223a2264796d31617932636b78347338766e686379763336686835713673713434763032766863726177726176227d', + }, + { key: 'packet_timeout_height', value: '1-23278545' }, + { key: 'packet_timeout_timestamp', value: '0' }, + { key: 'packet_sequence', value: '399171' }, + { key: 'packet_src_port', value: 'transfer' }, + { key: 'packet_src_channel', value: 'channel-2' }, + { key: 'packet_dst_port', value: 'transfer' }, + { key: 'packet_dst_channel', value: 'channel-19774' }, + { + key: 'packet_ack', + value: + '{"result":"eyJjb250cmFjdF9yZXN1bHQiOm51bGwsImliY19hY2siOiJleUp5WlhOMWJIUWlPaUpCVVQwOUluMD0ifQ=="}', + }, + { + key: 'packet_ack_hex', + value: + '7b22726573756c74223a2265794a6a62323530636d466a644639795a584e31624851694f6d353162477773496d6c6959313968593273694f694a6c65557035576c684f4d574a4955576c5061557043565651774f556c754d44306966513d3d227d', + }, + { key: 'packet_channel_ordering', value: 'ORDER_UNORDERED' }, + { key: 'packet_connection', value: 'connection-2566' }, + { key: 'connection_id', value: 'connection-2566' }, + { key: 'msg_index', value: '1' }, + ], +} diff --git a/src/lib/eventParser.ts b/src/lib/eventParser.ts index f5f5876..8e34ba6 100644 --- a/src/lib/eventParser.ts +++ b/src/lib/eventParser.ts @@ -1,58 +1,41 @@ -import { Height, Packet } from '@initia/initia.js' import { Event } from '@cosmjs/tendermint-rpc/build/comet38/responses' -import { Ack } from 'src/msgs' +import { ChannelOpenCloseInfo, PacketFeeEvent, PacketInfo } from 'src/types' -export function parseSendPacketEvent( - event: Event, - connectionId: string -): Packet | undefined { - if (event.type !== 'send_packet') return - - // connection filter - if ( - event.attributes.filter((v) => v.key === 'connection_id')[0].value !== - connectionId - ) { - return - } +export function parsePacketEvent(event: Event, height: number): PacketInfo { + const connectionId = getConnection(event) as string + + const sequence = Number(find(event, 'packet_sequence') as string) + + const srcPort = find(event, 'packet_src_port') as string + + const srcChannel = find(event, 'packet_src_channel') as string - const sequence = Number( - event.attributes.filter((v) => v.key === 'packet_sequence')[0].value - ) + const dstPort = find(event, 'packet_dst_port') as string - const srcPort = event.attributes.filter((v) => v.key === 'packet_src_port')[0] - .value + const dstChannel = find(event, 'packet_dst_channel') as string - const srcChannel = event.attributes.filter( - (v) => v.key === 'packet_src_channel' - )[0].value + const dataHex = find(event, 'packet_data_hex') as string - const dstPort = event.attributes.filter((v) => v.key === 'packet_dst_port')[0] - .value + const data = dataHex + ? Buffer.from(dataHex, 'hex').toString('base64') + : undefined - const dstChannel = event.attributes.filter( - (v) => v.key === 'packet_dst_channel' - )[0].value + const timeoutHeightRaw = find(event, 'packet_timeout_height') as string - const data = Buffer.from( - event.attributes.filter((v) => v.key === 'packet_data_hex')[0].value, - 'hex' - ).toString('base64') + const timeoutHeight = Number(timeoutHeightRaw.split('-')[1]) - const timeoutHeightRaw = event.attributes.filter( - (v) => v.key === 'packet_timeout_height' - )[0].value + const timeoutTimestampRaw = find(event, 'packet_timeout_timestamp') as string + const timeoutTimestamp = Number(BigInt(timeoutTimestampRaw) / 1_000_000_000n) // store in second - const timeoutHeight = new Height( - Number(timeoutHeightRaw.split('-')[0]), - Number(timeoutHeightRaw.split('-')[1]) - ) + const ackHex = find(event, 'packet_ack_hex') - const timeoutTimestamp = event.attributes.filter( - (v) => v.key === 'packet_timeout_timestamp' - )[0].value + const ordering = find(event, 'packet_channel_ordering') - return new Packet( + const ack = ackHex ? Buffer.from(ackHex, 'hex').toString('base64') : undefined + + return { + height, + connectionId, sequence, srcPort, srcChannel, @@ -60,77 +43,112 @@ export function parseSendPacketEvent( dstChannel, data, timeoutHeight, - timeoutTimestamp - ) + timeoutTimestamp, + timeoutHeightRaw, + timeoutTimestampRaw, + ordering, + ack, + } } -export function parseWriteAckEvent( +export function parseChannelOpenEvent( event: Event, - connectionId: string -): Ack | undefined { - if (event.type !== 'write_acknowledgement') return - - // connection filter - if ( - event.attributes.filter((v) => v.key === 'connection_id')[0].value !== - connectionId - ) { - return - } + height: number +): ChannelOpenCloseInfo { + const isSrc = + event.type === 'channel_open_init' || event.type === 'channel_open_ack' - const sequence = Number( - event.attributes.filter((v) => v.key === 'packet_sequence')[0].value - ) + const connectionId = getConnection(event) as string - const srcPort = event.attributes.filter((v) => v.key === 'packet_src_port')[0] - .value + const portId = find(event, 'port_id') as string - const srcChannel = event.attributes.filter( - (v) => v.key === 'packet_src_channel' - )[0].value + const channelId = find(event, 'channel_id') as string - const dstPort = event.attributes.filter((v) => v.key === 'packet_dst_port')[0] - .value + const counterpartyPortId = find(event, 'counterparty_port_id') as string - const dstChannel = event.attributes.filter( - (v) => v.key === 'packet_dst_channel' - )[0].value + const counterpartyChannelId = find(event, 'counterparty_channel_id') as string - const data = Buffer.from( - event.attributes.filter((v) => v.key === 'packet_data')[0].value - ).toString('base64') + return { + height, + srcConnectionId: isSrc ? connectionId : '', + srcPortId: isSrc ? portId : counterpartyPortId, + srcChannelId: isSrc ? channelId : counterpartyChannelId, + dstConnectionId: isSrc ? '' : connectionId, + dstPortId: isSrc ? counterpartyPortId : portId, + dstChannelId: isSrc ? counterpartyChannelId : channelId, + } +} - const timeoutHeightRaw = event.attributes.filter( - (v) => v.key === 'packet_timeout_height' - )[0].value +export function parseChannelCloseEvent( + event: Event, + height: number +): ChannelOpenCloseInfo { + const portId = find(event, 'port_id') as string + const channelId = find(event, 'channel_id') as string + const connectionId = getConnection(event) as string + const counterpartyPortId = find(event, 'counterparty_port_id') as string + const counterpartyChannelId = find(event, 'counterparty_channel_id') as string + const isSrc = event.type === 'channel_close_init' || 'channel_close' - const timeoutHeight = new Height( - Number(timeoutHeightRaw.split('-')[0]), - Number(timeoutHeightRaw.split('-')[1]) - ) + return { + height, + srcConnectionId: isSrc ? connectionId : '', + srcPortId: isSrc ? portId : counterpartyPortId, + srcChannelId: isSrc ? channelId : counterpartyChannelId, + dstConnectionId: isSrc ? '' : connectionId, + dstPortId: isSrc ? counterpartyPortId : portId, + dstChannelId: isSrc ? counterpartyChannelId : channelId, + } +} - const timeoutTimestamp = event.attributes.filter( - (v) => v.key === 'packet_timeout_timestamp' - )[0].value +export function parsePacketFeeEvent(event: Event): PacketFeeEvent { + const portId = find(event, 'port_id') as string - const packet = new Packet( - sequence, - srcPort, - srcChannel, - dstPort, - dstChannel, - data, - timeoutHeight, - timeoutTimestamp - ) + const channelId = find(event, 'channel_id') as string - const acknowledgement = Buffer.from( - event.attributes.filter((v) => v.key === 'packet_ack_hex')[0].value, - 'hex' - ).toString('base64') + const sequence = Number(find(event, 'packet_sequence') as string) + + const recvFee = find(event, 'recv_fee') as string + + const ackFee = find(event, 'ack_fee') as string + + const timeoutFee = find(event, 'timeout_fee') as string return { - packet, - acknowledgement, + portId, + channelId, + sequence, + recvFee, + ackFee, + timeoutFee, } } + +function getConnection(event: Event): string | undefined { + return find(event, 'connection_id') || find(event, 'packet_connection') +} + +function find( + event: Event, + key: string, + defaultValue = '' +): string | undefined { + // check key + { + const vals = event.attributes.filter((v) => v.key === key) + if (vals.length !== 0) { + return vals[0].value + } + } + + { + // check base64 encoded key + const base64Key = Buffer.from(key).toString('base64') + const vals = event.attributes.filter((v) => v.key === base64Key) + if (vals.length !== 0) { + return Buffer.from(vals[0].value, 'base64').toString() + } + } + + return defaultValue +} diff --git a/src/lib/logger.ts b/src/lib/logger.ts index 6f37cd0..603bf81 100644 --- a/src/lib/logger.ts +++ b/src/lib/logger.ts @@ -27,3 +27,15 @@ export function error(msg: string): void { export function debug(msg: string): void { logger.debug(msg) } + +export function createLoggerWithPrefix(prefix: string) { + const format = winston.format.printf(({ level, message, timestamp }) => { + return `${timestamp} ${level}: ${prefix}${message}` + }) + + return winston.createLogger({ + level: config.logLevel, + format: winston.format.combine(winston.format.timestamp(), format), + transports: [new winston.transports.Console()], + }) +} diff --git a/src/lib/rawProof.ts b/src/lib/proof.ts similarity index 60% rename from src/lib/rawProof.ts rename to src/lib/proof.ts index d740f62..8dfc215 100644 --- a/src/lib/rawProof.ts +++ b/src/lib/proof.ts @@ -1,11 +1,13 @@ import { ics23 } from '@confio/ics23' import { tendermint34 } from '@cosmjs/tendermint-rpc' -import { Chain } from 'src/chain' import { Height } from 'cosmjs-types/ibc/core/client/v1/client' import { ProofOps } from 'cosmjs-types/tendermint/crypto/proof' +import { ChainWorker } from 'src/workers/chain' +import { CommitmentProof } from 'cosmjs-types/cosmos/ics23/v1/proofs' +import { MerkleProof } from 'cosmjs-types/ibc/core/commitment/v1/commitment' export async function getRawProof( - chain: Chain, + chain: ChainWorker, queryKey: Uint8Array, proofHeight: Height ): Promise { @@ -42,6 +44,29 @@ export async function getRawProof( } } +export async function getChannelProof( + chain: ChainWorker, + portId: string, + channelId: string, + headerHeight: Height +): Promise { + const key = new Uint8Array( + Buffer.from(`channelEnds/ports/${portId}/channels/${channelId}`) + ) + const proof = await getRawProof(chain, key, headerHeight) + const ics23Proof = convertProofsToIcs23(proof) + + return Buffer.from(ics23Proof).toString('base64') +} + +export function convertProofsToIcs23(ops: ProofOps): Uint8Array { + const proofs = ops.ops.map((op) => CommitmentProof.decode(op.data)) + const resp = MerkleProof.fromPartial({ + proofs, + }) + return MerkleProof.encode(resp).finish() +} + function checkAndParseOp( op: tendermint34.ProofOp, kind: string diff --git a/src/lib/restClient.ts b/src/lib/restClient.ts new file mode 100644 index 0000000..5901939 --- /dev/null +++ b/src/lib/restClient.ts @@ -0,0 +1,105 @@ +import { + APIRequester, + Channel, + IbcAPI as IbcAPI_, + RESTClientConfig, + RESTClient as RESTClient_, +} from '@initia/initia.js' +import { Order, State } from '@initia/initia.proto/ibc/core/channel/v1/channel' +import { ClientState, ConnectionInfo } from 'src/types' + +export class RESTClient extends RESTClient_ { + public ibc: IbcAPI + constructor( + URL: string, + config?: RESTClientConfig, + apiRequester?: APIRequester + ) { + super(URL, config, apiRequester) + + this.ibc = new IbcAPI(this.apiRequester) + } +} + +class IbcAPI extends IbcAPI_ { + constructor(c: APIRequester) { + super(c) + } + + async channel(portId: string, channelId: string): Promise { + const rawRes = await this.c.get( + `/ibc/core/channel/v1/channels/${channelId}/ports/${portId}` + ) + + const state = + State[rawRes.channel.state as keyof typeof State] || State.UNRECOGNIZED + const ordering = + Order[rawRes.channel.ordering as keyof typeof Order] || Order.UNRECOGNIZED + + return { + channel: { + state, + ordering, + counterparty: rawRes.channel.counterparty, + connection_hops: rawRes.channel.connection_hops, + version: rawRes.channel.version, + }, + proof: rawRes.proof, + proof_height: rawRes.proof_height, + } + } + + async getClientState(clientId: string): Promise { + return this.c.get( + `/ibc/core/client/v1/client_states/${clientId}` + ) + } + + async getConnection(connectionId: string): Promise { + return this.c.get( + `/ibc/core/connection/v1/connections/${connectionId}` + ) + } + + async nextSequence(portId: string, channelId: string): Promise { + return this.c.get( + `/ibc/core/channel/v1/channels/${channelId}/ports/${portId}/next_sequence` + ) + } +} + +interface ChannelResponse { + channel: Channel.Data + proof: null | string + proof_height: { + revision_number: number + revision_height: number + } +} + +interface ChannelResponseRaw { + channel: { + state: string + ordering: string + counterparty?: { + port_id: string + channel_id: string + } + connection_hops: string[] + version: string + } + proof: null | string + proof_height: { + revision_number: number + revision_height: number + } +} + +interface NextSequence { + next_sequence_receive: string + proof: null | string + proof_height: { + revision_number: string + revision_height: string + } +} diff --git a/src/msgs/ack.ts b/src/msgs/ack.ts index f70db42..68d925a 100644 --- a/src/msgs/ack.ts +++ b/src/msgs/ack.ts @@ -1,58 +1,48 @@ -import { Packet } from '@initia/initia.js' -import { MsgAcknowledgement } from '@initia/initia.js/dist/core/ibc/core/channel/msgs' +import { Packet, MsgAcknowledgement } from '@initia/initia.js' import { Height } from 'cosmjs-types/ibc/core/client/v1/client' -import { ProofOps } from 'cosmjs-types/tendermint/crypto/proof' -import { CommitmentProof } from 'cosmjs-types/cosmos/ics23/v1/proofs' -import { MerkleProof } from 'cosmjs-types/ibc/core/commitment/v1/commitment' -import { Chain } from 'src/chain' import { Transform } from 'src/lib/transform' -import { getRawProof } from 'src/lib/rawProof' +import { convertProofsToIcs23, getRawProof } from 'src/lib/proof' +import { ChainWorker } from 'src/workers/chain' +import { PacketWriteAckTable } from 'src/types' +import { packetTableToPacket } from 'src/db/utils' export async function generateMsgAck( - srcChain: Chain, - destChain: Chain, - ack: Ack, - height: Height + dstChain: ChainWorker, + ack: PacketWriteAckTable, + height: Height, + executorAddress: string ) { - const proof = await getAckProof(destChain, ack, height) + const packet = packetTableToPacket(ack) + const proof = await getAckProof(dstChain, packet, height) const msg = new MsgAcknowledgement( - ack.packet, - ack.acknowledgement, + packet, + ack.ack, proof, Transform.height(height), - srcChain.wallet.address() + executorAddress ) return msg } async function getAckProof( - destChain: Chain, - ack: Ack, + dstChain: ChainWorker, + packet: Packet, headerHeight: Height ): Promise { - const packet = ack.packet const key = new Uint8Array( Buffer.from( `acks/ports/${packet.destination_port}/channels/${packet.destination_channel}/sequences/${packet.sequence}` ) ) - const proof = await getRawProof(destChain, key, headerHeight) + const proof = await getRawProof(dstChain, key, headerHeight) const ics23Proof = convertProofsToIcs23(proof) return Buffer.from(ics23Proof).toString('base64') } -export function convertProofsToIcs23(ops: ProofOps): Uint8Array { - const proofs = ops.ops.map((op) => CommitmentProof.decode(op.data)) - const resp = MerkleProof.fromPartial({ - proofs, - }) - return MerkleProof.encode(resp).finish() -} - export interface Ack { acknowledgement: string packet: Packet diff --git a/src/msgs/channelCloseConfirm.ts b/src/msgs/channelCloseConfirm.ts new file mode 100644 index 0000000..555264b --- /dev/null +++ b/src/msgs/channelCloseConfirm.ts @@ -0,0 +1,23 @@ +import { MsgChannelCloseConfirm } from '@initia/initia.js' +import { Height } from 'cosmjs-types/ibc/core/client/v1/client' +import { getChannelProof } from 'src/lib/proof' +import { ChainWorker } from 'src/workers/chain' +import { Transform } from 'src/lib/transform' + +export async function generateMsgChannelCloseConfirm( + srcChain: ChainWorker, + srcPortId: string, + srcChannelId: string, + dstPortId: string, + dstChannelId: string, + height: Height, + msgExecutor: string +): Promise { + return new MsgChannelCloseConfirm( + dstPortId, + dstChannelId, + await getChannelProof(srcChain, srcPortId, srcChannelId, height), + Transform.height(height), + msgExecutor + ) +} diff --git a/src/msgs/channelOpenAck.ts b/src/msgs/channelOpenAck.ts new file mode 100644 index 0000000..9736001 --- /dev/null +++ b/src/msgs/channelOpenAck.ts @@ -0,0 +1,29 @@ +import { MsgChannelOpenAck } from '@initia/initia.js' +import { Height } from 'cosmjs-types/ibc/core/client/v1/client' +import { getChannelProof } from 'src/lib/proof' +import { ChainWorker } from 'src/workers/chain' +import { Transform } from 'src/lib/transform' + +export async function generateMsgChannelOpenAck( + srcPortId: string, + srcChannelId: string, + dstChain: ChainWorker, + dstPortId: string, + dstChannelId: string, + height: Height, + msgExecutor: string +): Promise { + const { + channel: { version }, + } = await dstChain.rest.ibc.channel(dstPortId, dstChannelId) + + return new MsgChannelOpenAck( + srcPortId, + srcChannelId, + dstChannelId, + version, + await getChannelProof(dstChain, dstPortId, dstChannelId, height), + Transform.height(height), + msgExecutor + ) +} diff --git a/src/msgs/channelOpenConfirm.ts b/src/msgs/channelOpenConfirm.ts new file mode 100644 index 0000000..0c49954 --- /dev/null +++ b/src/msgs/channelOpenConfirm.ts @@ -0,0 +1,23 @@ +import { MsgChannelOpenConfirm } from '@initia/initia.js' +import { Height } from 'cosmjs-types/ibc/core/client/v1/client' +import { getChannelProof } from 'src/lib/proof' +import { ChainWorker } from 'src/workers/chain' +import { Transform } from 'src/lib/transform' + +export async function generateMsgChannelOpenConfirm( + srcChain: ChainWorker, + srcPortId: string, + srcChannelId: string, + dstPortId: string, + dstChannelId: string, + height: Height, + msgExecutor: string +): Promise { + return new MsgChannelOpenConfirm( + dstPortId, + dstChannelId, + await getChannelProof(srcChain, srcPortId, srcChannelId, height), + Transform.height(height), + msgExecutor + ) +} diff --git a/src/msgs/channelOpenTry.ts b/src/msgs/channelOpenTry.ts new file mode 100644 index 0000000..5afbc89 --- /dev/null +++ b/src/msgs/channelOpenTry.ts @@ -0,0 +1,38 @@ +import { Channel, ChannelCounterparty, State } from '@initia/initia.js' +import { MsgChannelOpenTry } from '@initia/initia.js' +import { Height } from 'cosmjs-types/ibc/core/client/v1/client' +import { getChannelProof } from 'src/lib/proof' +import { ChainWorker } from 'src/workers/chain' +import { Transform } from 'src/lib/transform' + +export async function generateMsgChannelOpenTry( + srcChain: ChainWorker, + srcPortId: string, + srcChannelId: string, + dstConnectionId: string, + dstPortId: string, + height: Height, + msgExecutor: string +): Promise { + const { + channel: { ordering, version }, + } = await srcChain.rest.ibc.channel(srcPortId, srcChannelId) + + const channel = new Channel( + State.STATE_TRYOPEN, + ordering, + new ChannelCounterparty(srcPortId, srcChannelId), + [dstConnectionId], + version + ) + + return new MsgChannelOpenTry( + dstPortId, + '', + channel, + version, + await getChannelProof(srcChain, srcPortId, srcChannelId, height), + Transform.height(height), + msgExecutor + ) +} diff --git a/src/msgs/index.ts b/src/msgs/index.ts index 4db1a56..c13a0a6 100644 --- a/src/msgs/index.ts +++ b/src/msgs/index.ts @@ -1,95 +1,7 @@ -import { Msg } from '@initia/initia.js' -import { - SendPacketEventWithIndex, - WriteAckEventWithIndex, -} from 'src/chain/types' -import { generateMsgUpdateClient } from './updateClient' -import { Chain } from 'src/chain' -import { generateMsgRecvPacket } from './recvPacet' -import { generateMsgAck } from './ack' -import { generateMsgTimeout } from './timeout' -import { metrics } from 'src/lib/metric' - export * from './ack' -export * from './recvPacet' +export * from './recvPacket' export * from './timeout' export * from './updateClient' - -export async function generateThisChainMessages( - thisChain: Chain, - counterpartyChain: Chain, - timeoutPackets: SendPacketEventWithIndex[] -): Promise { - const thisMsgs: Msg[] = [] - if (timeoutPackets.length !== 0) { - const { msg: msgUpdateClient, height } = await generateMsgUpdateClient( - counterpartyChain, - thisChain - ) - thisMsgs.push(msgUpdateClient) - thisChain.inc(metrics.chain.handlePacketWorker.updateClientMsg) - - const msgTimeouts = await Promise.all( - timeoutPackets.map(async (packet) => - generateMsgTimeout( - thisChain, - counterpartyChain, - packet.packetData, - height - ) - ) - ) - thisMsgs.push(...msgTimeouts) - thisChain.inc( - metrics.chain.handlePacketWorker.timeoutMsg, - msgTimeouts.length - ) - } - - return thisMsgs -} - -export async function generateCounterpartyChainMessages( - thisChain: Chain, - counterpartyChain: Chain, - recvPackets: SendPacketEventWithIndex[], - acks: WriteAckEventWithIndex[] -): Promise { - const counterpartyMsgs: Msg[] = [] - if (recvPackets.length + acks.length !== 0) { - const { msg: msgUpdateClient, height } = await generateMsgUpdateClient( - thisChain, - counterpartyChain - ) - counterpartyMsgs.push(msgUpdateClient) - counterpartyChain.inc(metrics.chain.handlePacketWorker.updateClientMsg) - - const msgRecvPackets = await Promise.all( - recvPackets.map(async (packet) => - generateMsgRecvPacket( - counterpartyChain, - thisChain, - packet.packetData, - height - ) - ) - ) - counterpartyMsgs.push(...msgRecvPackets) - counterpartyChain.inc( - metrics.chain.handlePacketWorker.recvMsg, - msgRecvPackets.length - ) - - const msgAcks = await Promise.all( - acks.map(async (ack) => - generateMsgAck(counterpartyChain, thisChain, ack.packetData, height) - ) - ) - counterpartyMsgs.push(...msgAcks) - counterpartyChain.inc( - metrics.chain.handlePacketWorker.ackMsg, - msgAcks.length - ) - } - return counterpartyMsgs -} +export * from './channelOpenAck' +export * from './channelOpenConfirm' +export * from './channelOpenTry' diff --git a/src/msgs/recvPacket.ts b/src/msgs/recvPacket.ts new file mode 100644 index 0000000..aa260ba --- /dev/null +++ b/src/msgs/recvPacket.ts @@ -0,0 +1,43 @@ +import { Packet } from '@initia/initia.js' +import { MsgRecvPacket } from '@initia/initia.js' +import { Height } from 'cosmjs-types/ibc/core/client/v1/client' +import { Transform } from 'src/lib/transform' +import { convertProofsToIcs23, getRawProof } from 'src/lib/proof' +import { ChainWorker } from 'src/workers/chain' +import { PacketSendTable } from 'src/types' +import { packetTableToPacket } from 'src/db/utils' + +export async function generateMsgRecvPacket( + srcChain: ChainWorker, + packetSend: PacketSendTable, + height: Height, + msgExecutor: string +): Promise { + const packet = packetTableToPacket(packetSend) + const proof = await getPacketProof(srcChain, packet, height) + + const msg = new MsgRecvPacket( + packet, + proof, + Transform.height(height), + msgExecutor + ) + + return msg +} + +async function getPacketProof( + dstChain: ChainWorker, + packet: Packet, + headerHeight: Height +): Promise { + const key = new Uint8Array( + Buffer.from( + `commitments/ports/${packet.source_port}/channels/${packet.source_channel}/sequences/${packet.sequence}` + ) + ) + const proof = await getRawProof(dstChain, key, headerHeight) + const ics23Proof = convertProofsToIcs23(proof) + + return Buffer.from(ics23Proof).toString('base64') +} diff --git a/src/msgs/signedHeader.ts b/src/msgs/signedHeader.ts index 7b2612e..888c53a 100644 --- a/src/msgs/signedHeader.ts +++ b/src/msgs/signedHeader.ts @@ -5,14 +5,14 @@ import { } from 'cosmjs-types/tendermint/types/types' import { Timestamp } from 'cosmjs-types/google/protobuf/timestamp' import { BlockIDFlag } from '@initia/initia.proto/tendermint/types/validator' -import { Chain } from 'src/chain' import { BlockIdFlag, ReadonlyDateWithNanoseconds, } from '@cosmjs/tendermint-rpc' +import { ChainWorker } from 'src/workers/chain' export async function getSignedHeader( - chain: Chain, + chain: ChainWorker, height?: number ): Promise { const commitRes = await chain.rpc.commit(height) diff --git a/src/msgs/timeout.ts b/src/msgs/timeout.ts index fa804b4..49c332d 100644 --- a/src/msgs/timeout.ts +++ b/src/msgs/timeout.ts @@ -1,43 +1,85 @@ -import { MsgTimeout } from '@initia/initia.js/dist/core/ibc/core/channel/msgs' import { Height } from 'cosmjs-types/ibc/core/client/v1/client' import { Uint64 } from '@cosmjs/math' -import { Chain } from 'src/chain' import { Transform } from 'src/lib/transform' -import { Packet } from '@initia/initia.js' -import { getRawProof } from 'src/lib/rawProof' -import { convertProofsToIcs23 } from './ack' +import { Packet, MsgTimeout, MsgTimeoutOnClose } from '@initia/initia.js' +import { + convertProofsToIcs23, + getChannelProof, + getRawProof, +} from 'src/lib/proof' import { delay } from 'bluebird' +import { ChainWorker } from 'src/workers/chain' +import { Bool, PacketTimeoutTable } from 'src/types' +import { packetTableToPacket } from 'src/db/utils' export async function generateMsgTimeout( - srcChain: Chain, - destChain: Chain, - packet: Packet, - proofHeight: Height + dstChain: ChainWorker, + packetTable: PacketTimeoutTable, + proofHeight: Height, + executorAddress: string ): Promise { - const sequence = await getNextSequenceRecv(packet, destChain, proofHeight) - const proof = await getTimeoutProof(destChain, packet, proofHeight) + const packet = packetTableToPacket(packetTable) + const sequence = await getNextSequenceRecv(packet, dstChain, proofHeight) + const proof = await getTimeoutProof( + dstChain, + packet, + proofHeight, + packetTable.is_ordered === Bool.TRUE + ) return new MsgTimeout( packet, proof, Transform.height(proofHeight), sequence, - srcChain.wallet.address() + executorAddress + ) +} + +export async function generateMsgTimeoutOnClose( + dstChain: ChainWorker, + packetTable: PacketTimeoutTable, + proofHeight: Height, + executorAddress: string +): Promise { + const packet = packetTableToPacket(packetTable) + const sequence = await getNextSequenceRecv(packet, dstChain, proofHeight) + const proof = await getTimeoutProof( + dstChain, + packet, + proofHeight, + packetTable.is_ordered === Bool.TRUE + ) + + const channelProof = await getChannelProof( + dstChain, + packet.destination_port, + packet.destination_channel, + proofHeight + ) + + return new MsgTimeoutOnClose( + packet, + proof, + channelProof, + Transform.height(proofHeight), + sequence, + executorAddress ) } async function getNextSequenceRecv( packet: Packet, - destChain: Chain, + dstChain: ChainWorker, headerHeight: Height -) { +): Promise { const key = new Uint8Array( Buffer.from( `nextSequenceRecv/ports/${packet.destination_port}/channels/${packet.destination_channel}` ) ) - let { value } = await destChain.rpc.abciQuery({ + let { value } = await dstChain.rpc.abciQuery({ path: `/store/ibc/key`, data: key, prove: true, @@ -46,7 +88,7 @@ async function getNextSequenceRecv( let count = 0 while (value.length === 0 && count < 5) { - const result = await destChain.rpc.abciQuery({ + const result = await dstChain.rpc.abciQuery({ path: `/store/ibc/key`, data: key, prove: true, @@ -63,16 +105,19 @@ async function getNextSequenceRecv( } async function getTimeoutProof( - destChain: Chain, + dstChain: ChainWorker, packet: Packet, - headerHeight: Height + headerHeight: Height, + isOrdererd: boolean ): Promise { const queryKey = new Uint8Array( Buffer.from( - `receipts/ports/${packet.destination_port}/channels/${packet.destination_channel}/sequences/${packet.sequence}` + isOrdererd + ? `nextSequenceRecv/ports/${packet.destination_port}/channels/${packet.destination_channel}` + : `receipts/ports/${packet.destination_port}/channels/${packet.destination_channel}/sequences/${packet.sequence}` ) ) - const proof = await getRawProof(destChain, queryKey, headerHeight) + const proof = await getRawProof(dstChain, queryKey, headerHeight) const ics23Proof = convertProofsToIcs23(proof) return Buffer.from(ics23Proof).toString('base64') diff --git a/src/msgs/updateClient.ts b/src/msgs/updateClient.ts index d94826c..bf3cd0c 100644 --- a/src/msgs/updateClient.ts +++ b/src/msgs/updateClient.ts @@ -1,6 +1,5 @@ import { getSignedHeader } from './signedHeader' -import { MsgUpdateClient } from '@initia/initia.js/dist/core/ibc/core/client/msgs' -import { Chain } from 'src/chain' +import { MsgUpdateClient } from '@initia/initia.js' import { Header } from 'cosmjs-types/ibc/lightclients/tendermint/v1/tendermint' import { ValidatorSet, @@ -8,16 +7,22 @@ import { } from 'cosmjs-types/tendermint/types/validator' import { Height } from 'cosmjs-types/ibc/core/client/v1/client' import { delay } from 'bluebird' +import { ChainWorker } from 'src/workers/chain' +// generateMsgUpdateClient generates a MsgUpdateClient message +// which is used to update the client state on the destination chain +// with the latest header from the source chain and the latest validator set. export async function generateMsgUpdateClient( - srcChain: Chain, - destChain: Chain + srcChain: ChainWorker, + dstChain: ChainWorker, + dstClientId: string, + executorAddress: string ): Promise<{ msg: MsgUpdateClient height: Height }> { const latestHeight = Number( - ((await destChain.lcd.ibc.clientState(destChain.clientId)) as ClientState) + ((await dstChain.rest.ibc.clientState(dstClientId)) as ClientState) .client_state.latest_height.revision_height ) const signedHeader = await getSignedHeader(srcChain) @@ -45,11 +50,7 @@ export async function generateMsgUpdateClient( const revisionHeight = getRevisionHeight(currentHeight, header.chainId) return { - msg: new MsgUpdateClient( - destChain.clientId, - tmHeader, - destChain.wallet.address() - ), + msg: new MsgUpdateClient(dstClientId, tmHeader, executorAddress), height: revisionHeight, } } @@ -72,15 +73,15 @@ export function getRevisionHeight(height: number, chainId: string): Height { } async function getValidatorSet( - chain: Chain, + chain: ChainWorker, height: number ): Promise { - let block = await chain.lcd.tendermint + let block = await chain.rest.tendermint .blockInfo(height) .catch(() => undefined) let count = 0 while (block === undefined) { - block = await chain.lcd.tendermint.blockInfo(height).catch((e) => { + block = await chain.rest.tendermint.blockInfo(height).catch((e) => { if (count > 5) { throw e } diff --git a/src/test/config.test.json b/src/test/config.test.json new file mode 100644 index 0000000..a78aa1d --- /dev/null +++ b/src/test/config.test.json @@ -0,0 +1,41 @@ +{ + "$schema": "../../config.schema.json", + "dbPath": "./test_db", + "port": 7010, + "metricPort": 70001, + "logLevel": "info", + "chains": [ + { + "bech32Prefix": "init", + "chainId": "chain-1", + "gasPrice": "0.15gas", + "restUri": "https://rest.chain-1.com", + "rpcUri": "https://rpc.chain-1.com", + "wallets": [ + { + "key": { + "type": "mnemonic", + "privateKey": "repair family apology column ..." + }, + "maxHandlePacket": 10 + } + ] + }, + { + "bech32Prefix": "init", + "chainId": "chain-2", + "gasPrice": "0gas", + "restUri": "https://rest.chain-2.com", + "rpcUri": "https://rpc.chain-2.com", + "wallets": [ + { + "key": { + "type": "raw", + "privateKey": "123..." + }, + "maxHandlePacket": 10 + } + ] + } + ] +} diff --git a/src/test/mockServer/rest.ts b/src/test/mockServer/rest.ts new file mode 100644 index 0000000..9843cfe --- /dev/null +++ b/src/test/mockServer/rest.ts @@ -0,0 +1,43 @@ +import { ClientState, ConnectionInfo } from 'src/types' +import { RESTClient } from 'src/lib/restClient' +import { APIRequester } from '@initia/initia.js' + +export class RestMockServer { + public connections: Record + private clients: Record + constructor( + public chainId: string, + public restUri: string + ) { + this.connections = {} + this.clients = {} + } + + client(): RESTClient { + return new RESTClient( + this.restUri, + undefined, + new APIRequester(this.restUri, { timeout: 500 }) + ) + } + + addConnection(connectionId: string, connectionInfo: ConnectionInfo) { + // check client exists + if (this.clients[connectionInfo.connection.client_id] === undefined) { + throw Error('client not found') + } + this.connections[connectionId] = connectionInfo + } + + getConnection(connectionId: string): ConnectionInfo { + return this.connections[connectionId] + } + + addClientState(clientId: string, clientState: ClientState) { + this.clients[clientId] = clientState + } + + getClientState(clientId: string): ClientState { + return this.clients[clientId] + } +} diff --git a/src/test/mockServer/rpc.ts b/src/test/mockServer/rpc.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/test/testSetup.ts b/src/test/testSetup.ts new file mode 100644 index 0000000..552ee38 --- /dev/null +++ b/src/test/testSetup.ts @@ -0,0 +1,98 @@ +import 'tsconfig-paths/register' +import { env } from 'node:process' +env.CONFIGFILE = 'src/test/config.test.json' +import { config } from 'src/lib/config' +import * as fs from 'fs' +import { initDBConnection } from 'src/db' +import { RestMockServer } from './mockServer/rest' +import { http, RequestHandler, HttpResponse } from 'msw' +import { setupServer } from 'msw/node' + +export let mockServers: { rest: RestMockServer }[] = [] + +const setup = () => { + // remove db + const dbPath = config.dbPath as string + + if (fs.existsSync(dbPath)) { + fs.rmSync(dbPath, { recursive: true }) + } + + fs.mkdirSync(dbPath) + + // init db and mock server + initDBConnection() + const handlers: RequestHandler[] = [] + mockServers = config.chains.map((chain, i) => { + const index = i + 1 + const counterpartyIndex = index + (index % 2 === 0 ? -1 : 1) + const restServer = new RestMockServer(chain.chainId, chain.restUri) + + restServer.addClientState(`07-tendermint-${index}`, { + client_state: { + chain_id: config.chains[counterpartyIndex - 1].chainId, + trusting_period: '3000s', + latest_height: { + revision_height: `${index}-100`, + }, + }, + }) + restServer.addConnection(`connection-${index}`, { + connection: { + client_id: `07-tendermint-${index}`, + counterparty: { + client_id: `07-tendermint-${counterpartyIndex}`, + connection_id: `connection-${counterpartyIndex}`, + }, + }, + }) + + handlers.push( + http.get( + new URL( + '/ibc/core/connection/v1/connections/:connectionId', + chain.restUri + ).href, + ({ params }) => { + const { connectionId } = params + // ...and respond to them using this JSON response. + try { + const connectionInfo = restServer.getConnection( + connectionId as string + ) + return HttpResponse.json(connectionInfo) + } catch (error) { + return new HttpResponse('Failed to retrieve connection info', { + status: 500, + }) + } + } + ) + ) + + handlers.push( + http.get( + new URL('/ibc/core/client/v1/client_states/:clientId', chain.restUri) + .href, + ({ params }) => { + const { clientId } = params + + try { + const clientState = restServer.getClientState(clientId as string) + return HttpResponse.json(clientState) + } catch (error) { + return new HttpResponse('Failed to retrieve client info', { + status: 500, + }) + } + } + ) + ) + + return { rest: restServer } + }) + + setupServer(...handlers).listen() +} + +beforeAll(() => setup()) diff --git a/src/types/event.ts b/src/types/event.ts new file mode 100644 index 0000000..1b4f6c8 --- /dev/null +++ b/src/types/event.ts @@ -0,0 +1,81 @@ +export type PacketEvent = + | AcknowledgePacketEvent + | SendPacketEvent + | TimeoutPacketEvent + | WriteAckEvent + +export type PacketType = PacketEvent['type'] + +export interface AcknowledgePacketEvent { + type: 'acknowledge_packet' + packetInfo: PacketInfo +} + +export interface SendPacketEvent { + type: 'send_packet' + packetInfo: PacketInfo +} + +export interface TimeoutPacketEvent { + type: 'timeout_packet' + packetInfo: PacketInfo +} + +export interface WriteAckEvent { + type: 'write_acknowledgement' + packetInfo: PacketInfo +} + +export interface PacketInfo { + height: number + connectionId: string + sequence: number + srcPort: string + srcChannel: string + dstPort: string + dstChannel: string + data?: string + timeoutHeight: number + timeoutTimestamp: number + timeoutHeightRaw: string + timeoutTimestampRaw: string + ordering?: string // some version doesn't have ordering in write ack event + ack?: string +} + +export interface UpdateClientEvent { + clientId: string + header: string + consensusHeights: string +} + +export interface ChannelOpenCloseEvent { + type: + | 'channel_open_init' + | 'channel_open_try' + | 'channel_open_ack' + | 'channel_open_confirm' + | 'channel_close_init' + | 'channel_close' + | 'channel_close_confirm' + channelOpenCloseInfo: ChannelOpenCloseInfo +} + +export interface ChannelOpenCloseInfo { + height: number + srcConnectionId: string + srcPortId: string + srcChannelId: string + dstConnectionId: string + dstPortId: string + dstChannelId: string +} + +export interface PacketFeeEvent { + portId: string + channelId: string + sequence: number + recvFee: string + ackFee: string + timeoutFee: string +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..13bd68e --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,3 @@ +export * from './event' +export * from './response' +export * from './table' diff --git a/src/types/response.ts b/src/types/response.ts new file mode 100644 index 0000000..49eedcb --- /dev/null +++ b/src/types/response.ts @@ -0,0 +1,19 @@ +export interface ClientState { + client_state: { + chain_id: string + trusting_period: string + latest_height: { + revision_height: string + } + } +} + +export interface ConnectionInfo { + connection: { + client_id: string + counterparty: { + client_id: string + connection_id: string + } + } +} diff --git a/src/types/table.ts b/src/types/table.ts new file mode 100644 index 0000000..dbfbfc4 --- /dev/null +++ b/src/types/table.ts @@ -0,0 +1,131 @@ +export interface VersionTable { + id: number + version: string +} + +export interface SyncInfoTable { + chain_id: string + start_height: number + end_height: number + synced_height: number +} + +export interface ClientTable { + chain_id: string + client_id: string + counterparty_chain_id: string + trusting_period: number + revision_height: number + last_update_time: number +} + +export interface ConnectionTable { + chain_id: string + connection_id: string + client_id: string + counterparty_chain_id: string + counterparty_connection_id: string + counterparty_client_id: string +} + +export interface PacketSendTable { + dst_chain_id: string + dst_connection_id: string + dst_channel_id: string + sequence: number + in_progress: Bool + is_ordered: Bool + height: number + dst_port: string + src_chain_id: string + src_connection_id: string + src_port: string + src_channel_id: string + packet_data: string + timeout_height: number + timeout_timestamp: number + timeout_height_raw: string + timeout_timestamp_raw: string +} + +export interface PacketTimeoutTable { + src_chain_id: string + src_connection_id: string + src_channel_id: string + sequence: number + in_progress: Bool + is_ordered: Bool + src_port: string + dst_chain_id: string + dst_connection_id: string + dst_port: string + dst_channel_id: string + packet_data: string + timeout_height: number + timeout_timestamp: number + timeout_height_raw: string + timeout_timestamp_raw: string +} + +export interface PacketWriteAckTable { + src_chain_id: string + src_connection_id: string + src_channel_id: string + sequence: number + in_progress: Bool + is_ordered: Bool + height: number + src_port: string + dst_chain_id: string + dst_connection_id: string + dst_port: string + dst_channel_id: string + packet_data: string + ack: string + timeout_height: number + timeout_timestamp: number + timeout_height_raw: string + timeout_timestamp_raw: string +} + +export interface ChannelOpenCloseTable { + id?: number + in_progress: Bool + height: number + state: ChannelState + chain_id: string + connection_id: string + port_id: string + channel_id: string + counterparty_chain_id: string + counterparty_connection_id: string + counterparty_port_id: string + counterparty_channel_id: string +} + +export interface PacketFeeTable { + chain_id: string + channel_id: string + sequence: number + fee_type: FeeType + denom: string + amount: number +} + +export enum Bool { + TRUE = 1, + FALSE = 0, +} + +export enum ChannelState { + INIT = 1, + TRYOPEN = 2, + ACK = 3, + CLOSE = 4, +} + +export enum FeeType { + RECV = 1, + ACK = 2, + TIMEOUT = 3, +} diff --git a/src/workers/chain.ts b/src/workers/chain.ts new file mode 100644 index 0000000..37d0d7d --- /dev/null +++ b/src/workers/chain.ts @@ -0,0 +1,266 @@ +import { RPCClient } from 'src/lib/rpcClient' +import { createLoggerWithPrefix } from 'src/lib/logger' +import { ChannelOpenCloseEvent, PacketEvent, PacketFeeEvent } from 'src/types' +import { + parseChannelCloseEvent, + parseChannelOpenEvent, + parsePacketEvent, + parsePacketFeeEvent, +} from 'src/lib/eventParser' +import { DB } from 'src/db' +import { SyncInfoController } from 'src/db/controller/syncInfo' +import { PacketController } from 'src/db/controller/packet' +import { delay } from 'bluebird' +import { Logger } from 'winston' +import { RESTClient } from 'src/lib/restClient' +import { ChannelController } from 'src/db/controller/channel' +import { PacketFeeController } from 'src/db/controller/packetFee' +import { PacketFee } from 'src/lib/config' + +export class ChainWorker { + public latestHeight: number + public latestTimestamp: number + public syncWorkers: Record + public logger: Logger + + public constructor( + public chainId: string, + public rest: RESTClient, + public rpc: RPCClient, + public bech32Prefix: string, + public feeFilter: PacketFee, + latestHeight: number, + startHeights: number[] + ) { + this.logger = createLoggerWithPrefix(``) + const syncInfos = SyncInfoController.init( + chainId, + startHeights, + latestHeight + ) + this.syncWorkers = {} + for (const syncInfo of syncInfos) { + this.syncWorkers[syncInfo.start_height] = new SyncWorker( + this, + syncInfo.start_height, + syncInfo.end_height, + syncInfo.synced_height + ) + void this.latestHeightWorker() + } + } + + public terminateSyncWorker(startHeight: number) { + const endHeight = this.syncWorkers[startHeight].endHeight + + const nextWorker = this.syncWorkers[endHeight + 1] + + // drop sync workers + delete this.syncWorkers[startHeight] + delete this.syncWorkers[endHeight + 1] + + // update and store next range worker + nextWorker.startHeight = startHeight + this.syncWorkers[startHeight] = nextWorker + } + + private async latestHeightWorker() { + this.logger.debug('Activate latest height worker') + // TODO add websocket options + const MAX_RETRY = 10 + let retried = 0 + for (;;) { + try { + await this.updateLatestHeight() + this.logger.debug( + `Set latest height. Height - ${this.latestHeight}, Timestamp - ${this.latestTimestamp}` + ) + + retried = 0 + } catch (e) { + this.logger.error( + `[latestHeightWorker] Got error while fetching latest height (${e})` + ) + retried++ + if (retried >= MAX_RETRY) { + throw Error( + `<${this.chainId}> [latestHeightWorker] Max retry exceeded` + ) + } + } finally { + await delay(1000) + } + } + } + + private async updateLatestHeight() { + this.latestHeight = await queryLatestHeight(this.rpc) + this.latestTimestamp = new Date().valueOf() // is it okay to use local timestamp? + + // this.inc(metrics.chain.latestHeightWorker) + } +} + +class SyncWorker { + private logger: Logger + public constructor( + public chain: ChainWorker, + public startHeight: number, + public endHeight: number, + public syncedHeight: number + ) { + this.logger = createLoggerWithPrefix( + `` + ) + void this.feedEvents() + } + + private async feedEvents() { + this.logger.debug('Activate event feeder') + + for (;;) { + try { + // height to fetch + const endHeight = + this.endHeight === -1 ? this.chain.latestHeight : this.endHeight + const heights = Array.from( + { length: 20 }, + (_, i) => i + this.syncedHeight + 1 + ).filter( + (height) => height <= endHeight && height <= this.chain.latestHeight + ) + + if (heights.length === 0) continue + + const events = await Promise.all( + heights.map((height) => this.fetchEvents(height)) + ) + const packetEvents = events.map((e) => e.packetEvents).flat() + const channelOpenEvents = events.map((e) => e.channelOpenEvents).flat() + const packetFeeEvents = events.map((e) => e.packetFeeEvents).flat() + + this.logger.debug( + `Fetched block results for heights (${JSON.stringify(heights)})` + ) + + let finish = false + + const packetEventFeed = await PacketController.feedEvents( + this.chain.rest, + this.chain.chainId, + packetEvents + ) + + const channelOpenEventFeed = await ChannelController.feedEvents( + this.chain.rest, + this.chain.chainId, + channelOpenEvents + ) + + DB.transaction(() => { + packetEventFeed() + channelOpenEventFeed() + PacketFeeController.feedEvents(this.chain.chainId, packetFeeEvents)() + + finish = SyncInfoController.update( + this.chain.chainId, + this.startHeight, + this.endHeight, + heights[heights.length - 1] + ) + + this.logger.debug( + `Store packet events(${packetEvents.flat().length})` + ) + })() + + this.syncedHeight = heights[heights.length - 1] + + // terminate worker + if (finish) { + this.logger.info( + 'Synced height reached to end height. Terminate sync worker' + ) + this.chain.terminateSyncWorker(this.startHeight) + break + } + } catch (e) { + this.logger.error(`Fail to fecth block result. resonse - ${e}`) + } finally { + await delay(500) + } + } + } + + private async fetchEvents(height: number): Promise<{ + packetEvents: PacketEvent[] + channelOpenEvents: ChannelOpenCloseEvent[] + packetFeeEvents: PacketFeeEvent[] + }> { + this.logger.debug(`Fetch new block results (height - ${height})`) + const blockResult = await this.chain.rpc.blockResults(height) + const txData = [...blockResult.results] + + const packetEvents: PacketEvent[] = [] + const channelOpenEvents: ChannelOpenCloseEvent[] = [] + const packetFeeEvents: PacketFeeEvent[] = [] + + txData.map((data) => { + for (const event of data.events) { + if ( + event.type === 'send_packet' || + event.type === 'write_acknowledgement' || + event.type === 'acknowledge_packet' || + event.type === 'timeout_packet' + ) { + packetEvents.push({ + type: event.type, + packetInfo: parsePacketEvent(event, height), + }) + } + + if ( + event.type === 'channel_open_init' || + event.type === 'channel_open_try' || + event.type === 'channel_open_ack' || + event.type === 'channel_open_confirm' + ) { + channelOpenEvents.push({ + type: event.type, + channelOpenCloseInfo: parseChannelOpenEvent(event, height), + }) + } + + if ( + event.type === 'channel_close_init' || + event.type === 'channel_close' || + event.type === 'channel_close_confirm' + ) { + channelOpenEvents.push({ + type: event.type, + channelOpenCloseInfo: parseChannelCloseEvent(event, height), + }) + } + + if (event.type === 'incentivized_ibc_packet') { + packetFeeEvents.push(parsePacketFeeEvent(event)) + } + } + }) + + return { + packetEvents, + channelOpenEvents, + packetFeeEvents, + } + } +} + +export async function queryLatestHeight(rpc: RPCClient): Promise { + const abciInfo = await rpc.abciInfo() + if (!abciInfo.lastBlockHeight) { + throw Error('Can not get last block height') + } + const height = abciInfo.lastBlockHeight + return Number(height) +} diff --git a/src/workers/index.ts b/src/workers/index.ts new file mode 100644 index 0000000..768dd3a --- /dev/null +++ b/src/workers/index.ts @@ -0,0 +1,329 @@ +import { ChainWorker, queryLatestHeight } from './chain' +import { WalletWorker } from './wallet' +import { + generateMsgAck, + generateMsgRecvPacket, + generateMsgTimeout, + generateMsgUpdateClient, + generateMsgChannelOpenTry, + generateMsgChannelOpenAck, + generateMsgChannelOpenConfirm, + generateMsgTimeoutOnClose, +} from 'src/msgs' +import { Height } from 'cosmjs-types/ibc/core/client/v1/client' +import { ClientController } from 'src/db/controller/client' +import { + ChannelOpenCloseTable, + PacketSendTable, + PacketTimeoutTable, + PacketWriteAckTable, +} from 'src/types' +import { + MsgRecvPacket, + MsgUpdateClient, + Key, + MnemonicKey, + RawKey, + APIRequester, + Wallet, + MsgChannelCloseConfirm, + MsgChannelOpenAck, + MsgChannelOpenConfirm, + MsgChannelOpenTry, +} from '@initia/initia.js' +import { Config, PacketFee, KeyConfig } from 'src/lib/config' +import { env } from 'node:process' +import { RPCClient } from 'src/lib/rpcClient' +import * as http from 'http' +import * as https from 'https' +import { PacketFilter } from 'src/db/controller/packet' +import { RESTClient } from 'src/lib/restClient' + +import { State } from '@initia/initia.proto/ibc/core/channel/v1/channel' +import { generateMsgChannelCloseConfirm } from 'src/msgs/channelCloseConfirm' + +export class WorkerController { + public chains: Record // chainId => ChainWorker + public wallets: Record // chainId::addr => WalletWorker + public initiated: boolean + + public constructor() { + this.chains = {} + this.wallets = {} + this.initiated = false + } + + public async init(config: Config) { + if (this.initiated) { + throw Error('already initiated') + } + this.initiated = true + + for (const chainConfig of config.chains) { + const rest = new RESTClient( + chainConfig.restUri, + { + chainId: chainConfig.chainId, + gasPrices: chainConfig.gasPrice, + }, + new APIRequester(chainConfig.restUri, { + httpAgent: new http.Agent({ keepAlive: true }), + httpsAgent: new https.Agent({ keepAlive: true }), + timeout: 60000, + }) + ) + const rpc = new RPCClient(chainConfig.rpcUri) + const latestHeight = await queryLatestHeight(rpc) + const chain = new ChainWorker( + chainConfig.chainId, + rest, + rpc, + chainConfig.bech32Prefix, + chainConfig.feeFilter ?? {}, + latestHeight, + chainConfig.wallets + .map((wallet) => wallet.startHeight) + .filter((v) => v !== undefined) as number[] + ) + + this.chains[chainConfig.chainId] = chain + + for (const walletConfig of chainConfig.wallets) { + const key = createKey(walletConfig.key) + const wallet = new WalletWorker( + chain, + this, + walletConfig.maxHandlePacket ?? 100, + new Wallet(rest, key), + walletConfig.packetFilter + ) + + this.wallets[`${chainConfig.chainId}::${wallet.address()}`] = wallet + } + } + } + + public getFeeFilters(): { chainId: string; feeFilter: PacketFee }[] { + return Object.entries(this.chains).map(([chainId, chain]) => { + return { + chainId, + feeFilter: chain.feeFilter, + } + }) + } + + public getStatus(): { chains: ChainStatus[] } { + const wallets = Object.values(this.wallets); + const chains: ChainStatus[] = Object.values(this.chains).map(chain => { + const syncWorkerKeys = Object.keys(chain.syncWorkers) + const syncWorkers = syncWorkerKeys.map((key) => { + const syncWorker = chain.syncWorkers[Number(key)] + return { + startHeight: syncWorker.startHeight, + endHeight: syncWorker.endHeight === -1 ? null : syncWorker.endHeight, + syncedHeight: syncWorker.syncedHeight, + } + }) + + const walletWorkers = wallets.filter(wallet => wallet.chain.chainId === chain.chainId).map(wallet => { + return { + address: wallet.address(), + packetFilter: wallet.packetFilter, + } + }); + + return { + chainId: chain.chainId, + latestHeight: chain.latestHeight, + latestTimestamp: new Date(chain.latestTimestamp), + syncWorkers, + walletWorkers, + } + }) + + return { + chains, + } + } + + async generateMsgUpdateClient( + chainId: string, + clientId: string, + executorAddress: string + ): Promise<{ + msg: MsgUpdateClient + height: Height + }> { + // get client + const client = await ClientController.getClient( + this.chains[chainId].rest, + chainId, + clientId + ) + + return generateMsgUpdateClient( + this.chains[client.counterparty_chain_id], + this.chains[chainId], + client.client_id, + executorAddress + ) + } + + async generateRecvPacketMsg( + packet: PacketSendTable, + height: Height, + executorAddress: string + ): Promise { + const srcChain = this.chains[packet.src_chain_id] + return generateMsgRecvPacket(srcChain, packet, height, executorAddress) + } + + async generateAckMsg( + packet: PacketWriteAckTable, + height: Height, + executorAddress: string + ) { + const dstChain = this.chains[packet.dst_chain_id] + return generateMsgAck(dstChain, packet, height, executorAddress) + } + + async generateTimeoutMsg( + packet: PacketTimeoutTable, + height: Height, + executorAddress: string + ) { + const dstChain = this.chains[packet.dst_chain_id] + // check dst channel state + const channel = await dstChain.rest.ibc.channel( + packet.dst_port, + packet.dst_channel_id + ) + if (channel.channel.state === State.STATE_CLOSED) { + return generateMsgTimeoutOnClose( + dstChain, + packet, + height, + executorAddress + ) + } + return generateMsgTimeout(dstChain, packet, height, executorAddress) + } + + async generateChannelOpenTryMsg( + event: ChannelOpenCloseTable, + height: Height, + executorAddress: string + ): Promise { + const srcChain = this.chains[event.counterparty_chain_id] + return generateMsgChannelOpenTry( + srcChain, + event.counterparty_port_id, + event.counterparty_channel_id, + event.connection_id, + event.port_id, + height, + executorAddress + ) + } + + async generateChannelOpenAckMsg( + event: ChannelOpenCloseTable, + height: Height, + executorAddress: string + ): Promise { + const dstChain = this.chains[event.counterparty_chain_id] + return generateMsgChannelOpenAck( + event.port_id, + event.channel_id, + dstChain, + event.counterparty_port_id, + event.counterparty_channel_id, + height, + executorAddress + ) + } + + async generateChannelOpenConfirmMsg( + event: ChannelOpenCloseTable, + height: Height, + executorAddress: string + ): Promise { + const srcChain = this.chains[event.counterparty_chain_id] + return generateMsgChannelOpenConfirm( + srcChain, + event.counterparty_port_id, + event.counterparty_channel_id, + event.port_id, + event.channel_id, + height, + executorAddress + ) + } + + async generateChannelCloseConfirmMsg( + event: ChannelOpenCloseTable, + height: Height, + executorAddress: string + ): Promise { + const srcChain = this.chains[event.counterparty_chain_id] + return generateMsgChannelCloseConfirm( + srcChain, + event.counterparty_port_id, + event.counterparty_channel_id, + event.port_id, + event.channel_id, + height, + executorAddress + ) + } +} + +function createKey(rawKey: KeyConfig): Key { + let keyReturn + switch (rawKey.type) { + case 'mnemonic': { + const options = rawKey.options || {} + + keyReturn = new MnemonicKey({ mnemonic: rawKey.privateKey, ...options }) + break + } + case 'env_mnemonic': { + const key = env[rawKey.privateKey] + if (!key) { + throw Error(`missing environment ${rawKey.privateKey}`) + } + const options = rawKey.options || {} + + keyReturn = new MnemonicKey({ mnemonic: key, ...options }) + break + } + case 'raw': { + keyReturn = new RawKey(Buffer.from(rawKey.privateKey, 'hex')) + break + } + case 'env_raw': { + const key = env[rawKey.privateKey] + if (!key) { + throw Error(`missing environment ${rawKey.privateKey}`) + } + keyReturn = new RawKey(Buffer.from(key, 'hex')) + break + } + } + return keyReturn +} + +interface ChainStatus { + chainId: string + latestHeight: number + latestTimestamp: Date + syncWorkers: { + startHeight: number + endHeight: number | null + syncedHeight: number + }[] + walletWorkers: { + address: string + packetFilter?: PacketFilter + }[] +} diff --git a/src/workers/wallet.ts b/src/workers/wallet.ts new file mode 100644 index 0000000..fa9c64d --- /dev/null +++ b/src/workers/wallet.ts @@ -0,0 +1,674 @@ +import { PacketController, PacketFilter } from 'src/db/controller/packet' +import { ChainWorker } from './chain' +import { + Bool, + ChannelOpenCloseTable, + ChannelState, + PacketSendTable, + PacketTimeoutTable, + PacketWriteAckTable, +} from 'src/types' +import { WorkerController } from '.' +import { DB } from 'src/db' +import { Height } from 'cosmjs-types/ibc/core/client/v1/client' +import { ConnectionController } from 'src/db/controller/connection' +import { Wallet, isTxError, MsgUpdateClient } from '@initia/initia.js' +import { createLoggerWithPrefix } from 'src/lib/logger' +import { bech32 } from 'bech32' +import { delay } from 'bluebird' +import { Logger } from 'winston' +import { ChannelController } from 'src/db/controller/channel' +import { State } from '@initia/initia.proto/ibc/core/channel/v1/channel' +import { PacketFee } from 'src/lib/config' + +// TODO: add update client worker +export class WalletWorker { + private sequence?: number + private accountNumber?: number + private logger: Logger + + constructor( + public chain: ChainWorker, + public workerController: WorkerController, + private maxHandlePacket: number, + public wallet: Wallet, + public packetFilter?: PacketFilter + ) { + this.logger = createLoggerWithPrefix( + `` + ) + void this.run() + } + + public async run() { + for (;;) { + try { + await this.handlePackets() + } catch (e) { + this.logger.error(`[run] ${e}`) + } + await delay(500) + } + } + + private async initAccInfo() { + const accInfo = await this.wallet.rest.auth.accountInfo(this.address()) + this.sequence = accInfo.getSequenceNumber() + this.accountNumber = accInfo.getAccountNumber() + } + + private async handlePackets() { + if (this.chain.latestHeight === undefined) return + + // get packets to handle + let remain = this.maxHandlePacket + + const chainIdsWithFeeFilter = this.workerController.getFeeFilters() + const counterpartyChainIdsWithFeeFilter = chainIdsWithFeeFilter.filter( + (v) => v.chainId !== this.chain.chainId + ) + const counterpartyChainIds = counterpartyChainIdsWithFeeFilter.map( + (v) => v.chainId + ) + const feeFilter = ( + chainIdsWithFeeFilter.find((v) => v.chainId === this.chain.chainId) as { + chainId: string + feeFilter: PacketFee + } + ).feeFilter + + const sendPackets = PacketController.getSendPackets( + this.chain.chainId, + this.chain.latestHeight, + Number((this.chain.latestTimestamp / 1000).toFixed()), + counterpartyChainIdsWithFeeFilter, + this.packetFilter, + remain + ).filter( + (packet) => + packet.height < + this.workerController.chains[packet.src_chain_id].latestHeight + ) + + remain -= sendPackets.length + + const writeAckPackets = + remain === 0 + ? [] + : PacketController.getWriteAckPackets( + this.chain.chainId, + counterpartyChainIds, + feeFilter, + this.packetFilter, + remain + ).filter( + (packet) => + packet.height < + this.workerController.chains[packet.dst_chain_id].latestHeight + ) + + remain -= writeAckPackets.length + + const timeoutPackets = + remain === 0 + ? [] + : PacketController.getTimeoutPackets( + this.chain.chainId, + this.chain.latestHeight, + Number((this.chain.latestTimestamp / 1000).toFixed()), + counterpartyChainIds, + feeFilter, + this.packetFilter, + remain + ) + + remain -= timeoutPackets.length + + const channelOpenEvents = + remain === 0 + ? [] + : ChannelController.getOpenEvent( + this.chain.chainId, + counterpartyChainIds, + this.packetFilter, + undefined, + remain + ).filter( + (event) => + event.height < + this.workerController.chains[event.counterparty_chain_id] + .latestHeight + ) + + // update packet in progress + DB.transaction(() => { + sendPackets.map((packet) => + PacketController.updateSendPacketInProgress(packet) + ) + writeAckPackets.map((packet) => + PacketController.updateWriteAckPacketInProgress(packet) + ) + timeoutPackets.map((packet) => + PacketController.updateTimeoutPacketInProgress(packet) + ) + channelOpenEvents.map((e) => ChannelController.updateInProgress(e.id)) + })() + + try { + // filter packets + const filteredSendPackets = await this.filterSendPackets(sendPackets) + const filteredWriteAckPackets = + await this.filterWriteAckPackets(writeAckPackets) + const filteredTimeoutPackets = + await this.filterTimeoutPackets(timeoutPackets) + const filteredChannelOpenCloseEvents = + await this.filterChannelOpenCloseEvents(channelOpenEvents) + if ( + filteredSendPackets.length === 0 && + filteredWriteAckPackets.length === 0 && + filteredTimeoutPackets.length === 0 && + filteredChannelOpenCloseEvents.length === 0 + ) { + return + } + + // create msgs + + // generate update client msgs + // get unique client id + const connections = [ + ...filteredSendPackets.map((packet) => packet.dst_connection_id), + ...filteredWriteAckPackets.map((packet) => packet.src_connection_id), + ...filteredTimeoutPackets.map((packet) => packet.src_connection_id), + ...filteredChannelOpenCloseEvents.map((event) => event.connection_id), + ].filter((v, i, a) => a.indexOf(v) === i) + + const connectionClientMap: Record = {} + await Promise.all( + connections.map(async (connection) => { + const connectionInfo = await ConnectionController.getConnection( + this.chain.rest, + this.chain.chainId, + connection + ) + connectionClientMap[connection] = connectionInfo.client_id + }) + ) + + const clientIds = Object.values(connectionClientMap).filter( + (v, i, a) => a.indexOf(v) === i + ) + + // generate msgs + const updateClientMsgs: Record< + string, + { msg: MsgUpdateClient; height: Height } + > = {} + + await Promise.all( + clientIds.map(async (clientId) => { + updateClientMsgs[clientId] = + await this.workerController.generateMsgUpdateClient( + this.chain.chainId, + clientId, + this.address() + ) + }) + ) + + // generate recv packet msgs + const recvPacketMsgs = await Promise.all( + filteredSendPackets.map((packet) => { + const clientId = connectionClientMap[packet.dst_connection_id] + const height = updateClientMsgs[clientId].height + + return this.workerController.generateRecvPacketMsg( + packet, + height, + this.address() + ) + }) + ) + + // generate ack msgs + const ackMsgs = await Promise.all( + filteredWriteAckPackets.map((packet) => { + const clientId = connectionClientMap[packet.src_connection_id] + const height = updateClientMsgs[clientId].height + + return this.workerController.generateAckMsg( + packet, + height, + this.address() + ) + }) + ) + + // generate timeout msgs + const timeoutMsgs = await Promise.all( + filteredTimeoutPackets.map((packet) => { + const clientId = connectionClientMap[packet.src_connection_id] + const height = updateClientMsgs[clientId].height + + return this.workerController.generateTimeoutMsg( + packet, + height, + this.address() + ) + }) + ) + + // generate channel open, close msgs + const channelOpenMsgs = await Promise.all( + filteredChannelOpenCloseEvents + .sort((a, b) => b.state - a.state) // to make execute close first + .map((event) => { + const clientId = connectionClientMap[event.connection_id] + const height = updateClientMsgs[clientId].height + + switch (event.state) { + case ChannelState.INIT: + return this.workerController.generateChannelOpenTryMsg( + event, + height, + this.address() + ) + case ChannelState.TRYOPEN: + return this.workerController.generateChannelOpenAckMsg( + event, + height, + this.address() + ) + case ChannelState.ACK: + return this.workerController.generateChannelOpenConfirmMsg( + event, + height, + this.address() + ) + case ChannelState.CLOSE: + return this.workerController.generateChannelCloseConfirmMsg( + event, + height, + this.address() + ) + } + }) + ) + + const msgs = [ + ...Object.values(updateClientMsgs).map((v) => v.msg), + ...recvPacketMsgs, + ...ackMsgs, + ...timeoutMsgs, + ...channelOpenMsgs, + ] + + // init sequence + if (!this.sequence) { + await this.initAccInfo() + if (this.sequence === undefined) { + throw Error('Failed to update sequence number') + } + } + + const signedTx = await this.wallet.createAndSignTx({ + msgs, + sequence: this.sequence, + accountNumber: this.accountNumber, + }) + + const result = await this.wallet.rest.tx.broadcast(signedTx) + + if (isTxError(result)) { + if (result.raw_log.startsWith('account sequence mismatch')) { + try { + const expected = result.raw_log.split(', ')[1] + this.sequence = Number(expected.split(' ')[1]) - 1 + this.logger.info(`update sequence`) + } catch (e) { + this.logger.warn(`error to parse sequence`) + } + } + + this.logger.error( + `Tx failed. raw log - ${result.raw_log}, code - ${result.code}` + ) + throw Error( + `Tx failed. raw log - ${result.raw_log}, code - ${result.code}` + ) + } + + this.logger.info( + `Handled msgs(${msgs.length}). txhash - ${result.txhash}` + ) + + this.sequence++ + } catch (e) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (e?.response?.data) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + this.logger.error(e.response.data) + // tmp: refresh sequence when got error. TODO: parse sequence from error + await this.initAccInfo() + } else { + this.logger.error(e) + } + + // revert packet in progress + DB.transaction(() => { + sendPackets.map((packet) => + PacketController.updateSendPacketInProgress(packet, false) + ) + writeAckPackets.map((packet) => + PacketController.updateWriteAckPacketInProgress(packet, false) + ) + timeoutPackets.map((packet) => + PacketController.updateTimeoutPacketInProgress(packet, false) + ) + channelOpenEvents.map((event) => + ChannelController.updateInProgress(event.id, false) + ) + })() + } + } + + public address(): string { + const address = this.wallet.key.accAddress + return bech32.encode(this.chain.bech32Prefix, bech32.decode(address).words) + } + + private async filterSendPackets( + sendPackets: PacketSendTable[] + ): Promise { + // create path => packet map + const sendPacketMap: Record = {} + const sendPacketsToDel: PacketSendTable[] = [] + + for (const packet of sendPackets) { + const path = `${packet.dst_port}/${packet.dst_channel_id}` + if (!sendPacketMap[path]) { + sendPacketMap[path] = [] + } + + sendPacketMap[path].push(packet) + } + + // filter send packet + await Promise.all( + Object.keys(sendPacketMap).map(async (path) => { + if (sendPacketMap[path].length === 0) return + // check channel state + const dstChannel = await this.chain.rest.ibc.channel( + sendPacketMap[path][0].dst_port, + sendPacketMap[path][0].dst_channel_id + ) + + if (dstChannel.channel.state === State.STATE_CLOSED) { + sendPacketsToDel.push(...sendPacketMap[path]) + delete sendPacketMap[path] + return + } + + const srcChannel = await this.workerController.chains[ + sendPacketMap[path][0].src_chain_id + ].rest.ibc.channel( + sendPacketMap[path][0].src_port, + sendPacketMap[path][0].src_channel_id + ) + + if (srcChannel.channel.state === State.STATE_CLOSED) { + sendPacketsToDel.push(...sendPacketMap[path]) + delete sendPacketMap[path] + return + } + + // handle ordered channels + if (sendPacketMap[path][0].is_ordered === Bool.TRUE) { + // check next sequence + const nextSequence = await this.chain.rest.ibc.nextSequence( + sendPacketMap[path][0].dst_port, + sendPacketMap[path][0].dst_channel_id + ) + + let sequence = Number(nextSequence.next_sequence_receive) + const sequences: number[] = [] + + for (const packet of sendPacketMap[path]) { + if (packet.sequence !== sequence) { + break + } + + sequences.push(sequence) + sequence++ + } + + sendPacketMap[path] = sendPacketMap[path].filter((packet) => + sequences.includes(packet.sequence) + ) + + return + } + + const unreceivedPackets = await this.chain.rest.ibc.unreceivedPackets( + sendPacketMap[path][0].dst_port, + sendPacketMap[path][0].dst_channel_id, + sendPacketMap[path].map((packet) => packet.sequence) + ) + + const unreceivedSequences = unreceivedPackets.sequences.map( + (sequence) => Number(sequence) + ) + + sendPacketsToDel.push( + ...sendPacketMap[path].filter( + (packet) => !unreceivedSequences.includes(packet.sequence) + ) + ) + + sendPacketMap[path] = sendPacketMap[path].filter((packet) => + unreceivedSequences.includes(packet.sequence) + ) + }) + ) + + // delete packets that already executed or in closed channel + PacketController.delSendPackets(sendPacketsToDel) + + return Object.values(sendPacketMap).flat() + } + + private async filterWriteAckPackets( + writeAckPackets: PacketWriteAckTable[] + ): Promise { + // create path => packet map + const writeAckPacketMap: Record = {} + const writeAckPacketsToDel: PacketWriteAckTable[] = [] + + for (const packet of writeAckPackets) { + const path = `${packet.src_port}/${packet.src_channel_id}` + if (!writeAckPacketMap[path]) { + writeAckPacketMap[path] = [] + } + + writeAckPacketMap[path].push(packet) + } + + // filter write ack packet + await Promise.all( + Object.keys(writeAckPacketMap).map(async (path) => { + if (writeAckPacketMap[path].length === 0) return + const unreceivedAcks = await this.chain.rest.ibc.unreceivedAcks( + writeAckPacketMap[path][0].src_port, + writeAckPacketMap[path][0].src_channel_id, + writeAckPacketMap[path].map((packet) => packet.sequence) + ) + + const unreceivedSequences = unreceivedAcks.sequences.map((sequence) => + Number(sequence) + ) + + writeAckPacketsToDel.push( + ...writeAckPacketMap[path].filter( + (packet) => !unreceivedSequences.includes(packet.sequence) + ) + ) + + writeAckPacketMap[path] = writeAckPacketMap[path].filter((packet) => + unreceivedSequences.includes(packet.sequence) + ) + }) + ) + + // delete packets that already executed + PacketController.delWriteAckPackets(writeAckPacketsToDel) + + return Object.values(writeAckPacketMap).flat() + } + + private async filterTimeoutPackets( + timeoutPackets: PacketTimeoutTable[] | PacketSendTable[] + ): Promise { + // create path => packet map + const timeoutPacketMap: Record = {} + const timeoutPacketsToDel: PacketTimeoutTable[] = [] + + for (const packet of timeoutPackets) { + const path = `${packet.src_port}/${packet.src_channel_id}` + if (!timeoutPacketMap[path]) { + timeoutPacketMap[path] = [] + } + + timeoutPacketMap[path].push(packet) + } + + // filter timeout packet + + // check unreceived ack + await Promise.all( + Object.keys(timeoutPacketMap).map(async (path) => { + if (timeoutPacketMap[path].length === 0) return + const unreceivedAcks = await this.chain.rest.ibc.unreceivedAcks( + timeoutPacketMap[path][0].src_port, + timeoutPacketMap[path][0].src_channel_id, + timeoutPacketMap[path].map((packet) => packet.sequence) + ) + + const unreceivedSequences = unreceivedAcks.sequences.map((sequence) => + Number(sequence) + ) + + timeoutPacketsToDel.push( + ...timeoutPacketMap[path].filter( + (packet) => !unreceivedSequences.includes(packet.sequence) + ) + ) + + timeoutPacketMap[path] = timeoutPacketMap[path].filter((packet) => + unreceivedSequences.includes(packet.sequence) + ) + }) + ) + + // check unreceived packet + await Promise.all( + Object.keys(timeoutPacketMap).map(async (path) => { + if (timeoutPacketMap[path].length === 0) return + const chain = + this.workerController.chains[timeoutPacketMap[path][0].dst_chain_id] + const unreceivedPackets = await chain.rest.ibc.unreceivedPackets( + timeoutPacketMap[path][0].dst_port, + timeoutPacketMap[path][0].dst_channel_id, + timeoutPacketMap[path].map((packet) => packet.sequence) + ) + + const unreceivedSequences = unreceivedPackets.sequences.map( + (sequence) => Number(sequence) + ) + + timeoutPacketsToDel.push( + ...timeoutPacketMap[path].filter( + (packet) => !unreceivedSequences.includes(packet.sequence) + ) + ) + + timeoutPacketMap[path] = timeoutPacketMap[path].filter((packet) => + unreceivedSequences.includes(packet.sequence) + ) + }) + ) + + // delete packets that already executed + PacketController.delTimeoutPackets(timeoutPacketsToDel) + + return Object.values(timeoutPacketMap).flat() + } + + private async filterChannelOpenCloseEvents( + channelOnOpens: ChannelOpenCloseTable[] + ): Promise { + // filter duplicated open try + channelOnOpens = channelOnOpens.filter((v, i, a) => { + if (v.state !== ChannelState.TRYOPEN) { + return true + } + + return ( + i === + a.findIndex( + (val) => val.channel_id === v.channel_id && val.port_id === v.port_id + ) + ) + }) + + const eventsToDel: ChannelOpenCloseTable[] = [] + + // check already executed + const res = await Promise.all( + channelOnOpens.map(async (v) => { + const counterpartyChain = + this.workerController.chains[v.counterparty_chain_id] + const counterpartyChannel = await counterpartyChain.rest.ibc.channel( + v.counterparty_port_id, + v.counterparty_channel_id + ) + const channel = + v.channel_id !== '' + ? await this.chain.rest.ibc.channel(v.port_id, v.channel_id) + : undefined + switch (v.state) { + // check src channel state + case ChannelState.INIT: + if (counterpartyChannel.channel.state === State.STATE_INIT) { + return v + } + break + // check src channel state + case ChannelState.TRYOPEN: + if (channel && channel.channel.state === State.STATE_INIT) { + return v + } + break + // check dst channel state + case ChannelState.ACK: + if (channel && channel.channel.state === State.STATE_TRYOPEN) { + return v + } + break + case ChannelState.CLOSE: + if (channel && channel.channel.state !== State.STATE_CLOSED) { + return v + } + break + } + + eventsToDel.push(v) + + return undefined + }) + ) + + ChannelController.delOpenEvents(eventsToDel) + + return res.filter((v) => v !== undefined) as ChannelOpenCloseTable[] + } +} diff --git a/tsconfig.json b/tsconfig.json index 7dd7fb3..45277fb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,7 +22,8 @@ "noUnusedLocals": true, "noFallthroughCasesInSwitch": true, "skipLibCheck": true, + "esModuleInterop": true }, "include": ["src/**/*.ts", "**/*.mjs"], - "exclude": ["node_modules", "dist"], + "exclude": ["node_modules", "dist"] }