diff --git a/modules/chronik-client/README.md b/modules/chronik-client/README.md index d8ebcd1a8..eb4763be4 100644 --- a/modules/chronik-client/README.md +++ b/modules/chronik-client/README.md @@ -1,108 +1,109 @@ # Chronik Indexer Client Access Chronik Indexer via browser or Node. ## Installation `npm install chronik-client` `yarn add chronik-client` ## Usage ```js import { ChronikClient } from 'chronik-client'; // For XEC, eCash chain: const chronik = new ChronikClient('https://chronik.be.cash/xec'); // For XPI, Lotus chain: const chronik = new ChronikClient('https://chronik.be.cash/xpi'); As of version 0.9.0, the ChronikClient constructor can also optionally accept an array of chronik urls. e.g. const chronik = new ChronikClient([ 'https://chronik.be.cash/xec', 'https://chronik.fabien.cash', ]); If the first url is non-responsive it will cycle through the rest of the array. // Get Genesis block (on eCash): const block = await chronik.block( '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f', ); // Get the first 11 blocks of the chain: const blocks = await chronik.blocks(0, 10); // Get SLP tx details on eCash: const tx = await chronik.tx( '0f3c3908a2ddec8dea91d2fe1f77295bbbb158af869bff345d44ae800f0a5498', ); // Get token details for a given token ID const tokenDetails = await chronik.token( '0daf200e3418f2df1158efef36fbb507f12928f1fdcf3543703e64e75a4a9073', ); // Validate Genesis UTXO (considered 'unspent' by Chronik): const validationResult = await chronik.validateUtxos([ { txid: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b', outIdx: 0, }, ]); const GENESIS_PK = '04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc' + '3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f'; // Get first page of tx history of the Genesis pubkey, most recent first: const history = await chronik .script('p2pk', GENESIS_PK) .history(/*page=*/ 0, /*page_size=*/ 10); // Get all UTXOs of the Genesis pubkey: const utxos = await chronik.script('p2pk', GENESIS_PK).utxos(); // Listen to updates on scripts: const ws = chronik.ws({ onMessage: msg => { console.log('Got update: ', msg); }, onReconnect: e => { // Fired before a reconnect attempt is made: console.log('Reconnecting websocket, disconnection cause: ', e); }, // Optional: ping the ws every 30s to reduce disconnects keepAlive: true, }); // Wait for WS to be connected: await ws.waitForOpen(); // Subscribe to scripts (on Lotus, current ABC payout address): // Will give a message on avg every 2 minutes ws.subscribe('p2pkh', 'b8ae1c47effb58f72f7bca819fe7fc252f9e852e'); // Unsubscribe: ws.unsubscribe('p2pkh', 'b8ae1c47effb58f72f7bca819fe7fc252f9e852e'); ``` ## Changelog - 0.10.1 - Deprecate client-side ping keepAlive. Server-side is now available. - 0.11.0 - Add support for `chronikInfo()` method to `ChronikClientNode` - 0.11.1 - Do not try next server if error is unrelated to server failure - 0.12.0 - Add support for `block(hashOrHeight)` and `blocks(startHeight, endHeight)` methods to `ChronikClientNode` - 0.13.0 - Add support for `blockTxs(hashOrHeight, page, pageSize)` and `tx(txid)` methods to `ChronikClientNode` - 0.14.0 - Add support for `rawTx(txid)` method to `ChronikClientNode` - 0.15.0 - Add support for `script` endpoints `history()` and `utxos()` to `ChronikClientNode` - 0.16.0 - Add support for `broadcastTx` and `broadcastTxs` endpoints to `ChronikClientNode` - 0.17.0 - Add support for token proto to endpoints that return `Tx_InNode` to `ChronikClientNode` - 0.18.0 - Add support for websocket connections to `ChronikClientNode` - 0.19.0 - Add support for token data in tx inputs and outputs to `ChronikClientNode` - 0.20.0 - Add support for calling script endpoints by address to `ChronikClientNode` - 0.21.0 - Skipped as accidentally published 0.22.0 before diff approval at 0.21.1-rc.1 - 0.22.0 - Add support for `tokenId` endpoints and token data in utxos to `ChronikClientNode` - 0.22.1 - Return `script` key for utxos fetched from `tokenId` endpoint - 0.23.0 - Add support for returning `TokenInfo` from `chronik.token(tokenId)` calls to `ChronikClientNode` - 0.24.0 - Support `subscribeToAddress` and `unsubscribeFromAddress` methods in the `ChronikClientNode` websocket - 0.25.0 - Organize websocket subscriptions for `ChronikClientNode` under object instead of array - 0.25.1 - Move `ecashaddrjs` from dev dependency to dependency - 0.25.2 - Fix this package to work in the browser without requiring `Buffer` shim - 0.26.0 - Add `confirmedTxs` and `unconfirmedTxs` to `script` endpoint - 0.26.1 - If websocket takes longer than 5s to connect, try the next ws +- 0.26.2 - Return type `number` for `timeFirstSeen` from `chronik.token()` endpoint in `ChronikClientNode` diff --git a/modules/chronik-client/package-lock.json b/modules/chronik-client/package-lock.json index 66eaa6561..0d2a23f4b 100644 --- a/modules/chronik-client/package-lock.json +++ b/modules/chronik-client/package-lock.json @@ -1,5295 +1,5295 @@ { "name": "chronik-client", - "version": "0.26.1", + "version": "0.26.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "chronik-client", - "version": "0.26.1", + "version": "0.26.2", "license": "MIT", "dependencies": { "@types/ws": "^8.2.1", "axios": "^1.6.3", "ecashaddrjs": "^1.5.6", "isomorphic-ws": "^4.0.1", "protobufjs": "^6.8.8", "ws": "^8.3.0" }, "devDependencies": { "@types/chai": "^4.2.22", "@types/chai-as-promised": "^7.1.4", "@types/mocha": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.5.0", "@typescript-eslint/parser": "^5.5.0", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", "eslint": "^8.37.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-header": "^3.1.1", "mocha": "^9.1.3", "mocha-junit-reporter": "^2.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.5.1", "prettier-plugin-organize-imports": "^2.3.4", "ts-node": "^10.4.0", "ts-proto": "^1.92.1", "typedoc": "^0.22.10", "typescript": "^4.5.2" } }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, "engines": { "node": ">=12" } }, "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.10.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "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/js": { "version": "8.37.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", "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==", "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/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.2", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "node_modules/@noble/hashes": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", "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/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", "dev": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, "node_modules/@types/chai": { "version": "4.3.11", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", "dev": true }, "node_modules/@types/chai-as-promised": { "version": "7.1.8", "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", "dev": true, "dependencies": { "@types/chai": "*" } }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/mocha": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", "dev": true }, "node_modules/@types/node": { "version": "20.11.16", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dependencies": { "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/type-utils": "5.62.0", "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { "@typescript-eslint/parser": "^5.0.0", "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, "node_modules/@typescript-eslint/parser": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", "@typescript-eslint/typescript-estree": "5.62.0", "debug": "^4.3.4" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@typescript-eslint/type-utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "dependencies": { "@typescript-eslint/typescript-estree": "5.62.0", "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { "eslint": "*" }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, "node_modules/@typescript-eslint/types": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@typescript-eslint/typescript-estree": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "semver": "^7.3.7", "tsutils": "^3.21.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, "node_modules/@typescript-eslint/utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "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", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "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-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, "engines": { "node": ">=6" } }, "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/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, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "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/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, "engines": { "node": "*" } }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "dependencies": { "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.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/big-integer": { "version": "1.6.36", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz", "integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==", "engines": { "node": ">=0.6" } }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { "node": ">=8" } }, "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.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "node_modules/bs58": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", "dependencies": { "base-x": "^4.0.0" } }, "node_modules/bs58check": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", "dependencies": { "@noble/hashes": "^1.2.0", "bs58": "^5.0.0" } }, "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": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/case-anything": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz", "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==", "dev": true, "engines": { "node": ">=12.13" }, "funding": { "url": "https://github.com/sponsors/mesqueeb" } }, "node_modules/chai": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", "deep-eql": "^4.1.3", "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", "type-detect": "^4.0.8" }, "engines": { "node": ">=4" } }, "node_modules/chai-as-promised": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "dev": true, "dependencies": { "check-error": "^1.0.2" }, "peerDependencies": { "chai": ">= 2.1.2 < 5" } }, "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/charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "dev": true, "engines": { "node": "*" } }, "node_modules/check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, "dependencies": { "get-func-name": "^2.0.2" }, "engines": { "node": "*" } }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/chokidar/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": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "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/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/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "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/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, "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/crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, "engines": { "node": "*" } }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "dependencies": { "type-detect": "^4.0.0" }, "engines": { "node": ">=6" } }, "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/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { "node": ">=0.4.0" } }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "dev": true, "bin": { "detect-libc": "bin/detect-libc.js" }, "engines": { "node": ">=0.10" } }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, "engines": { "node": ">=0.3.1" } }, "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": { "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, "dependencies": { "esutils": "^2.0.2" }, "engines": { "node": ">=6.0.0" } }, "node_modules/dprint-node": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz", "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==", "dev": true, "dependencies": { "detect-libc": "^1.0.3" } }, "node_modules/ecashaddrjs": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/ecashaddrjs/-/ecashaddrjs-1.5.6.tgz", "integrity": "sha512-U3vF3pMkMTlgfwYEzWV2+MIItlTqHbOebRmV553DuKPjj6IFNWhqcOnAk8eyPGUJ83xG7VRXS6mv4BGZGMB0Kg==", "dependencies": { "big-integer": "1.6.36", "bs58check": "^3.0.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 }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" } }, "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": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { "version": "8.37.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", "@eslint/js": "8.37.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "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.1.1", "eslint-visitor-keys": "^3.4.0", "espree": "^9.5.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", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "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.1", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-config-prettier": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-plugin-header": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz", "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==", "dev": true, "peerDependencies": { "eslint": ">=7.7.0" } }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" }, "engines": { "node": ">=8.0.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": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/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": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/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/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": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" }, "engines": { "node": ">=0.10" } }, "node_modules/esquery/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/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" } }, "node_modules/esrecurse/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/estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "engines": { "node": ">=4.0" } }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { "node": ">=0.10.0" } }, "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-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": { "@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/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": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "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/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/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, "engines": { "node": "^10.12.0 || >=12.0.0" } }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "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": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, "bin": { "flat": "cli.js" } }, "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": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/follow-redirects": { "version": "1.15.5", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], "engines": { "node": ">=4.0" }, "peerDependenciesMeta": { "debug": { "optional": true } } }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" }, "engines": { "node": ">= 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/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, "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "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, "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, "engines": { "node": "*" } }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "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==", "dev": true, "dependencies": { "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" } }, "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": { "type-fest": "^0.20.2" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "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": { "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": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/grapheme-splitter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, "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/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true, "engines": { "node": ">=4.x" } }, "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, "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "bin": { "he": "bin/he" } }, "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": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { "node": ">=0.8.19" } }, "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==", "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "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, "engines": { "node": ">=0.10.0" } }, "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, "engines": { "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==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.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==", "dev": true, "engines": { "node": ">=0.12.0" } }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "engines": { "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/isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", "peerDependencies": { "ws": "*" } }, "node_modules/js-sdsl": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/js-sdsl" } }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "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-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "node_modules/jsonc-parser": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", "dev": true }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { "get-func-name": "^2.0.1" } }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "node_modules/marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, "bin": { "marked": "bin/marked.js" }, "engines": { "node": ">= 12" } }, "node_modules/md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "dev": true, "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", "is-buffer": "~1.1.6" } }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "engines": { "node": ">= 8" } }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { "braces": "^3.0.2", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, "bin": { "mkdirp": "dist/cjs/src/bin.js" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha-junit-reporter": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz", "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==", "dev": true, "dependencies": { "debug": "^4.3.4", "md5": "^2.3.0", "mkdirp": "^3.0.0", "strip-ansi": "^6.0.1", "xml": "^1.0.1" }, "peerDependencies": { "mocha": ">=2.2.5" } }, "node_modules/mocha-suppress-logs": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/mocha-suppress-logs/-/mocha-suppress-logs-0.3.1.tgz", "integrity": "sha512-Iu6jyTguAtFzmt7l4Agfnve0v+cQNbH92iMau1kjWwom7MNn18/Mzo1EaVhwDrH24cQ87RDKAMse2rDUkuXy8A==", "dev": true }, "node_modules/mocha/node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/mocha/node_modules/debug/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/mocha/node_modules/minimatch": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": ">=10" } }, "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/mocha/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, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "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/nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node_modules/natural-compare-lite": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, "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, "engines": { "node": ">=0.10.0" } }, "node_modules/once": { "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" } }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "dependencies": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "dependencies": { "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, "engines": { "node": "*" } }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/prettier-plugin-organize-imports": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-2.3.4.tgz", "integrity": "sha512-R8o23sf5iVL/U71h9SFUdhdOEPsi3nm42FD/oDYIZ2PQa4TNWWuWecxln6jlIQzpZTDMUeO1NicJP6lLn2TtRw==", "dev": true, "peerDependencies": { "prettier": ">=2.0", "typescript": ">=2.9" } }, "node_modules/protobufjs": { "version": "6.11.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", "hasInstallScript": true, "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/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": ">=8.10.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, "engines": { "node": ">=0.10.0" } }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/shiki": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", "dev": true, "dependencies": { "jsonc-parser": "^3.0.0", "vscode-oniguruma": "^1.6.1", "vscode-textmate": "5.2.0" } }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { "node": ">=8" } }, "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, "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", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { "ts-node": "dist/bin.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js", "ts-script": "dist/bin-script-deprecated.js" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "peerDependenciesMeta": { "@swc/core": { "optional": true }, "@swc/wasm": { "optional": true } } }, "node_modules/ts-node/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "engines": { "node": ">=0.3.1" } }, "node_modules/ts-poet": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.6.0.tgz", "integrity": "sha512-4vEH/wkhcjRPFOdBwIh9ItO6jOoumVLRF4aABDX5JSNEubSqwOulihxQPqai+OkuygJm3WYMInxXQX4QwVNMuw==", "dev": true, "dependencies": { "dprint-node": "^1.0.7" } }, "node_modules/ts-proto": { "version": "1.167.3", "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-1.167.3.tgz", "integrity": "sha512-quBKTeIgqhTGKXl5JN7HHZjLwrdMaNIoQ0+X11PqNLVRqTlnEzfiCUXM6HOW4pZa6PD5+qSyKOEGaTa3kS7Glg==", "dev": true, "dependencies": { "case-anything": "^2.1.13", "protobufjs": "^7.2.4", "ts-poet": "^6.5.0", "ts-proto-descriptors": "1.15.0" }, "bin": { "protoc-gen-ts_proto": "protoc-gen-ts_proto" } }, "node_modules/ts-proto-descriptors": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.15.0.tgz", "integrity": "sha512-TYyJ7+H+7Jsqawdv+mfsEpZPTIj9siDHS6EMCzG/z3b/PZiphsX+mWtqFfFVe5/N0Th6V3elK9lQqjnrgTOfrg==", "dev": true, "dependencies": { "long": "^5.2.3", "protobufjs": "^7.2.4" } }, "node_modules/ts-proto-descriptors/node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "dev": true }, "node_modules/ts-proto-descriptors/node_modules/protobufjs": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", "dev": true, "hasInstallScript": true, "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/node": ">=13.7.0", "long": "^5.0.0" }, "engines": { "node": ">=12.0.0" } }, "node_modules/ts-proto/node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "dev": true }, "node_modules/ts-proto/node_modules/protobufjs": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", "dev": true, "hasInstallScript": true, "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/node": ">=13.7.0", "long": "^5.0.0" }, "engines": { "node": ">=12.0.0" } }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "dependencies": { "tslib": "^1.8.1" }, "engines": { "node": ">= 6" }, "peerDependencies": { "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, "engines": { "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, "engines": { "node": ">=4" } }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/typedoc": { "version": "0.22.18", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.18.tgz", "integrity": "sha512-NK9RlLhRUGMvc6Rw5USEYgT4DVAUFk7IF7Q6MYfpJ88KnTZP7EneEa4RcP+tX1auAcz7QT1Iy0bUSZBYYHdoyA==", "dev": true, "dependencies": { "glob": "^8.0.3", "lunr": "^2.3.9", "marked": "^4.0.16", "minimatch": "^5.1.0", "shiki": "^0.10.1" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { "node": ">= 12.10.0" }, "peerDependencies": { "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x || 4.7.x" } }, "node_modules/typedoc/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/typedoc/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/typedoc/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, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" } }, "node_modules/typescript": { "version": "4.7.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=4.2.0" } }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { "punycode": "^2.1.0" } }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", "dev": true }, "node_modules/vscode-textmate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", "dev": true }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, "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, "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 }, "node_modules/ws": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { "optional": true }, "utf-8-validate": { "optional": true } } }, "node_modules/xml": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "dev": true }, "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, "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" } }, "node_modules/yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" }, "engines": { "node": ">=10" } }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } }, "dependencies": { "@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true }, "@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "requires": { "@jridgewell/trace-mapping": "0.3.9" } }, "@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, "requires": { "eslint-visitor-keys": "^3.3.0" } }, "@eslint-community/regexpp": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true }, "@eslint/eslintrc": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "requires": { "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" } }, "@eslint/js": { "version": "8.37.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz", "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", "dev": true }, "@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^2.0.2", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "@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 }, "@humanwhocodes/object-schema": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "@jridgewell/resolve-uri": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true }, "@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "@noble/hashes": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==" }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" }, "@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, "@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" }, "@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" }, "@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "requires": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, "@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" }, "@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" }, "@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, "@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", "dev": true }, "@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true }, "@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true }, "@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, "@types/chai": { "version": "4.3.11", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", "dev": true }, "@types/chai-as-promised": { "version": "7.1.8", "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", "dev": true, "requires": { "@types/chai": "*" } }, "@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "@types/mocha": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", "dev": true }, "@types/node": { "version": "20.11.16", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "requires": { "undici-types": "~5.26.4" } }, "@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "requires": { "@types/node": "*" } }, "@typescript-eslint/eslint-plugin": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/type-utils": "5.62.0", "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "requires": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", "@typescript-eslint/typescript-estree": "5.62.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "requires": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" } }, "@typescript-eslint/type-utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "requires": { "@typescript-eslint/typescript-estree": "5.62.0", "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true }, "@typescript-eslint/typescript-estree": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "requires": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "requires": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" } }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, "acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "requires": {} }, "acorn-walk": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { "color-convert": "^2.0.1" } }, "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, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "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 }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "axios": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "requires": { "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "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 }, "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==" }, "big-integer": { "version": "1.6.36", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz", "integrity": "sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==" }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { "fill-range": "^7.0.1" } }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "bs58": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", "requires": { "base-x": "^4.0.0" } }, "bs58check": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", "requires": { "@noble/hashes": "^1.2.0", "bs58": "^5.0.0" } }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, "case-anything": { "version": "2.1.13", "resolved": "https://registry.npmjs.org/case-anything/-/case-anything-2.1.13.tgz", "integrity": "sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==", "dev": true }, "chai": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", "deep-eql": "^4.1.3", "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", "type-detect": "^4.0.8" } }, "chai-as-promised": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "dev": true, "requires": { "check-error": "^1.0.2" } }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", "dev": true }, "check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, "requires": { "get-func-name": "^2.0.2" } }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "dependencies": { "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" } } } }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { "color-name": "~1.1.4" } }, "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { "ms": "2.1.2" } }, "decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, "deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "requires": { "type-detect": "^4.0.0" } }, "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 }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "dev": true }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "requires": { "path-type": "^4.0.0" } }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" } }, "dprint-node": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/dprint-node/-/dprint-node-1.0.8.tgz", "integrity": "sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==", "dev": true, "requires": { "detect-libc": "^1.0.3" } }, "ecashaddrjs": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/ecashaddrjs/-/ecashaddrjs-1.5.6.tgz", "integrity": "sha512-U3vF3pMkMTlgfwYEzWV2+MIItlTqHbOebRmV553DuKPjj6IFNWhqcOnAk8eyPGUJ83xG7VRXS6mv4BGZGMB0Kg==", "requires": { "big-integer": "1.6.36", "bs58check": "^3.0.1" } }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, "eslint": { "version": "8.37.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz", "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.2", "@eslint/js": "8.37.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "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.1.1", "eslint-visitor-keys": "^3.4.0", "espree": "^9.5.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", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", "js-sdsl": "^4.1.4", "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.1", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "dependencies": { "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, "requires": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } }, "eslint-config-prettier": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", "dev": true, "requires": {} }, "eslint-plugin-header": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz", "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==", "dev": true, "requires": {} }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "eslint-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 }, "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, "requires": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { "estraverse": "^5.2.0" }, "dependencies": { "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } }, "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-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, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" }, "dependencies": { "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" } } } }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "requires": { "reusify": "^1.0.4" } }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { "flat-cache": "^3.0.4" } }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { "to-regex-range": "^5.0.1" } }, "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, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, "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, "requires": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "flatted": { "version": "3.2.9", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "follow-redirects": { "version": "1.15.5", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==" }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "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 }, "fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "requires": { "is-glob": "^4.0.3" } }, "globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "requires": { "type-fest": "^0.20.2" } }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { "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" } }, "grapheme-splitter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, "graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { "binary-extensions": "^2.0.0" } }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", "requires": {} }, "js-sdsl": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", "dev": true }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" } }, "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 }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "jsonc-parser": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", "dev": true }, "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "requires": { "json-buffer": "3.0.1" } }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { "p-locate": "^5.0.0" } }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, "loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "requires": { "get-func-name": "^2.0.1" } }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { "yallist": "^4.0.0" } }, "lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "marked": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true }, "md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "dev": true, "requires": { "charenc": "0.0.2", "crypt": "0.0.2", "is-buffer": "~1.1.6" } }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" } }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { "mime-db": "1.52.0" } }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true }, "mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "dependencies": { "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { "ms": "2.1.2" }, "dependencies": { "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } }, "minimatch": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" } } } }, "mocha-junit-reporter": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz", "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==", "dev": true, "requires": { "debug": "^4.3.4", "md5": "^2.3.0", "mkdirp": "^3.0.0", "strip-ansi": "^6.0.1", "xml": "^1.0.1" } }, "mocha-suppress-logs": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/mocha-suppress-logs/-/mocha-suppress-logs-0.3.1.tgz", "integrity": "sha512-Iu6jyTguAtFzmt7l4Agfnve0v+cQNbH92iMau1kjWwom7MNn18/Mzo1EaVhwDrH24cQ87RDKAMse2rDUkuXy8A==", "dev": true }, "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 }, "nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "natural-compare-lite": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, "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 }, "once": { "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, "requires": { "wrappy": "1" } }, "optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, "requires": { "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0" } }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { "yocto-queue": "^0.1.0" } }, "p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { "p-limit": "^3.0.2" } }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { "callsites": "^3.0.0" } }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "prettier-plugin-organize-imports": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-2.3.4.tgz", "integrity": "sha512-R8o23sf5iVL/U71h9SFUdhdOEPsi3nm42FD/oDYIZ2PQa4TNWWuWecxln6jlIQzpZTDMUeO1NicJP6lLn2TtRw==", "dev": true, "requires": {} }, "protobufjs": { "version": "6.11.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", "requires": { "@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" } }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" } }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" } }, "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 }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" } }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "requires": { "queue-microtask": "^1.2.2" } }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" } }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { "shebang-regex": "^3.0.0" } }, "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "shiki": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", "dev": true, "requires": { "jsonc-parser": "^3.0.0", "vscode-oniguruma": "^1.6.1", "vscode-textmate": "5.2.0" } }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "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, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { "ansi-regex": "^5.0.1" } }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { "is-number": "^7.0.0" } }, "ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "requires": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "dependencies": { "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true } } }, "ts-poet": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/ts-poet/-/ts-poet-6.6.0.tgz", "integrity": "sha512-4vEH/wkhcjRPFOdBwIh9ItO6jOoumVLRF4aABDX5JSNEubSqwOulihxQPqai+OkuygJm3WYMInxXQX4QwVNMuw==", "dev": true, "requires": { "dprint-node": "^1.0.7" } }, "ts-proto": { "version": "1.167.3", "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-1.167.3.tgz", "integrity": "sha512-quBKTeIgqhTGKXl5JN7HHZjLwrdMaNIoQ0+X11PqNLVRqTlnEzfiCUXM6HOW4pZa6PD5+qSyKOEGaTa3kS7Glg==", "dev": true, "requires": { "case-anything": "^2.1.13", "protobufjs": "^7.2.4", "ts-poet": "^6.5.0", "ts-proto-descriptors": "1.15.0" }, "dependencies": { "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "dev": true }, "protobufjs": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", "dev": true, "requires": { "@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/node": ">=13.7.0", "long": "^5.0.0" } } } }, "ts-proto-descriptors": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/ts-proto-descriptors/-/ts-proto-descriptors-1.15.0.tgz", "integrity": "sha512-TYyJ7+H+7Jsqawdv+mfsEpZPTIj9siDHS6EMCzG/z3b/PZiphsX+mWtqFfFVe5/N0Th6V3elK9lQqjnrgTOfrg==", "dev": true, "requires": { "long": "^5.2.3", "protobufjs": "^7.2.4" }, "dependencies": { "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "dev": true }, "protobufjs": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", "dev": true, "requires": { "@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/node": ">=13.7.0", "long": "^5.0.0" } } } }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "requires": { "tslib": "^1.8.1" } }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { "prelude-ls": "^1.2.1" } }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, "typedoc": { "version": "0.22.18", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.18.tgz", "integrity": "sha512-NK9RlLhRUGMvc6Rw5USEYgT4DVAUFk7IF7Q6MYfpJ88KnTZP7EneEa4RcP+tX1auAcz7QT1Iy0bUSZBYYHdoyA==", "dev": true, "requires": { "glob": "^8.0.3", "lunr": "^2.3.9", "marked": "^4.0.16", "minimatch": "^5.1.0", "shiki": "^0.10.1" }, "dependencies": { "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, "requires": { "balanced-match": "^1.0.0" } }, "glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } } } }, "typescript": { "version": "4.7.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true }, "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" } }, "v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, "vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", "dev": true }, "vscode-textmate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", "dev": true }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" } }, "workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "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 }, "ws": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "requires": {} }, "xml": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "dev": true }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true }, "yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" } }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true } } } diff --git a/modules/chronik-client/package.json b/modules/chronik-client/package.json index 2f47f3578..1a815e381 100644 --- a/modules/chronik-client/package.json +++ b/modules/chronik-client/package.json @@ -1,49 +1,49 @@ { "name": "chronik-client", - "version": "0.26.1", + "version": "0.26.2", "description": "A client for accessing the Chronik Indexer API", "main": "dist/index.js", "types": "dist/index.d.ts", "author": "Tobias Ruck", "license": "MIT", "scripts": { "build-proto": "protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=proto/ ../../chronik/chronik-proto/proto/chronik.proto -I=../../chronik/chronik-proto/proto/ --ts_proto_opt=esModuleInterop=true --ts_proto_opt=forceLong=string && mv proto/chronik.ts proto/chronikNode.ts", "build": "tsc", "build-docs": "typedoc --out docs index.ts", "test": "mocha -r ts-node/register test/test.ts", "integration-tests": "mocha -j1 -r ts-node/register test/integration/*.ts", "test-long": "mocha -r ts-node/register test/test.ts --timeout 1000000000", "format": "prettier --write .", "lint": "eslint . --ext .js,.jsx,.ts,.tsx && prettier --check .", "prepublish": "npm run build" }, "devDependencies": { "@types/chai": "^4.2.22", "@types/chai-as-promised": "^7.1.4", "@types/mocha": "^9.0.0", "@typescript-eslint/eslint-plugin": "^5.5.0", "@typescript-eslint/parser": "^5.5.0", "chai": "^4.3.4", "chai-as-promised": "^7.1.1", "eslint": "^8.37.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-header": "^3.1.1", "mocha": "^9.1.3", "mocha-junit-reporter": "^2.2.0", "mocha-suppress-logs": "^0.3.1", "prettier": "^2.5.1", "prettier-plugin-organize-imports": "^2.3.4", "ts-node": "^10.4.0", "ts-proto": "^1.92.1", "typedoc": "^0.22.10", "typescript": "^4.5.2" }, "dependencies": { "@types/ws": "^8.2.1", "axios": "^1.6.3", "ecashaddrjs": "^1.5.6", "isomorphic-ws": "^4.0.1", "protobufjs": "^6.8.8", "ws": "^8.3.0" } } diff --git a/modules/chronik-client/src/ChronikClientNode.ts b/modules/chronik-client/src/ChronikClientNode.ts index 3c6df94ff..944bcbfab 100644 --- a/modules/chronik-client/src/ChronikClientNode.ts +++ b/modules/chronik-client/src/ChronikClientNode.ts @@ -1,1509 +1,1509 @@ // Copyright (c) 2023-2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. import cashaddr from 'ecashaddrjs'; import WebSocket from 'isomorphic-ws'; import * as ws from 'ws'; import * as proto from '../proto/chronikNode'; import { BlockchainInfo, OutPoint } from './ChronikClient'; import { FailoverProxy } from './failoverProxy'; import { fromHex, toHex, toHexRev } from './hex'; import { isValidWsSubscription } from './validation'; type MessageEvent = ws.MessageEvent | { data: Blob }; /** * Client to access an in-node Chronik instance. * Plain object, without any connections. */ export class ChronikClientNode { private _proxyInterface: FailoverProxy; /** * Create a new client. This just creates an object, without any connections. * * @param {string[]} urls Array of valid urls. A valid url comes with schema and without a trailing slash. * e.g. '['https://chronik.be.cash/xec2', 'https://chronik-native.fabien.cash'] * The approach of accepting an array of urls as input is to ensure redundancy if the * first url encounters downtime. * @throws {error} throws error on invalid constructor inputs */ constructor(urls: string[]) { // Instantiate FailoverProxy with the urls array this._proxyInterface = new FailoverProxy(urls); } // For unit test verification public proxyInterface(): FailoverProxy { return this._proxyInterface; } /** * Broadcasts the `rawTx` on the network. * If `skipTokenChecks` is false, it will be checked that the tx doesn't burn * any tokens before broadcasting. */ public async broadcastTx( rawTx: Uint8Array | string, skipTokenChecks = false, ): Promise<{ txid: string }> { const request = proto.BroadcastTxRequest.encode({ rawTx: typeof rawTx === 'string' ? fromHex(rawTx) : rawTx, skipTokenChecks, }).finish(); const data = await this._proxyInterface.post('/broadcast-tx', request); const broadcastResponse = proto.BroadcastTxResponse.decode(data); return { txid: toHexRev(broadcastResponse.txid), }; } /** * Broadcasts the `rawTxs` on the network, only if all of them are valid. * If `skipTokenChecks` is false, it will be checked that the txs don't burn * any tokens before broadcasting. */ public async broadcastTxs( rawTxs: (Uint8Array | string)[], skipTokenChecks = false, ): Promise<{ txids: string[] }> { const request = proto.BroadcastTxsRequest.encode({ rawTxs: rawTxs.map(rawTx => typeof rawTx === 'string' ? fromHex(rawTx) : rawTx, ), skipTokenChecks, }).finish(); const data = await this._proxyInterface.post('/broadcast-txs', request); const broadcastResponse = proto.BroadcastTxsResponse.decode(data); return { txids: broadcastResponse.txids.map(toHexRev), }; } /** Fetch current info of the blockchain, such as tip hash and height. */ public async blockchainInfo(): Promise { const data = await this._proxyInterface.get(`/blockchain-info`); const blockchainInfo = proto.BlockchainInfo.decode(data); return convertToBlockchainInfo(blockchainInfo); } /** Fetch info about the current running chronik server */ public async chronikInfo(): Promise { const data = await this._proxyInterface.get(`/chronik-info`); const chronikServerInfo = proto.ChronikInfo.decode(data); return convertToChronikInfo(chronikServerInfo); } /** Fetch the block given hash or height. */ public async block(hashOrHeight: string | number): Promise { const data = await this._proxyInterface.get(`/block/${hashOrHeight}`); const block = proto.Block.decode(data); return convertToBlock(block); } /** Fetch the tx history of a block given hash or height. */ public async blockTxs( hashOrHeight: string | number, page = 0, // Get the first page if unspecified pageSize = 25, // Must be less than 200, let server handle error as server setting could change ): Promise { const data = await this._proxyInterface.get( `/block-txs/${hashOrHeight}?page=${page}&page_size=${pageSize}`, ); const blockTxs = proto.TxHistoryPage.decode(data); return convertToTxHistoryPage(blockTxs); } /** * Fetch block info of a range of blocks. * `startHeight` and `endHeight` are inclusive ranges. */ public async blocks( startHeight: number, endHeight: number, ): Promise { const data = await this._proxyInterface.get( `/blocks/${startHeight}/${endHeight}`, ); const blocks = proto.Blocks.decode(data); return blocks.blocks.map(convertToBlockInfo); } /** Fetch token info and stats given the tokenId. */ public async token(tokenId: string): Promise { const data = await this._proxyInterface.get(`/token/${tokenId}`); const tokenInfo = proto.TokenInfo.decode(data); return convertToTokenInfo(tokenInfo); } /** Fetch tx details given the txid. */ public async tx(txid: string): Promise { const data = await this._proxyInterface.get(`/tx/${txid}`); const tx = proto.Tx.decode(data); return convertToTx(tx); } /** Fetch tx details given the txid. */ public async rawTx(txid: string): Promise { const data = await this._proxyInterface.get(`/raw-tx/${txid}`); const rawTx = proto.RawTx.decode(data); return convertToRawTx(rawTx); } /** Create object that allows fetching info about a given token */ public tokenId(tokenId: string): TokenIdEndpoint { return new TokenIdEndpoint(this._proxyInterface, tokenId); } /** Create object that allows fetching script history or UTXOs. */ public script( scriptType: ScriptType_InNode, scriptPayload: string, ): ScriptEndpointInNode { return new ScriptEndpointInNode( this._proxyInterface, scriptType, scriptPayload, ); } /** Create object that allows fetching script history or UTXOs by p2pkh or p2sh address */ public address(address: string): ScriptEndpointInNode { const { type, hash } = cashaddr.decode(address, true); return new ScriptEndpointInNode( this._proxyInterface, type, hash as string, ); } /** Open a WebSocket connection to listen for updates. */ public ws(config: WsConfig_InNode): WsEndpoint_InNode { return new WsEndpoint_InNode(this._proxyInterface, config); } } /** Allows fetching script history and UTXOs. */ export class ScriptEndpointInNode { private _proxyInterface: FailoverProxy; private _scriptType: string; private _scriptPayload: string; constructor( proxyInterface: FailoverProxy, scriptType: string, scriptPayload: string, ) { this._proxyInterface = proxyInterface; this._scriptType = scriptType; this._scriptPayload = scriptPayload; } /** * Fetches the tx history of this script, in anti-chronological order. * This means it's ordered by first-seen first, i.e. TxHistoryPage_InNode.txs[0] * will be the most recent tx. If the tx hasn't been seen * by the indexer before, it's ordered by the block timestamp. * @param page Page index of the tx history. * @param pageSize Number of txs per page. */ public async history( page = 0, // Get the first page if unspecified pageSize = 25, // Must be less than 200, let server handle error as server setting could change ): Promise { const data = await this._proxyInterface.get( `/script/${this._scriptType}/${this._scriptPayload}/history?page=${page}&page_size=${pageSize}`, ); const historyPage = proto.TxHistoryPage.decode(data); return { txs: historyPage.txs.map(convertToTx), numPages: historyPage.numPages, numTxs: historyPage.numTxs, }; } /** * Fetches the confirmed tx history of this script, in the order they appear on the blockchain. * @param page Page index of the tx history. * @param pageSize Number of txs per page. */ public async confirmedTxs( page = 0, // Get the first page if unspecified pageSize = 25, // Must be less than 200, let server handle error as server setting could change ): Promise { const data = await this._proxyInterface.get( `/script/${this._scriptType}/${this._scriptPayload}/confirmed-txs?page=${page}&page_size=${pageSize}`, ); const historyPage = proto.TxHistoryPage.decode(data); return { txs: historyPage.txs.map(convertToTx), numPages: historyPage.numPages, numTxs: historyPage.numTxs, }; } /** * Fetches the unconfirmed tx history of this script, in chronological order. * @param page Page index of the tx history. * @param pageSize Number of txs per page. */ public async unconfirmedTxs( page = 0, // Get the first page if unspecified pageSize = 25, // Must be less than 200, let server handle error as server setting could change ): Promise { const data = await this._proxyInterface.get( `/script/${this._scriptType}/${this._scriptPayload}/unconfirmed-txs?page=${page}&page_size=${pageSize}`, ); const historyPage = proto.TxHistoryPage.decode(data); return { txs: historyPage.txs.map(convertToTx), numPages: historyPage.numPages, numTxs: historyPage.numTxs, }; } /** * Fetches the current UTXO set for this script. * It is grouped by output script, in case a script type can match multiple * different output scripts (e.g. Taproot on Lotus). */ public async utxos(): Promise { const data = await this._proxyInterface.get( `/script/${this._scriptType}/${this._scriptPayload}/utxos`, ); const scriptUtxos = proto.ScriptUtxos.decode(data); return { outputScript: toHex(scriptUtxos.script), utxos: scriptUtxos.utxos.map(convertToScriptUtxo), }; } } /** Allows fetching tokenId confirmedTxs, unconfirmedTxs, history, and UTXOs. */ export class TokenIdEndpoint { private _proxyInterface: FailoverProxy; private _tokenId: string; constructor(proxyInterface: FailoverProxy, tokenId: string) { this._proxyInterface = proxyInterface; this._tokenId = tokenId; } /** * Fetches the tx history of this tokenId, in anti-chronological order. * @param page Page index of the tx history. * @param pageSize Number of txs per page. */ public async history( page = 0, // Get the first page if unspecified pageSize = 25, // Must be less than 200, let server handle error as server setting could change ): Promise { const data = await this._proxyInterface.get( `/token-id/${this._tokenId}/history?page=${page}&page_size=${pageSize}`, ); const historyPage = proto.TxHistoryPage.decode(data); return { txs: historyPage.txs.map(convertToTx), numPages: historyPage.numPages, numTxs: historyPage.numTxs, }; } /** * Fetches the confirmed tx history of this tokenId, in the order they appear on the blockchain. * @param page Page index of the tx history. * @param pageSize Number of txs per page. */ public async confirmedTxs( page = 0, // Get the first page if unspecified pageSize = 25, // Must be less than 200, let server handle error as server setting could change ): Promise { const data = await this._proxyInterface.get( `/token-id/${this._tokenId}/confirmed-txs?page=${page}&page_size=${pageSize}`, ); const historyPage = proto.TxHistoryPage.decode(data); return { txs: historyPage.txs.map(convertToTx), numPages: historyPage.numPages, numTxs: historyPage.numTxs, }; } /** * Fetches the unconfirmed tx history of this tokenId, in chronological order. * @param page Page index of the tx history. * @param pageSize Number of txs per page. */ public async unconfirmedTxs( page = 0, // Get the first page if unspecified pageSize = 25, // Must be less than 200, let server handle error as server setting could change ): Promise { const data = await this._proxyInterface.get( `/token-id/${this._tokenId}/unconfirmed-txs?page=${page}&page_size=${pageSize}`, ); const historyPage = proto.TxHistoryPage.decode(data); return { txs: historyPage.txs.map(convertToTx), numPages: historyPage.numPages, numTxs: historyPage.numTxs, }; } /** * Fetches the current UTXO set for this tokenId. */ public async utxos(): Promise { const data = await this._proxyInterface.get( `/token-id/${this._tokenId}/utxos`, ); const utxos = proto.Utxos.decode(data); return { tokenId: this._tokenId, utxos: utxos.utxos.map(convertToUtxo), }; } } /** Config for a WebSocket connection to Chronik. */ export interface WsConfig_InNode { /** Fired when a message is sent from the WebSocket. */ onMessage?: (msg: WsMsgClient) => void; /** Fired when a connection has been (re)established. */ onConnect?: (e: ws.Event) => void; /** * Fired after a connection has been unexpectedly closed, and before a * reconnection attempt is made. Only fired if `autoReconnect` is true. */ onReconnect?: (e: ws.Event) => void; /** Fired when an error with the WebSocket occurs. */ onError?: (e: ws.ErrorEvent) => void; /** * Fired after a connection has been manually closed, or if `autoReconnect` * is false, if the WebSocket disconnects for any reason. */ onEnd?: (e: ws.Event) => void; /** Whether to automatically reconnect on disconnect, default true. */ autoReconnect?: boolean; } /** WebSocket connection to Chronik. */ export class WsEndpoint_InNode { private _proxyInterface: FailoverProxy; /** Fired when a message is sent from the WebSocket. */ public onMessage?: (msg: WsMsgClient) => void; /** Fired when a connection has been (re)established. */ public onConnect?: (e: ws.Event) => void; /** * Fired after a connection has been unexpectedly closed, and before a * reconnection attempt is made. Only fired if `autoReconnect` is true. */ public onReconnect?: (e: ws.Event) => void; /** Fired when an error with the WebSocket occurs. */ public onError?: (e: ws.ErrorEvent) => void; /** * Fired after a connection has been manually closed, or if `autoReconnect` * is false, if the WebSocket disconnects for any reason. */ public onEnd?: (e: ws.Event) => void; /** Whether to automatically reconnect on disconnect, default true. */ public autoReconnect: boolean; public ws: ws.WebSocket | undefined; public connected: Promise | undefined; public manuallyClosed: boolean; public subs: WsSubscriptions; constructor(proxyInterface: FailoverProxy, config: WsConfig_InNode) { this.onMessage = config.onMessage; this.onConnect = config.onConnect; this.onReconnect = config.onReconnect; this.onEnd = config.onEnd; this.autoReconnect = config.autoReconnect !== undefined ? config.autoReconnect : true; this.manuallyClosed = false; this.subs = { scripts: [], tokens: [], blocks: false }; this._proxyInterface = proxyInterface; } /** Wait for the WebSocket to be connected. */ public async waitForOpen() { await this._proxyInterface.connectWs(this); await this.connected; } /** * Subscribe to block messages */ public subscribeToBlocks() { this.subs.blocks = true; if (this.ws?.readyState === WebSocket.OPEN) { this._subUnsubBlocks(false); } } /** * Unsubscribe from block messages */ public unsubscribeFromBlocks() { this.subs.blocks = false; if (this.ws?.readyState === WebSocket.OPEN) { this._subUnsubBlocks(true); } } /** * Subscribe to the given script type and payload. * For "p2pkh", `scriptPayload` is the 20 byte public key hash. */ public subscribeToScript(type: ScriptType_InNode, payload: string) { // Build sub according to chronik expected type const subscription: WsSubScriptClient = { scriptType: type, payload, }; // We do not want to add invalid subs to ws.subs const scriptSubscriptionValidationCheck = isValidWsSubscription(subscription); if (scriptSubscriptionValidationCheck !== true) { // isValidWsSubscription returns string error msg if the sub is invalid throw new Error(scriptSubscriptionValidationCheck as string); } this.subs.scripts.push(subscription as WsSubScriptClient); if (this.ws?.readyState === WebSocket.OPEN) { this._subUnsubScript(false, subscription); } } /** Unsubscribe from the given script type and payload. */ public unsubscribeFromScript(type: ScriptType_InNode, payload: string) { // Build sub according to chronik expected type const subscription: WsSubScriptClient = { scriptType: type, payload, }; // Find the requested unsub script and remove it const unsubIndex = this.subs.scripts.findIndex( sub => sub.scriptType === type && sub.payload === payload, ); if (unsubIndex === -1) { // If we cannot find this subscription in this.subs, throw an error // We do not want an app developer thinking they have unsubscribed from something throw new Error(`No existing sub at ${type}, ${payload}`); } // Remove the requested subscription from this.subs this.subs.scripts.splice(unsubIndex, 1); if (this.ws?.readyState === WebSocket.OPEN) { this._subUnsubScript(true, subscription); } } /** * Subscribe to an address * Method can be used for p2pkh or p2sh addresses */ public subscribeToAddress(address: string) { // Get type and hash const { type, hash } = cashaddr.decode(address, true); // Subscribe to script this.subscribeToScript(type as 'p2pkh' | 'p2sh', hash as string); } /** Unsubscribe from the given address */ public unsubscribeFromAddress(address: string) { // Get type and hash const { type, hash } = cashaddr.decode(address, true); // Unsubscribe from script this.unsubscribeFromScript(type as 'p2pkh' | 'p2sh', hash as string); } /** * Close the WebSocket connection and prevent any future reconnection * attempts. */ public close() { this.manuallyClosed = true; this.ws?.close(); } private _subUnsubBlocks(isUnsub: boolean) { // Blocks subscription is empty object const BLOCKS_SUBSCRIPTION: proto.WsSubBlocks = {}; const encodedSubscription = proto.WsSub.encode({ isUnsub, blocks: BLOCKS_SUBSCRIPTION, }).finish(); if (this.ws === undefined) { throw new Error('Invalid state; _ws is undefined'); } this.ws.send(encodedSubscription); } private _subUnsubScript(isUnsub: boolean, subscription: WsSubScriptClient) { // If this subscription is to an address, leave the 'blocks' key undefined const encodedSubscription = proto.WsSub.encode({ isUnsub, script: { scriptType: (subscription as WsSubScriptClient).scriptType, payload: fromHex((subscription as WsSubScriptClient).payload), }, }).finish(); if (this.ws === undefined) { throw new Error('Invalid state; _ws is undefined'); } this.ws.send(encodedSubscription); } public async handleMsg(wsMsg: MessageEvent) { if (typeof this.onMessage === 'undefined') { return; } const data = typeof window === 'undefined' ? // NodeJS (wsMsg.data as Uint8Array) : // Browser new Uint8Array(await (wsMsg.data as Blob).arrayBuffer()); const msg = proto.WsMsg.decode(data); if (typeof msg.error !== 'undefined') { this.onMessage({ type: 'Error', ...msg.error }); } else if (typeof msg.block !== 'undefined') { this.onMessage({ type: 'Block', msgType: convertToBlockMsgType(msg.block.msgType), blockHash: toHexRev(msg.block.blockHash), blockHeight: msg.block.blockHeight, }); } else if (typeof msg.tx !== 'undefined') { this.onMessage({ type: 'Tx', msgType: convertToTxMsgType(msg.tx.msgType), txid: toHexRev(msg.tx.txid), }); } else { console.log('Silently ignored unknown Chronik message:', msg); } } } function convertToBlockchainInfo( blockchainInfo: proto.BlockchainInfo, ): BlockchainInfo { return { tipHash: toHexRev(blockchainInfo.tipHash), tipHeight: blockchainInfo.tipHeight, }; } function convertToChronikInfo(chronikInfo: proto.ChronikInfo): ChronikInfo { if (chronikInfo.version === undefined) { throw new Error('chronikInfo has no version'); } return { version: chronikInfo.version.length !== 0 ? chronikInfo.version : '', }; } function convertToBlock(block: proto.Block): Block_InNode { if (block.blockInfo === undefined) { throw new Error('Block has no blockInfo'); } return { blockInfo: convertToBlockInfo(block.blockInfo), }; } function convertToTxHistoryPage( blockTxs: proto.TxHistoryPage, ): TxHistoryPage_InNode { const { txs, numPages, numTxs } = blockTxs; const convertedTxs = txs.map(convertToTx); return { txs: convertedTxs, numPages, numTxs, }; } function convertToBlockInfo(block: proto.BlockInfo): BlockInfo_InNode { return { ...block, hash: toHexRev(block.hash), prevHash: toHexRev(block.prevHash), timestamp: parseInt(block.timestamp), blockSize: parseInt(block.blockSize), numTxs: parseInt(block.numTxs), numInputs: parseInt(block.numInputs), numOutputs: parseInt(block.numOutputs), sumInputSats: parseInt(block.sumInputSats), sumCoinbaseOutputSats: parseInt(block.sumCoinbaseOutputSats), sumNormalOutputSats: parseInt(block.sumNormalOutputSats), sumBurnedSats: parseInt(block.sumBurnedSats), }; } function convertToTx(tx: proto.Tx): Tx_InNode { const convertedTx: Tx_InNode = { txid: toHexRev(tx.txid), version: tx.version, inputs: tx.inputs.map(convertToTxInput), outputs: tx.outputs.map(convertToTxOutput), lockTime: tx.lockTime, timeFirstSeen: parseInt(tx.timeFirstSeen), size: tx.size, isCoinbase: tx.isCoinbase, tokenEntries: tx.tokenEntries.map(convertToTokenEntry), tokenFailedParsings: tx.tokenFailedParsings.map( convertToTokenFailedParsing, ), tokenStatus: convertToTokenStatus(tx.tokenStatus), }; if (typeof tx.block !== 'undefined') { // Only include block if the tx is in a block convertedTx.block = convertToBlockMeta(tx.block); } return convertedTx; } function convertToTxInput(input: proto.TxInput): TxInput_InNode { if (input.prevOut === undefined) { throw new Error('Invalid proto, no prevOut'); } const txInput: TxInput_InNode = { prevOut: { txid: toHexRev(input.prevOut.txid), outIdx: input.prevOut.outIdx, }, inputScript: toHex(input.inputScript), value: parseInt(input.value), sequenceNo: input.sequenceNo, }; if (typeof input.token !== 'undefined') { // We only return a token key if we have token data for this input txInput.token = convertToTokenInNode(input.token); } if ( typeof input.outputScript !== 'undefined' && input.outputScript.length > 0 ) { // Coinbase tx inputs do not have an outputScript txInput.outputScript = toHex(input.outputScript); } return txInput; } function convertToTxOutput(output: proto.TxOutput): TxOutput_InNode { const txOutput: TxOutput_InNode = { value: parseInt(output.value), outputScript: toHex(output.outputScript), }; if (typeof output.token !== 'undefined') { // We only return a token key if we have token data for this input txOutput.token = convertToTokenInNode(output.token); } if (typeof output.spentBy !== 'undefined') { // We only return a spentBy key if this output has been spent txOutput.spentBy = { txid: toHexRev(output.spentBy.txid), outIdx: output.spentBy.inputIdx, }; } return txOutput; } function convertToBlockMeta(block: proto.BlockMetadata): BlockMetadata_InNode { return { height: block.height, hash: toHexRev(block.hash), timestamp: parseInt(block.timestamp), }; } function convertToRawTx(rawTx: proto.RawTx): RawTx { return { rawTx: toHex(rawTx.rawTx), }; } function convertToScriptUtxo(utxo: proto.ScriptUtxo): ScriptUtxo_InNode { if (utxo.outpoint === undefined) { throw new Error('UTXO outpoint is undefined'); } const utxoInNode: ScriptUtxo_InNode = { outpoint: { txid: toHexRev(utxo.outpoint.txid), outIdx: utxo.outpoint.outIdx, }, blockHeight: utxo.blockHeight, isCoinbase: utxo.isCoinbase, value: parseInt(utxo.value), isFinal: utxo.isFinal, }; if (typeof utxo.token !== 'undefined') { // We only return a token key if we have token data for this input utxoInNode.token = convertToTokenInNode(utxo.token); } return utxoInNode; } function convertToUtxo(utxo: proto.Utxo): Utxo_InNode { if (utxo.outpoint === undefined) { throw new Error('UTXO outpoint is undefined'); } const utxoInNode: Utxo_InNode = { outpoint: { txid: toHexRev(utxo.outpoint.txid), outIdx: utxo.outpoint.outIdx, }, blockHeight: utxo.blockHeight, isCoinbase: utxo.isCoinbase, script: toHex(utxo.script), value: parseInt(utxo.value), isFinal: utxo.isFinal, }; if (typeof utxo.token !== 'undefined') { // We only return a token key if we have token data for this input utxoInNode.token = convertToTokenInNode(utxo.token); } return utxoInNode; } function convertToTokenEntry(tokenEntry: proto.TokenEntry): TokenEntry { if (typeof tokenEntry.tokenType === 'undefined') { // Not expected to ever happen throw new Error( `chronik returned undefined tokenEntry.tokenType for tokenId "${tokenEntry.tokenId}"`, ); } const returnObj: TokenEntry = { tokenId: tokenEntry.tokenId, tokenType: convertToTokenType(tokenEntry.tokenType), txType: convertToTokenTxType(tokenEntry.txType), isInvalid: tokenEntry.isInvalid, burnSummary: tokenEntry.burnSummary, failedColorings: tokenEntry.failedColorings, actualBurnAmount: tokenEntry.actualBurnAmount, intentionalBurn: tokenEntry.intentionalBurn, burnsMintBatons: tokenEntry.burnsMintBatons, }; if (tokenEntry.groupTokenId !== '') { // Only include groupTokenId if it is not empty returnObj.groupTokenId = tokenEntry.groupTokenId; } return returnObj; } function convertToTokenFailedParsing( tokenFailedParsing: proto.TokenFailedParsing, ): TokenFailedParsing { return { pushdataIdx: tokenFailedParsing.pushdataIdx, bytes: toHex(tokenFailedParsing.bytes), error: tokenFailedParsing.error, }; } function convertToTokenType(tokenType: proto.TokenType): TokenType { if (typeof tokenType.alp !== 'undefined') { return { protocol: 'ALP', type: convertToAlpTokenType(tokenType.alp), number: tokenType.alp, }; } if (typeof tokenType.slp !== 'undefined') { return { protocol: 'SLP', type: convertToSlpTokenType(tokenType.slp), number: tokenType.slp, }; } // Should never happen throw new Error('chronik did not return a token protocol for this token'); } function convertToSlpTokenType( msgType: proto.SlpTokenType, ): SlpTokenType_InNode_Type { const slpTokenType = proto.slpTokenTypeToJSON(msgType); if (isSlpTokenType(slpTokenType)) { return slpTokenType; } return 'SLP_TOKEN_TYPE_UNKNOWN'; } function isSlpTokenType(msgType: any): msgType is SlpTokenType_InNode_Type { return SLP_TOKEN_TYPES.includes(msgType); } function convertToAlpTokenType(msgType: proto.AlpTokenType): AlpTokenType_Type { const alpTokenType = proto.alpTokenTypeToJSON(msgType); if (isAlpTokenType(alpTokenType)) { return alpTokenType; } return 'ALP_TOKEN_TYPE_UNKNOWN'; } function isAlpTokenType(msgType: any): msgType is AlpTokenType_Type { return ALP_TOKEN_TYPES.includes(msgType); } function convertToTokenStatus(msgType: proto.TokenStatus): TokenStatus { const tokenStatus = proto.tokenStatusToJSON(msgType); if (isTokenStatus(tokenStatus)) { return tokenStatus; } return 'TOKEN_STATUS_UNKNOWN'; } function isTokenStatus(msgType: any): msgType is TokenStatus { return TOKEN_STATUS_TYPES.includes(msgType); } function convertToTokenTxType(msgType: proto.TokenTxType): TokenTxType { const tokenTxType = proto.tokenTxTypeToJSON(msgType); if (isTokenTxType(tokenTxType)) { return tokenTxType; } return 'UNKNOWN'; } function isTokenTxType(msgType: any): msgType is TokenTxType { return TOKEN_TX_TYPE_TYPES.includes(msgType); } function convertToTokenInNode(token: proto.Token): Token_InNode { if (typeof token.tokenType === 'undefined') { // Not expected to ever happen throw new Error( `chronik returned undefined token.tokenType for tokenId "${token.tokenId}"`, ); } const tokenInNode: Token_InNode = { tokenId: token.tokenId, tokenType: convertToTokenType(token.tokenType), amount: token.amount, isMintBaton: token.isMintBaton, }; // We do not bother including entryIdx for utxos, where it is always -1 if (token.entryIdx !== -1) { tokenInNode.entryIdx = token.entryIdx; } return tokenInNode; } function convertToBlockMsgType(msgType: proto.BlockMsgType): BlockMsgType { const blockMsgType = proto.blockMsgTypeToJSON(msgType); if (isBlockMsgType(blockMsgType)) { return blockMsgType; } return 'UNRECOGNIZED'; } function isBlockMsgType(msgType: any): msgType is BlockMsgType { return BLK_MSG_TYPES.includes(msgType); } function convertToTxMsgType(msgType: proto.TxMsgType): TxMsgType { const txMsgType = proto.txMsgTypeToJSON(msgType); if (isTxMsgType(txMsgType)) { return txMsgType; } return 'UNRECOGNIZED'; } function convertToTokenInfo(tokenInfo: proto.TokenInfo): TokenInfo { if (typeof tokenInfo.tokenType === 'undefined') { // Not expected to ever happen throw new Error( `chronik returned undefined tokenInfo.tokenType for tokenId "${tokenInfo.tokenId}"`, ); } if (typeof tokenInfo.genesisInfo === 'undefined') { // Not expected to ever happen throw new Error( `chronik returned undefined tokenInfo.genesisInfo for tokenId "${tokenInfo.tokenId}"`, ); } // We use tokenType to get the correct shape of genesisInfo const tokenType = convertToTokenType(tokenInfo.tokenType); const returnedTokenInfo: TokenInfo = { tokenId: tokenInfo.tokenId, tokenType, - timeFirstSeen: tokenInfo.timeFirstSeen, + timeFirstSeen: parseInt(tokenInfo.timeFirstSeen), genesisInfo: convertToGenesisInfo(tokenInfo.genesisInfo, tokenType), }; if (typeof tokenInfo.block !== 'undefined') { // Only include block if the tx is in a block returnedTokenInfo.block = convertToBlockMeta(tokenInfo.block); } return returnedTokenInfo; } function convertToGenesisInfo( genesisInfo: proto.GenesisInfo, tokenType: TokenType, ): GenesisInfo { const decoder = new TextDecoder(); const returnedGenesisInfo: GenesisInfo = { tokenTicker: decoder.decode(genesisInfo.tokenTicker), tokenName: decoder.decode(genesisInfo.tokenName), url: decoder.decode(genesisInfo.url), decimals: genesisInfo.decimals, }; // Add ALP fields for ALP types only if (tokenType.protocol === 'ALP') { returnedGenesisInfo.data = genesisInfo.data; returnedGenesisInfo.authPubkey = toHex(genesisInfo.authPubkey); } // Add mintVaultHash for SLP Mint Vault only if (tokenType.type === 'SLP_TOKEN_TYPE_MINT_VAULT') { returnedGenesisInfo.mintVaultScripthash = toHex( genesisInfo.mintVaultScripthash, ); } // Add url for SLP only if (tokenType.protocol === 'SLP') { returnedGenesisInfo.hash = toHex(genesisInfo.hash); } return returnedGenesisInfo; } function isTxMsgType(msgType: any): msgType is TxMsgType { return TX_MSG_TYPES.includes(msgType); } /** Info about connected chronik server */ export interface ChronikInfo { version: string; } /** BlockInfo interface for in-node chronik */ export interface BlockInfo_InNode { /** Block hash of the block, in 'human-readable' (big-endian) hex encoding. */ hash: string; /** Block hash of the prev block, in 'human-readable' (big-endian) hex encoding. */ prevHash: string; /** Height of the block; Genesis block has height 0. */ height: number; /** nBits field of the block, encodes the target compactly. */ nBits: number; /** * Timestamp of the block. Filled in by the miner, * so might not be 100 % precise. */ timestamp: number; /** Is this block avalanche finalized? */ isFinal: boolean; /** Block size of this block in bytes (including headers etc.). */ blockSize: number; /** Number of txs in this block. */ numTxs: number; /** Total number of tx inputs in block (including coinbase). */ numInputs: number; /** Total number of tx output in block (including coinbase). */ numOutputs: number; /** Total number of satoshis spent by tx inputs. */ sumInputSats: number; /** Total block reward for this block. */ sumCoinbaseOutputSats: number; /** Total number of satoshis in non-coinbase tx outputs. */ sumNormalOutputSats: number; /** Total number of satoshis burned using OP_RETURN. */ sumBurnedSats: number; } /** Block interface for in-node chronik */ export interface Block_InNode { /** Contains the blockInfo object defined above */ blockInfo: BlockInfo_InNode; } /** A page of in-node chronik tx history */ export interface TxHistoryPage_InNode { /** Txs of the page */ txs: Tx_InNode[]; /** How many pages there are total */ numPages: number; /** How many txs there are total */ numTxs: number; } /** The hex bytes of a raw tx */ export interface RawTx { rawTx: string; } /** A transaction on the blockchain or in the mempool. */ export interface Tx_InNode { /** Transaction ID. */ txid: string; /** `version` field of the transaction. */ version: number; /** Inputs of this transaction. */ inputs: TxInput_InNode[]; /** Outputs of this transaction. */ outputs: TxOutput_InNode[]; /** `locktime` field of the transaction, tx is not valid before this time. */ lockTime: number; /** Block data for this tx, if it is in a block. */ block?: BlockMetadata_InNode; /** * UNIX timestamp when this tx has first been seen in the mempool. * 0 if unknown -> make sure to check. */ timeFirstSeen: number; /** Serialized size of the tx. */ size: number; /** Whether this tx is a coinbase tx. */ isCoinbase: boolean; /** Tokens involved in this txs */ tokenEntries: TokenEntry[]; /** Failed parsing attempts of this tx */ tokenFailedParsings: TokenFailedParsing[]; /** * Token status, i.e. whether this tx has any tokens or unintentional token burns * or something unexpected, like failed parsings etc. */ tokenStatus: TokenStatus; } /** Input of a tx, spends an output of a previous tx. */ export interface TxInput_InNode { /** Points to an output spent by this input. */ prevOut: OutPoint; /** * Script unlocking the output, in hex encoding. * Aka. `scriptSig` in bitcoind parlance. */ inputScript: string; /** * Script of the output, in hex encoding. * Aka. `scriptPubKey` in bitcoind parlance. * Not present for coinbase txs */ outputScript?: string; /** Value of the output spent by this input, in satoshis. */ value: number; /** `sequence` field of the input; can be used for relative time locking. */ sequenceNo: number; /** Token value attached to this input */ token?: Token_InNode; } /** Output of a tx, creates new UTXOs. */ export interface TxOutput_InNode { /** Value of the output, in satoshis. */ value: number; /** * Script of this output, locking the coins. * Aka. `scriptPubKey` in bitcoind parlance. */ outputScript: string; /** * Transaction & input index spending this output, if * spent. */ spentBy?: OutPoint; /** Token value attached to this output */ token?: Token_InNode; } /** Metadata of a block, used in transaction data. */ export interface BlockMetadata_InNode { /** Height of the block. */ height: number; /** Hash of the block. */ hash: string; /** * Timestamp of the block; useful if `timeFirstSeen` of a transaction is * unknown. */ timestamp: number; } /** Token involved in a transaction */ interface TokenEntry { /** * Hex token_id (in big-endian, like usually displayed to users) of the token. * This is not `bytes` because SLP and ALP use different endiannes, so to avoid * this we use hex, which conventionally implies big-endian in a bitcoin context. */ tokenId: string; /** Token type of the token */ tokenType: TokenType; /** Tx type of the token; NONE if there's no section that introduced it (e.g. in an accidental burn) */ txType: TokenTxType; /** * For NFT1 Child tokens: group ID * Unset if the token is not an NFT1 Child token */ groupTokenId?: string; /** Whether the validation rules have been violated for this section */ isInvalid: boolean; /** Human-readable error message of why this entry burned tokens */ burnSummary: string; /** Human-readable error messages of why colorings failed */ failedColorings: TokenFailedColoring[]; /** * Number of actually burned tokens (as decimal integer string, e.g. "2000"). * This is because burns can exceed the 64-bit range of values and protobuf doesn't have a nice type to encode this. */ actualBurnAmount: string; /** Burn amount the user explicitly opted into (as decimal integer string) */ intentionalBurn: string; /** Whether any mint batons have been burned of this token */ burnsMintBatons: boolean; } /** * SLP/ALP token type */ export type TokenType = SlpTokenType_InNode | AlpTokenType; export interface SlpTokenType_InNode { protocol: 'SLP'; type: SlpTokenType_InNode_Type; number: number; } export interface AlpTokenType { protocol: 'ALP'; type: AlpTokenType_Type; number: number; } /** Possible ALP token types returned by chronik */ export type AlpTokenType_Type = | 'ALP_TOKEN_TYPE_STANDARD' | 'ALP_TOKEN_TYPE_UNKNOWN'; export const ALP_TOKEN_TYPES: AlpTokenType_Type[] = [ 'ALP_TOKEN_TYPE_STANDARD', 'ALP_TOKEN_TYPE_UNKNOWN', ]; /** Possible SLP token types returned by chronik */ export type SlpTokenType_InNode_Type = | 'SLP_TOKEN_TYPE_FUNGIBLE' | 'SLP_TOKEN_TYPE_MINT_VAULT' | 'SLP_TOKEN_TYPE_NFT1_GROUP' | 'SLP_TOKEN_TYPE_NFT1_CHILD' | 'SLP_TOKEN_TYPE_UNKNOWN'; const SLP_TOKEN_TYPES: SlpTokenType_InNode_Type[] = [ 'SLP_TOKEN_TYPE_FUNGIBLE', 'SLP_TOKEN_TYPE_MINT_VAULT', 'SLP_TOKEN_TYPE_NFT1_GROUP', 'SLP_TOKEN_TYPE_NFT1_CHILD', 'SLP_TOKEN_TYPE_UNKNOWN', ]; /** * TokenStatus * TOKEN_STATUS_NON_TOKEN - Tx involves no tokens whatsover, i.e. neither any burns nor any failed * parsing/coloring or any tokens being created / moved. * TOKEN_STATUS_NORMAL - Tx involves tokens but no unintentional burns or failed parsings/colorings * TOKEN_STATUS_NOT_NORMAL - Tx involves tokens but contains unintentional burns or failed parsings/colorings * TOKEN_STATUS_UNKNOWN - Token tx of unknown status */ export type TokenStatus = | 'TOKEN_STATUS_NON_TOKEN' | 'TOKEN_STATUS_NORMAL' | 'TOKEN_STATUS_NOT_NORMAL' | 'TOKEN_STATUS_UNKNOWN'; const TOKEN_STATUS_TYPES: TokenStatus[] = [ 'TOKEN_STATUS_NON_TOKEN', 'TOKEN_STATUS_NORMAL', 'TOKEN_STATUS_NOT_NORMAL', 'TOKEN_STATUS_UNKNOWN', ]; /** SLP/ALP tx type */ export type TokenTxType = /** NONE - No tx type, e.g. when input tokens are burned */ | 'NONE' /** UNKNOWN - Unknown tx type, i.e. for unknown token types */ | 'UNKNOWN' /** GENESIS - GENESIS tx */ | 'GENESIS' /** SEND - SEND tx */ | 'SEND' /** MINT - MINT tx */ | 'MINT' /** BURN - BURN tx */ | 'BURN'; const TOKEN_TX_TYPE_TYPES: TokenTxType[] = [ 'NONE', 'UNKNOWN', 'GENESIS', 'SEND', 'MINT', 'BURN', ]; /** * A report of a failed coloring attempt of SLP/ALP. * This should always indicate something went wrong when building the tx. */ export interface TokenFailedColoring { /** For ALP, the index of the pushdata in the OP_RETURN that failed parsing. */ pushdataIdx: number; /** Human-readable message of what went wrong */ error: string; } /** * TokenFailedParsing * A report of a failed parsing attempt of SLP/ALP. * This should always indicate something went wrong when building the tx. */ export interface TokenFailedParsing { /** * For ALP, the index of the pushdata in the OP_RETURN that failed parsing. * -1 if the whole OP_RETURN failed, e.g. for SLP or eMPP */ pushdataIdx: number; /** The bytes that failed parsing, useful for debugging */ bytes: string; /** Human-readable message of what went wrong */ error: string; } /** Group of UTXOs by output script. */ export interface ScriptUtxos_InNode { /** Output script in hex. */ outputScript: string; /** UTXOs of the output script. */ utxos: ScriptUtxo_InNode[]; } /** An unspent transaction output (aka. UTXO, aka. "Coin") of a script. */ export interface ScriptUtxo_InNode { /** Outpoint of the UTXO. */ outpoint: OutPoint; /** Which block this UTXO is in, or -1 if in the mempool. */ blockHeight: number; /** Whether this UTXO is a coinbase UTXO * (make sure it's buried 100 blocks before spending!) */ isCoinbase: boolean; /** Value of the UTXO in satoshis. */ value: number; /** Is this utxo avalanche finalized */ isFinal: boolean; /** Token value attached to this utxo */ token?: Token_InNode; } /** * An unspent transaction output (aka. UTXO, aka. "Coin") with script attached * Useful when getting utxos by something other than script, e.g. tokenId */ export interface Utxo_InNode { /** Outpoint of the UTXO. */ outpoint: OutPoint; /** Which block this UTXO is in, or -1 if in the mempool. */ blockHeight: number; /** Whether this UTXO is a coinbase UTXO * (make sure it's buried 100 blocks before spending!) */ isCoinbase: boolean; /** Value of the UTXO in satoshis. */ value: number; /** Bytecode of the script of the output */ script: string; /** Is this utxo avalanche finalized */ isFinal: boolean; /** Token value attached to this utxo */ token?: Token_InNode; } /** Token coloring an input or output */ export interface Token_InNode { /** Hex token_id of the token, see `TokenInfo` for details */ tokenId: string; /** Token type of the token */ tokenType: TokenType; /** * Index into `token_entries` for `Tx` * chronik returns -1 for UTXOs, chronik-client * passes no entryIdx key for UTXOS */ entryIdx?: number; /** Base token amount of the input/output */ amount: string; /** Whether the token is a mint baton */ isMintBaton: boolean; } /** * Script type queried in the `script` method. * - `other`: Script type not covered by the standard script types; payload is * the raw hex. * - `p2pk`: Pay-to-Public-Key (` OP_CHECKSIG`), payload is the hex of the * pubkey (compressed (33 bytes) or uncompressed (65 bytes)). * - `p2pkh`: Pay-to-Public-Key-Hash * (`OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG`). * Payload is the 20 byte public key hash. * - `p2sh`: Pay-to-Script-Hash (`OP_HASH160 OP_EQUAL`). * Payload is the 20 byte script hash. */ export type ScriptType_InNode = 'other' | 'p2pk' | 'p2pkh' | 'p2sh'; /** Message returned from the WebSocket, translated to be more human-readable for client */ export type WsMsgClient = Error_InNode | MsgBlockClient | MsgTxClient; /** Block got connected, disconnected, finalized, etc.*/ export interface MsgBlockClient { type: 'Block'; /** What happened to the block */ msgType: BlockMsgType; /** Hash of the block (human-readable big-endian) */ blockHash: string; /** Height of the block */ blockHeight: number; } /** Block message types that can come from chronik */ export type BlockMsgType = | 'BLK_CONNECTED' | 'BLK_DISCONNECTED' | 'BLK_FINALIZED' | 'UNRECOGNIZED'; const BLK_MSG_TYPES: BlockMsgType[] = [ 'BLK_CONNECTED', 'BLK_DISCONNECTED', 'BLK_FINALIZED', 'UNRECOGNIZED', ]; /** Tx got added to/removed from mempool, or confirmed in a block, etc.*/ export interface MsgTxClient { type: 'Tx'; /** What happened to the tx */ msgType: TxMsgType; /** Txid of the tx (human-readable big-endian) */ txid: string; } /** Tx message types that can come from chronik */ export type TxMsgType = | 'TX_ADDED_TO_MEMPOOL' | 'TX_REMOVED_FROM_MEMPOOL' | 'TX_CONFIRMED' | 'TX_FINALIZED' | 'UNRECOGNIZED'; const TX_MSG_TYPES: TxMsgType[] = [ 'TX_ADDED_TO_MEMPOOL', 'TX_REMOVED_FROM_MEMPOOL', 'TX_CONFIRMED', 'TX_FINALIZED', 'UNRECOGNIZED', ]; /* The script type and its associated payload for a chronik-client subscribeToScript subscription */ export interface WsSubScriptClient { /** Script type to subscribe to ("p2pkh", "p2sh", "p2pk", "other"). */ scriptType: ScriptType_InNode; /** * Payload for the given script type: * - 20-byte hash for "p2pkh" and "p2sh" * - 33-byte or 65-byte pubkey for "p2pk" * - Serialized script for "other" */ payload: string; } export interface Error_InNode { type: 'Error'; msg: string; } /** List of UTXOs */ export interface TokenIdUtxos { /** TokenId used to fetch these utxos */ tokenId: string; /** UTXOs */ utxos: Utxo_InNode[]; } /** Info about a token */ export interface TokenInfo { /** * Hex token_id (in big-endian, like usually displayed to users) of the token. * This is not `bytes` because SLP and ALP use different endiannnes, * so to avoid this we use hex, which conventionally implies big-endian in a bitcoin context. */ tokenId: string; /** Token type of the token */ tokenType: TokenType; /** Info found in the token's GENESIS tx */ genesisInfo: GenesisInfo; /** Block of the GENESIS tx, if it's mined already */ block?: BlockMetadata_InNode; /** Time the GENESIS tx has first been seen by the indexer */ - timeFirstSeen: string; + timeFirstSeen: number; } /** Genesis info found in GENESIS txs of tokens */ export interface GenesisInfo { /** token_ticker of the token */ tokenTicker: string; /** token_name of the token */ tokenName: string; /** URL of the token */ url: string; /** token_document_hash of the token (only on SLP) */ hash?: string; /** mint_vault_scripthash (only on SLP V2 Mint Vault) */ mintVaultScripthash?: string; /** Arbitray payload data of the token (only on ALP) */ data?: Uint8Array; /** auth_pubkey of the token (only on ALP) */ authPubkey?: string; /** decimals of the token, i.e. how many decimal places the token should be displayed with. */ decimals: number; } interface WsSubscriptions { /** Subscriptions to scripts */ scripts: WsSubScriptClient[]; /** Subscriptions to tokens by tokenId */ tokens: string[]; /** Subscription to blocks */ blocks: boolean; } diff --git a/modules/chronik-client/test/integration/token_alp.ts b/modules/chronik-client/test/integration/token_alp.ts index c62f3b568..42c814647 100644 --- a/modules/chronik-client/test/integration/token_alp.ts +++ b/modules/chronik-client/test/integration/token_alp.ts @@ -1,1423 +1,1423 @@ // Copyright (c) 2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. import * as chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { ChildProcess } from 'node:child_process'; import { EventEmitter, once } from 'node:events'; import path from 'path'; import { ChronikClientNode, TokenInfo, Token_InNode, TxHistoryPage_InNode, Tx_InNode, } from '../../index'; import initializeTestRunner, { cleanupMochaRegtest, setMochaTimeout, TestInfo, } from '../setup/testRunner'; const expect = chai.expect; chai.use(chaiAsPromised); describe('Get blocktxs, txs, and history for ALP token txs', () => { // Define variables used in scope of this test const testName = path.basename(__filename); let testRunner: ChildProcess; let get_alp_genesis_txid: Promise; let get_alp_mint_txid: Promise; let get_alp_send_txid: Promise; let get_alp_genesis2_txid: Promise; let get_alp_multi_txid: Promise; let get_alp_mega_txid: Promise; let get_alp_mint_two_txid: Promise; let get_alp_nonutf8_genesis_txid: Promise; const statusEvent = new EventEmitter(); let get_test_info: Promise; let chronikUrl: string[]; let setupScriptTermination: ReturnType; before(async function () { // Initialize testRunner before mocha tests testRunner = initializeTestRunner(testName, statusEvent); // Handle IPC messages from the setup script testRunner.on('message', function (message: any) { if (message && message.test_info) { get_test_info = new Promise(resolve => { resolve(message.test_info); }); } if (message && message.alp_genesis_txid) { get_alp_genesis_txid = new Promise(resolve => { resolve(message.alp_genesis_txid); }); } if (message && message.alp_mint_txid) { get_alp_mint_txid = new Promise(resolve => { resolve(message.alp_mint_txid); }); } if (message && message.alp_send_txid) { get_alp_send_txid = new Promise(resolve => { resolve(message.alp_send_txid); }); } if (message && message.alp_genesis2_txid) { get_alp_genesis2_txid = new Promise(resolve => { resolve(message.alp_genesis2_txid); }); } if (message && message.alp_multi_txid) { get_alp_multi_txid = new Promise(resolve => { resolve(message.alp_multi_txid); }); } if (message && message.alp_mega_txid) { get_alp_mega_txid = new Promise(resolve => { resolve(message.alp_mega_txid); }); } if (message && message.alp_mint_two_txid) { get_alp_mint_two_txid = new Promise(resolve => { resolve(message.alp_mint_two_txid); }); } if (message && message.alp_nonutf8_genesis_txid) { get_alp_nonutf8_genesis_txid = new Promise(resolve => { resolve(message.alp_nonutf8_genesis_txid); }); } if (message && message.status) { statusEvent.emit(message.status); } }); await once(statusEvent, 'ready'); const testInfo = await get_test_info; chronikUrl = [testInfo.chronik]; console.log(`chronikUrl set to ${JSON.stringify(chronikUrl)}`); setupScriptTermination = setMochaTimeout( this, testName, testInfo, testRunner, ); testRunner.send('next'); }); after(async () => { await cleanupMochaRegtest( testName, testRunner, setupScriptTermination, statusEvent, ); }); beforeEach(async () => { await once(statusEvent, 'ready'); }); afterEach(() => { testRunner.send('next'); }); const CHAIN_INIT_HEIGHT = 100; const SCRIPTSIG_OP_TRUE_PAYLOAD = 'da1745e9b549bd0bfa1a569971c77eba30cd5a4b'; const BASE_TX_INPUT = { inputScript: '0151', outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', value: 5000, sequenceNo: 0, }; const BASE_TX_OUTPUT = { value: 546, outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', }; const BASE_TX_TOKEN_INFO_ALP = { tokenType: { protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', number: 0, }, entryIdx: 0, amount: '0', isMintBaton: false, }; const BASE_TOKEN_ENTRY = { // omit tokenId, txType, and tokenType as these should always be tested isInvalid: false, burnSummary: '', failedColorings: [], actualBurnAmount: '0', intentionalBurn: '0', burnsMintBatons: false, }; let alpGenesisTxid = ''; let alpMintTxid = ''; let alpSendTxid = ''; let alpNextGenesisTxid = ''; let alpMultiTxid = ''; let alpMegaTxid = ''; let alpMintTwoTxid = ''; let alpNonUtf8GenesisTxid = ''; let alpGenesis: Tx_InNode; let alpMint: Tx_InNode; let alpSend: Tx_InNode; let alpNextGenesis: Tx_InNode; let alpMulti: Tx_InNode; let alpMega: Tx_InNode; let alpMintTwo: Tx_InNode; let alpSendTwo: Tx_InNode; const alpTokenInfo: TokenInfo = { tokenId: '1111111111111111111111111111111111111111111111111111111111111111', - timeFirstSeen: '1300000000', + timeFirstSeen: 1300000000, tokenType: { protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', number: 0, }, // We do not get hash in GenesisInfo for ALP // We get data and authPubkey keys in GenesisInfo for ALP // We do not get mintVaultScripthash for non-SLP_MINT_VAULT genesisInfo: { tokenTicker: 'TEST', tokenName: 'Test Token', url: 'http://example.com', data: new Uint8Array([84, 111, 107, 101, 110, 32, 68, 97, 116, 97]), authPubkey: '546f6b656e205075626b6579', decimals: 4, }, }; let confirmedTxsForAlpGenesisTxid: TxHistoryPage_InNode; it('Gets an ALP genesis tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); alpGenesisTxid = await get_alp_genesis_txid; // We can get an alp genesis tx from the mempool alpGenesis = await chronik.tx(alpGenesisTxid); // We get expected inputs including expected Token data // We get no token info in tx inputs expect(alpGenesis.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: '3fa435fca55edf447ef7539ecba141a6585fa71ac4062cdcc61f1235c40f4613', outIdx: 0, }, value: 5000000000, }, ]); // We get expected outputs including expected Token data const expectedOutputs = [ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a504c63534c5032000747454e4553495304544553540a5465737420546f6b656e12687474703a2f2f6578616d706c652e636f6d0a546f6b656e20446174610c546f6b656e205075626b657904040a00000000001400000000001e000000000000000000000002', }, { ...BASE_TX_OUTPUT, value: 10000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '10', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '20', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '30', }, }, { ...BASE_TX_OUTPUT, value: 4999900000, }, { ...BASE_TX_OUTPUT, value: 5000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, isMintBaton: true, }, }, ]; expect(alpGenesis.outputs).to.deep.equal(expectedOutputs); // We get a Entries of expected shape, with tokenId the txid for a genesis tx expect(alpGenesis.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: alpGenesisTxid, txType: 'GENESIS', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, ]); // The token did not fail parsings expect(alpGenesis.tokenFailedParsings).to.deep.equal([]); // Normal status expect(alpGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); // We can get the same token info from calling chronik.tokenId.utxos() on this genesis txid const utxosByTokenId = await chronik.tokenId(alpGenesisTxid).utxos(); // We get the calling tokenId returned expect(utxosByTokenId.tokenId).to.eql(alpGenesisTxid); // Utxos returned by token id include Token object matching the outputs, except they have no entryIdx // Get only the outputs that are token utxos for alpGenesisTxid const outputsWithTokenKey = expectedOutputs.filter( output => 'token' in output, ); const utxoTokenKeysFromOutputs: Token_InNode[] = []; for (const output of outputsWithTokenKey) { if ('token' in output) { const { token } = output; // Remove the entryIdx key from these outputs, as we do not expect to see it in tokenId.utxos() output delete (token as Token_InNode).entryIdx; utxoTokenKeysFromOutputs.push(output.token as Token_InNode); } } // We have as many utxosByTokenId as we do outputs with token key expect(utxosByTokenId.utxos.length).to.eql( utxoTokenKeysFromOutputs.length, ); // They match and are in the same order for (let i = 0; i < utxosByTokenId.utxos.length; i += 1) { expect(utxosByTokenId.utxos[i].token).to.deep.equal( utxoTokenKeysFromOutputs[i], ); } // Utxos called by tokenId return expected script for (const utxo of utxosByTokenId.utxos) { expect(utxo.script).to.eql(`a914${SCRIPTSIG_OP_TRUE_PAYLOAD}87`); } // We get the same tx info for this tx from calling chronik.tokenId().unconfirmedTxs() const unconfirmedTxsForThisTokenId = await chronik .tokenId(alpGenesisTxid) .unconfirmedTxs(); expect(unconfirmedTxsForThisTokenId.txs.length).to.eql(1); expect(unconfirmedTxsForThisTokenId.txs[0]).to.deep.equal(alpGenesis); // We get nothing from confirmedTxs() as none are confirmed const confirmedTxsForThisTokenId = await chronik .tokenId(alpGenesisTxid) .confirmedTxs(); expect(confirmedTxsForThisTokenId.txs.length).to.eql(0); // History returns the output of confirmed + unconfirmed (in this case, just unconfirmed) const historyForThisTokenId = await chronik .tokenId(alpGenesisTxid) .history(); expect(historyForThisTokenId.txs.length).to.eql(1); expect(historyForThisTokenId.txs[0]).to.deep.equal(alpGenesis); // We can get token info of an alp token from the mempool const alpGenesisMempoolInfo = await chronik.token(alpGenesisTxid); expect(alpGenesisMempoolInfo).to.deep.equal({ ...alpTokenInfo, tokenId: alpGenesisTxid, }); // Invalid tokenId is rejected await expect(chronik.token('somestring')).to.be.rejectedWith( Error, `Failed getting /token/somestring (): 400: Not a txid: somestring`, ); // We get expected error for a txid that is not in the mempool await expect( chronik.token( '0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f', ), ).to.be.rejectedWith( Error, `Failed getting /token/0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f (): 404: Token 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f not found in the index`, ); }); it('Gets an ALP mint tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); // We can get an alp mint tx from the mempool alpMintTxid = await get_alp_mint_txid; alpMint = await chronik.tx(alpMintTxid); // We get expected inputs including expected Token data expect(alpMint.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: alpGenesisTxid, outIdx: 5, }, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '0', isMintBaton: true, }, }, ]); // We get expected outputs including expected Token data expect(alpMint.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a5038534c503200044d494e54e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb0205000000000000000000000001', }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '5', }, }, { ...BASE_TX_OUTPUT, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '0', isMintBaton: true, }, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(alpMint.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: alpGenesisTxid, txType: 'MINT', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, ]); // The token did not fail parsings expect(alpMint.tokenFailedParsings).to.deep.equal([]); // Normal status expect(alpMint.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); // Error is thrown for a txid that is in the mempool but is not a tokenId await expect(chronik.token(alpMintTxid)).to.be.rejectedWith( Error, `Failed getting /token/0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f (): 404: Token 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f not found in the index`, ); }); it('Gets an ALP send tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); // We can get an alp send tx from the mempool alpSendTxid = await get_alp_send_txid; alpSend = await chronik.tx(alpSendTxid); // We get expected inputs including expected Token data expect(alpSend.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: alpGenesisTxid, outIdx: 1, }, value: 10000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '10', }, }, { ...BASE_TX_INPUT, prevOut: { txid: '0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f', outIdx: 1, }, value: 546, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '5', }, }, ]); // We get expected outputs including expected Token data expect(alpSend.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a5037534c5032000453454e44e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb020300000000000c0000000000', }, { ...BASE_TX_OUTPUT, value: 5000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '3', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, amount: '12', }, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(alpSend.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: alpGenesisTxid, txType: 'SEND', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, ]); // The token did not fail parsings expect(alpSend.tokenFailedParsings).to.deep.equal([]); // Normal status expect(alpSend.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Gets another ALP genesis tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); // We can get another alp genesis tx from the mempool alpNextGenesisTxid = await get_alp_genesis2_txid; alpNextGenesis = await chronik.tx(alpNextGenesisTxid); // We get expected inputs including expected Token data expect(alpNextGenesis.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: alpGenesisTxid, outIdx: 4, }, value: 4999900000, }, ]); // We get expected outputs including expected Token data expect(alpNextGenesis.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a501b534c5032000747454e455349530000000000000164000000000002', }, { ...BASE_TX_OUTPUT, value: 5000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, amount: '100', }, }, { ...BASE_TX_OUTPUT, value: 5000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, value: 5000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, value: 4999800000, }, ]); // We get a Entries of expected shape, with tokenId the txid of this new genesis tx expect(alpNextGenesis.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: alpNextGenesisTxid, txType: 'GENESIS', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, ]); // The token did not fail parsings expect(alpNextGenesis.tokenFailedParsings).to.deep.equal([]); // Normal status expect(alpNextGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Gets an ALP genesis, mint, and send (also a burn) combo tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); // We can get an ALP GENESIS + MINT + SEND all in one tx from the mempool alpMultiTxid = await get_alp_multi_txid; alpMulti = await chronik.tx(alpMultiTxid); // We get expected inputs including expected Token data expect(alpMulti.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: 'e623ab8971c93fa1a831a4310da65554c8dfd811c16cd5d41c6612268cb5dd5f', outIdx: 1, }, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, entryIdx: 2, amount: '3', }, }, { ...BASE_TX_INPUT, prevOut: { txid: alpNextGenesisTxid, outIdx: 2, }, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, entryIdx: 1, isMintBaton: true, }, }, ]); // We get expected outputs including expected Token data expect(alpMulti.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a5026534c5032000747454e45534953054d554c5449000000000002ffffffffffff0000000000000138534c503200044d494e542c787e508ba86115c7fb13cc582d97a6f3b7d60dad070dcf49e19d0aec12df72020000000000000500000000000030534c503200044255524ee2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb01000000000049534c5032000453454e44e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb05000000000000000000000000000000000000000000000000020000000000', }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMultiTxid, amount: '281474976710655', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, entryIdx: 1, amount: '5', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMultiTxid, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, entryIdx: 2, amount: '2', }, }, { ...BASE_TX_OUTPUT, }, ]); // We get a Entries of expected shape, with genesis tokenId the txid of this new genesis tx // and other tokenIds corresponding to the tokens burned or sent expect(alpMulti.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: alpMultiTxid, txType: 'GENESIS', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, { ...BASE_TOKEN_ENTRY, tokenId: alpNextGenesisTxid, txType: 'MINT', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, { ...BASE_TOKEN_ENTRY, tokenId: alpGenesisTxid, txType: 'SEND', actualBurnAmount: '1', intentionalBurn: '1', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, ]); // The token did not fail parsings expect(alpMulti.tokenFailedParsings).to.deep.equal([]); // Normal status expect(alpMulti.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); // Test order of tokenId.history() const unconfirmedTxs = await chronik .tokenId(alpGenesisTxid) .unconfirmedTxs(); const alphabeticalBroadcastAlpGenesisMempoolTxs = [ alpGenesisTxid, alpMintTxid, alpSendTxid, alpMultiTxid, ].sort(); // Unconfirmed txs come in alphabetical order by txid // Note that the genesis tx was broadcast first but is alphabetically 2nd for (let i = 0; i < unconfirmedTxs.txs.length; i += 1) { expect(unconfirmedTxs.txs[i].txid).to.eql( alphabeticalBroadcastAlpGenesisMempoolTxs[i], ); } // Test order of tokenId.history() const historyTxs = await chronik.tokenId(alpGenesisTxid).history(); // History txs are sorted by blockheight, then timeFirstSeen, then reverse alphabetical by txid // These txs all have the same blockheight and timeFirstSeen, so we see them in reverse alphabetical order const reverseAlphabeticalBroadcastAlpGenesisMempoolTxs = [ alpGenesisTxid, alpMintTxid, alpSendTxid, alpMultiTxid, ] .sort() .reverse(); for (let i = 0; i < historyTxs.txs.length; i += 1) { expect(historyTxs.txs[i].txid).to.eql( reverseAlphabeticalBroadcastAlpGenesisMempoolTxs[i], ); } }); it('Can get all of the above txs, and a wild mega-tx, from the blockTxs endpoint after they are mined in a block', async () => { const chronik = new ChronikClientNode(chronikUrl); // Now that we have a block, we get a block key from token info const alpGenesisConfirmedInfo = await chronik.token(alpGenesisTxid); expect(alpGenesisConfirmedInfo).to.deep.equal({ ...alpTokenInfo, tokenId: alpGenesisTxid, block: { hash: '5e75fc2b2b101c4cf8beec2a68303fcdc5e6d0e3684cc8fbe5ebea60d781b1bb', height: 102, timestamp: 1300000500, }, }); alpMegaTxid = await get_alp_mega_txid; // Can this one from the tx endpoint alpMega = await chronik.tx(alpMegaTxid); // We get expected inputs including expected Token data expect(alpMega.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: alpNextGenesisTxid, outIdx: 3, }, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, entryIdx: 1, isMintBaton: true, }, }, { ...BASE_TX_INPUT, prevOut: { txid: alpGenesisTxid, outIdx: 6, }, value: 546, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, entryIdx: 2, isMintBaton: true, }, }, { ...BASE_TX_INPUT, prevOut: { txid: alpMultiTxid, outIdx: 1, }, value: 546, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMultiTxid, entryIdx: 3, amount: '281474976710655', }, }, ]); // We get expected outputs including expected Token data expect(alpMega.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a5036534c5032000747454e4553495303414c4c0000000000050000000000000700000000000000000000000000000000000100000000000215534c5032000747454e4553495300000000000000004c56534c503200044d494e54e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb070000000000000000000000000000000000000000000000000000000000000000000000000000000000006338534c503200044d494e54e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb02000000000000ffffffffffff0032534c503200044d494e54e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb010000000000000130534c503200044255524ee2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb02000000000038534c503200044d494e542c787e508ba86115c7fb13cc582d97a6f3b7d60dad070dcf49e19d0aec12df7202030000000000000000000000014c56534c503200044d494e54e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb07000000000000000000000000000000000000020000000000000000000000000000000000000000000000012c534c503200044d494e54e2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb000030534c503200044255524ee2c68fa87324d048fbb0b72ca7d386ad757967f20244854f14920a6caa714dbb0000000000004c73534c5032000453454e44ba2ea53336d07ab7bab5eb95f53a6dd041acfca80f2af3a6b93abad7147fc4e30c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b00000000004c67534c5032000453454e44ba2ea53336d07ab7bab5eb95f53a6dd041acfca80f2af3a6b93abad7147fc4e30a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffff2c534c503200044d494e54ba2ea53336d07ab7bab5eb95f53a6dd041acfca80f2af3a6b93abad7147fc4e3000005534c50328930534c503200044255524eba2ea53336d07ab7bab5eb95f53a6dd041acfca80f2af3a6b93abad7147fc4e300000000000005534c50329a', }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, entryIdx: 1, amount: '3', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMegaTxid, amount: '7', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpNextGenesisTxid, entryIdx: 1, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, value: 1000, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, entryIdx: 2, amount: '2', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMegaTxid, amount: '1', }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMegaTxid, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMegaTxid, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpGenesisTxid, entryIdx: 2, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: '0000000000000000000000000000000000000000000000000000000000000000', tokenType: { protocol: 'ALP', type: 'ALP_TOKEN_TYPE_UNKNOWN', number: 137, }, entryIdx: 4, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_ALP, tokenId: alpMultiTxid, entryIdx: 3, amount: '281474976710655', }, }, ]); // We get the mega token entries expect(alpMega.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: '72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565', txType: 'GENESIS', burnSummary: 'Invalid coloring at pushdata idx 1: GENESIS must be the first pushdata', failedColorings: [ { pushdataIdx: 1, error: 'GENESIS must be the first pushdata', }, ], tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, { ...BASE_TOKEN_ENTRY, tokenId: '72df12ec0a9de149cf0d07ad0dd6b7f3a6972d58cc13fbc71561a88b507e782c', txType: 'MINT', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, { ...BASE_TOKEN_ENTRY, tokenId: 'bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2', txType: 'MINT', burnSummary: 'Invalid coloring at pushdata idx 2: Too few outputs, expected 107 but got 11. Invalid coloring at pushdata idx 3: Overlapping amount when trying to color 281474976710655 at index 2, output is already colored with 7 of 72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565 (ALP STANDARD (V0)). Invalid coloring at pushdata idx 4: Overlapping mint baton when trying to color mint baton at index 2, output is already colored with 7 of 72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565 (ALP STANDARD (V0)). Invalid coloring at pushdata idx 8: Duplicate token_id bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2, found in section 2. Invalid coloring at pushdata idx 9: Duplicate intentional burn token_id bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2, found in burn #0 and #1', failedColorings: [ { pushdataIdx: 2, error: 'Too few outputs, expected 107 but got 11', }, { pushdataIdx: 3, error: 'Overlapping amount when trying to color 281474976710655 at index 2, output is already colored with 7 of 72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565 (ALP STANDARD (V0))', }, { pushdataIdx: 4, error: 'Overlapping mint baton when trying to color mint baton at index 2, output is already colored with 7 of 72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565 (ALP STANDARD (V0))', }, { pushdataIdx: 8, error: 'Duplicate token_id bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2, found in section 2', }, { pushdataIdx: 9, error: 'Duplicate intentional burn token_id bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2, found in burn #0 and #1', }, ], intentionalBurn: '2', tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, { ...BASE_TOKEN_ENTRY, tokenId: alpMultiTxid, txType: 'SEND', burnSummary: 'Invalid coloring at pushdata idx 10: Too few outputs, expected 13 but got 11. Invalid coloring at pushdata idx 12: Duplicate token_id e3c47f14d7ba3ab9a6f32a0fa8fcac41d06d3af595ebb5bab77ad03633a52eba, found in section 3. Invalid coloring at pushdata idx 14: Descending token type: 137 > 0, token types must be in ascending order', failedColorings: [ { pushdataIdx: 10, error: 'Too few outputs, expected 13 but got 11', }, { pushdataIdx: 12, error: 'Duplicate token_id e3c47f14d7ba3ab9a6f32a0fa8fcac41d06d3af595ebb5bab77ad03633a52eba, found in section 3', }, { pushdataIdx: 14, error: 'Descending token type: 137 > 0, token types must be in ascending order', }, ], tokenType: { number: 0, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_STANDARD', }, }, { ...BASE_TOKEN_ENTRY, tokenId: '0000000000000000000000000000000000000000000000000000000000000000', txType: 'UNKNOWN', tokenType: { number: 137, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_UNKNOWN', }, }, { ...BASE_TOKEN_ENTRY, tokenId: '0000000000000000000000000000000000000000000000000000000000000000', txType: 'UNKNOWN', tokenType: { number: 154, protocol: 'ALP', type: 'ALP_TOKEN_TYPE_UNKNOWN', }, }, ]); const blockTxs = await chronik.blockTxs(CHAIN_INIT_HEIGHT + 2); // Clone as we will use blockTxs.txs later const txsFromBlock = JSON.parse(JSON.stringify(blockTxs.txs)); // The first tx is the coinbase tx, which is not a token const coinbaseTx = txsFromBlock.shift()!; expect(coinbaseTx.tokenEntries).to.deep.equal([]); expect(coinbaseTx.tokenFailedParsings).to.deep.equal([]); expect(coinbaseTx.tokenStatus).to.equal('TOKEN_STATUS_NON_TOKEN'); // The next txs are alphabetical by txid const broadcastAlpTxs = [ alpGenesis, alpMint, alpSend, alpNextGenesis, alpMulti, alpMega, ].sort((a, b) => a.txid.localeCompare(b.txid)); // The token fields of Tx_InNode(s) from blockTxs match the Tx_InNode(s) from tx // Note the txs are not expected to fully match bc now we have block key and spentBy, // expected after confirmation // This type of functionality is tested in blocktxs_and_tx_and_rawtx.ts for (const tx of broadcastAlpTxs) { const nextTxFromBlock = txsFromBlock.shift()!; expect(tx.tokenEntries).to.deep.equal(nextTxFromBlock.tokenEntries); expect(tx.tokenFailedParsings).to.deep.equal( nextTxFromBlock.tokenFailedParsings, ); expect(tx.tokenStatus).to.deep.equal(nextTxFromBlock.tokenStatus); } // These are the only txs in from blockTxs expect(txsFromBlock.length).to.eql(0); // i.e., the coinbase tx + the six ALP txs broadcast expect(blockTxs.numTxs).to.eql(7); // We can also get the expected Tx shape by calling the script.history() const history = await chronik .script('p2sh', SCRIPTSIG_OP_TRUE_PAYLOAD) .history(); // Same as blockTxs, except different coinbase tx // Remove coinbase tx from both to compare // For blockTxs, it's the first tx blockTxs.txs.shift(); // For historyTxs, it's the last (oldest in time) history.txs.pop(); // We are not exhaustively testing the script endpoint here, see script_endpoints.ts expect(history.txs).to.have.deep.members(blockTxs.txs); // Same tx count as blockTxs expect(history.numTxs).to.eql(7); // Now we have no unconfirmed txs for the alpGenesisTxid const unconfirmedTxsForThisTokenId = await chronik .tokenId(alpGenesisTxid) .unconfirmedTxs(); expect(unconfirmedTxsForThisTokenId.txs.length).to.eql(0); // We can get all the confirmedTxs for alpGenesisTxid // Note: they are in alphabetical order by txid (at least, in this block) const broadcastAlpTxsOfAlpGenesisTokenId = [ alpGenesis, alpMint, alpSend, alpMulti, alpMega, ].sort((a, b) => a.txid.localeCompare(b.txid)); confirmedTxsForAlpGenesisTxid = await chronik .tokenId(alpGenesisTxid) .confirmedTxs(); expect(confirmedTxsForAlpGenesisTxid.txs.length).to.eql( broadcastAlpTxsOfAlpGenesisTokenId.length, ); // They are sorted by blockheight, then alphabetical by txid // In this case, they all have the same blockheight -- so we see alphabetical by txid // Note that timeFirstSeen is not considered from this endpoint, as alpMega has timeFirstSeen of 0 // But it appears second here for (let i = 0; i < confirmedTxsForAlpGenesisTxid.txs.length; i += 1) { // in practice, everything matches except for the 'block' and 'output.spentBy' keys // these are expected to have changed since we stored the txs when they were in the mempool // now we are comparing result to confirmed txs expect(confirmedTxsForAlpGenesisTxid.txs[i].txid).to.eql( broadcastAlpTxsOfAlpGenesisTokenId[i].txid, ); expect(confirmedTxsForAlpGenesisTxid.txs[i].inputs).to.deep.equal( broadcastAlpTxsOfAlpGenesisTokenId[i].inputs, ); expect( confirmedTxsForAlpGenesisTxid.txs[i].tokenEntries, ).to.deep.equal(broadcastAlpTxsOfAlpGenesisTokenId[i].tokenEntries); } }); it('Can get confirmed and unconfirmed txs from tokenId.history()', async () => { const chronik = new ChronikClientNode(chronikUrl); alpNonUtf8GenesisTxid = await get_alp_nonutf8_genesis_txid; alpMintTwoTxid = await get_alp_mint_two_txid; // Can get the tx object from the tx endpoint alpMintTwo = await chronik.tx(alpMintTwoTxid); alpSendTwo = await chronik.tx(alpNonUtf8GenesisTxid); // We can get genesis info even if utf8 expected fields are not utf8 // In practice we do not expect this to ever happen, but someone could do this // We confirm it doesn't break anything const thisTokenInfo = await chronik.token(alpNonUtf8GenesisTxid); // hex 0304b60c048de8d9650881002834d6490000 // A user of chronik-client would see output of '\x03\x04�\f\x04���e\b�\x00(4�I\x00\x00' for tokenInfo.genesisInfo.tokenName expect(thisTokenInfo.genesisInfo?.tokenName).to.eql( '\x03\x04\uFFFD\f\x04\uFFFD\uFFFD\uFFFDe\b\uFFFD\x00(4\uFFFDI\x00\x00', ); // hex 00fabe6d6d6f5486f62c703086014607f5bed91d093b092a8faf5ac882a0ccf462682a22f002 // A user of chronik-client would see output of '\x00��mmoT��,p0�\x01F\x07���\x1D\t;\t*��ZȂ���bh*"�\x02' for thisTokenInfo.genesisInfo.url expect(thisTokenInfo.genesisInfo?.url).to.eql( '\x00\uFFFD\uFFFDmmoT\uFFFD\uFFFD,p0\uFFFD\x01F\x07\uFFFD\uFFFD\uFFFD\x1D\t;\t*\uFFFD\uFFFDZȂ\uFFFD\uFFFD\uFFFDbh*"\uFFFD\x02', ); // alpNonUtf8GenesisTxid 65c63c950ec88a723cd37fc40f2e6f7732508a3703febed620b91d8b0c423eea (broadcast 1st, alphabetically 2nd) // alpMintTwoTxid 163ebdbd2b915d090d602970b2e2737abf631a1ce31345c90d656e98b60e2b8c (broadcast 2nd, alphabetically 1st) const alphabeticalUnconfirmedAlpGenesisTxs = [ alpMintTwo, alpSendTwo, ].sort((a, b) => a.txid.localeCompare(b.txid)); // Can get these from unconfirmed txs const unconfirmedTxs = await chronik .tokenId(alpGenesisTxid) .unconfirmedTxs(); // unconfirmedTxs returns them in alphabetical order for (let i = 0; i < unconfirmedTxs.txs.length; i += 1) { expect(unconfirmedTxs.txs[i]).to.deep.equal( alphabeticalUnconfirmedAlpGenesisTxs[i], ); } // They are the only unconfirmed txs expect(unconfirmedTxs.txs.length).to.eql(2); // Calling chronik.tokenId.history() returns all confirmed and unconfirmed txs const allTokenTxsForAlpGenesisTxid = await chronik .tokenId(alpGenesisTxid) .history(); // We get all expected txs, confirmed and unconfirmed expect(allTokenTxsForAlpGenesisTxid.txs.length).to.eql( confirmedTxsForAlpGenesisTxid.txs.length + unconfirmedTxs.txs.length, ); // Txs from history are sorted by blockheight, then timeFirstSeen, then txid // In this case, timeFirstSeen is a mock time, so it is the same for each // So we expect reverse alphabetical order by txid const unconfirmedInHistory = allTokenTxsForAlpGenesisTxid.txs.splice( 0, 2, ); const reverseAlphabeticalUnconfirmedAlpGenesisTxs = [ alpMintTwo, alpSendTwo, ].sort((b, a) => a.txid.localeCompare(b.txid)); expect(unconfirmedInHistory).to.deep.equal( reverseAlphabeticalUnconfirmedAlpGenesisTxs, ); // We get the rest of the txs in expected order // Sorted by blockheight, then timeFirstSeen, then txid // In this case, all txs have the same blockheight // alpMegaTxid has timeFirstSeen of 0 since it was manually mined // All other txs have the same timeFirstSeen so are sorted in reverse alphabetical order // Confirm the order of txs from .history() const confirmedAlpTxs = [ alpMegaTxid, // timeFirstSeen 0 | 72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565 alpSendTxid, // timeFirstSeen 1300000000 | e623ab8971c93fa1a831a4310da65554c8dfd811c16cd5d41c6612268cb5dd5f alpMultiTxid, // timeFirstSeen 1300000000 | e3c47f14d7ba3ab9a6f32a0fa8fcac41d06d3af595ebb5bab77ad03633a52eba alpGenesisTxid, // timeFirstSeen 1300000000 | bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2 alpMintTxid, // timeFirstSeen 1300000000 | 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f ]; for (let i = 0; i < allTokenTxsForAlpGenesisTxid.txs.length; i += 1) { expect(confirmedAlpTxs[i]).to.eql( allTokenTxsForAlpGenesisTxid.txs[i].txid, ); } // Make sure other parts of returned tx objects are as expected // Since one of the utxos from confirmedTxsForAlpGenesisTxid was spent to create // the second mint tx, this spentBy key has changed // We spent the mint baton const newConfirmedMintTxIndex = allTokenTxsForAlpGenesisTxid.txs.findIndex( tx => tx.txid === alpMintTxid, ); const newMintTx = allTokenTxsForAlpGenesisTxid.txs.splice( newConfirmedMintTxIndex, 1, )[0]; const confirmedMintTxIndex = confirmedTxsForAlpGenesisTxid.txs.findIndex( tx => tx.txid === alpMintTxid, ); const oldMintTx = confirmedTxsForAlpGenesisTxid.txs.splice( confirmedMintTxIndex, 1, )[0]; // We have removed this tx from both histories expect(allTokenTxsForAlpGenesisTxid.txs.length).to.eql( confirmedTxsForAlpGenesisTxid.txs.length, ); // They are the same except for outputs, as expected expect(oldMintTx.inputs).to.deep.equal(newMintTx.inputs); expect(oldMintTx.tokenEntries).to.deep.equal(newMintTx.tokenEntries); // Since one of the utxos from confirmedTxsForAlpGenesisTxid was spent to create // the second send tx, this spentBy key has changed const newConfirmedSendTxIndex = allTokenTxsForAlpGenesisTxid.txs.findIndex( tx => tx.txid === alpSendTxid, ); const newSendTx = allTokenTxsForAlpGenesisTxid.txs.splice( newConfirmedSendTxIndex, 1, )[0]; const confirmedSendTxIndex = confirmedTxsForAlpGenesisTxid.txs.findIndex( tx => tx.txid === alpSendTxid, ); const oldSendTx = confirmedTxsForAlpGenesisTxid.txs.splice( confirmedSendTxIndex, 1, )[0]; // We have removed this tx from both histories expect(allTokenTxsForAlpGenesisTxid.txs.length).to.eql( confirmedTxsForAlpGenesisTxid.txs.length, ); // They are the same except for outputs, as expected expect(oldSendTx.inputs).to.deep.equal(newSendTx.inputs); expect(oldSendTx.tokenEntries).to.deep.equal(newSendTx.tokenEntries); // The other txs are the same, though the order is not the same // allTokenTxsForAlpGenesisTxid is sorted by blockheight, then timeFirstSeen, then reverse alphabetical by txid // confirmedTxsForAlpGenesisTxid is sorted by blockheight, then alphabetical by txid // These respective orderings are already tested above, here we test they have the same content expect( allTokenTxsForAlpGenesisTxid.txs.sort((a, b) => a.txid.localeCompare(b.txid), ), ).to.deep.equal( confirmedTxsForAlpGenesisTxid.txs.sort((a, b) => a.txid.localeCompare(b.txid), ), ); }); it('We get tx history in expected order from both tokenId().history() and tokenId.confirmedTxs()', async () => { const chronik = new ChronikClientNode(chronikUrl); // Can get all confirmed token txs for alpGenesisTxid const confirmedTxs = await chronik .tokenId(alpGenesisTxid) .confirmedTxs(); // Confirmed txs are sorted by blockheight, then alphabetically by txid // timeFirstSeen is not considered, demonstrated by alpMegaTxid not being first const confirmedAlpTxids = [ alpMintTxid, // blockheight 102, timeFirstSeen 1300000000 | 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f alpMegaTxid, // blockheight 102, timeFirstSeen 0 | 72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565 alpGenesisTxid, // blockheight 102, timeFirstSeen 1300000000 | bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2 alpMultiTxid, // blockheight 102, timeFirstSeen 1300000000 | e3c47f14d7ba3ab9a6f32a0fa8fcac41d06d3af595ebb5bab77ad03633a52eba alpSendTxid, //blockheight 102, timeFirstSeen 1300000000 | e623ab8971c93fa1a831a4310da65554c8dfd811c16cd5d41c6612268cb5dd5f alpMintTwoTxid, // blockheight 103, timeFirstSeen 1300000000 | 163ebdbd2b915d090d602970b2e2737abf631a1ce31345c90d656e98b60e2b8c alpNonUtf8GenesisTxid, // blockheight 103, timeFirstSeen 1300000000 | 65c63c950ec88a723cd37fc40f2e6f7732508a3703febed620b91d8b0c423eea ]; // Same amount of txs in each expect(confirmedTxs.txs.length).to.eql(confirmedAlpTxids.length); // Txs are in expected order for (let i = 0; i < confirmedTxs.txs.length; i += 1) { expect(confirmedTxs.txs[i].txid).to.eql(confirmedAlpTxids[i]); } // Can get all confirmed token txs for alpGenesisTxid const history = await chronik.tokenId(alpGenesisTxid).history(); // Txs from history are ordered by blockheight, then timeFirstSeen, then reverse alphabetical by txid // In this case, alpSendTwoTxid and alpMintTwoTxid are from the highest blockheight. // alpMegaTxid has timeFirstSeen of 0 because it had to be manually mined in block. So, it comes first in the next block // The other txids in the alpMegaTxid block all have the same timeFirstSeen, so they are sorted reverse alphabetically const historyAlpTxids = [ alpNonUtf8GenesisTxid, // timeFirstSeen 1300000000, blockheight 103 | 65c63c950ec88a723cd37fc40f2e6f7732508a3703febed620b91d8b0c423eea alpMintTwoTxid, // timeFirstSeen 1300000000, blockheight 103 | 163ebdbd2b915d090d602970b2e2737abf631a1ce31345c90d656e98b60e2b8c alpMegaTxid, // timeFirstSeen 0, blockheight 102 | 72101f535470e0a6de7db9ba0ba115845566f738cc5124255b472347b5927565 alpSendTxid, // timeFirstSeen 1300000000, blockheight 102 | e623ab8971c93fa1a831a4310da65554c8dfd811c16cd5d41c6612268cb5dd5f alpMultiTxid, // timeFirstSeen 1300000000, blockheight 102 | e3c47f14d7ba3ab9a6f32a0fa8fcac41d06d3af595ebb5bab77ad03633a52eba alpGenesisTxid, // timeFirstSeen 1300000000, blockheight 102 | bb4d71aa6c0a92144f854402f2677975ad86d3a72cb7b0fb48d02473a88fc6e2 alpMintTxid, // timeFirstSeen 1300000000, blockheight 102 | 0dab1008db30343a4f771983e9fd96cbc15f0c6efc73f5249c9bae311ef1e92f ]; // Same amount of txs in each expect(history.txs.length).to.eql(historyAlpTxids.length); // Txs in expected order for (let i = 0; i < confirmedTxs.txs.length; i += 1) { expect(history.txs[i].txid).to.eql(historyAlpTxids[i]); } }); }); diff --git a/modules/chronik-client/test/integration/token_slp_fungible.ts b/modules/chronik-client/test/integration/token_slp_fungible.ts index 0281e0b8b..10e95f1e8 100644 --- a/modules/chronik-client/test/integration/token_slp_fungible.ts +++ b/modules/chronik-client/test/integration/token_slp_fungible.ts @@ -1,507 +1,507 @@ // Copyright (c) 2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. import * as chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { ChildProcess } from 'node:child_process'; import { EventEmitter, once } from 'node:events'; import path from 'path'; import { ChronikClientNode, Tx_InNode } from '../../index'; import initializeTestRunner, { cleanupMochaRegtest, setMochaTimeout, TestInfo, } from '../setup/testRunner'; const expect = chai.expect; chai.use(chaiAsPromised); describe('Get blocktxs, txs, and history for SLP fungible token txs', () => { // Define variables used in scope of this test const testName = path.basename(__filename); let testRunner: ChildProcess; let get_slp_fungible_genesis_txid: Promise; let get_slp_fungible_mint_txid: Promise; let get_slp_fungible_send_txid: Promise; let get_slp_fungible_genesis_empty_txid: Promise; const statusEvent = new EventEmitter(); let get_test_info: Promise; let chronikUrl: string[]; let setupScriptTermination: ReturnType; before(async function () { // Initialize testRunner before mocha tests testRunner = initializeTestRunner(testName, statusEvent); // Handle IPC messages from the setup script testRunner.on('message', function (message: any) { if (message && message.test_info) { get_test_info = new Promise(resolve => { resolve(message.test_info); }); } if (message && message.slp_fungible_genesis_txid) { get_slp_fungible_genesis_txid = new Promise(resolve => { resolve(message.slp_fungible_genesis_txid); }); } if (message && message.slp_fungible_mint_txid) { get_slp_fungible_mint_txid = new Promise(resolve => { resolve(message.slp_fungible_mint_txid); }); } if (message && message.slp_fungible_send_txid) { get_slp_fungible_send_txid = new Promise(resolve => { resolve(message.slp_fungible_send_txid); }); } if (message && message.slp_fungible_genesis_empty_txid) { get_slp_fungible_genesis_empty_txid = new Promise(resolve => { resolve(message.slp_fungible_genesis_empty_txid); }); } if (message && message.status) { statusEvent.emit(message.status); } }); await once(statusEvent, 'ready'); const testInfo = await get_test_info; chronikUrl = [testInfo.chronik]; console.log(`chronikUrl set to ${JSON.stringify(chronikUrl)}`); setupScriptTermination = setMochaTimeout( this, testName, testInfo, testRunner, ); testRunner.send('next'); }); after(async () => { await cleanupMochaRegtest( testName, testRunner, setupScriptTermination, statusEvent, ); }); beforeEach(async () => { await once(statusEvent, 'ready'); }); afterEach(() => { testRunner.send('next'); }); const CHAIN_INIT_HEIGHT = 100; const SCRIPTSIG_OP_TRUE_PAYLOAD = 'da1745e9b549bd0bfa1a569971c77eba30cd5a4b'; const BASE_TX_INPUT = { inputScript: '0151', outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', value: 5000000000, sequenceNo: 0, }; const BASE_TX_OUTPUT = { value: 2000, outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', }; const BASE_TX_TOKEN_INFO_SLP_FUNGIBLE = { tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_FUNGIBLE', number: 1, }, entryIdx: 0, amount: '0', isMintBaton: false, }; const BASE_TOKEN_ENTRY = { // omit tokenId, txType, and tokenType as these should always be tested isInvalid: false, burnSummary: '', failedColorings: [], actualBurnAmount: '0', intentionalBurn: '0', burnsMintBatons: false, }; let slpGenesisTxid = ''; let slpMintTxid = ''; let slpSendTxid = ''; let slpEmptyGenesisTxid = ''; let slpGenesis: Tx_InNode; let slpMint: Tx_InNode; let slpSend: Tx_InNode; let slpEmptyGenesis: Tx_InNode; it('Gets an SLP genesis tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpGenesisTxid = await get_slp_fungible_genesis_txid; slpGenesis = await chronik.tx(slpGenesisTxid); // We get expected inputs including expected Token data // We get no token info in tx inputs expect(slpGenesis.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: '3fa435fca55edf447ef7539ecba141a6585fa71ac4062cdcc61f1235c40f4613', outIdx: 0, }, }, ]); // We get expected outputs including expected Token data expect(slpGenesis.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c500001010747454e4553495307534c5054455354105465737420534c5020546f6b656e203312687474703a2f2f6578616d706c652f736c7020787878787878787878787878787878787878787878787878787878787878787801040102080000000000001388', }, { ...BASE_TX_OUTPUT, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, amount: '5000', }, }, { ...BASE_TX_OUTPUT, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, isMintBaton: true, }, }, { ...BASE_TX_OUTPUT, value: 4999600000, }, ]); // We get a Entries of expected shape, with tokenId the txid for a genesis tx expect(slpGenesis.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpGenesisTxid, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_FUNGIBLE', number: 1, }, txType: 'GENESIS', }, ]); // The token did not fail parsings expect(slpGenesis.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); // We can get token info of an slp token from the mempool const slpGenesisMempoolInfo = await chronik.token(slpGenesisTxid); expect(slpGenesisMempoolInfo).to.deep.equal({ tokenId: slpGenesisTxid, - timeFirstSeen: '1300000000', + timeFirstSeen: 1300000000, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_FUNGIBLE', number: 1, }, // We get hash in GenesisInfo for SLP // We do not get mintVaultScripthash for non-SLP_MINT_VAULT // We do not get data or authPubkey keys in GenesisInfo for non-ALP genesisInfo: { tokenTicker: 'SLPTEST', tokenName: 'Test SLP Token 3', url: 'http://example/slp', hash: '7878787878787878787878787878787878787878787878787878787878787878', decimals: 4, }, }); }); it('Gets an SLP fungible mint tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpMintTxid = await get_slp_fungible_mint_txid; slpMint = await chronik.tx(slpMintTxid); // We get expected inputs including expected Token data expect(slpMint.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: slpGenesisTxid, outIdx: 2, }, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, isMintBaton: true, }, }, ]); // We get expected outputs including expected Token data expect(slpMint.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c50000101044d494e5420cd295e7eb883b5826e2d8872b1626a4af4ce7ec81c468f1bfdad14632036d20a0103080000000000000014', }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, amount: '20', }, }, { ...BASE_TX_OUTPUT, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, isMintBaton: true, }, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(slpMint.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpGenesisTxid, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_FUNGIBLE', number: 1, }, txType: 'MINT', }, ]); // The token did not fail parsings expect(slpMint.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpMint.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Gets an SLP fungible send tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpSendTxid = await get_slp_fungible_send_txid; slpSend = await chronik.tx(slpSendTxid); // We get expected inputs including expected Token data expect(slpSend.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: slpGenesisTxid, outIdx: 1, }, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, amount: '5000', }, }, ]); // We get expected outputs including expected Token data expect(slpSend.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c500001010453454e4420cd295e7eb883b5826e2d8872b1626a4af4ce7ec81c468f1bfdad14632036d20a0800000000000003e8080000000000000fa0', }, { ...BASE_TX_OUTPUT, value: 4000, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, amount: '1000', }, }, { ...BASE_TX_OUTPUT, value: 4000, token: { ...BASE_TX_TOKEN_INFO_SLP_FUNGIBLE, tokenId: slpGenesisTxid, amount: '4000', }, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(slpSend.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpGenesisTxid, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_FUNGIBLE', number: 1, }, txType: 'SEND', }, ]); // The token did not fail parsings expect(slpSend.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpSend.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Gets an SLP fungible empty genesis tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpEmptyGenesisTxid = await get_slp_fungible_genesis_empty_txid; slpEmptyGenesis = await chronik.tx(slpEmptyGenesisTxid); // We get expected inputs including expected Token data // We get no token info in tx inputs expect(slpEmptyGenesis.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: slpGenesisTxid, outIdx: 3, }, value: 4999600000, }, ]); // We get expected outputs including expected Token data // We get no token info in tx outputs expect(slpEmptyGenesis.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c500001010747454e455349534c004c004c004c0001004c00080000000000000000', }, { ...BASE_TX_OUTPUT, value: 4999500000, }, ]); // We get a Entries of expected shape, with slpEmptyGenesisTxid the tokenId expect(slpEmptyGenesis.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpEmptyGenesisTxid, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_FUNGIBLE', number: 1, }, txType: 'GENESIS', }, ]); // The token did not fail parsings expect(slpEmptyGenesis.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpEmptyGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Can get all of the above txs from the blockTxs endpoint after they are mined in a block', async () => { const chronik = new ChronikClientNode(chronikUrl); // Now that we have a block, we get a block key from token info const slpGenesisConfirmedInfo = await chronik.token(slpGenesisTxid); expect(typeof slpGenesisConfirmedInfo.block !== 'undefined').to.eql( true, ); const blockTxs = await chronik.blockTxs(CHAIN_INIT_HEIGHT + 2); // Clone as we will use blockTxs.txs later const txsFromBlock = JSON.parse(JSON.stringify(blockTxs.txs)); // The first tx is the coinbase tx, which is not a token const coinbaseTx = txsFromBlock.shift()!; expect(coinbaseTx.tokenEntries).to.deep.equal([]); expect(coinbaseTx.tokenFailedParsings).to.deep.equal([]); expect(coinbaseTx.tokenStatus).to.eql('TOKEN_STATUS_NON_TOKEN'); // The next txs are alphabetical by txid const broadcastTxs = [ slpGenesis, slpMint, slpSend, slpEmptyGenesis, ].sort((a, b) => a.txid.localeCompare(b.txid)); // The token fields of Tx_InNode(s) from blockTxs match the Tx_InNode(s) from tx // Note the txs are not expected to fully match bc now we have block and spentBy keys, // which are expected after confirmation // Full endpoint output is tested in blocktxs_and_tx_and_rawtx.ts for (const tx of broadcastTxs) { const nextTxFromBlock = txsFromBlock.shift()!; expect(tx.tokenEntries).to.deep.equal(nextTxFromBlock.tokenEntries); expect(tx.tokenFailedParsings).to.deep.equal( nextTxFromBlock.tokenFailedParsings, ); expect(tx.tokenStatus).to.deep.equal(nextTxFromBlock.tokenStatus); } // These are the only txs in from blockTxs expect(txsFromBlock.length).to.eql(0); // i.e., the coinbase tx + the four SLP fungible txs broadcast expect(blockTxs.numTxs).to.eql(5); // We can also get the expected Tx shape by calling the script.history() const history = await chronik .script('p2sh', SCRIPTSIG_OP_TRUE_PAYLOAD) .history(); // Same as blockTxs, except different coinbase tx // Remove coinbase tx from both to compare // For blockTxs, it's the first tx blockTxs.txs.shift(); // For historyTxs, it's the last (oldest in time) history.txs.pop(); // We are not exhaustively testing the script endpoint here, see script_endpoints.ts expect(history.txs).to.have.deep.members(blockTxs.txs); // Same tx count as blockTxs expect(history.numTxs).to.eql(5); }); }); diff --git a/modules/chronik-client/test/integration/token_slp_mint_vault.ts b/modules/chronik-client/test/integration/token_slp_mint_vault.ts index e553e0014..dde9e5df4 100644 --- a/modules/chronik-client/test/integration/token_slp_mint_vault.ts +++ b/modules/chronik-client/test/integration/token_slp_mint_vault.ts @@ -1,349 +1,349 @@ // Copyright (c) 2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. import * as chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { ChildProcess } from 'node:child_process'; import { EventEmitter, once } from 'node:events'; import path from 'path'; import { ChronikClientNode, Tx_InNode } from '../../index'; import initializeTestRunner, { cleanupMochaRegtest, setMochaTimeout, TestInfo, } from '../setup/testRunner'; const expect = chai.expect; chai.use(chaiAsPromised); describe('Get blocktxs, txs, and history for SLP 2 mint vault token txs', () => { // Define variables used in scope of this test const testName = path.basename(__filename); let testRunner: ChildProcess; let get_vault_setup_txid: Promise; let get_slp_vault_genesis_txid: Promise; let get_slp_vault_mint_txid: Promise; const statusEvent = new EventEmitter(); let get_test_info: Promise; let chronikUrl: string[]; let setupScriptTermination: ReturnType; before(async function () { // Initialize testRunner before mocha tests testRunner = initializeTestRunner(testName, statusEvent); // Handle IPC messages from the setup script testRunner.on('message', function (message: any) { if (message && message.test_info) { get_test_info = new Promise(resolve => { resolve(message.test_info); }); } if (message && message.vault_setup_txid) { get_vault_setup_txid = new Promise(resolve => { resolve(message.vault_setup_txid); }); } if (message && message.slp_vault_genesis_txid) { get_slp_vault_genesis_txid = new Promise(resolve => { resolve(message.slp_vault_genesis_txid); }); } if (message && message.slp_vault_mint_txid) { get_slp_vault_mint_txid = new Promise(resolve => { resolve(message.slp_vault_mint_txid); }); } if (message && message.status) { statusEvent.emit(message.status); } }); await once(statusEvent, 'ready'); const testInfo = await get_test_info; chronikUrl = [testInfo.chronik]; console.log(`chronikUrl set to ${JSON.stringify(chronikUrl)}`); setupScriptTermination = setMochaTimeout( this, testName, testInfo, testRunner, ); testRunner.send('next'); }); after(async () => { await cleanupMochaRegtest( testName, testRunner, setupScriptTermination, statusEvent, ); }); beforeEach(async () => { await once(statusEvent, 'ready'); }); afterEach(() => { testRunner.send('next'); }); const CHAIN_INIT_HEIGHT = 100; const MINT_VAULT_SCRIPTHASH = '28e2146de5a061bf57845a04968d89cbdab733e3'; const BASE_TX_INPUT = { prevOut: { txid: 'b85c9fecfc2aeb0992fd05c62688c5b631c22e2e874ffeb4c3fbf5ad778848a3', outIdx: 1, }, inputScript: '0151', outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', value: 100000, sequenceNo: 0, }; const BASE_TX_OUTPUT = { value: 10000, outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', }; const BASE_TX_TOKEN_INFO_SLP_V2 = { tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_MINT_VAULT', number: 2, }, entryIdx: 0, amount: '1000', isMintBaton: false, }; const BASE_TOKEN_ENTRY = { // omit tokenId, txType, and tokenType as these should always be tested isInvalid: false, burnSummary: '', failedColorings: [], actualBurnAmount: '0', intentionalBurn: '0', burnsMintBatons: false, }; let vaultSetupTxid = ''; let slpVaultGenesisTxid = ''; let slpVaultMintTxid = ''; let vaultSetup: Tx_InNode; let slpVaultGenesis: Tx_InNode; let slpVaultMint: Tx_InNode; it('Gets an SLP vault setup tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); vaultSetupTxid = await get_vault_setup_txid; vaultSetup = await chronik.tx(vaultSetupTxid); // We get expected inputs including expected Token data // We get no token info in tx inputs expect(vaultSetup.inputs).to.deep.equal([ { ...BASE_TX_INPUT, }, ]); // We get expected outputs including expected Token data // We get no token info in tx outputs expect(vaultSetup.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, outputScript: 'a91428e2146de5a061bf57845a04968d89cbdab733e387', }, { ...BASE_TX_OUTPUT, outputScript: 'a91428e2146de5a061bf57845a04968d89cbdab733e387', }, { ...BASE_TX_OUTPUT, value: 79000, outputScript: 'a91428e2146de5a061bf57845a04968d89cbdab733e387', }, ]); // No token entries before confirmation expect(vaultSetup.tokenEntries).to.deep.equal([]); // The token did not fail parsings expect(vaultSetup.tokenFailedParsings).to.deep.equal([]); // Normal status expect(vaultSetup.tokenStatus).to.eql('TOKEN_STATUS_NON_TOKEN'); }); it('Gets this tx from a block', async () => { const chronik = new ChronikClientNode(chronikUrl); const blockTxs = await chronik.blockTxs(CHAIN_INIT_HEIGHT + 2); const confirmedVaultSetup = blockTxs.txs.find( tx => tx.txid === vaultSetupTxid, ); // No change in tokenEntries expect(confirmedVaultSetup?.tokenEntries).to.deep.equal( vaultSetup.tokenEntries, ); // We can also get this tx from script history const history = await chronik .script('p2sh', MINT_VAULT_SCRIPTHASH) .history(); // It's the same as what we get from blockTxs expect(history.txs[0]).to.deep.equal(confirmedVaultSetup); }); it('Gets an SLP vault genesis tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpVaultGenesisTxid = await get_slp_vault_genesis_txid; slpVaultGenesis = await chronik.tx(slpVaultGenesisTxid); // We get expected inputs // No token data is expected or returned expect(slpVaultGenesis.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: 'b85c9fecfc2aeb0992fd05c62688c5b631c22e2e874ffeb4c3fbf5ad778848a3', outIdx: 0, }, }, ]); // We get expected outputs including expected Token data expect(slpVaultGenesis.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c500001020747454e4553495308534c505641554c540130013020787878787878787878787878787878787878787878787878787878787878787801001428e2146de5a061bf57845a04968d89cbdab733e30800000000000003e8', }, { ...BASE_TX_OUTPUT, value: 546, token: { ...BASE_TX_TOKEN_INFO_SLP_V2, tokenId: slpVaultGenesisTxid, }, }, { ...BASE_TX_OUTPUT, value: 99000, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(slpVaultGenesis.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: '768626ba27515513f148d714453bd2964f0de49c6686fa54da56ae4e19387c70', tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_MINT_VAULT', number: 2, }, txType: 'GENESIS', }, ]); // The token did not fail parsings expect(slpVaultGenesis.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpVaultGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); // We can get token info of an slp vault token from the mempool const slpGenesisMempoolInfo = await chronik.token(slpVaultGenesisTxid); expect(slpGenesisMempoolInfo).to.deep.equal({ tokenId: slpVaultGenesisTxid, - timeFirstSeen: '1300000000', + timeFirstSeen: 1300000000, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_MINT_VAULT', number: 2, }, // We get mintVaultScripthash in GenesisInfo for SLP MINT VAULT // We get hash in GenesisInfo for SLP // We do not get data or authPubkey keys in GenesisInfo for non-ALP genesisInfo: { tokenTicker: 'SLPVAULT', tokenName: '0', url: '0', hash: '7878787878787878787878787878787878787878787878787878787878787878', mintVaultScripthash: '28e2146de5a061bf57845a04968d89cbdab733e3', decimals: 0, }, }); }); it('Gets a badly constructed SLP v2 Vault Mint tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpVaultMintTxid = await get_slp_vault_mint_txid; slpVaultMint = await chronik.tx(slpVaultMintTxid); // We get expected inputs. No token data is expected in inputs. expect(slpVaultMint.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: '34d22b0d3dd9b1ac75a01125fa5d778d5ddde2dea098416479c011340684702f', outIdx: 0, }, inputScript: '015c', outputScript: 'a91428e2146de5a061bf57845a04968d89cbdab733e387', value: 10000, }, ]); // We get expected outputs. No token data expected in outputs due to validation error in this tx. expect(slpVaultMint.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c50000102044d494e5420768626ba27515513f148d714453bd2964f0de49c6686fa54da56ae4e19387c70080000000000000fa0', }, { ...BASE_TX_OUTPUT, value: 9000, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(slpVaultMint.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpVaultGenesisTxid, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_MINT_VAULT', number: 2, }, txType: 'MINT', isInvalid: true, burnSummary: 'Validation error: Missing MINT vault', }, ]); // The token did not fail parsings expect(slpVaultMint.tokenFailedParsings).to.deep.equal([]); // Not normal status (missing mint vault) expect(slpVaultMint.tokenStatus).to.eql('TOKEN_STATUS_NOT_NORMAL'); }); }); diff --git a/modules/chronik-client/test/integration/token_slp_nft1.ts b/modules/chronik-client/test/integration/token_slp_nft1.ts index 8b80c4e3d..c2fe9a78e 100644 --- a/modules/chronik-client/test/integration/token_slp_nft1.ts +++ b/modules/chronik-client/test/integration/token_slp_nft1.ts @@ -1,583 +1,583 @@ // Copyright (c) 2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. import * as chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { ChildProcess } from 'node:child_process'; import { EventEmitter, once } from 'node:events'; import path from 'path'; import { ChronikClientNode, Tx_InNode } from '../../index'; import initializeTestRunner, { cleanupMochaRegtest, setMochaTimeout, TestInfo, } from '../setup/testRunner'; const expect = chai.expect; chai.use(chaiAsPromised); describe('Get blocktxs, txs, and history for SLP NFT1 token txs', () => { // Define variables used in scope of this test const testName = path.basename(__filename); let testRunner: ChildProcess; let get_slp_nft1_genesis_txid: Promise; let get_slp_nft1_mint_txid: Promise; let get_slp_nft1_send_txid: Promise; let get_slp_nft1_child_genesis1_txid: Promise; const statusEvent = new EventEmitter(); let get_test_info: Promise; let chronikUrl: string[]; let setupScriptTermination: ReturnType; before(async function () { // Initialize testRunner before mocha tests testRunner = initializeTestRunner(testName, statusEvent); // Handle IPC messages from the setup script testRunner.on('message', function (message: any) { if (message && message.test_info) { get_test_info = new Promise(resolve => { resolve(message.test_info); }); } if (message && message.slp_nft1_genesis_txid) { get_slp_nft1_genesis_txid = new Promise(resolve => { resolve(message.slp_nft1_genesis_txid); }); } if (message && message.slp_nft1_mint_txid) { get_slp_nft1_mint_txid = new Promise(resolve => { resolve(message.slp_nft1_mint_txid); }); } if (message && message.slp_nft1_send_txid) { get_slp_nft1_send_txid = new Promise(resolve => { resolve(message.slp_nft1_send_txid); }); } if (message && message.slp_nft1_child_genesis1_txid) { get_slp_nft1_child_genesis1_txid = new Promise(resolve => { resolve(message.slp_nft1_child_genesis1_txid); }); } if (message && message.status) { statusEvent.emit(message.status); } }); await once(statusEvent, 'ready'); const testInfo = await get_test_info; chronikUrl = [testInfo.chronik]; console.log(`chronikUrl set to ${JSON.stringify(chronikUrl)}`); setupScriptTermination = setMochaTimeout( this, testName, testInfo, testRunner, ); testRunner.send('next'); }); after(async () => { await cleanupMochaRegtest( testName, testRunner, setupScriptTermination, statusEvent, ); }); beforeEach(async () => { await once(statusEvent, 'ready'); }); afterEach(() => { testRunner.send('next'); }); const CHAIN_INIT_HEIGHT = 100; const SCRIPTSIG_OP_TRUE_PAYLOAD = 'da1745e9b549bd0bfa1a569971c77eba30cd5a4b'; const BASE_TX_INPUT = { prevOut: { txid: '3fa435fca55edf447ef7539ecba141a6585fa71ac4062cdcc61f1235c40f4613', outIdx: 0, }, inputScript: '0151', outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', value: 5000000000, sequenceNo: 0, }; const BASE_TX_OUTPUT = { value: 2000, outputScript: 'a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87', }; const BASE_TX_TOKEN_INFO_SLP_NFT = { tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_GROUP', number: 129, }, entryIdx: 0, amount: '0', isMintBaton: true, }; const BASE_TOKEN_ENTRY = { // omit tokenId, txType, and tokenType as these should always be tested isInvalid: false, burnSummary: '', failedColorings: [], actualBurnAmount: '0', intentionalBurn: '0', burnsMintBatons: false, }; let slpGenesisTxid = ''; let slpMintTxid = ''; let slpSendTxid = ''; let slpChildGenesisTxid = ''; let slpGenesis: Tx_InNode; let slpMint: Tx_InNode; let slpSend: Tx_InNode; let slpChildGenesis: Tx_InNode; it('Gets an SLP NFT1 genesis tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpGenesisTxid = await get_slp_nft1_genesis_txid; slpGenesis = await chronik.tx(slpGenesisTxid); // We get expected inputs including expected Token data // We get no token info in tx inputs expect(slpGenesis.inputs).to.deep.equal([ { ...BASE_TX_INPUT, }, ]); // We get expected outputs including expected Token data expect(slpGenesis.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c500001810747454e455349530d534c50204e46542047524f555013536c70204e46542047524f555020746f6b656e0e687474703a2f2f736c702e6e667420787878787878787878787878787878787878787878787878787878787878787801040102080000000000001388', }, { ...BASE_TX_OUTPUT, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, amount: '5000', isMintBaton: false, }, }, { ...BASE_TX_OUTPUT, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, }, }, { ...BASE_TX_OUTPUT, value: 4999600000, }, ]); // We get a Entries of expected shape, with tokenId the txid for a genesis tx expect(slpGenesis.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpGenesisTxid, txType: 'GENESIS', tokenType: { number: 129, protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_GROUP', }, }, ]); // The token did not fail parsings expect(slpGenesis.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); // We can get token info of an slp nft1 from the mempool const slpGenesisMempoolInfo = await chronik.token(slpGenesisTxid); // We do not get mintVaultScripthash for non-SLP_MINT_VAULT // We do not get data or authPubkey keys in GenesisInfo for non-ALP expect(slpGenesisMempoolInfo).to.deep.equal({ tokenId: slpGenesisTxid, - timeFirstSeen: '1300000000', + timeFirstSeen: 1300000000, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_GROUP', number: 129, }, genesisInfo: { tokenTicker: 'SLP NFT GROUP', tokenName: 'Slp NFT GROUP token', url: 'http://slp.nft', hash: '7878787878787878787878787878787878787878787878787878787878787878', decimals: 4, }, }); }); it('Gets an SLP NFT1 mint tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpMintTxid = await get_slp_nft1_mint_txid; slpMint = await chronik.tx(slpMintTxid); // We get expected inputs including expected Token data expect(slpMint.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: 'b5100125684e0a7ccb8a6a2a0272586e1275f438924464000df5c834ed64bccb', outIdx: 2, }, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, }, }, ]); // We get expected outputs including expected Token data expect(slpMint.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c50000181044d494e5420b5100125684e0a7ccb8a6a2a0272586e1275f438924464000df5c834ed64bccb0103080000000000000014', }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, amount: '20', isMintBaton: false, }, }, { ...BASE_TX_OUTPUT, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, }, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(slpMint.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpGenesisTxid, txType: 'MINT', tokenType: { number: 129, protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_GROUP', }, }, ]); // The token did not fail parsings expect(slpMint.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpMint.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Gets an SLP NFT1 send tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpSendTxid = await get_slp_nft1_send_txid; slpSend = await chronik.tx(slpSendTxid); // We get expected inputs including expected Token data expect(slpSend.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: 'b5100125684e0a7ccb8a6a2a0272586e1275f438924464000df5c834ed64bccb', outIdx: 1, }, value: 10000, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, amount: '5000', isMintBaton: false, }, }, ]); // We get expected outputs including expected Token data expect(slpSend.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c500001810453454e4420b5100125684e0a7ccb8a6a2a0272586e1275f438924464000df5c834ed64bccb080000000000000001080000000000000063080000000000000384080000000000000fa0', }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, amount: '1', isMintBaton: false, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, amount: '99', isMintBaton: false, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, amount: '900', isMintBaton: false, }, }, { ...BASE_TX_OUTPUT, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, amount: '4000', isMintBaton: false, }, }, ]); // We get a Entries of expected shape, with tokenId the txid of the genesis tx expect(slpSend.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpGenesisTxid, txType: 'SEND', tokenType: { number: 129, protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_GROUP', }, }, ]); // The token did not fail parsings expect(slpSend.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpSend.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Gets an SLP NFT1 child genesis tx from the mempool', async () => { const chronik = new ChronikClientNode(chronikUrl); slpChildGenesisTxid = await get_slp_nft1_child_genesis1_txid; // We can get token info of an slp nft1 child genesis const slpChildGenesisMempoolInfo = await chronik.token( slpChildGenesisTxid, ); // We do not get mintVaultScripthash, data, or authPubkey keys in GenesisInfo for SLP NFT1 expect(slpChildGenesisMempoolInfo).to.deep.equal({ tokenId: slpChildGenesisTxid, - timeFirstSeen: '1300000000', + timeFirstSeen: 1300000000, tokenType: { protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_CHILD', number: 65, }, genesisInfo: { tokenTicker: 'SLP NFT CHILD', tokenName: 'Slp NFT CHILD token', url: '', // We get hash even if blank because SLP tokens can have this field hash: '', decimals: 0, }, }); slpChildGenesis = await chronik.tx(slpChildGenesisTxid); // We get expected inputs including expected Token data expect(slpChildGenesis.inputs).to.deep.equal([ { ...BASE_TX_INPUT, prevOut: { txid: '2c6258bee9033399108e845b3c69e60746b89624b3ec18c5d5cc4b2e88c6ccab', outIdx: 1, }, value: 2000, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpGenesisTxid, entryIdx: 1, amount: '1', isMintBaton: false, }, }, ]); // We get expected outputs including expected Token data expect(slpChildGenesis.outputs).to.deep.equal([ { ...BASE_TX_OUTPUT, value: 0, outputScript: '6a04534c500001410747454e455349530d534c50204e4654204348494c4413536c70204e4654204348494c4420746f6b656e4c004c0001004c00080000000000000001', }, { ...BASE_TX_OUTPUT, value: 1400, token: { ...BASE_TX_TOKEN_INFO_SLP_NFT, tokenId: slpChildGenesisTxid, tokenType: { number: 65, protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_CHILD', }, amount: '1', isMintBaton: false, }, }, ]); // We get a Entries of expected shape, with groupTokenId the txid of the genesis tx for this group // and tokenId of this txid expect(slpChildGenesis.tokenEntries).to.deep.equal([ { ...BASE_TOKEN_ENTRY, tokenId: slpChildGenesisTxid, txType: 'GENESIS', tokenType: { number: 65, protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_CHILD', }, groupTokenId: slpGenesisTxid, }, { ...BASE_TOKEN_ENTRY, tokenId: slpGenesisTxid, txType: 'NONE', tokenType: { number: 129, protocol: 'SLP', type: 'SLP_TOKEN_TYPE_NFT1_GROUP', }, }, ]); // The token did not fail parsings expect(slpChildGenesis.tokenFailedParsings).to.deep.equal([]); // Normal status expect(slpChildGenesis.tokenStatus).to.eql('TOKEN_STATUS_NORMAL'); }); it('Can get all of the above txs from the blockTxs endpoint after they are mined in a block', async () => { const chronik = new ChronikClientNode(chronikUrl); const blockTxs = await chronik.blockTxs(CHAIN_INIT_HEIGHT + 2); // Now that we have a block, we get a block key from token info const slpGenesisConfirmedInfo = await chronik.token(slpGenesisTxid); expect(typeof slpGenesisConfirmedInfo.block !== 'undefined').to.eql( true, ); const slpChildGenesisConfirmedInfo = await chronik.token( slpChildGenesisTxid, ); expect( typeof slpChildGenesisConfirmedInfo.block !== 'undefined', ).to.eql(true); // Clone as we will use blockTxs.txs later const txsFromBlock = JSON.parse(JSON.stringify(blockTxs.txs)); // The first tx is the coinbase tx, which is not a token const coinbaseTx = txsFromBlock.shift()!; expect(coinbaseTx.tokenEntries).to.deep.equal([]); expect(coinbaseTx.tokenFailedParsings).to.deep.equal([]); expect(coinbaseTx.tokenStatus).to.eql('TOKEN_STATUS_NON_TOKEN'); // The next txs are alphabetical by txid const broadcastTxs = [ slpGenesis, slpMint, slpSend, slpChildGenesis, ].sort((a, b) => a.txid.localeCompare(b.txid)); // The token fields of Tx_InNode(s) from blockTxs match the Tx_InNode(s) from tx // Note the txs are not expected to fully match bc now we have block and spentBy keys, // which are expected after confirmation // Full endpoint output is tested in blocktxs_and_tx_and_rawtx.ts for (const tx of broadcastTxs) { const nextTxFromBlock = txsFromBlock.shift()!; expect(tx.tokenEntries).to.deep.equal(nextTxFromBlock.tokenEntries); expect(tx.tokenFailedParsings).to.deep.equal( nextTxFromBlock.tokenFailedParsings, ); expect(tx.tokenStatus).to.deep.equal(nextTxFromBlock.tokenStatus); } // These are the only txs in from blockTxs expect(txsFromBlock.length).to.eql(0); // i.e., the coinbase tx + the 4 NFT1 txs broadcast expect(blockTxs.numTxs).to.eql(5); // We can also get the expected Tx shape by calling the script.history() const history = await chronik .script('p2sh', SCRIPTSIG_OP_TRUE_PAYLOAD) .history(); // Same as blockTxs, except different coinbase tx // Remove coinbase tx from both to compare // For blockTxs, it's the first tx blockTxs.txs.shift(); // For historyTxs, it's the last (oldest in time) history.txs.pop(); // We are not exhaustively testing the script endpoint here, see script_endpoints.ts expect(history.txs).to.have.deep.members(blockTxs.txs); // Same tx count as blockTxs expect(history.numTxs).to.eql(5); }); });