From adbe2b16aef244badb7ac010201a192b9d0bef67 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 20 Apr 2023 17:09:57 +0000 Subject: [PATCH 01/91] chore(release): 7.2.0-beta.1 [skip ci] ## [7.2.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.1.7...v7.2.0-beta.1) (2023-04-20) ### Features * stacking pool members endpoint ([#1592](https://github.com/hirosystems/stacks-blockchain-api/issues/1592)) ([3cd6023](https://github.com/hirosystems/stacks-blockchain-api/commit/3cd6023e895c964ed3d744652b169d51254ea6ed)), closes [#465](https://github.com/hirosystems/stacks-blockchain-api/issues/465) * support for subnets ([#1549](https://github.com/hirosystems/stacks-blockchain-api/issues/1549)) ([5d7056c](https://github.com/hirosystems/stacks-blockchain-api/commit/5d7056c1ba0aa0b202f341a83adf0f6bd2d13c71)) * support for subnets ([#1625](https://github.com/hirosystems/stacks-blockchain-api/issues/1625)) ([bfac932](https://github.com/hirosystems/stacks-blockchain-api/commit/bfac932f098f0311c9cf180b87724f871d1df82b)), closes [#1549](https://github.com/hirosystems/stacks-blockchain-api/issues/1549) [#1528](https://github.com/hirosystems/stacks-blockchain-api/issues/1528) [#1583](https://github.com/hirosystems/stacks-blockchain-api/issues/1583) [#1583](https://github.com/hirosystems/stacks-blockchain-api/issues/1583) ### Bug Fixes * disabled BTC faucet endpoint ([#1530](https://github.com/hirosystems/stacks-blockchain-api/issues/1530)) ([ce55212](https://github.com/hirosystems/stacks-blockchain-api/commit/ce55212f95fc52a3e890e78681e89682079c8f0f)) * domain migration ([#1596](https://github.com/hirosystems/stacks-blockchain-api/issues/1596)) ([2769e68](https://github.com/hirosystems/stacks-blockchain-api/commit/2769e684688f6d6c049baabc1d7777a330bc3f40)) * fixed the order of microblocks_streamed returned in reverse order in block endpoint ([#1528](https://github.com/hirosystems/stacks-blockchain-api/issues/1528)) ([764f64a](https://github.com/hirosystems/stacks-blockchain-api/commit/764f64a538c88a17c381eccb867ed3032e73bea1)) * log cleanup ([#1613](https://github.com/hirosystems/stacks-blockchain-api/issues/1613)) ([a067e39](https://github.com/hirosystems/stacks-blockchain-api/commit/a067e3906b89f9e1b40adb98072927d977f870d2)) * log level issues ([#1605](https://github.com/hirosystems/stacks-blockchain-api/issues/1605)) ([c3a2377](https://github.com/hirosystems/stacks-blockchain-api/commit/c3a237709a241eef4867258c8aac79dfdf4569e3)), closes [#1603](https://github.com/hirosystems/stacks-blockchain-api/issues/1603) [#1603](https://github.com/hirosystems/stacks-blockchain-api/issues/1603) [#1604](https://github.com/hirosystems/stacks-blockchain-api/issues/1604) [#1604](https://github.com/hirosystems/stacks-blockchain-api/issues/1604) [#1452](https://github.com/hirosystems/stacks-blockchain-api/issues/1452) * npm publish step ([#1617](https://github.com/hirosystems/stacks-blockchain-api/issues/1617)) ([c9cdbb6](https://github.com/hirosystems/stacks-blockchain-api/commit/c9cdbb693eb95cc0048041339ef3f0a7c2f5219f)) * optimize queries to retrieve BNS names ([#1581](https://github.com/hirosystems/stacks-blockchain-api/issues/1581)) ([1a6fde1](https://github.com/hirosystems/stacks-blockchain-api/commit/1a6fde145bd979614c614af95cd38d08a022ea3d)) * use chaintip-cache-control in `/stx_supply` endpoints [#1590](https://github.com/hirosystems/stacks-blockchain-api/issues/1590) ([#1594](https://github.com/hirosystems/stacks-blockchain-api/issues/1594)) ([a47f153](https://github.com/hirosystems/stacks-blockchain-api/commit/a47f1530a24da18bdcd9e6da64076a722e76af20)) * warning logger level for RPC proxy errors ([#1612](https://github.com/hirosystems/stacks-blockchain-api/issues/1612)) ([2454932](https://github.com/hirosystems/stacks-blockchain-api/commit/24549328d2e5ae974b7beb18baaccaa5e9d6685e)) --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f384527025..5368e36a0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,25 @@ +## [7.2.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.1.7...v7.2.0-beta.1) (2023-04-20) + + +### Features + +* stacking pool members endpoint ([#1592](https://github.com/hirosystems/stacks-blockchain-api/issues/1592)) ([3cd6023](https://github.com/hirosystems/stacks-blockchain-api/commit/3cd6023e895c964ed3d744652b169d51254ea6ed)), closes [#465](https://github.com/hirosystems/stacks-blockchain-api/issues/465) +* support for subnets ([#1549](https://github.com/hirosystems/stacks-blockchain-api/issues/1549)) ([5d7056c](https://github.com/hirosystems/stacks-blockchain-api/commit/5d7056c1ba0aa0b202f341a83adf0f6bd2d13c71)) +* support for subnets ([#1625](https://github.com/hirosystems/stacks-blockchain-api/issues/1625)) ([bfac932](https://github.com/hirosystems/stacks-blockchain-api/commit/bfac932f098f0311c9cf180b87724f871d1df82b)), closes [#1549](https://github.com/hirosystems/stacks-blockchain-api/issues/1549) [#1528](https://github.com/hirosystems/stacks-blockchain-api/issues/1528) [#1583](https://github.com/hirosystems/stacks-blockchain-api/issues/1583) [#1583](https://github.com/hirosystems/stacks-blockchain-api/issues/1583) + + +### Bug Fixes + +* disabled BTC faucet endpoint ([#1530](https://github.com/hirosystems/stacks-blockchain-api/issues/1530)) ([ce55212](https://github.com/hirosystems/stacks-blockchain-api/commit/ce55212f95fc52a3e890e78681e89682079c8f0f)) +* domain migration ([#1596](https://github.com/hirosystems/stacks-blockchain-api/issues/1596)) ([2769e68](https://github.com/hirosystems/stacks-blockchain-api/commit/2769e684688f6d6c049baabc1d7777a330bc3f40)) +* fixed the order of microblocks_streamed returned in reverse order in block endpoint ([#1528](https://github.com/hirosystems/stacks-blockchain-api/issues/1528)) ([764f64a](https://github.com/hirosystems/stacks-blockchain-api/commit/764f64a538c88a17c381eccb867ed3032e73bea1)) +* log cleanup ([#1613](https://github.com/hirosystems/stacks-blockchain-api/issues/1613)) ([a067e39](https://github.com/hirosystems/stacks-blockchain-api/commit/a067e3906b89f9e1b40adb98072927d977f870d2)) +* log level issues ([#1605](https://github.com/hirosystems/stacks-blockchain-api/issues/1605)) ([c3a2377](https://github.com/hirosystems/stacks-blockchain-api/commit/c3a237709a241eef4867258c8aac79dfdf4569e3)), closes [#1603](https://github.com/hirosystems/stacks-blockchain-api/issues/1603) [#1603](https://github.com/hirosystems/stacks-blockchain-api/issues/1603) [#1604](https://github.com/hirosystems/stacks-blockchain-api/issues/1604) [#1604](https://github.com/hirosystems/stacks-blockchain-api/issues/1604) [#1452](https://github.com/hirosystems/stacks-blockchain-api/issues/1452) +* npm publish step ([#1617](https://github.com/hirosystems/stacks-blockchain-api/issues/1617)) ([c9cdbb6](https://github.com/hirosystems/stacks-blockchain-api/commit/c9cdbb693eb95cc0048041339ef3f0a7c2f5219f)) +* optimize queries to retrieve BNS names ([#1581](https://github.com/hirosystems/stacks-blockchain-api/issues/1581)) ([1a6fde1](https://github.com/hirosystems/stacks-blockchain-api/commit/1a6fde145bd979614c614af95cd38d08a022ea3d)) +* use chaintip-cache-control in `/stx_supply` endpoints [#1590](https://github.com/hirosystems/stacks-blockchain-api/issues/1590) ([#1594](https://github.com/hirosystems/stacks-blockchain-api/issues/1594)) ([a47f153](https://github.com/hirosystems/stacks-blockchain-api/commit/a47f1530a24da18bdcd9e6da64076a722e76af20)) +* warning logger level for RPC proxy errors ([#1612](https://github.com/hirosystems/stacks-blockchain-api/issues/1612)) ([2454932](https://github.com/hirosystems/stacks-blockchain-api/commit/24549328d2e5ae974b7beb18baaccaa5e9d6685e)) + ## [7.1.7](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.1.5...v7.1.7) (2023-04-18) From 16d359370b413de36444d15a3a48cf479823367f Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Wed, 10 May 2023 13:19:52 -0600 Subject: [PATCH 02/91] fix: release pino logger and mempool nonces From ca03a814625f9e6ea0756510dfdcafee1e066258 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 11 May 2023 14:41:56 +0000 Subject: [PATCH 03/91] chore(release): 7.2.0-beta.2 [skip ci] ## [7.2.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.1...v7.2.0-beta.2) (2023-05-11) ### Bug Fixes * release pino logger and mempool nonces ([16d3593](https://github.com/hirosystems/stacks-blockchain-api/commit/16d359370b413de36444d15a3a48cf479823367f)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5368e36a0e..2cf8ec68c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.2.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.1...v7.2.0-beta.2) (2023-05-11) + + +### Bug Fixes + +* release pino logger and mempool nonces ([16d3593](https://github.com/hirosystems/stacks-blockchain-api/commit/16d359370b413de36444d15a3a48cf479823367f)) + ## [7.2.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.1.7...v7.2.0-beta.1) (2023-04-20) From 8a2c863ca73853a0cc2749455c5586b5d0f0375b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 12 May 2023 14:28:33 +0000 Subject: [PATCH 04/91] chore(release): 7.2.0-beta.3 [skip ci] ## [7.2.0-beta.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.2...v7.2.0-beta.3) (2023-05-12) ### Bug Fixes * enable requests auto logging ([#1656](https://github.com/hirosystems/stacks-blockchain-api/issues/1656)) ([2015b9c](https://github.com/hirosystems/stacks-blockchain-api/commit/2015b9c8805c189ebd80dfe16b775f805810a63f)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cf8ec68c3..777be8cd2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.2.0-beta.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.2...v7.2.0-beta.3) (2023-05-12) + + +### Bug Fixes + +* enable requests auto logging ([#1656](https://github.com/hirosystems/stacks-blockchain-api/issues/1656)) ([2015b9c](https://github.com/hirosystems/stacks-blockchain-api/commit/2015b9c8805c189ebd80dfe16b775f805810a63f)) + ## [7.2.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.1...v7.2.0-beta.2) (2023-05-11) From 1da46c6a756e74615610972bcd307f1e683113ef Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 10 Jun 2023 12:41:34 +0000 Subject: [PATCH 05/91] chore(release): 7.2.0-beta.4 [skip ci] ## [7.2.0-beta.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.3...v7.2.0-beta.4) (2023-06-10) ### Features * support custom chain_id (e.g. for subnets) ([#1669](https://github.com/hirosystems/stacks-blockchain-api/issues/1669)) ([1c6e35a](https://github.com/hirosystems/stacks-blockchain-api/commit/1c6e35a2dc0b5c161d35f291220a0bef6c6f5d28)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 777be8cd2c..c8228efb34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.2.0-beta.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.3...v7.2.0-beta.4) (2023-06-10) + + +### Features + +* support custom chain_id (e.g. for subnets) ([#1669](https://github.com/hirosystems/stacks-blockchain-api/issues/1669)) ([1c6e35a](https://github.com/hirosystems/stacks-blockchain-api/commit/1c6e35a2dc0b5c161d35f291220a0bef6c6f5d28)) + ## [7.2.0-beta.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.2.0-beta.2...v7.2.0-beta.3) (2023-05-12) From d5084c6689bb3cf08b58e0f96562234bc9c99417 Mon Sep 17 00:00:00 2001 From: max-crawford <102705427+max-crawford@users.noreply.github.com> Date: Wed, 4 Oct 2023 01:27:39 -0700 Subject: [PATCH 06/91] docs: Update how-to-install-stacks-cli.md (#1727) Cleaned up the voice and made this page more conversational. Of note, similar to my last PR, I'm removing some language around "Stacks 2.0" here alongside this cleanup --- .../how-to-install-stacks-cli.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/content/how-to-guides/how-to-install-stacks-cli.md b/content/how-to-guides/how-to-install-stacks-cli.md index 2822084f40..be78bafac4 100644 --- a/content/how-to-guides/how-to-install-stacks-cli.md +++ b/content/how-to-guides/how-to-install-stacks-cli.md @@ -2,7 +2,7 @@ title: How to install Stacks CLI --- -The Stacks CLI enables interactions with the Stacks 2.0 blockchain through a set of commands. +The Stacks CLI enables interactions with the Stacks blockchain through a set of commands. ## Installation @@ -18,7 +18,7 @@ The `-g` flag makes the CLI commands available globally ## Network selection -By default, the CLI will attempt to interact with the mainnet of the Stacks 2.0 blockchain. However, it is possible to override the network and set it to the testnet: +By default, the CLI will attempt to interact with Stacks mainnet. However, it is possible to override the network and set it to testnet: ```sh stx -t @@ -26,7 +26,7 @@ stx -t :::info -For account usage, that means addresses generated will _only_ be available for the specific network. An account generated for the testnet cannot be used on the mainnet. +For account usage, that means addresses generated will _only_ be available for the specific network. An account generated for testnet cannot be used on mainnet. ::: @@ -42,7 +42,7 @@ This section describes how to use the CLI to manage an account. :::caution -It is not recommended to use the CLI to handle accounts with real STX tokens on the mainnet. Using an appropriate wallet build to support secure token holding is recommended. +We don't recommended you use the CLI to handle accounts with real STX tokens on the mainnet. Instead, use an appropriate wallet to support secure token holding. ::: @@ -68,14 +68,14 @@ Your response should look like this: } ``` -The mnemonic is your 24 word seed phrase which you should back up securely if you want access to this account again in the future. Once lost, it cannot be recovered. +The mnemonic is your 24 word seed phrase, which you should back up securely if you want access to this account again in the future. Once lost, it cannot be recovered. The Stacks address associated with the newly generated account is: `ST1BG7MHW2R524WMF7X8PGG3V45ZN040EB9EW0GQJ` :::note -The preceding address is a testnet address that can only be used on the testnet. +The preceding address is a testnet address that can only be used on testnet. ::: @@ -115,10 +115,10 @@ This section describes how to use the CLI to generate and broadcast transactions In order to send tokens, the CLI command requires 5 parameters: - **Recipient Address**: The Stacks address of the recipient -- **Amount**: The number of Stacks to send denoted in microstacks (1 STX = 1000000 microstacks) -- **Fee Rate**: The transaction fee rate for this transaction. You can safely set a fee rate of 200 for Testnet +- **Amount**: The number of Stacks to send denoted in microstacks (1 STX = 1,000,000 microstacks) +- **Fee Rate**: The fee rate for this transaction. You can safely set a fee rate of 200 for testnet - **Nonce**: The nonce is a number that needs to be incremented monotonically for each transaction from the account. This ensures transactions are not duplicated -- **Private Key**: This is the private key corresponding to your account that was generated when +- **Private Key**: This is the private key corresponding to your account The CLI command to use with these parameters is `send_tokens`: @@ -135,7 +135,7 @@ stx send_tokens ST2KMMVJAB00W5Z6XWTFPH6B13JE9RJ2DCSHYX0S7 1000 200 0 381314da39a With this command we’re sending 1000 microstacks to the Stacks address `ST2KMMVJAB00W5Z6XWTFPH6B13JE9RJ2DCSHYX0S7`. -We set the fee rate to `200` microstacks. If you're not sure how much your transaction will cost. +We set the fee rate to `200` microstacks. :::tip @@ -147,9 +147,9 @@ The nonce is set to `0` for this transaction, since it will be the first transac Finally, the last parameter is the private key for the account. `381314da39a45f43f45ffd33b5d8767d1a38db0da71fea50ed9508e048765cf301` -Once again, we’re using the `-t` option to indicate that this is a Testnet transaction, so it should be broadcasted to Testnet. +Once again, we’re using the `-t` option to indicate that this is a testnet transaction, so it should be broadcast to testnet. -If valid, the transaction will be broadcasted to the network and the command will respond with a transaction ID. +If valid, the transaction will be broadcast to the network, and the command will respond with a transaction ID. :::tip From ca59fad6b3fd07e06daf186ebb2693aea1eb18a0 Mon Sep 17 00:00:00 2001 From: max-crawford <102705427+max-crawford@users.noreply.github.com> Date: Wed, 4 Oct 2023 01:28:34 -0700 Subject: [PATCH 07/91] docs: Update rosetta-support.md (#1728) there is a missing period --- content/feature-guides/rosetta-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/feature-guides/rosetta-support.md b/content/feature-guides/rosetta-support.md index 1d24082fc5..7059b3df65 100644 --- a/content/feature-guides/rosetta-support.md +++ b/content/feature-guides/rosetta-support.md @@ -56,4 +56,4 @@ rosetta-cli \ `rosetta-cli` will then sync with the blockchain until it reaches the tip, and then exit, displaying the test results. Currently, account reconciliation is disabled; proper testing of that feature requires token transfer transactions while `rosetta-cli` is running. Documentation for the Rosetta APIs can be found [here](https://hirosystems.github.io/stacks-blockchain-api/). -You may also review Data and Construction Rosetta endpoints [here](https://docs.hiro.so/api#tag/Rosetta) +You may also review Data and Construction Rosetta endpoints [here](https://docs.hiro.so/api#tag/Rosetta). From 8e2aa7624ffb247fed7b579d547e93d48961a592 Mon Sep 17 00:00:00 2001 From: max-crawford <102705427+max-crawford@users.noreply.github.com> Date: Wed, 4 Oct 2023 01:29:51 -0700 Subject: [PATCH 08/91] docs: Update overview.md (#1729) Grammar fixes --- content/overview.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/overview.md b/content/overview.md index 9e408725bb..3f3904cc50 100644 --- a/content/overview.md +++ b/content/overview.md @@ -6,7 +6,7 @@ Title: Overview The Stacks blockchain API allows you to query the Stacks blockchain and interact with smart contracts. It was built to maintain paginated, materialized views of the Stacks Blockchain. -The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust the hosted server, but this API also provides a faster development experience. You may wish to consider running your own API instance to create a fully trustless architecture for your app. +The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust us as the hosted server, but in return we provide a faster development experience. If you want a fully trustless architecture for your app, you may wish to consider running your own API instance. > **_NOTE:_** > @@ -18,14 +18,14 @@ The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust the ![API architecture!](images/api-architecture.png) -* The `stacks-node` has it's own minimal set of http endpoints referred to as `RPC endpoints` +* The `stacks-node` has its own minimal set of http endpoints referred to as `RPC endpoints` * The `stacks-blockchain-api` allows clients to access these endpoints by proxying them through to a load-balanced pool of `stacks-nodes`. * See: https://github.com/blockstack/stacks-blockchain/blob/master/docs/rpc-endpoints.md -- some common ones: - * `POST /v2/transactions` - broadcast a tx. + * `POST /v2/transactions` - broadcast a transaction. * `GET /v2/pox` - get current PoX-relevant information. - * `POST /v2/contracts/call-read//` - evaluates and returns the result of calling a Clarity function. - * `POST /v2/fees/transaction` - evaluates a given transaction and returns tx fee estimation data. - * `GET /v2/accounts/
` - used to get the current `nonce` required for creating transactions. + * `POST /v2/contracts/call-read//` - evaluate and return the result of calling a Clarity function. + * `POST /v2/fees/transaction` - evaluate a given transaction and return transaction fee estimation data. + * `GET /v2/accounts/
` - get the current `nonce` required for creating transactions. * The endpoints implemented by `stacks-blockchain-api` provide data that the `stacks-node` can't due to various constraints. @@ -52,7 +52,7 @@ The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust the * ALSO the OpenAPI + JSONSchemas are used to generate a standalone `@stacks/blockchain-api-client`. -* The easiest/quickest way to develop in this repo is using the vscode debugger. It uses docker-compose to setup a `stacks-node` and postgres instance. +* The easiest/quickest way to develop in this repo is using the VS Code debugger. It uses docker-compose to setup a `stacks-node` and Postgres instance. * Alternatively, you can run `npm run dev:integrated` which does the same thing but without a debugger. From bb6bc49bd71a31d791e6a57aab4d6be1e6fe673d Mon Sep 17 00:00:00 2001 From: max-crawford <102705427+max-crawford@users.noreply.github.com> Date: Wed, 4 Oct 2023 01:31:14 -0700 Subject: [PATCH 09/91] docs: Update how-to-run-api-node.md (#1730) A number of grammar fixes and tweaks --- content/how-to-guides/how-to-run-api-node.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/content/how-to-guides/how-to-run-api-node.md b/content/how-to-guides/how-to-run-api-node.md index 7d63685509..4c54448747 100644 --- a/content/how-to-guides/how-to-run-api-node.md +++ b/content/how-to-guides/how-to-run-api-node.md @@ -1,23 +1,23 @@ --- -title: How to run API node +title: How to Run an API Node --- -This procedure demonstrates how to run a local API node using Docker images. There are several components that must be +This guide shows you how to run a local API node using Docker images. There are several components that must be configured and run in a specific order for the local API node to work. -For this procedure, the order in which the services are brought up is very important. In order to start the API node +Note: the order in which the services are brought up is very important. In order to start the API node successfully, you need to bring up the services in the following order: 1. `postgres` 2. `stacks-blockchain-api` 3. `stacks-blockchain` -When bringing down the API node, you should bring the services down in the exact reverse order in which they were -brought up, to avoid losing data. +When bringing down the API node, you should bring the services down in the reverse order in which they were +brought up in order to avoid losing data. :::note -This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on +This guide focuses on Unix-like operating systems (Linux and MacOS). This has not been tested on Windows. ::: @@ -25,7 +25,7 @@ Windows. ## Prerequisites Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi -boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software +boards and other system-on-chip architectures. However, in order to complete this guide, you do need the following software installed on the node host machine: - [Docker](https://docs.docker.com/get-docker/) @@ -234,13 +234,13 @@ To verify the database is ready: 2. List current databases with the command `\l` 3. Disconnect from the database with the command `\q` -To verify the `stacks-blockchain` tip height is progressing use the following command: +To verify that the `stacks-blockchain` tip height is progressing, use the following command: ```sh curl -sL localhost:20443/v2/info | jq ``` -If the instance is running you should receive terminal output similar to the following: +If the instance is running, you should receive terminal output similar to the following: ```json { From 20097fcb415b965073b61dca33a5effca4f56d7c Mon Sep 17 00:00:00 2001 From: max-crawford <102705427+max-crawford@users.noreply.github.com> Date: Wed, 4 Oct 2023 01:32:27 -0700 Subject: [PATCH 10/91] docs: Update how-to-run-mainnet-node.md (#1731) Grammar fixes! --- content/how-to-guides/how-to-run-mainnet-node.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/how-to-guides/how-to-run-mainnet-node.md b/content/how-to-guides/how-to-run-mainnet-node.md index c3539a7fd6..6114213652 100644 --- a/content/how-to-guides/how-to-run-mainnet-node.md +++ b/content/how-to-guides/how-to-run-mainnet-node.md @@ -1,12 +1,12 @@ --- -title: How to run mainnet node +title: How to Run a Mainnet Node --- -This procedure demonstrates how to run a local mainnet node using Docker images. +This guide shows you how to run a local mainnet node using Docker images. :::note -This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on +This guide focuses on Unix-like operating systems (Linux and MacOS). This has not been tested on Windows. ::: @@ -14,7 +14,7 @@ Windows. ## Prerequisites Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi -boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software +boards and other system-on-chip architectures. However, in order to complete this guide, you do need the following software installed on the node host machine: - [Docker](https://docs.docker.com/get-docker/) @@ -129,13 +129,13 @@ INFO [1626290748.103291] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitc INFO [1626290776.956535] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.7% (12000 out of 691034) ``` -To verify the `stacks-blockchain` tip height is progressing use the following command: +To verify that the `stacks-blockchain` tip height is progressing, use the following command: ```sh curl -sL localhost:20443/v2/info | jq ``` -If the instance is running you should receive terminal output similar to the following: +If the instance is running, you should receive terminal output similar to the following: ```json { From cc4d0e5eea7876a25e349eef5991497f8b61e673 Mon Sep 17 00:00:00 2001 From: max-crawford <102705427+max-crawford@users.noreply.github.com> Date: Wed, 4 Oct 2023 01:33:40 -0700 Subject: [PATCH 11/91] docs: Update how-to-run-testnet-node.md (#1732) Grammar fixes --- content/how-to-guides/how-to-run-testnet-node.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/content/how-to-guides/how-to-run-testnet-node.md b/content/how-to-guides/how-to-run-testnet-node.md index b5e5cc2f98..d1db09ee7c 100644 --- a/content/how-to-guides/how-to-run-testnet-node.md +++ b/content/how-to-guides/how-to-run-testnet-node.md @@ -1,12 +1,12 @@ --- -title: How to run testnet node +title: How to Run a Testnet Node --- -This procedure demonstrates how to run a local testnet node using Docker images. +This guide shows you how to run a local testnet node using Docker images. :::note -This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on +This guide focuses on Unix-like operating systems (Linux and MacOS). This has not been tested on Windows. ::: @@ -14,7 +14,7 @@ Windows. ## Prerequisites Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi -boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software +boards and other system-on-chip architectures. However, in order to complete this procedure, you do need the following software installed on the node host machine: - [Docker](https://docs.docker.com/get-docker/) @@ -45,7 +45,7 @@ These egress ports are for syncing `stacks-blockchain` and Bitcoin headers. If t ## Step 1: Initial setup -In order to run the testnet node, you must download the Docker images and create a directory structure to hold the +In order to run a testnet node, you must download the Docker images and create a directory structure to hold the persistent data from the services. Download and configure the Docker images with the following commands: ```sh @@ -100,13 +100,13 @@ INFO [1626290748.103291] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitc INFO [1626290776.956535] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.7% (12000 out of 2034380) ``` -To verify the `stacks-blockchain` tip height is progressing use the following command: +To verify that the `stacks-blockchain` tip height is progressing, use the following command: ```sh curl -sL localhost:20443/v2/info | jq ``` -If the instance is running you should receive terminal output similar to the following: +If the instance is running, you should receive terminal output similar to the following: ```json { From fb0d0eaa93a0614c54cfa28464fe5df25ac9c7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Wed, 25 Oct 2023 10:48:03 -0600 Subject: [PATCH 12/91] fix: move nft custody view into a table (#1741) * fix: move to table * fix: old nft events query * fix: nft-custody-table migration * fix: no longer rename old views, just remove them --------- Co-authored-by: Matt --- .../1696872367486_nft-custody-tables.js | 215 ++++++++++++++++++ src/datastore/common.ts | 14 ++ src/datastore/pg-store.ts | 7 +- src/datastore/pg-write-store.ts | 161 +++++++++---- src/tests/search-tests.ts | 4 +- src/tests/token-tests.ts | 1 - 6 files changed, 349 insertions(+), 53 deletions(-) create mode 100644 migrations/1696872367486_nft-custody-tables.js diff --git a/migrations/1696872367486_nft-custody-tables.js b/migrations/1696872367486_nft-custody-tables.js new file mode 100644 index 0000000000..f74a748f5e --- /dev/null +++ b/migrations/1696872367486_nft-custody-tables.js @@ -0,0 +1,215 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.dropMaterializedView('nft_custody'); + pgm.createTable('nft_custody', { + asset_identifier: { + type: 'string', + notNull: true, + }, + value: { + type: 'bytea', + notNull: true, + }, + recipient: { + type: 'text', + }, + block_height: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + parent_index_block_hash: { + type: 'bytea', + notNull: true, + }, + microblock_hash: { + type: 'bytea', + notNull: true, + }, + microblock_sequence: { + type: 'integer', + notNull: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + tx_index: { + type: 'smallint', + notNull: true, + }, + event_index: { + type: 'integer', + notNull: true, + }, + }); + pgm.createConstraint('nft_custody', 'nft_custody_unique', 'UNIQUE(asset_identifier, value)'); + pgm.createIndex('nft_custody', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody', 'value'); + pgm.createIndex('nft_custody', [ + { name: 'block_height', sort: 'DESC' }, + { name: 'microblock_sequence', sort: 'DESC' }, + { name: 'tx_index', sort: 'DESC' }, + { name: 'event_index', sort: 'DESC' } + ]); + pgm.sql(` + INSERT INTO nft_custody (asset_identifier, value, recipient, tx_id, block_height, index_block_hash, parent_index_block_hash, microblock_hash, microblock_sequence, tx_index, event_index) ( + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height, + nft.index_block_hash, nft.parent_index_block_hash, nft.microblock_hash, nft.microblock_sequence, nft.tx_index, nft.event_index + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + ) + `); + + pgm.dropMaterializedView('nft_custody_unanchored'); + pgm.createTable('nft_custody_unanchored', { + asset_identifier: { + type: 'string', + notNull: true, + }, + value: { + type: 'bytea', + notNull: true, + }, + recipient: { + type: 'text', + }, + block_height: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + parent_index_block_hash: { + type: 'bytea', + notNull: true, + }, + microblock_hash: { + type: 'bytea', + notNull: true, + }, + microblock_sequence: { + type: 'integer', + notNull: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + tx_index: { + type: 'smallint', + notNull: true, + }, + event_index: { + type: 'integer', + notNull: true, + }, + }); + pgm.createConstraint('nft_custody_unanchored', 'nft_custody_unanchored_unique', 'UNIQUE(asset_identifier, value)'); + pgm.createIndex('nft_custody_unanchored', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody_unanchored', 'value'); + pgm.createIndex('nft_custody_unanchored', [ + { name: 'block_height', sort: 'DESC' }, + { name: 'microblock_sequence', sort: 'DESC' }, + { name: 'tx_index', sort: 'DESC' }, + { name: 'event_index', sort: 'DESC' } + ]); + pgm.sql(` + INSERT INTO nft_custody_unanchored (asset_identifier, value, recipient, tx_id, block_height, index_block_hash, parent_index_block_hash, microblock_hash, microblock_sequence, tx_index, event_index) ( + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height, + nft.index_block_hash, nft.parent_index_block_hash, nft.microblock_hash, nft.microblock_sequence, nft.tx_index, nft.event_index + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + ) + `); +}; + +exports.down = pgm => { + pgm.dropTable('nft_custody'); + pgm.createMaterializedView('nft_custody', { data: true }, ` + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + `); + pgm.createIndex('nft_custody', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody', ['asset_identifier', 'value'], { unique: true }); + pgm.createIndex('nft_custody', 'value'); + + pgm.dropTable('nft_custody_unanchored'); + pgm.createMaterializedView('nft_custody_unanchored', { data: true }, ` + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + `); + pgm.createIndex('nft_custody_unanchored', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody_unanchored', ['asset_identifier', 'value'], { unique: true }); + pgm.createIndex('nft_custody_unanchored', 'value'); +}; diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 7a0a2062a8..57e6caffb7 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -1357,6 +1357,20 @@ export interface NftEventInsertValues { value: PgBytea; } +export interface NftCustodyInsertValues { + event_index: number; + tx_id: PgBytea; + tx_index: number; + block_height: number; + index_block_hash: PgBytea; + parent_index_block_hash: PgBytea; + microblock_hash: PgBytea; + microblock_sequence: number; + recipient: string | null; + asset_identifier: string; + value: PgBytea; +} + export interface FtEventInsertValues { event_index: number; tx_id: PgBytea; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 29ab013922..b351323871 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -3318,6 +3318,7 @@ export class PgStore { FROM ${nftCustody} AS nft WHERE nft.recipient = ${args.principal} ${assetIdFilter} + ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC LIMIT ${args.limit} OFFSET ${args.offset} ) @@ -3519,11 +3520,11 @@ export class PgStore { AND block_height <= ${args.blockHeight} ORDER BY asset_identifier, value, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC ) - SELECT sender, recipient, asset_identifier, value, event_index, asset_event_type_id, address_transfers.block_height, address_transfers.tx_id, (COUNT(*) OVER())::INTEGER AS count - FROM address_transfers + SELECT sender, recipient, asset_identifier, value, at.event_index, asset_event_type_id, at.block_height, at.tx_id, (COUNT(*) OVER())::INTEGER AS count + FROM address_transfers AS at INNER JOIN ${args.includeUnanchored ? this.sql`last_nft_transfers` : this.sql`nft_custody`} USING (asset_identifier, value, recipient) - ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC + ORDER BY at.block_height DESC, at.microblock_sequence DESC, at.tx_index DESC, event_index DESC LIMIT ${args.limit} OFFSET ${args.offset} `; diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 07b1614060..29bb435d63 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -9,7 +9,6 @@ import { DbSmartContractEvent, DbSmartContract, DataStoreBlockUpdateData, - DbMempoolTx, DbStxLockEvent, DbMinerReward, DbBurnchainReward, @@ -63,6 +62,7 @@ import { DbMempoolTxRaw, DbChainTip, DbPox3Event, + NftCustodyInsertValues, } from './common'; import { ClarityAbi } from '@stacks/transactions'; import { @@ -407,7 +407,7 @@ export class PgWriteStore extends PgStore { await this.updateFtEvent(sql, entry.tx, ftEvent); } for (const nftEvent of entry.nftEvents) { - await this.updateNftEvent(sql, entry.tx, nftEvent); + await this.updateNftEvent(sql, entry.tx, nftEvent, false); } deployedSmartContracts.push(...entry.smartContracts); for (const smartContract of entry.smartContracts) { @@ -466,7 +466,6 @@ export class PgWriteStore extends PgStore { const ibdHeight = getIbdBlockHeight(); this.isIbdBlockHeightReached = ibdHeight ? data.block.block_height > ibdHeight : true; - await this.refreshNftCustody(batchedTxData); await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); @@ -746,7 +745,6 @@ export class PgWriteStore extends PgStore { } }); - await this.refreshNftCustody(txData, true); await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); @@ -1313,27 +1311,65 @@ export class PgWriteStore extends PgStore { `; } - async updateNftEvent(sql: PgSqlClient, tx: DbTx, event: DbNftEvent) { - const values: NftEventInsertValues = { + async updateNftEvent(sql: PgSqlClient, tx: DbTx, event: DbNftEvent, microblock: boolean) { + const custody: NftCustodyInsertValues = { + asset_identifier: event.asset_identifier, + value: event.value, tx_id: event.tx_id, index_block_hash: tx.index_block_hash, parent_index_block_hash: tx.parent_index_block_hash, microblock_hash: tx.microblock_hash, microblock_sequence: tx.microblock_sequence, - microblock_canonical: tx.microblock_canonical, - sender: event.sender ?? null, recipient: event.recipient ?? null, event_index: event.event_index, tx_index: event.tx_index, block_height: event.block_height, + }; + const values: NftEventInsertValues = { + ...custody, + microblock_canonical: tx.microblock_canonical, canonical: event.canonical, + sender: event.sender ?? null, asset_event_type_id: event.asset_event_type_id, - asset_identifier: event.asset_identifier, - value: event.value, }; await sql` INSERT INTO nft_events ${sql(values)} `; + if (tx.canonical && tx.microblock_canonical && event.canonical) { + const table = microblock ? sql`nft_custody_unanchored` : sql`nft_custody`; + await sql` + INSERT INTO ${table} ${sql(custody)} + ON CONFLICT ON CONSTRAINT ${table}_unique DO UPDATE SET + tx_id = EXCLUDED.tx_id, + index_block_hash = EXCLUDED.index_block_hash, + parent_index_block_hash = EXCLUDED.parent_index_block_hash, + microblock_hash = EXCLUDED.microblock_hash, + microblock_sequence = EXCLUDED.microblock_sequence, + recipient = EXCLUDED.recipient, + event_index = EXCLUDED.event_index, + tx_index = EXCLUDED.tx_index, + block_height = EXCLUDED.block_height + WHERE + ( + EXCLUDED.block_height > ${table}.block_height + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence > ${table}.microblock_sequence + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence + AND EXCLUDED.tx_index > ${table}.tx_index + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence + AND EXCLUDED.tx_index = ${table}.tx_index + AND EXCLUDED.event_index > ${table}.event_index + ) + `; + } } async updateBatchSmartContractEvent(sql: PgSqlClient, tx: DbTx, events: DbSmartContractEvent[]) { @@ -2206,7 +2242,7 @@ export class PgWriteStore extends PgStore { await this.updateFtEvent(sql, entry.tx, ftEvent); } for (const nftEvent of entry.nftEvents) { - await this.updateNftEvent(sql, entry.tx, nftEvent); + await this.updateNftEvent(sql, entry.tx, nftEvent, true); } for (const smartContract of entry.smartContracts) { await this.updateSmartContract(sql, entry.tx, smartContract); @@ -2288,11 +2324,74 @@ export class PgWriteStore extends PgStore { AND (index_block_hash = ${args.indexBlockHash} OR index_block_hash = '\\x'::bytea) AND tx_id IN ${sql(txIds)} `; + await this.updateNftCustodyFromReOrg(sql, { + index_block_hash: args.indexBlockHash, + microblocks: args.microblocks, + }); } return { updatedTxs: updatedMbTxs }; } + /** + * Refreshes NFT custody data for events within a block or series of microblocks. + * @param sql - SQL client + * @param args - Block and microblock hashes + */ + async updateNftCustodyFromReOrg( + sql: PgSqlClient, + args: { + index_block_hash: string; + microblocks: string[]; + } + ): Promise { + for (const table of [sql`nft_custody`, sql`nft_custody_unanchored`]) { + await sql` + INSERT INTO ${table} + (asset_identifier, value, tx_id, index_block_hash, parent_index_block_hash, microblock_hash, + microblock_sequence, recipient, event_index, tx_index, block_height) + ( + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, tx_id, txs.index_block_hash, + txs.parent_index_block_hash, txs.microblock_hash, txs.microblock_sequence, recipient, + nft.event_index, txs.tx_index, txs.block_height + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + AND nft.index_block_hash = ${args.index_block_hash} + ${ + args.microblocks.length > 0 + ? sql`AND nft.microblock_hash IN ${sql(args.microblocks)}` + : sql`` + } + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + ) + ON CONFLICT ON CONSTRAINT ${table}_unique DO UPDATE SET + tx_id = EXCLUDED.tx_id, + index_block_hash = EXCLUDED.index_block_hash, + parent_index_block_hash = EXCLUDED.parent_index_block_hash, + microblock_hash = EXCLUDED.microblock_hash, + microblock_sequence = EXCLUDED.microblock_sequence, + recipient = EXCLUDED.recipient, + event_index = EXCLUDED.event_index, + tx_index = EXCLUDED.tx_index, + block_height = EXCLUDED.block_height + `; + } + } + /** * Fetches from the `microblocks` table with a given `parent_index_block_hash` and a known * latest unanchored microblock tip. Microblocks that are chained to the given tip are @@ -2554,6 +2653,10 @@ export class PgWriteStore extends PgStore { } else { updatedEntities.markedNonCanonical.nftEvents += nftResult.count; } + await this.updateNftCustodyFromReOrg(sql, { + index_block_hash: indexBlockHash, + microblocks: [], + }); // todo: do we still need pox2 marking here? const pox2Result = await sql` @@ -2922,40 +3025,6 @@ export class PgWriteStore extends PgStore { await sql`REFRESH MATERIALIZED VIEW ${isProdEnv ? sql`CONCURRENTLY` : sql``} ${sql(viewName)}`; } - /** - * Refreshes the `nft_custody` and `nft_custody_unanchored` materialized views if necessary. - * @param sql - DB client - * @param txs - Transaction event data - * @param unanchored - If this refresh is requested from a block or microblock - */ - async refreshNftCustody(txs: DataStoreTxEventData[], unanchored: boolean = false) { - await this.sqlWriteTransaction(async sql => { - const newNftEventCount = txs - .map(tx => tx.nftEvents.length) - .reduce((prev, cur) => prev + cur, 0); - if (newNftEventCount > 0) { - // Always refresh unanchored view since even if we're in a new anchored block we should update the - // unanchored state to the current one. - await this.refreshMaterializedView('nft_custody_unanchored', sql); - if (!unanchored) { - await this.refreshMaterializedView('nft_custody', sql); - } - } else if (!unanchored) { - // Even if we didn't receive new NFT events in a new anchor block, we should check if we need to - // update the anchored view to reflect any changes made by previous microblocks. - const result = await sql<{ outdated: boolean }[]>` - WITH anchored_height AS (SELECT MAX(block_height) AS anchored FROM nft_custody), - unanchored_height AS (SELECT MAX(block_height) AS unanchored FROM nft_custody_unanchored) - SELECT unanchored > anchored AS outdated - FROM anchored_height CROSS JOIN unanchored_height - `; - if (result.length > 0 && result[0].outdated) { - await this.refreshMaterializedView('nft_custody', sql); - } - } - }); - } - /** * Called when a full event import is complete. */ @@ -2964,8 +3033,6 @@ export class PgWriteStore extends PgStore { return; } await this.sqlWriteTransaction(async sql => { - await this.refreshMaterializedView('nft_custody', sql, false); - await this.refreshMaterializedView('nft_custody_unanchored', sql, false); await this.refreshMaterializedView('chain_tip', sql, false); await this.refreshMaterializedView('mempool_digest', sql, false); }); diff --git a/src/tests/search-tests.ts b/src/tests/search-tests.ts index 32b0ee3b23..c994399ee6 100644 --- a/src/tests/search-tests.ts +++ b/src/tests/search-tests.ts @@ -820,7 +820,7 @@ describe('search tests', () => { recipient: addr7, sender: 'none', }; - await db.updateNftEvent(client, stxTx1, nftEvent1); + await db.updateNftEvent(client, stxTx1, nftEvent1, false); // test address as a nft event recipient const searchResult7 = await supertest(api.server).get(`/extended/v1/search/${addr7}`); @@ -848,7 +848,7 @@ describe('search tests', () => { recipient: 'none', sender: addr8, }; - await db.updateNftEvent(client, stxTx1, nftEvent2); + await db.updateNftEvent(client, stxTx1, nftEvent2, false); // test address as a nft event sender const searchResult8 = await supertest(api.server).get(`/extended/v1/search/${addr8}`); diff --git a/src/tests/token-tests.ts b/src/tests/token-tests.ts index d93ee3026b..12d6d5aebc 100644 --- a/src/tests/token-tests.ts +++ b/src/tests/token-tests.ts @@ -3,7 +3,6 @@ import { ChainID } from '@stacks/transactions'; import { ApiServer, startApiServer } from '../api/init'; import { TestBlockBuilder, TestMicroblockStreamBuilder } from '../test-utils/test-builders'; import { DbAssetEventTypeId } from '../datastore/common'; -import { hexToBuffer } from '../helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; import { cycleMigrations, runMigrations } from '../datastore/migrations'; From 74606c7e479ac82ea1caac90a51a5db0a82ad7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 31 Oct 2023 13:05:35 -0600 Subject: [PATCH 13/91] refactor: use the API toolkit, upgrade to node 18 (#1743) --- .github/workflows/ci.yml | 138 +- .nvmrc | 2 +- .releaserc | 51 + Dockerfile | 4 +- docker/rosetta.Dockerfile | 3 +- docker/standalone-regtest.Dockerfile | 3 +- docs/package-lock.json | 274 +- docs/package.json | 6 +- git-info-generator.mjs | 23 - package-lock.json | 16272 ++++------------ package.json | 149 +- running_api_from_source.md | 1 - src/api/controllers/cache-controller.ts | 3 +- src/api/init.ts | 22 +- src/api/query-helpers.ts | 3 +- src/api/rosetta-validate.ts | 3 +- src/api/routes/address.ts | 13 +- src/api/routes/block.ts | 2 +- src/api/routes/core-node-rpc-proxy.ts | 2 +- src/api/routes/debug.ts | 26 +- src/api/routes/info.ts | 2 +- src/api/routes/microblock.ts | 2 +- src/api/routes/rosetta/account.ts | 3 +- src/api/routes/rosetta/block.ts | 3 +- src/api/routes/rosetta/construction.ts | 3 +- src/api/routes/rosetta/mempool.ts | 3 +- src/api/routes/search.ts | 3 +- src/api/routes/status.ts | 4 +- src/api/routes/tokens/tokens.ts | 3 +- src/api/routes/tx.ts | 3 +- .../routes/ws/channels/socket-io-channel.ts | 3 +- src/api/routes/ws/channels/ws-rpc-channel.ts | 8 +- src/btc-faucet.ts | 3 +- src/core-rpc/client.ts | 3 +- src/datastore/common.ts | 2 +- src/datastore/connection.ts | 205 +- src/datastore/helpers.ts | 48 +- src/datastore/migrations.ts | 102 - src/datastore/pg-notifier.ts | 11 +- src/datastore/pg-store.ts | 98 +- src/datastore/pg-write-store.ts | 44 +- src/ec-helpers.ts | 2 +- .../connection-legacy.ts | 15 +- src/event-replay/event-replay.ts | 22 +- .../event-requests.ts | 38 +- src/event-replay/helpers.ts | 22 - src/event-replay/parquet-based/helpers.ts | 4 +- .../parquet-based/replay-controller.ts | 14 +- src/event-stream/bns/bns-helpers.ts | 6 +- src/event-stream/core-node-message.ts | 4 +- src/event-stream/event-server.ts | 14 +- src/event-stream/pox2-event-parsing.ts | 9 +- src/event-stream/reader.ts | 30 +- src/helpers.ts | 274 +- src/import-v1/index.ts | 2 +- src/index.ts | 18 +- src/inspector-util.ts | 13 +- src/rosetta-helpers.ts | 3 +- src/shutdown-handler.ts | 92 - src/test-utils/shared-setup.ts | 9 +- src/test-utils/test-builders.ts | 15 +- src/test-utils/test-helpers.ts | 14 +- src/tests-2.4/global-setup.ts | 9 +- src/tests-2.4/global-teardown.ts | 2 + src/tests-2.4/pox-3-btc-address-formats.ts | 3 +- src/tests-2.4/pox-3-burnchain-delegate-stx.ts | 10 +- src/tests-2.4/pox-3-burnchain-stack-stx.ts | 5 +- src/tests-2.4/pox-3-rosetta-segwit.ts | 2 +- src/tests-2.4/pox-3-stack-extend-increase.ts | 12 +- src/tests-bns-e2e/bns-integration-tests.ts | 17 +- src/tests-bns/api.ts | 19 +- src/tests-bns/event-server-tests.ts | 11 +- src/tests-bns/v1-import-tests.ts | 7 +- src/tests-btc-faucet/faucet-btc-tests.ts | 22 +- src/tests-btc-faucet/setup.ts | 3 +- src/tests-event-replay/import-export-tests.ts | 42 +- .../poison-microblock-tests.ts | 1 - .../raw-event-request-tests.ts | 12 +- src/tests-event-replay/setup.ts | 1 + src/tests-rosetta-cli-construction/setup.ts | 1 + .../teardown.ts | 2 +- .../validate-construction.ts | 9 +- src/tests-rosetta-cli-data/setup.ts | 1 + src/tests-rosetta-cli-data/teardown.ts | 2 +- .../validate-rosetta.ts | 11 +- .../construction.ts | 25 +- src/tests-rosetta/account-tests.ts | 18 +- src/tests-rosetta/api.ts | 22 +- src/tests-rosetta/block-tests.ts | 25 +- src/tests-rosetta/offline-api-tests.ts | 22 +- src/tests-rosetta/setup.ts | 1 + src/tests-rpc/core-rpc-tests.ts | 10 - src/tests-subnets/global-setup.ts | 11 +- src/tests-subnets/subnet-tests.ts | 8 +- .../tokens-metadata-tests.ts | 26 +- src/tests-tokens-strict/strict-mode-tests.ts | 17 +- src/tests/address-tests.ts | 51 +- src/tests/block-tests.ts | 31 +- src/tests/burnchain-tests.ts | 19 +- src/tests/cache-control-tests.ts | 26 +- src/tests/datastore-tests.ts | 318 +- src/tests/git-info-script-tests.ts | 56 - src/tests/helpers-tests.ts | 9 +- src/tests/import-genesis-tests.ts | 15 +- src/tests/mempool-tests.ts | 49 +- src/tests/microblock-tests.ts | 41 +- src/tests/other-tests.ts | 23 +- src/tests/search-tests.ts | 45 +- src/tests/smart-contract-tests.ts | 29 +- src/tests/socket-io-tests.ts | 19 +- src/tests/synthetic-stx-txs-tests.ts | 6 +- src/tests/token-tests.ts | 18 +- src/tests/tx-tests.ts | 103 +- src/tests/v2-proxy-tests.ts | 16 +- src/tests/websocket-tests.ts | 19 +- src/tests/ws-transmitter-tests.ts | 14 +- src/token-metadata/helpers.ts | 4 +- src/token-metadata/tokens-contract-handler.ts | 3 +- 118 files changed, 4976 insertions(+), 14503 deletions(-) create mode 100644 .releaserc delete mode 100644 git-info-generator.mjs delete mode 100644 src/datastore/migrations.ts rename src/{datastore => event-replay}/connection-legacy.ts (91%) rename src/{datastore => event-replay}/event-requests.ts (76%) delete mode 100644 src/shutdown-handler.ts delete mode 100644 src/tests/git-info-script-tests.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20115adf60..7ac6bc5440 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,15 +18,15 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -57,17 +57,17 @@ jobs: run: working-directory: ./docs steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -104,15 +104,15 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -157,7 +157,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -171,15 +171,15 @@ jobs: test-event-replay: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -213,7 +213,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -227,15 +227,15 @@ jobs: test-rpc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -272,7 +272,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -286,15 +286,15 @@ jobs: test-btc-faucet: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -331,7 +331,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -345,15 +345,15 @@ jobs: test-bns: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -390,7 +390,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -404,15 +404,15 @@ jobs: test-subnets: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -449,7 +449,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -463,15 +463,15 @@ jobs: test-bns-e2e: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -508,7 +508,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -540,15 +540,15 @@ jobs: ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -585,7 +585,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -599,15 +599,15 @@ jobs: test-rosetta: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -644,7 +644,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -658,15 +658,15 @@ jobs: test-rosetta-construction: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -703,7 +703,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -717,15 +717,15 @@ jobs: test-rosetta-cli-data: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -770,7 +770,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -784,15 +784,15 @@ jobs: test-rosetta-cli-construction: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -837,7 +837,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -851,10 +851,10 @@ jobs: test-tokens-metadata: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" @@ -882,7 +882,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -896,10 +896,10 @@ jobs: test-tokens-strict: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" @@ -927,7 +927,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -950,13 +950,13 @@ jobs: - test-rosetta-cli-construction - test-tokens-strict steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: token: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }} fetch-depth: 0 persist-credentials: false - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" @@ -978,11 +978,11 @@ jobs: conventional-changelog-conventionalcommits@6.1.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Docker Meta id: meta - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v5 with: images: | blockstack/${{ github.event.repository.name }} @@ -996,7 +996,7 @@ jobs: - name: Docker Standalone Meta id: meta_standalone - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v5 with: images: | blockstack/${{ github.event.repository.name }}-standalone @@ -1009,13 +1009,13 @@ jobs: type=raw,value=latest,enable={{is_default_branch}} - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Build/Tag/Push Image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: context: . tags: ${{ steps.meta.outputs.tags }} @@ -1024,7 +1024,7 @@ jobs: push: ${{ (github.ref != 'refs/heads/master' || steps.semantic.outputs.new_release_version != '') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - name: Build/Tag/Push Standalone Image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: context: . build-args: | @@ -1037,7 +1037,7 @@ jobs: - name: API Discord notification if: steps.semantic.outputs.new_release_version != '' - uses: Ilshidur/action-discord@f1ed8844d9b33c17221fab0f36672cde39800eed + uses: Ilshidur/action-discord@master env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_API_WEBHOOK }} DISCORD_USERNAME: Hiro Team diff --git a/.nvmrc b/.nvmrc index 6f7f377bf5..3f430af82b 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v16 +v18 diff --git a/.releaserc b/.releaserc new file mode 100644 index 0000000000..82ddf7a705 --- /dev/null +++ b/.releaserc @@ -0,0 +1,51 @@ +{ + "branches": [ + "master", + { + "name": "beta", + "channel": "beta", + "prerelease": true + }, + { + "name": "stacks-2.4", + "channel": "stacks-2.4", + "prerelease": true + } + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits" + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits" + } + ], + [ + "@semantic-release/exec", + { + "execCwd": "client", + "prepareCmd": "npm ci" + } + ], + [ + "@semantic-release/npm", + { + "pkgRoot": "./docs" + } + ], + [ + "@semantic-release/npm", + { + "pkgRoot": "./client" + } + ], + "@semantic-release/github", + "@semantic-release/changelog", + "@semantic-release/git" + ] +} diff --git a/Dockerfile b/Dockerfile index cc9a9afa19..c26f06b65f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,11 @@ -FROM node:16-alpine +FROM node:18-alpine WORKDIR /app COPY . . RUN apk add --no-cache --virtual .build-deps alpine-sdk python3 git openjdk8-jre cmake RUN echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env -RUN npm config set unsafe-perm true && npm ci && npm run build && npm run build:docs && npm prune --production +RUN npm ci && npm run build && npm run build:docs && npm prune --production RUN apk del .build-deps # As no pre-built binaries of duckdb can be found for Alpine (musl based), diff --git a/docker/rosetta.Dockerfile b/docker/rosetta.Dockerfile index bc368be8b1..24fa3db5f9 100644 --- a/docker/rosetta.Dockerfile +++ b/docker/rosetta.Dockerfile @@ -12,7 +12,7 @@ ARG ARCHIVE_VERSION=latest ####################################################################### ## Build the stacks-blockchain-api -FROM node:16-buster as stacks-blockchain-api-build +FROM node:18-buster as stacks-blockchain-api-build ARG STACKS_API_VERSION ENV STACKS_API_REPO=hirosystems/stacks-blockchain-api ENV STACKS_API_VERSION=${STACKS_API_VERSION} @@ -26,7 +26,6 @@ RUN apt-get update -y \ cmake \ && git clone -b ${STACKS_API_VERSION} https://github.com/${STACKS_API_REPO} . \ && echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env \ - && npm config set unsafe-perm true \ && npm ci \ && npm run build \ && npm prune --production diff --git a/docker/standalone-regtest.Dockerfile b/docker/standalone-regtest.Dockerfile index 4489220411..33532c5d4e 100644 --- a/docker/standalone-regtest.Dockerfile +++ b/docker/standalone-regtest.Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -FROM node:16-bullseye as api-builder +FROM node:18-bullseye as api-builder ARG API_GIT_COMMIT ARG STACKS_API_VERSION @@ -25,7 +25,6 @@ RUN rm ".env" && \ git describe --tags --abbrev=0 || git -c user.name='user' -c user.email='email' tag "${STACKS_API_VERSION:-vNext}" && \ echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env && \ npm config set update-notifier false && \ - npm config set unsafe-perm true && \ npm ci --audit=false && \ npm run build && \ npm prune --production diff --git a/docs/package-lock.json b/docs/package-lock.json index 690e03717e..4174eb24ce 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -12,7 +12,7 @@ "@apidevtools/json-schema-ref-parser": "9.0.7", "@apidevtools/swagger-cli": "4.0.4", "@types/json-schema-merge-allof": "0.6.0", - "@types/node": "16.18.3", + "@types/node": "^18.13.0", "ajv": "6.12.6", "any-json": "^3.1.0", "chalk": "4.1.1", @@ -30,8 +30,8 @@ "redoc-cli": "0.13.16", "shx": "0.3.3", "speccy": "0.11.0", - "ts-node": "9.1.1", - "typescript": "4.2.4", + "ts-node": "^10.8.2", + "typescript": "^4.7.4", "yaml-lint": "1.2.4" } }, @@ -364,6 +364,18 @@ "integrity": "sha512-P3n0hEgk1m6uKWgL4Yb1owzXVG4pM70G4kRnDQxZXiVvfCRtaqiHu+ZRiRPzmwGBiLTO1LWc2yR1M8oz0YkXww==", "dev": true }, + "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/@emotion/is-prop-valid": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", @@ -401,6 +413,31 @@ "integrity": "sha512-GoXw0U2Qaa33m3eUcxuHnHpNvHjNlLo0gtV091XBpaRINaB4X6FGCG5XKxSFNFiPpugUDqNruHzaqpTdDm4AOg==", "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/@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", @@ -442,6 +479,30 @@ "node": ">= 8" } }, + "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/glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", @@ -480,9 +541,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", "dev": true }, "node_modules/@types/prettier": { @@ -504,6 +565,27 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/adler-32": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", @@ -12713,25 +12795,6 @@ "urix": "^0.1.0" } }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-url": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", @@ -13769,29 +13832,46 @@ } }, "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.2.tgz", + "integrity": "sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==", "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", - "source-map-support": "^0.5.17", + "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" }, - "engines": { - "node": ">=10.0.0" - }, "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/tunnel-agent": { @@ -13909,9 +13989,9 @@ "dev": true }, "node_modules/typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -14165,6 +14245,12 @@ "uuid": "dist/bin/uuid" } }, + "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/v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", @@ -15050,6 +15136,15 @@ "integrity": "sha512-P3n0hEgk1m6uKWgL4Yb1owzXVG4pM70G4kRnDQxZXiVvfCRtaqiHu+ZRiRPzmwGBiLTO1LWc2yR1M8oz0YkXww==", "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" + } + }, "@emotion/is-prop-valid": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", @@ -15087,6 +15182,28 @@ "integrity": "sha512-GoXw0U2Qaa33m3eUcxuHnHpNvHjNlLo0gtV091XBpaRINaB4X6FGCG5XKxSFNFiPpugUDqNruHzaqpTdDm4AOg==", "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" + } + }, "@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", @@ -15119,6 +15236,30 @@ "fastq": "^1.6.0" } }, + "@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/glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", @@ -15157,9 +15298,9 @@ "dev": true }, "@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==", "dev": true }, "@types/prettier": { @@ -15178,6 +15319,18 @@ "negotiator": "0.6.2" } }, + "acorn": { + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "dev": true + }, + "acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "dev": true + }, "adler-32": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", @@ -25088,24 +25241,6 @@ "urix": "^0.1.0" } }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "source-map-url": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", @@ -25958,16 +26093,23 @@ "dev": true }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.2.tgz", + "integrity": "sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==", "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", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" } }, @@ -26056,9 +26198,9 @@ "dev": true }, "typescript": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", - "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true }, "unbox-primitive": { @@ -26265,6 +26407,12 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, + "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 + }, "v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", diff --git a/docs/package.json b/docs/package.json index b896479b62..730e22b9ce 100644 --- a/docs/package.json +++ b/docs/package.json @@ -38,7 +38,7 @@ "@apidevtools/json-schema-ref-parser": "9.0.7", "@apidevtools/swagger-cli": "4.0.4", "@types/json-schema-merge-allof": "0.6.0", - "@types/node": "16.18.3", + "@types/node": "^18.13.0", "ajv": "6.12.6", "any-json": "^3.1.0", "chalk": "4.1.1", @@ -56,8 +56,8 @@ "redoc-cli": "0.13.16", "shx": "0.3.3", "speccy": "0.11.0", - "ts-node": "9.1.1", - "typescript": "4.2.4", + "ts-node": "^10.8.2", + "typescript": "^4.7.4", "yaml-lint": "1.2.4" } } diff --git a/git-info-generator.mjs b/git-info-generator.mjs deleted file mode 100644 index b16b68b09c..0000000000 --- a/git-info-generator.mjs +++ /dev/null @@ -1,23 +0,0 @@ -import { execSync } from 'child_process'; -import { writeFileSync } from 'fs'; - -try { - execSync('git --version'); -} catch (error) { - console.error(error.message); - throw new Error(`git is missing, please install git and retry`); -} -const gitInfo = [ - 'git rev-parse --abbrev-ref HEAD', - 'git log -1 --pretty=format:%h', - 'git describe --tags --abbrev=0', -].map((r, index) => { - try { - return execSync(r, { encoding: 'utf8' }).trim(); - } catch (error) { - console.error(error.message); - if (index === 2) throw new Error(`no tag found fetch tags by running "git fetch --all --tags"`); - throw error; - } -}); -writeFileSync('.git-info', gitInfo.join('\n')); diff --git a/package-lock.json b/package-lock.json index 8acde7fd38..015e651d2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "@hirosystems/stacks-blockchain-api", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -10,14 +10,15 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "9.0.9", + "@hirosystems/api-toolkit": "1.2.2", "@promster/express": "6.0.0", "@promster/server": "6.0.6", "@promster/types": "3.2.3", "@scure/base": "1.1.1", - "@stacks/common": "6.5.2", - "@stacks/network": "6.5.2", - "@stacks/stacking": "6.5.3-pr.693e11b.0", - "@stacks/transactions": "6.5.2", + "@stacks/common": "6.8.1", + "@stacks/network": "6.8.1", + "@stacks/stacking": "6.9.0", + "@stacks/transactions": "6.9.0", "@types/express-list-endpoints": "4.0.1", "@types/lru-cache": "5.1.1", "@types/ws": "7.4.7", @@ -65,7 +66,6 @@ "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", - "typescript": "4.6.2", "uuid": "8.3.2", "ws": "7.5.9", "zone-file": "2.0.0-beta.3" @@ -78,7 +78,6 @@ "@commitlint/cli": "9.1.2", "@commitlint/config-conventional": "10.0.0", "@stacks/eslint-config": "1.2.0", - "@stacks/prettier-config": "0.0.10", "@types/ajv": "1.0.0", "@types/bluebird": "3.5.36", "@types/cors": "2.8.12", @@ -86,8 +85,8 @@ "@types/elliptic": "6.4.14", "@types/express": "4.17.13", "@types/is-ci": "3.0.0", - "@types/jest": "27.4.1", - "@types/node": "16.11.17", + "@types/jest": "29.5.6", + "@types/node": "18.13.0", "@types/node-fetch": "2.5.12", "@types/pg": "7.14.11", "@types/pg-copy-streams": "1.2.1", @@ -96,98 +95,87 @@ "@types/supertest": "2.0.11", "@types/tiny-secp256k1": "2.0.1", "@types/uuid": "7.0.5", - "@typescript-eslint/eslint-plugin": "5.15.0", - "@typescript-eslint/parser": "5.15.0", + "@typescript-eslint/eslint-plugin": "5.46.1", + "@typescript-eslint/parser": "5.51.0", "concurrently": "7.3.0", "docker-compose": "0.23.14", - "eslint": "8.11.0", - "eslint-config-prettier": "8.5.0", - "eslint-plugin-prettier": "4.0.0", - "eslint-plugin-tsdoc": "0.2.14", + "eslint": "8.29.0", + "eslint-plugin-prettier": "4.2.1", + "eslint-plugin-tsdoc": "0.2.17", + "fastify": "4.15.0", "husky": "4.3.8", "is-ci": "3.0.1", - "jest": "27.5.1", + "jest": "29.7.0", "nock": "13.2.1", "nodemon": "2.0.19", "pg-connection-string": "2.5.0", - "prettier": "2.2.1", + "prettier": "2.8.8", "rimraf": "5.0.0", "rpc-websocket-client": "1.1.4", "socket.io-client": "4.5.4", "supertest": "4.0.2", - "ts-jest": "27.1.3", - "ts-node": "10.7.0", + "ts-jest": "29.1.1", + "ts-node": "10.8.2", + "typescript": "4.7.4", "why-is-node-running": "2.2.0" }, "engines": { - "node": ">=16" + "node": ">=18" }, "optionalDependencies": { "bufferutil": "4.0.5", "utf-8-validate": "5.0.7" } }, - "../stacks.js/packages/network": { - "name": "@stacks/network", - "version": "4.3.5", + "../api-toolkit": { + "name": "@hirosystems/api-toolkit", + "version": "1.1.0", "extraneous": true, - "license": "MIT", + "license": "Apache 2.0", "dependencies": { - "@stacks/common": "^4.3.5", - "cross-fetch": "^3.1.5" + "@fastify/cors": "^8.0.0", + "@fastify/swagger": "^8.3.1", + "@fastify/type-provider-typebox": "^3.2.0", + "fastify": "^4.3.0", + "fastify-metrics": "^10.2.0", + "node-pg-migrate": "^6.2.2", + "pino": "^8.11.0", + "postgres": "^3.3.4" }, - "devDependencies": { - "@types/jest": "^26.0.22", - "jest": "^26.6.3", - "jest-fetch-mock": "^3.0.3", - "jest-module-name-mapper": "^0.1.5", - "process": "^0.11.10", - "rimraf": "^3.0.2", - "ts-jest": "^26.5.5", - "ts-loader": "^9.1.1", - "typescript": "^4.2.4", - "webpack": "^5.36.1", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-cli": "^4.6.0" - } - }, - "../stacks.js/packages/transactions": { - "name": "@stacks/transactions", - "version": "4.3.5", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@noble/hashes": "^1.0.0", - "@noble/secp256k1": "^1.5.5", - "@stacks/common": "^4.3.5", - "@stacks/network": "^4.3.5", - "@types/node": "^18.0.4", - "@types/sha.js": "^2.4.0", - "c32check": "^1.1.3", - "lodash.clonedeep": "^4.5.0", - "ripemd160-min": "^0.0.6", - "sha.js": "^2.4.11", - "smart-buffer": "^4.1.0" + "bin": { + "api-toolkit-git-info": "bin/api-toolkit-git-info.js" }, "devDependencies": { - "@stacks/encryption": "^4.3.5", - "@types/common-tags": "^1.8.0", - "@types/elliptic": "^6.4.12", - "@types/jest": "^26.0.22", - "@types/lodash.clonedeep": "^4.5.6", - "common-tags": "^1.8.0", - "elliptic": "^6.5.4", - "jest": "^26.6.3", - "jest-fetch-mock": "^3.0.3", - "jest-module-name-mapper": "^0.1.5", - "process": "^0.11.10", - "rimraf": "^3.0.2", - "ts-jest": "^26.5.5", - "ts-loader": "^9.1.1", - "typescript": "^4.2.4", - "webpack": "^5.36.1", - "webpack-bundle-analyzer": "^4.5.0", - "webpack-cli": "^4.6.0" + "@commitlint/cli": "^17.5.0", + "@commitlint/config-conventional": "^17.4.4", + "@stacks/eslint-config": "^1.2.0", + "@types/jest": "^29.5.0", + "@typescript-eslint/eslint-plugin": "^5.56.0", + "@typescript-eslint/parser": "^5.56.0", + "babel-jest": "^29.5.0", + "copyfiles": "^2.4.1", + "eslint": "^8.36.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-tsdoc": "^0.2.17", + "husky": "^8.0.3", + "jest": "^29.5.0", + "prettier": "^2.8.6", + "rimraf": "^4.4.1", + "ts-jest": "^29.0.5", + "ts-node": "^10.9.1", + "typescript": "^5.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "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/@actions/core": { @@ -200,15 +188,6 @@ "uuid": "^8.3.2" } }, - "node_modules/@actions/core/node_modules/@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "dev": true, - "dependencies": { - "tunnel": "^0.0.6" - } - }, "node_modules/@actions/exec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz", @@ -229,7 +208,7 @@ "@octokit/rest": "^16.43.1" } }, - "node_modules/@actions/http-client": { + "node_modules/@actions/github/node_modules/@actions/http-client": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", @@ -238,6 +217,16 @@ "tunnel": "0.0.6" } }, + "node_modules/@actions/http-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz", + "integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==", + "dev": true, + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, "node_modules/@actions/io": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz", @@ -245,12 +234,13 @@ "dev": true }, "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -268,47 +258,119 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz", - "integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.9", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.9", - "@babel/parser": "^7.17.9", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -328,44 +390,43 @@ } }, "node_modules/@babel/generator": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", - "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { @@ -377,147 +438,159 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", - "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", - "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -562,13 +635,13 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "engines": { "node": ">=0.8.0" @@ -577,7 +650,7 @@ "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" @@ -596,9 +669,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", - "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -667,6 +740,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", @@ -755,12 +843,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", - "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.7" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -770,45 +858,45 @@ } }, "node_modules/@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "dev": true, "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", - "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.9", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.9", - "@babel/types": "^7.17.0", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -826,12 +914,13 @@ } }, "node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1059,157 +1148,453 @@ "node": ">=v8.17.0" } }, - "node_modules/@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "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": { - "@cspotcode/source-map-consumer": "0.8.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { "node": ">=12" } }, + "node_modules/@cspotcode/source-map-support/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/@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", + "espree": "^9.4.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "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/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, + "node_modules/@fastify/ajv-compiler": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.5.0.tgz", + "integrity": "sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "fast-uri": "^2.0.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@fastify/ajv-compiler/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=12" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/@fastify/busboy": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", + "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", + "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=14" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node_modules/@fastify/cors": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-8.4.0.tgz", + "integrity": "sha512-MlVvMTenltToByTpLwlWtO+7dQ3l2J+1OpmGrx9JpSNWo1d+dhfNCOi23zHhxdFhtpDzfwGwCsKu9DTeG7k7nQ==", + "dependencies": { + "fastify-plugin": "^4.0.0", + "mnemonist": "0.39.5" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "node_modules/@fastify/deepmerge": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-1.3.0.tgz", + "integrity": "sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==" }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@fastify/error": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.0.tgz", + "integrity": "sha512-e/mafFwbK3MNqxUcFBLgHhgxsF8UT1m8aj0dAlqEa2nJEgPsRtpHTZ3ObgrgkZ2M1eJHPTwgyUl/tXkvabsZdQ==" + }, + "node_modules/@fastify/fast-json-stringify-compiler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", + "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "fast-json-stringify": "^5.7.0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@fastify/swagger": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/@fastify/swagger/-/swagger-8.12.0.tgz", + "integrity": "sha512-IMRc0xYuzRvtFDMuaWHyVbvM7CuAi0g3o2jaVgLDvETXPrXWAMWsHYR5niIdWBDPgGUq+soHkag1DKXyhPDB0w==", "dependencies": { - "ansi-regex": "^6.0.1" - }, + "fastify-plugin": "^4.0.0", + "json-schema-resolver": "^2.0.0", + "openapi-types": "^12.0.0", + "rfdc": "^1.3.0", + "yaml": "^2.2.2" + } + }, + "node_modules/@fastify/swagger/node_modules/yaml": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", + "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">= 14" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "node_modules/@fastify/type-provider-typebox": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@fastify/type-provider-typebox/-/type-provider-typebox-3.5.0.tgz", + "integrity": "sha512-f48uGzvLflE/y4pvXOS8qjAC+mZmlqev9CPHnB8NDsBSL4EbeydO61IgPuzOkeNlAYeRP9Y56UOKj1XWFibgMw==", + "peerDependencies": { + "@sinclair/typebox": ">=0.26 <=0.31" + } + }, + "node_modules/@hirosystems/api-toolkit": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@hirosystems/api-toolkit/-/api-toolkit-1.2.2.tgz", + "integrity": "sha512-HLaodPN6dHUAkrOwECsMwQicBMhJn8CYlS0QwC4SC3smclno3fB0oKm1QYZFQEDy2KV3IPTAh70B/vkpib/Kkw==", + "dependencies": { + "@fastify/cors": "^8.0.0", + "@fastify/swagger": "^8.3.1", + "@fastify/type-provider-typebox": "^3.2.0", + "fastify": "^4.3.0", + "fastify-metrics": "^10.2.0", + "node-pg-migrate": "^6.2.2", + "pino": "^8.11.0", + "postgres": "^3.3.4" }, - "engines": { - "node": ">=12" + "bin": { + "api-toolkit-git-info": "bin/api-toolkit-git-info.js" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "engines": { + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config": { + "node_modules/@hirosystems/api-toolkit/node_modules/@types/pg": { + "version": "8.10.7", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.7.tgz", + "integrity": "sha512-ksJqHipwYaSEHz9e1fr6H6erjoEdNNaOxwyJgPx9bNeaqOW3iWBQgVHfpwiSAoqGzchfc+ZyRLwEfeCcyYD3uQ==", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "node_modules/@hirosystems/api-toolkit/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==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/node-pg-migrate": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/node-pg-migrate/-/node-pg-migrate-6.2.2.tgz", + "integrity": "sha512-0WYLTXpWu2doeZhiwJUW/1u21OqAFU2CMQ8YZ8VBcJ0xrdqYAjtd8GGFe5A5DM4NJdIZsqJcLPDFqY0FQsmivw==", + "dependencies": { + "@types/pg": "^8.0.0", + "decamelize": "^5.0.0", + "mkdirp": "~1.0.0", + "yargs": "~17.3.0" + }, + "bin": { + "node-pg-migrate": "bin/node-pg-migrate" + }, + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "pg": ">=4.3.0 <9.0.0" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/pg-types": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", + "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.0.1", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/postgres": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.2.tgz", + "integrity": "sha512-0UcCGvDBSaAzLeWwiq+QVmiGfOPTosFb+sxJUUtd+7Pi/ByFPuz6Gq05LbS0sM1ghMWC5atuks3pfl34g0qmFw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/postgres-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", + "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@hirosystems/api-toolkit/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==", + "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/@hirosystems/api-toolkit/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/yargs": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@hirosystems/api-toolkit/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", @@ -1257,59 +1642,59 @@ } }, "node_modules/@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "rimraf": "^3.0.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -1320,101 +1705,111 @@ } } }, - "node_modules/@jest/core/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" + "jest-get-type": "^29.6.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", - "glob": "^7.1.2", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", - "source-map": "^0.6.0", "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -1425,115 +1820,151 @@ } } }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" + "graceful-fs": "^4.2.9" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "dependencies": { - "@jest/test-result": "^27.5.1", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "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/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "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.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@jsdevtools/ono": { @@ -1542,9 +1973,9 @@ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" }, "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", - "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -1589,18 +2020,18 @@ } }, "node_modules/@microsoft/tsdoc": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", - "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", + "integrity": "sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==", "dev": true }, "node_modules/@microsoft/tsdoc-config": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", - "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.16.2.tgz", + "integrity": "sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==", "dev": true, "dependencies": { - "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc": "0.14.2", "ajv": "~6.12.6", "jju": "~1.4.0", "resolve": "~1.19.0" @@ -1711,19 +2142,111 @@ } }, "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.1.tgz", + "integrity": "sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==", "dev": true, "peer": true, "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/endpoint": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.1.tgz", + "integrity": "sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/types": "^12.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/graphql": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz", + "integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/request": "^8.0.1", + "@octokit/types": "^12.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz", + "integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==", + "dev": true, + "peer": true + }, + "node_modules/@octokit/core/node_modules/@octokit/request": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.4.tgz", + "integrity": "sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^12.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/request-error": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz", + "integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/types": "^12.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz", + "integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/openapi-types": "^19.0.0" } }, "node_modules/@octokit/endpoint": { @@ -1749,9 +2272,9 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", "dev": true }, "node_modules/@octokit/plugin-paginate-rest": { @@ -1879,12 +2402,12 @@ } }, "node_modules/@octokit/types": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", - "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^11.2.0" + "@octokit/openapi-types": "^12.11.0" } }, "node_modules/@pkgjs/parseargs": { @@ -2025,22 +2548,27 @@ "node": ">=6" } }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { - "@sinonjs/commons": "^1.7.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@socket.io/component-emitter": { @@ -2049,28 +2577,23 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@stacks/common": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.2.tgz", - "integrity": "sha512-tnkyEIA7YgX9GIkqlHocQPPax25uaboJ4aTX5wVs6kAGXY10+XI7VamRG4o+4DqnFVKwvIHR2fGcxdhtxNb/+Q==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.8.1.tgz", + "integrity": "sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==", "dependencies": { "@types/bn.js": "^5.1.0", "@types/node": "^18.0.4" } }, - "node_modules/@stacks/common/node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" - }, "node_modules/@stacks/encryption": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-RGpmTCvhlGdaHceBqba2bRnrPgcEZHs0irXOrYVMkLB7oC1Yi0BpAH0gf7Vz0xzfD+3omJ9E4i5uSYkn/unINg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.9.0.tgz", + "integrity": "sha512-hbpZ47eYgw9ZH5ly+GSgvw2Ffsu9L6d++2XIhvYSzL7yxYl4m1+FV5QYdJthJ2AS3vi8cI5otE254HTfCrhKzg==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.3-pr.ae8c520.0", + "@stacks/common": "^6.8.1", "@types/node": "^18.0.4", "base64-js": "^1.5.1", "bs58": "^5.0.0", @@ -2078,33 +2601,6 @@ "varuint-bitcoin": "^1.1.2" } }, - "node_modules/@stacks/encryption/node_modules/@stacks/common": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-qagihApT66HcppJYZgeAbKpSjJnR/2rkc4pgkjg/jYeevQARo5DNfJRBvheZ3DF4dAaNwTyOGMeoDBjr0OSEbw==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, - "node_modules/@stacks/encryption/node_modules/@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==" - }, - "node_modules/@stacks/encryption/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/@stacks/encryption/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/@stacks/eslint-config": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@stacks/eslint-config/-/eslint-config-1.2.0.tgz", @@ -2138,6 +2634,12 @@ "node": ">=10.10.0" } }, + "node_modules/@stacks/eslint-config/node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/@stacks/eslint-config/node_modules/@typescript-eslint/eslint-plugin": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", @@ -2326,10 +2828,31 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@stacks/eslint-config/node_modules/eslint-plugin-prettier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", + "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/@stacks/eslint-config/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "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", @@ -2337,6 +2860,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@stacks/eslint-config/node_modules/eslint/node_modules/ignore": { @@ -2385,11 +2911,11 @@ } }, "node_modules/@stacks/network": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.2.tgz", - "integrity": "sha512-+XNneecXCitis7OGDoCMqfKp0j4SICaij6XN9JTq+pAoaCbuJqLRZrrVP/ApkWbotTzeVZIbrZPqMLqkdgGTrg==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.8.1.tgz", + "integrity": "sha512-n8M25pPbLqpSBctabtsLOTBlmPvm9EPQpTI//x7HLdt5lEjDXxauEQt0XGSvDUZwecrmztqt9xNxlciiGApRBw==", "dependencies": { - "@stacks/common": "^6.5.2", + "@stacks/common": "^6.8.1", "cross-fetch": "^3.1.5" } }, @@ -2415,103 +2941,37 @@ } }, "node_modules/@stacks/stacking": { - "version": "6.5.3-pr.693e11b.0", - "resolved": "https://registry.npmjs.org/@stacks/stacking/-/stacking-6.5.3-pr.693e11b.0.tgz", - "integrity": "sha512-qW+9/2j+D8k1hITrML4O43M5Y6Xrsuem4JUY+gR0QcfkHSewVVHgCmMdMZCy/VHAJaoW7eB0S1slK5fA+xdTQw==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/stacking/-/stacking-6.9.0.tgz", + "integrity": "sha512-nxTGwaVBE/M06P8bTlXPXlzeV/bOLaxbMd3ftAnQUu8ubX2UB/iEHywnAkrg/Bj2Qy9ZjKyi6QKw+aG38rVZaw==", "dependencies": { "@scure/base": "1.1.1", - "@stacks/common": "^6.5.3-pr.693e11b.0", - "@stacks/encryption": "^6.5.3-pr.693e11b.0", - "@stacks/network": "^6.5.3-pr.693e11b.0", + "@stacks/common": "^6.8.1", + "@stacks/encryption": "^6.9.0", + "@stacks/network": "^6.8.1", "@stacks/stacks-blockchain-api-types": "^0.61.0", - "@stacks/transactions": "^6.5.3-pr.693e11b.0", + "@stacks/transactions": "^6.9.0", "bs58": "^5.0.0" } }, - "node_modules/@stacks/stacking/node_modules/@stacks/common": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-qagihApT66HcppJYZgeAbKpSjJnR/2rkc4pgkjg/jYeevQARo5DNfJRBvheZ3DF4dAaNwTyOGMeoDBjr0OSEbw==", - "dependencies": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, - "node_modules/@stacks/stacking/node_modules/@stacks/network": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-C4PFAjLQam7OF19WIrcDs+BgiZB8+EI/uQqnli2tw6gwwJfZVypXpV1EoieLQQ6ST8vXtkYbUcr1megN6QAdNw==", - "dependencies": { - "@stacks/common": "^6.5.3-pr.ae8c520.0", - "cross-fetch": "^3.1.5" - } - }, - "node_modules/@stacks/stacking/node_modules/@stacks/transactions": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-DtbQ3wG/3IJPEUmwMNLqTa4fpmmoATi3oSj1hS5X5MEmOFqaMMK/uMS48EqJZfHv8D/chXkpaUVmG0qzYBfYvw==", - "dependencies": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.5.3-pr.ae8c520.0", - "@stacks/network": "^6.5.3-pr.ae8c520.0", - "c32check": "^2.0.0", - "lodash.clonedeep": "^4.5.0" - } - }, - "node_modules/@stacks/stacking/node_modules/@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==" - }, - "node_modules/@stacks/stacking/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/@stacks/stacking/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/@stacks/stacking/node_modules/c32check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", - "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", - "dependencies": { - "@noble/hashes": "^1.1.2", - "base-x": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@stacks/stacks-blockchain-api-types": { "version": "0.61.0", "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-0.61.0.tgz", "integrity": "sha512-yPOfTUboo5eA9BZL/hqMcM71GstrFs9YWzOrJFPeP4cOO1wgYvAcckgBRbgiE3NqeX0A7SLZLDAXLZbATuRq9w==" }, "node_modules/@stacks/transactions": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.5.2.tgz", - "integrity": "sha512-xL4XF4xSFFJ+VMzeahBenGdg1T+y0Q0fSNA09jz7knTnnXvdAzzC+RP59xzuIjrAY/IWYO3X1sf0MGm9IIhYOg==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.9.0.tgz", + "integrity": "sha512-hSs9+0Ew++GwMZMgPObOx0iVCQRxkiCqI+DHdPEikAmg2utpyLh2/txHOjfSIkQHvcBfJJ6O5KphmxDP4gUqiA==", "dependencies": { "@noble/hashes": "1.1.5", "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.5.2", - "@stacks/network": "^6.5.2", + "@stacks/common": "^6.8.1", + "@stacks/network": "^6.8.1", "c32check": "^2.0.0", "lodash.clonedeep": "^4.5.0" } }, - "node_modules/@stacks/transactions/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/@stacks/transactions/node_modules/c32check": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", @@ -2525,42 +2985,41 @@ } }, "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "engines": { - "node": ">= 6" + "node": ">= 10" } }, "node_modules/@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "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.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "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.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "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.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "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/ajv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/ajv/-/ajv-1.0.0.tgz", - "integrity": "sha1-T7JEB0Ly9sMOf7B5e4OfxvaWaCo=", + "integrity": "sha512-yGSqw9/QKd5FXbTNrSANcJ6IHWeNhA+gokXqmlPquJgLDC87d4g2FGPs+AlCeGG0GuZXmPq42hOFA2hnPymCLw==", "deprecated": "This is a stub types definition for ajv (https://github.com/epoberezkin/ajv). ajv provides its own type definitions, so you don't need @types/ajv installed!", "dev": true, "dependencies": { @@ -2568,31 +3027,31 @@ } }, "node_modules/@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -2600,12 +3059,12 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", "dev": true, "dependencies": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "node_modules/@types/bluebird": { @@ -2615,31 +3074,31 @@ "dev": true }, "node_modules/@types/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-wT1B4iIO82ecXkdN6waCK8Ou7E71WU+mP1osDA5Q8c6Ur+ozU2vIKUIhSpUr6uE5L2YHocKS1Z2jG2fBC1YVeg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", + "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "node_modules/@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.4.tgz", + "integrity": "sha512-2in/lrHRNmDvHPgyormtEralhPcN3An1gLjJzj2Bw145VBxkQ75JEXW6CTdMAwShiHQcYsl2d10IjQSdJSJz4g==" }, "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", "dependencies": { "@types/node": "*" } @@ -2650,9 +3109,9 @@ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" }, "node_modules/@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-LZ8SD3LpNmLMDLkG2oCBjZg+ETnx6XdCjydUE0HwojDmnDfDUnhMKKbtth1TZh+hzcqb03azrYWoXLS8sMXdqg==", "dev": true }, "node_modules/@types/cors": { @@ -2695,28 +3154,34 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", "dependencies": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", "dev": true, "dependencies": { "@types/node": "*" } }, + "node_modules/@types/http-errors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==" + }, "node_modules/@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", + "version": "1.17.13", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", + "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", "dependencies": { "@types/node": "*" } @@ -2731,48 +3196,48 @@ } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", + "version": "29.5.6", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", + "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", "dev": true, "dependencies": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "node_modules/@types/lru-cache": { "version": "5.1.1", @@ -2780,20 +3245,20 @@ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", + "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==" }, "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.4.tgz", + "integrity": "sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ==", "dev": true }, "node_modules/@types/node": { - "version": "16.11.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.17.tgz", - "integrity": "sha512-C1vTZME8cFo8uxY2ui41xcynEotVkczIVI5AjLmy5pkpBv/FtG+jhtOlfcPysI8VRVwoOMv6NJm44LGnoMSWkw==" + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" }, "node_modules/@types/node-fetch": { "version": "2.5.12", @@ -2806,15 +3271,15 @@ } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.3.tgz", + "integrity": "sha512-ehPtgRgaULsFG8x0NeYJvmyH1hmlfsNLujHe9dQEia/7MAJYdzMSi19JtchUHjmBA6XC/75dK55mzZH+RyieSg==", "dev": true }, "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.1.tgz", + "integrity": "sha512-3YmXzzPAdOTVljVMkTMBdBEvlOLg2cDQaDhnnhT3nT9uDbnJzjWhKlzb+desT12Y7tGqaN6d+AbozcKzyL36Ng==", "dev": true }, "node_modules/@types/pg": { @@ -2838,26 +3303,20 @@ "@types/pg": "*" } }, - "node_modules/@types/prettier": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", - "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", - "dev": true - }, "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==" }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==" }, "node_modules/@types/request": { - "version": "2.48.8", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.8.tgz", - "integrity": "sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ==", + "version": "2.48.11", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.11.tgz", + "integrity": "sha512-HuihY1+Vss5RS9ZHzRyTGIzwPTdrJBkCm/mAeLRYrOQu/MGqyezKXWOK1VhCnR+SDbp9G2mRUP+OVEqCrzpcfA==", "dependencies": { "@types/caseless": "*", "@types/node": "*", @@ -2866,9 +3325,9 @@ } }, "node_modules/@types/request-promise-native": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/@types/request-promise-native/-/request-promise-native-1.0.18.tgz", - "integrity": "sha512-tPnODeISFc/c1LjWyLuZUY+Z0uLB3+IMfNoQyDEi395+j6kTFTTRAqjENjoPJUid4vHRGEozoTrcTrfZM+AcbA==", + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/@types/request-promise-native/-/request-promise-native-1.0.20.tgz", + "integrity": "sha512-1dfdWY0u6mNkAheZ5UqBGY/ARpDXE5xJ+npN3COoTfrQTt4FmHrwp8548zU6F1LniUK75qk06HoOvCG+hS/8Zw==", "dependencies": { "@types/request": "*" } @@ -2886,15 +3345,31 @@ "node": ">= 0.12" } }, - "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "node_modules/@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", + "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, + "node_modules/@types/serve-static": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, "node_modules/@types/source-map-support": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.4.tgz", @@ -2914,15 +3389,15 @@ } }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.2.tgz", + "integrity": "sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==", "dev": true }, "node_modules/@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", + "version": "4.1.20", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.20.tgz", + "integrity": "sha512-GfpwJgYSr3yO+nArFkmyqv3i0vZavyEG5xPd/o95RwpKYpsOKJYI5XLdxLpdRbZI3YiGKKdIOFIf/jlP7A0Jxg==", "dev": true, "dependencies": { "@types/cookiejar": "*", @@ -2949,9 +3424,9 @@ } }, "node_modules/@types/tough-cookie": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz", - "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.4.tgz", + "integrity": "sha512-95Sfz4nvMAb0Nl9DTxN3j64adfwfbBPEYq14VN7zT5J5O2M9V6iZMIIQU1U+pJyl9agHYHNCqhCXgyEtIRRa5A==" }, "node_modules/@types/uuid": { "version": "7.0.5", @@ -2968,34 +3443,34 @@ } }, "node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "version": "17.0.29", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.29.tgz", + "integrity": "sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "version": "21.0.2", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.2.tgz", + "integrity": "sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", - "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.46.1.tgz", + "integrity": "sha512-YpzNv3aayRBwjs4J3oz65eVLXc9xx0PDbIRisHj+dYhvBn02MjYOD96P8YGiWEIFBrojaUjxvkaUpakD82phsA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/type-utils": "5.15.0", - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/type-utils": "5.46.1", + "@typescript-eslint/utils": "5.46.1", + "debug": "^4.3.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", - "semver": "^7.3.5", + "semver": "^7.3.7", "tsutils": "^3.21.0" }, "engines": { @@ -3144,15 +3619,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", - "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", + "version": "5.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.51.0.tgz", + "integrity": "sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", - "debug": "^4.3.2" + "@typescript-eslint/scope-manager": "5.51.0", + "@typescript-eslint/types": "5.51.0", + "@typescript-eslint/typescript-estree": "5.51.0", + "debug": "^4.3.4" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3170,14 +3645,14 @@ } } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", - "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "5.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz", + "integrity": "sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0" + "@typescript-eslint/types": "5.51.0", + "@typescript-eslint/visitor-keys": "5.51.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3187,15 +3662,14 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", - "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz", + "integrity": "sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" + "@typescript-eslint/types": "5.51.0", + "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3203,21 +3677,17 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, - "node_modules/@typescript-eslint/types": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", - "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.46.1.tgz", + "integrity": "sha512-iOChVivo4jpwUdrJZyXSMrEIM/PvsbbDOX1y3UCKjSgWn+W89skxWaYXACQfxmIGhPVpRWK/VWPYc+bad6smIA==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/visitor-keys": "5.46.1" + }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -3226,18 +3696,126 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", - "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", + "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0", - "debug": "^4.3.2", - "globby": "^11.0.4", + "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.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.46.1.tgz", + "integrity": "sha512-V/zMyfI+jDmL1ADxfDxjZ0EMbtiVqj8LUGPAGyBkXXStWmCUErMpW873zEHsyguWCuq2iN4BrlWUkmuVj84yng==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.46.1", + "@typescript-eslint/utils": "5.46.1", + "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/type-utils/node_modules/@typescript-eslint/types": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", + "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", + "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/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz", + "integrity": "sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/visitor-keys": "5.46.1", + "debug": "^4.3.4", + "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.5", + "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/type-utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.51.0.tgz", + "integrity": "sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==", + "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.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz", + "integrity": "sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.51.0", + "@typescript-eslint/visitor-keys": "5.51.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", "tsutils": "^3.21.0" }, "engines": { @@ -3253,6 +3831,23 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.51.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz", + "integrity": "sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.51.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/@typescript-eslint/typescript-estree/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -3269,17 +3864,19 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", - "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.46.1.tgz", + "integrity": "sha512-RBdBAGv3oEpFojaCYT4Ghn4775pdjvwfDOfQ2P6qzNVgQOVrnSPe5/Pb88kv7xzYQjoio0eKHKB9GJ16ieSxvA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.46.1", + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/typescript-estree": "5.46.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3292,14 +3889,69 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", + "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", + "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/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.46.1.tgz", + "integrity": "sha512-j9W4t67QiNp90kh5Nbr1w92wzt+toiIsaVPnEblB2Ih2U9fqBTyqV9T3pYWZBRt6QoMh/zVWP59EpuCjc4VRBg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.46.1", + "@typescript-eslint/visitor-keys": "5.46.1", + "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/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", - "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.46.1.tgz", + "integrity": "sha512-jczZ9noovXwy59KjRTk1OftT78pwygdcmCuBf8yMoWt/8O8l+6x2LSEze0E4TeepXK4MezW3zGSyoDRZK7Y9cg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.15.0", - "eslint-visitor-keys": "^3.0.0" + "@typescript-eslint/types": "5.46.1", + "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3309,11 +3961,18 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", - "dev": true + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "5.46.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.46.1.tgz", + "integrity": "sha512-Z5pvlCaZgU+93ryiYUwGwLl9AQVB/PQ1TsJ9NZ/gHzZjN7g9IAn6RSDkpCV8hqTwAiaj6fmCcKSQeBPlIpW28w==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, "node_modules/abbrev": { "version": "1.1.1", @@ -3331,6 +3990,11 @@ "node": ">=6.5" } }, + "node_modules/abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -3344,31 +4008,9 @@ } }, "node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3387,9 +4029,9 @@ } }, "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -3407,26 +4049,16 @@ } }, "node_modules/agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", "dependencies": { - "debug": "^4.1.0", - "depd": "^2.0.0", "humanize-ms": "^1.2.1" }, "engines": { "node": ">= 8.0.0" } }, - "node_modules/agentkeepalive/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -3454,10 +4086,46 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "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==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "engines": { "node": ">=6" @@ -3513,9 +4181,9 @@ } }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3529,6 +4197,11 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" + }, "node_modules/are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", @@ -3552,27 +4225,40 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, "node_modules/array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" }, "engines": { @@ -3592,14 +4278,14 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -3609,10 +4295,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -3629,7 +4336,7 @@ "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "engines": { "node": ">=0.8" } @@ -3637,12 +4344,12 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/atob-lite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", + "integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==", "dev": true }, "node_modules/atomic-sleep": { @@ -3653,36 +4360,57 @@ "node": ">=8.0.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/avvio": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.2.1.tgz", + "integrity": "sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==", + "dependencies": { + "archy": "^1.0.0", + "debug": "^4.0.0", + "fastq": "^1.6.1" + } + }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "engines": { "node": "*" } }, "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" }, "node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" @@ -3704,24 +4432,49 @@ "node": ">=8" } }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=8" } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", "dev": true, "dependencies": { @@ -3743,16 +4496,16 @@ } }, "node_modules/babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -3764,12 +4517,9 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" }, "node_modules/base64-js": { "version": "1.5.1", @@ -3801,7 +4551,7 @@ "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dependencies": { "tweetnacl": "^0.14.3" } @@ -3812,9 +4562,9 @@ "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true }, "node_modules/bignumber.js": { @@ -3834,14 +4584,14 @@ } }, "node_modules/bintrees": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", - "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" }, "node_modules/bip174": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.0.tgz", - "integrity": "sha512-lkc0XyiX9E9KiVAS1ZiOqK1xfiwvf4FXDDdkDq5crcDzOq+xGytY+14qCsqz7kCiy8rpN1CRNfacRhf9G3JNSA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz", + "integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==", "engines": { "node": ">=8.0.0" } @@ -3930,18 +4680,12 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, "node_modules/browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, "funding": [ { @@ -3951,14 +4695,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -3980,11 +4727,11 @@ } }, "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", "dependencies": { - "base-x": "^3.0.2" + "base-x": "^4.0.0" } }, "node_modules/bs58check": { @@ -3997,6 +4744,22 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/bs58check/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/bs58check/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, "node_modules/bser": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", @@ -4009,7 +4772,7 @@ "node_modules/btoa-lite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", + "integrity": "sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==", "dev": true }, "node_modules/buffer": { @@ -4082,16 +4845,24 @@ "node": ">=8" } }, + "node_modules/c32check/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/cacache": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.3.tgz", - "integrity": "sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==", + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^7.7.1", - "minipass": "^5.0.0", + "minipass": "^7.0.3", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", @@ -4112,30 +4883,19 @@ "balanced-match": "^1.0.0" } }, - "node_modules/cacache/node_modules/fs-minipass": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", - "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", - "dependencies": { - "minipass": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/cacache/node_modules/glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", + "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" }, "bin": { - "glob": "dist/cjs/src/bin.js" + "glob": "dist/esm/bin.mjs" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -4167,30 +4927,31 @@ } }, "node_modules/cacache/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==" }, "node_modules/callsites": { "version": "3.1.0", @@ -4228,9 +4989,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001328", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001328.tgz", - "integrity": "sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ==", + "version": "1.0.30001553", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz", + "integrity": "sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==", "dev": true, "funding": [ { @@ -4240,13 +5001,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, "node_modules/chalk": { "version": "4.1.0", @@ -4307,10 +5072,19 @@ } }, "node_modules/ci-info": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", - "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", - "dev": true + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } }, "node_modules/cipher-base": { "version": "1.0.4", @@ -4322,9 +5096,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "node_modules/clean-stack": { @@ -4346,24 +5120,10 @@ "wrap-ansi": "^6.2.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "engines": { "iojs": ">= 1.0.0", @@ -4376,9 +5136,9 @@ "integrity": "sha512-XKnm9wwZzJRGuvR1BGNbFZEfa4SEr38do8Z5riq0797QwMT836EqhdPuhtbn8uAX8vCMqJ7+gS4CHa1G9M5xhw==" }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "node_modules/color-convert": { @@ -4446,7 +5206,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/concurrently": { "version": "7.3.0", @@ -4472,14 +5232,17 @@ } }, "node_modules/concurrently/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==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/concurrently/node_modules/supports-color": { @@ -4497,6 +5260,23 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/concurrently/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/concurrently/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -4507,18 +5287,18 @@ } }, "node_modules/concurrently/node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -4536,7 +5316,7 @@ "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, "node_modules/content-disposition": { "version": "0.5.4", @@ -4550,9 +5330,9 @@ } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } @@ -4605,18 +5385,9 @@ } }, "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, "node_modules/cookie": { @@ -4630,18 +5401,18 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, "node_modules/core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.1.tgz", + "integrity": "sha512-qVSq3s+d4+GsqN0teRCJtM6tdEEXyWxjzbhVrCHmBS5ZTM0FS2MOS0D13dUXAWDUN6a+lHI/N1hF9Ytz6iLl9Q==", "dev": true, "hasInstallScript": true, "funding": { @@ -4652,7 +5423,7 @@ "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -4694,6 +5465,27 @@ "sha.js": "^2.4.0" } }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -4718,11 +5510,30 @@ } }, "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { - "node-fetch": "2.6.7" + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, "node_modules/cross-sha256": { @@ -4746,30 +5557,6 @@ "node": ">= 8" } }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -4782,7 +5569,7 @@ "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dependencies": { "assert-plus": "^1.0.0" }, @@ -4790,25 +5577,14 @@ "node": ">=0.10" } }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dev": true, "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" + "@babel/runtime": "^7.21.0" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/date-fns": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", - "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", - "dev": true, "engines": { "node": ">=0.11" }, @@ -4844,16 +5620,16 @@ "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "dependencies": { "decamelize": "^1.1.0", @@ -4861,28 +5637,33 @@ }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/decamelize-keys/node_modules/map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deep-is": { "version": "0.1.4", @@ -4891,30 +5672,49 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { - "object-keys": "^1.0.12" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "engines": { "node": ">=0.4.0" } @@ -4922,12 +5722,12 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "engines": { "node": ">= 0.6" } @@ -4941,12 +5741,12 @@ "node_modules/destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" }, "node_modules/detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", "engines": { "node": ">=8" } @@ -4970,12 +5770,12 @@ } }, "node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/dir-glob": { @@ -5014,27 +5814,6 @@ "node": ">=6.0.0" } }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -5085,7 +5864,7 @@ "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -5107,12 +5886,12 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.107", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.107.tgz", - "integrity": "sha512-Huen6taaVrUrSy8o7mGStByba8PfOWWluHNxSHGBrCgEdFVLtvdQDBr9LBCF9Uci8SYxh28QNNMO0oC17wbGAg==", + "version": "1.4.563", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz", + "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==", "dev": true }, "node_modules/elliptic": { @@ -5130,12 +5909,12 @@ } }, "node_modules/emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sindresorhus/emittery?sponsor=1" @@ -5149,7 +5928,7 @@ "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -5238,9 +6017,9 @@ } }, "node_modules/engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.7.tgz", + "integrity": "sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ==", "engines": { "node": ">=10.0.0" } @@ -5266,12 +6045,13 @@ } }, "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8.6" @@ -5300,31 +6080,50 @@ } }, "node_modules/es-abstract": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.3.tgz", - "integrity": "sha512-4axXLNovnMYf0+csS5rVnS5hLmV1ek+ecx9MuCjByL1E5Nn54avf6CHQxIjgQIHBnfX9AMxTRIy0q+Yu5J/fXA==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", - "has": "^1.0.3", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -5333,13 +6132,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -5381,7 +6194,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -5395,96 +6208,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/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/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz", + "integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", + "@eslint/eslintrc": "^1.3.3", + "@humanwhocodes/config-array": "^0.11.6", + "@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", @@ -5494,30 +6227,32 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.15.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.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -5530,9 +6265,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "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" @@ -5542,13 +6277,14 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -5581,16 +6317,20 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "engines": { "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/eslint-module-utils/node_modules/debug": { @@ -5602,73 +6342,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-module-utils/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/eslint-plugin-import": { "version": "2.25.3", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz", @@ -5720,19 +6393,19 @@ "node_modules/eslint-plugin-import/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, "node_modules/eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=12.0.0" }, "peerDependencies": { "eslint": ">=7.28.0", @@ -5745,13 +6418,13 @@ } }, "node_modules/eslint-plugin-tsdoc": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", - "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.17.tgz", + "integrity": "sha512-xRmVi7Zx44lOBuYqG8vzTXuL6IdGOeF9nHX17bjJ8+VE6fsxpdGem0/SBTmAwgYMKYB1WBkqRJVQ+n8GK041pA==", "dev": true, "dependencies": { - "@microsoft/tsdoc": "0.13.2", - "@microsoft/tsdoc-config": "0.15.2" + "@microsoft/tsdoc": "0.14.2", + "@microsoft/tsdoc-config": "0.16.2" } }, "node_modules/eslint-scope": { @@ -5795,18 +6468,21 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "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.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "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", @@ -5814,6 +6490,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { @@ -5825,6 +6504,22 @@ "node": ">=4.0" } }, + "node_modules/eslint/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/eslint/node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -5837,18 +6532,51 @@ "node": ">=10.13.0" } }, + "node_modules/eslint/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/eslint/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/espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", + "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.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" + "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/esprima": { @@ -5865,9 +6593,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "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" @@ -5927,7 +6655,7 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } @@ -5988,25 +6716,26 @@ "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/exponential-backoff": { @@ -6073,12 +6802,12 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/express/node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/extend": { "version": "3.0.2", @@ -6088,31 +6817,41 @@ "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "engines": [ "node >=0.6.0" ] }, + "node_modules/fast-content-type-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz", + "integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==" + }, "node_modules/fast-copy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" }, + "node_modules/fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" + }, "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==" }, "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -6130,16 +6869,57 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-json-stringify": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.8.0.tgz", + "integrity": "sha512-VVwK8CFMSALIvt14U8AvrSzQAwN/0vaVRiFFUVlpnXSnDGrSkOAO5MtzyN8oQNjLd5AqTW5OZRgyjoNuAuR3jQ==", + "dependencies": { + "@fastify/deepmerge": "^1.0.0", + "ajv": "^8.10.0", + "ajv-formats": "^2.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^2.1.0", + "rfdc": "^1.2.0" + } + }, + "node_modules/fast-json-stringify/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-querystring": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", + "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", + "dependencies": { + "fast-decode-uri-component": "^1.0.1" + } + }, "node_modules/fast-redact": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.2.tgz", - "integrity": "sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz", + "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==", "engines": { "node": ">=6" } @@ -6149,62 +6929,206 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "dependencies": { - "bser": "2.1.1" + "node_modules/fast-uri": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.2.0.tgz", + "integrity": "sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg==" + }, + "node_modules/fastify": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.15.0.tgz", + "integrity": "sha512-m/CaRN8nf5uyYdrDe2qqq+0z3oGyE+A++qlKQoLJTI4WI0nWK9D6R3FxXQ3MVwt/md977GMR4F43pE9oqrS2zw==", + "dependencies": { + "@fastify/ajv-compiler": "^3.5.0", + "@fastify/error": "^3.0.0", + "@fastify/fast-json-stringify-compiler": "^4.2.0", + "abstract-logging": "^2.0.1", + "avvio": "^8.2.0", + "fast-content-type-parse": "^1.0.0", + "find-my-way": "^7.6.0", + "light-my-request": "^5.6.1", + "pino": "^8.5.0", + "process-warning": "^2.0.0", + "proxy-addr": "^2.0.7", + "rfdc": "^1.3.0", + "secure-json-parse": "^2.5.0", + "semver": "^7.3.7", + "tiny-lru": "^10.0.0" } }, - "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, + "node_modules/fastify-metrics": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/fastify-metrics/-/fastify-metrics-10.3.2.tgz", + "integrity": "sha512-02SEIGH02zfguqRMho0LB8L7YVAj5cIgWM0iqZslIErqaUWc1iHVAOC+YXYG3S2DZU6VHdFaMyuxjEOCQHAETA==", "dependencies": { - "flat-cache": "^3.0.4" + "fastify-plugin": "^4.3.0", + "prom-client": "^14.2.0" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "peerDependencies": { + "fastify": ">=4" } }, - "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==", + "node_modules/fastify-metrics/node_modules/prom-client": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.2.0.tgz", + "integrity": "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==", "dependencies": { - "to-regex-range": "^5.0.1" + "tdigest": "^0.1.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" + "node_modules/fastify-plugin": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", + "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==" + }, + "node_modules/fastify/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/fastify/node_modules/pino": { + "version": "8.16.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.16.1.tgz", + "integrity": "sha512-3bKsVhBmgPjGV9pyn4fO/8RtoVDR8ssW1ev819FsRXlRNgW8gR/9Kx+gCK4UPWd4JjrRDLWpzd/pb1AyWm3MGA==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.1.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^2.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/fastify/node_modules/pino-abstract-transport": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz", + "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/fastify/node_modules/readable-stream": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/fastify/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fastify/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, "node_modules/finalhandler/node_modules/debug": { @@ -6218,7 +7142,20 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-my-way": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-7.7.0.tgz", + "integrity": "sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-querystring": "^1.0.0", + "safe-regex2": "^2.0.0" + }, + "engines": { + "node": ">=14" + } }, "node_modules/find-up": { "version": "4.1.0", @@ -6249,16 +7186,17 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" } }, "node_modules/flat-cache/node_modules/rimraf": { @@ -6277,15 +7215,15 @@ } }, "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "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.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", "funding": [ { "type": "individual", @@ -6301,6 +7239,15 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -6317,9 +7264,9 @@ } }, "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { "node": ">=14" }, @@ -6330,7 +7277,7 @@ "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "engines": { "node": "*" } @@ -6370,7 +7317,7 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } @@ -6390,25 +7337,33 @@ } }, "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -6419,17 +7374,47 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", "dev": true }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -6467,14 +7452,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6534,7 +7520,7 @@ "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dependencies": { "assert-plus": "^1.0.0" } @@ -6559,14 +7545,14 @@ } }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -6591,7 +7577,7 @@ "node_modules/global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", "dev": true, "dependencies": { "ini": "^1.3.4" @@ -6601,9 +7587,9 @@ } }, "node_modules/globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -6615,6 +7601,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -6635,15 +7636,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "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/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "engines": { "node": ">=4" } @@ -6671,21 +7690,18 @@ } }, "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, "engines": { "node": ">= 0.4.0" } }, "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6699,6 +7715,30 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -6729,7 +7769,7 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, "node_modules/hash-base": { "version": "3.1.0", @@ -6753,6 +7793,18 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/help-me": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", @@ -6802,7 +7854,7 @@ "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -6821,18 +7873,6 @@ "node": ">=10" } }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -6873,12 +7913,11 @@ } }, "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dependencies": { - "@tootallnate/once": "1", + "@tootallnate/once": "2", "agent-base": "6", "debug": "4" }, @@ -6904,7 +7943,7 @@ "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -6916,9 +7955,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dependencies": { "agent-base": "6", "debug": "4" @@ -6981,9 +8020,9 @@ "dev": true }, "node_modules/husky/node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", @@ -7027,9 +8066,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" @@ -7038,7 +8077,7 @@ "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", "dev": true }, "node_modules/import-fresh": { @@ -7100,7 +8139,7 @@ "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "engines": { "node": ">=0.8.19" } @@ -7116,7 +8155,7 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -7134,13 +8173,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -7160,10 +8199,24 @@ "node": ">= 0.10" } }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, "node_modules/is-bigint": { @@ -7206,9 +8259,9 @@ } }, "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "engines": { "node": ">= 0.4" @@ -7230,12 +8283,12 @@ } }, "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7259,7 +8312,7 @@ "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "engines": { "node": ">=0.10.0" } @@ -7341,6 +8394,15 @@ "node": ">=8" } }, + "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": "3.0.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", @@ -7361,12 +8423,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -7440,7 +8496,7 @@ "node_modules/is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", "dev": true, "dependencies": { "text-extensions": "^1.0.0" @@ -7449,10 +8505,25 @@ "node": ">=0.10.0" } }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" }, "node_modules/is-weakref": { "version": "1.0.2", @@ -7467,15 +8538,15 @@ } }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isomorphic-ws": { "version": "4.0.1", @@ -7489,7 +8560,7 @@ "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -7501,42 +8572,78 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { @@ -7554,9 +8661,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -7567,9 +8674,9 @@ } }, "node_modules/jackspeak": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", - "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -7584,20 +8691,21 @@ } }, "node_modules/jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "dependencies": { - "@jest/core": "^27.5.1", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^27.5.1" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -7609,73 +8717,73 @@ } }, "node_modules/jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", "execa": "^5.0.0", - "throat": "^6.0.1" + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "dependencies": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -7687,14 +8795,34 @@ } }, "node_modules/jest-cli/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==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/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/jest-cli/node_modules/y18n": { @@ -7707,272 +8835,237 @@ } }, "node_modules/jest-cli/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" } }, "node_modules/jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", - "glob": "^7.1.1", + "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { + "@types/node": "*", "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "ts-node": { "optional": true } } }, "node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, "node_modules/jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { "node": ">=6" @@ -7987,167 +9080,175 @@ } }, "node_modules/jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", + "resolve.exports": "^2.0.0", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, "node_modules/jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dev": true, - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "dependencies": { - "@babel/core": "^7.7.2", + "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.5.1", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" } }, "node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -8155,24 +9256,24 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "dependencies": { - "@jest/types": "^27.5.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^27.5.1" + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate/node_modules/camelcase": { @@ -8188,35 +9289,37 @@ } }, "node_modules/jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.5.1", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker/node_modules/supports-color": { @@ -8237,7 +9340,7 @@ "node_modules/jju": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true }, "node_modules/joycon": { @@ -8248,6 +9351,16 @@ "node": ">=10" } }, + "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-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8268,53 +9381,7 @@ "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" }, "node_modules/jsesc": { "version": "2.5.2", @@ -8328,6 +9395,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -8339,6 +9412,22 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, + "node_modules/json-schema-resolver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-schema-resolver/-/json-schema-resolver-2.0.0.tgz", + "integrity": "sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg==", + "dependencies": { + "debug": "^4.1.1", + "rfdc": "^1.1.4", + "uri-js": "^4.2.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/Eomm/json-schema-resolver?sponsor=1" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -8347,18 +9436,18 @@ "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": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -8375,7 +9464,7 @@ "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" @@ -8384,7 +9473,7 @@ "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true, "engines": [ "node >= 0.2.0" @@ -8425,6 +9514,15 @@ "node": ">=0.6.0" } }, + "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/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -8465,6 +9563,24 @@ "node": ">= 0.8.0" } }, + "node_modules/light-my-request": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.11.0.tgz", + "integrity": "sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==", + "dependencies": { + "cookie": "^0.5.0", + "process-warning": "^2.0.0", + "set-cookie-parser": "^2.4.1" + } + }, + "node_modules/light-my-request/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -8496,13 +9612,13 @@ "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -8513,18 +9629,18 @@ "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, "node_modules/lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", + "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==", "dev": true }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true }, "node_modules/lru-cache": { @@ -8539,9 +9655,9 @@ } }, "node_modules/macos-release": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", - "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", + "integrity": "sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==", "dev": true, "engines": { "node": ">=6" @@ -8603,27 +9719,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -8632,14 +9727,6 @@ "node": ">=12" } }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -8719,7 +9806,7 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/merge-options": { "version": "3.0.4", @@ -8758,7 +9845,7 @@ "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -8829,9 +9916,9 @@ } }, "node_modules/minimal-polyfills": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/minimal-polyfills/-/minimal-polyfills-2.2.1.tgz", - "integrity": "sha512-WLmHQrsZob4rVYf8yHapZPNJZ3sspGa/sN8abuSD59b0FifDEE7HMfLUi24z7mPZqTpBXy4Svp+iGvAmclCmXg==" + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/minimal-polyfills/-/minimal-polyfills-2.2.3.tgz", + "integrity": "sha512-oxdmJ9cL+xV72h0xYxp4tP2d5/fTBpP45H8DIOn9pASuF8a3IYTf+25fMGDYGiWW+MFsuog6KD6nfmhZJQ+uUw==" }, "node_modules/minimalistic-assert": { "version": "1.0.1", @@ -8841,7 +9928,7 @@ "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" }, "node_modules/minimatch": { "version": "3.1.2", @@ -8855,9 +9942,12 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minimist-options": { "version": "4.1.0", @@ -8876,19 +9966,16 @@ "node_modules/minimist-options/node_modules/is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } @@ -8904,12 +9991,23 @@ "node": ">= 8" } }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", "dependencies": { - "minipass": "^5.0.0", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, @@ -8921,11 +10019,11 @@ } }, "node_modules/minipass-fetch/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minipass-flush": { @@ -8939,6 +10037,17 @@ "node": ">= 8" } }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -8950,6 +10059,17 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -8961,6 +10081,17 @@ "node": ">=8" } }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", @@ -8973,6 +10104,17 @@ "node": ">= 8" } }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -8984,21 +10126,35 @@ "node": ">=10" } }, + "node_modules/mnemonist": { + "version": "0.39.5", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.5.tgz", + "integrity": "sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==", + "dependencies": { + "obliterator": "^2.0.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==" }, "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", "optional": true }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "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/negotiator": { @@ -9054,25 +10210,6 @@ } } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/node-gyp": { "version": "9.4.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", @@ -9098,9 +10235,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", - "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", + "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", "optional": true, "bin": { "node-gyp-build": "bin.js", @@ -9197,7 +10334,7 @@ "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, "node_modules/node-pg-migrate": { @@ -9221,13 +10358,13 @@ } }, "node_modules/node-pg-migrate/node_modules/@types/pg": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.5.tgz", - "integrity": "sha512-tOkGtAqRVkHa/PVZicq67zuujI4Oorfglsr2IbKofDwBSysnaqSx7W1mDqFqdkGE6Fbgh+PZAl0r/BWON/mozw==", + "version": "8.10.7", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.7.tgz", + "integrity": "sha512-ksJqHipwYaSEHz9e1fr6H6erjoEdNNaOxwyJgPx9bNeaqOW3iWBQgVHfpwiSAoqGzchfc+ZyRLwEfeCcyYD3uQ==", "dependencies": { "@types/node": "*", "pg-protocol": "*", - "pg-types": "^2.2.0" + "pg-types": "^4.0.1" } }, "node_modules/node-pg-migrate/node_modules/cliui": { @@ -9251,6 +10388,74 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/node-pg-migrate/node_modules/pg-types": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", + "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.0.1", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-pg-migrate/node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "engines": { + "node": ">=12" + } + }, + "node_modules/node-pg-migrate/node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/node-pg-migrate/node_modules/postgres-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", + "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/node-pg-migrate/node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/node-pg-migrate/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==", + "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/node-pg-migrate/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -9277,17 +10482,17 @@ } }, "node_modules/node-pg-migrate/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "engines": { "node": ">=12" } }, "node_modules/node-releases": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz", - "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, "node_modules/nodemon": { @@ -9331,7 +10536,7 @@ "node_modules/nodemon/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" @@ -9433,12 +10638,6 @@ "set-blocking": "^2.0.0" } }, - "node_modules/nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -9450,15 +10649,15 @@ "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9474,14 +10673,14 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -9492,14 +10691,14 @@ } }, "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -9508,6 +10707,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -9520,14 +10724,17 @@ "dev": true }, "node_modules/on-exit-leak-free": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", - "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "engines": { + "node": ">=14.0.0" + } }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "dependencies": { "ee-first": "1.1.1" }, @@ -9538,7 +10745,7 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dependencies": { "wrappy": "1" } @@ -9558,6 +10765,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==" + }, "node_modules/opencollective-postinstall": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", @@ -9573,17 +10785,17 @@ "integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==" }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "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", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -9605,21 +10817,21 @@ "node_modules/p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", "engines": { "node": ">=4" } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "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": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9637,6 +10849,21 @@ "node": ">=8" } }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", @@ -9721,12 +10948,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -9747,7 +10968,7 @@ "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": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "engines": { "node": ">=0.10.0" } @@ -9782,21 +11003,13 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", - "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", "engines": { "node": "14 || >=16.14" } }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, "node_modules/path-to-regexp": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", @@ -9814,7 +11027,7 @@ "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/pg": { "version": "8.7.1", @@ -9870,18 +11083,26 @@ "node": ">=4.0.0" } }, + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "engines": { + "node": ">=4" + } + }, "node_modules/pg-pool": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", - "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", - "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" }, "node_modules/pg-types": { "version": "2.2.0", @@ -9907,9 +11128,9 @@ } }, "node_modules/pgpass/node_modules/split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "engines": { "node": ">= 10.x" } @@ -9985,14 +11206,15 @@ } }, "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz", - "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", - "process": "^0.11.10" + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -10065,28 +11287,29 @@ } }, "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz", - "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", + "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", - "process": "^0.11.10" + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/pino-std-serializers": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.0.tgz", - "integrity": "sha512-IWgSzUL8X1w4BIWTwErRgtV8PyOGOOi60uqv0oKuS/fOA8Nco/OeI6lBuc4dyP8MMfdFwyHqTMcBIA7nDiqEqA==" + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, "engines": { "node": ">= 6" @@ -10135,21 +11358,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/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/pkg-dir/node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", @@ -10194,7 +11402,7 @@ "node_modules/postgres-bytea": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", "engines": { "node": ">=0.10.0" } @@ -10218,6 +11426,11 @@ "node": ">=0.10.0" } }, + "node_modules/postgres-range": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", + "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -10228,15 +11441,18 @@ } }, "node_modules/prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "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-linter-helpers": { @@ -10252,17 +11468,17 @@ } }, "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "react-is": "^18.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/pretty-format/node_modules/ansi-styles": { @@ -10363,9 +11579,9 @@ } }, "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "node_modules/pstree.remy": { "version": "1.1.8", @@ -10383,17 +11599,33 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "engines": { "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", "dev": true, "engines": { "node": ">=0.6.0", @@ -10414,7 +11646,7 @@ "node_modules/querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "engines": { "node": ">=0.4.x" @@ -10485,9 +11717,9 @@ } }, "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/read-pkg": { @@ -10568,9 +11800,9 @@ } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -10613,11 +11845,28 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", "dev": true }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -10692,22 +11941,10 @@ "request": "^2.34" } }, - "node_modules/request-promise-native/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -10725,18 +11962,6 @@ "node": ">=0.6" } }, - "node_modules/request/node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/request/node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -10749,7 +11974,15 @@ "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "engines": { "node": ">=0.10.0" } @@ -10763,15 +11996,15 @@ "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -10816,14 +12049,22 @@ } }, "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, "engines": { "node": ">=10" } }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -10836,12 +12077,16 @@ "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/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, "node_modules/rimraf": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", @@ -10870,15 +12115,19 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.0.0.tgz", - "integrity": "sha512-zmp9ZDC6NpDNLujV2W2n+3lH+BafIVZ4/ct+Yj3BMZTH/+bgm/eVjHzeFLwxJrrIGgjjS2eiQLlpurHsNlEAtQ==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.6.4" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -10888,9 +12137,9 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -10902,15 +12151,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -10985,11 +12225,11 @@ } }, "node_modules/run-exclusive": { - "version": "2.2.14", - "resolved": "https://registry.npmjs.org/run-exclusive/-/run-exclusive-2.2.14.tgz", - "integrity": "sha512-NHaQfB3zPJFx7p4M06AcmoK8xz/h8YDMCdy3jxfyoC9VqIbl1U+DiVjUuAYZBRMwvj5qkQnOUGfsmyUC4k46dg==", + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/run-exclusive/-/run-exclusive-2.2.19.tgz", + "integrity": "sha512-K3mdoAi7tjJ/qT7Flj90L7QyPozwUaAG+CVhkdDje4HLKXUYC3N/Jzkau3flHVDLQVhiHBtcimVodMjN9egYbA==", "dependencies": { - "minimal-polyfills": "^2.1.5" + "minimal-polyfills": "^2.2.3" } }, "node_modules/run-parallel": { @@ -11016,14 +12256,32 @@ } }, "node_modules/rxjs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", - "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "dependencies": { "tslib": "^2.1.0" } }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -11043,10 +12301,32 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", + "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", + "dependencies": { + "ret": "~0.2.0" + } + }, "node_modules/safe-stable-stringify": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", - "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "engines": { "node": ">=10" } @@ -11056,18 +12336,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/secure-json-parse": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", @@ -11088,7 +12356,7 @@ "node_modules/semver-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true }, "node_modules/semver-regex": { @@ -11137,7 +12405,7 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", @@ -11161,7 +12429,41 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -11200,10 +12502,13 @@ } }, "node_modules/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/side-channel": { "version": "1.0.4", @@ -11231,9 +12536,9 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-update-notifier": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", - "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", "dev": true, "dependencies": { "semver": "~7.0.0" @@ -11335,9 +12640,9 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz", - "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -11373,9 +12678,9 @@ } }, "node_modules/sonic-boom": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", - "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.7.0.tgz", + "integrity": "sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==", "dependencies": { "atomic-sleep": "^1.0.0" } @@ -11400,13 +12705,13 @@ "node_modules/spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", "dev": true }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -11430,9 +12735,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", "dev": true }, "node_modules/split2": { @@ -11446,13 +12751,13 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -11474,28 +12779,28 @@ } }, "node_modules/ssri": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz", - "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", "dependencies": { - "minipass": "^5.0.0" + "minipass": "^7.0.3" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/ssri/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" @@ -11516,7 +12821,7 @@ "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha1-Gsig2Ug4SNFpXkGLbQMaPDzmjjs=", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, "node_modules/stacks-encoding-native-js": { @@ -11529,14 +12834,14 @@ } }, "node_modules/stacks-encoding-native-js/node_modules/@types/node": { - "version": "16.11.49", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.49.tgz", - "integrity": "sha512-Abq9fBviLV93OiXMu+f6r0elxCzRwc0RC5f99cU892uBITL44pTvgvEqlRlPRi8EGcO1z7Cp8A4d0s/p3J/+Nw==" + "version": "16.18.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.59.tgz", + "integrity": "sha512-PJ1w2cNeKUEdey4LiPra0ZuxZFOGvetswE8qHRriV/sUkL5Al4tTmPV9D2+Y/TPIxTHHgxTfRjZVKWhPw/ORhQ==" }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "engines": { "node": ">= 0.6" } @@ -11544,7 +12849,7 @@ "node_modules/stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", "engines": { "node": ">=0.10.0" } @@ -11602,27 +12907,46 @@ "node": ">=8" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11663,7 +12987,7 @@ "node_modules/strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", "dev": true, "engines": { "node": ">=0.10.0" @@ -11746,10 +13070,16 @@ "node": ">= 0.12" } }, + "node_modules/superagent/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/superagent/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -11800,19 +13130,6 @@ "node": ">=8" } }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -11825,50 +13142,50 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/tdigest": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", - "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dependencies": { - "bintrees": "1.0.1" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" + "yallist": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tdigest": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", + "dependencies": { + "bintrees": "1.0.2" } }, "node_modules/test-exclude": { @@ -11897,27 +13214,21 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "node_modules/thread-stream": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", - "integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", + "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", "dependencies": { "real-require": "^0.2.0" } }, - "node_modules/throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, "node_modules/through2": { @@ -11929,6 +13240,14 @@ "readable-stream": "3" } }, + "node_modules/tiny-lru": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-10.4.1.tgz", + "integrity": "sha512-buLIzw7ppqymuO3pt10jHk/6QMeZLbidihMQU+N6sogF6EnBzG0qtDWIHuhw1x3dyNgVL/KTGIZsTK81+yCzLg==", + "engines": { + "node": ">=12" + } + }, "node_modules/tiny-secp256k1": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", @@ -11949,7 +13268,7 @@ "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "engines": { "node": ">=4" @@ -11989,7 +13308,7 @@ "node_modules/touch/node_modules/nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", "dev": true, "dependencies": { "abbrev": "1" @@ -12002,30 +13321,21 @@ } }, "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" + "psl": "^1.1.28", + "punycode": "^2.1.1" }, "engines": { - "node": ">=6" + "node": ">=0.8" } }, "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/tree-kill": { "version": "1.2.2", @@ -12054,39 +13364,38 @@ } }, "node_modules/ts-jest": { - "version": "27.1.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.3.tgz", - "integrity": "sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA==", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", "dev": true, "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@types/jest": "^27.0.0", - "babel-jest": ">=27.0.0 <28", - "esbuild": "~0.14.0", - "jest": "^27.0.0", - "typescript": ">=3.8 <5.0" + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { "@babel/core": { "optional": true }, - "@types/jest": { + "@jest/types": { "optional": true }, "babel-jest": { @@ -12097,13 +13406,37 @@ } } }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.8.2.tgz", + "integrity": "sha512-LYdGnoGddf1D6v8REPtIH+5iq/gTDuZqv2/UJUU7tKjuEU8xVZorBM+buCGNjj+pGEud+sOoM4CX3/YzINpENA==", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -12114,7 +13447,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -12140,15 +13473,6 @@ } } }, - "node_modules/ts-node/node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/ts-unused-exports": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/ts-unused-exports/-/ts-unused-exports-7.0.3.tgz", @@ -12173,20 +13497,20 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dependencies": { "minimist": "^1.2.0" }, @@ -12197,7 +13521,7 @@ "node_modules/tsconfig-paths/node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "engines": { "node": ">=4" } @@ -12240,7 +13564,7 @@ "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dependencies": { "safe-buffer": "^5.0.1" }, @@ -12251,7 +13575,7 @@ "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" }, "node_modules/type-check": { "version": "0.4.0", @@ -12298,24 +13622,80 @@ "node": ">= 0.6" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", "dev": true, "dependencies": { - "is-typedarray": "^1.0.0" - } - }, + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typeforce": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" }, "node_modules/typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12333,14 +13713,14 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" }, "funding": { @@ -12353,6 +13733,18 @@ "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/undici": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.5.tgz", + "integrity": "sha512-cSb4bPFd5qgR7qr2jYAi0hlX9n5YKK2ONKkLFkxl+v/9BvC0sOpZjBHDBSXc5lWAf5ty9oZdRXytBIHzgUcerw==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/unique-filename": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", @@ -12393,11 +13785,41 @@ "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -12409,7 +13831,7 @@ "node_modules/url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" @@ -12426,7 +13848,7 @@ "node_modules/url/node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" }, "node_modules/utf-8-validate": { "version": "5.0.7", @@ -12444,12 +13866,12 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -12463,40 +13885,31 @@ } }, "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", "dev": true }, "node_modules/v8-compile-cache-lib": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", + "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/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -12518,7 +13931,7 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } @@ -12526,7 +13939,7 @@ "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "engines": [ "node >=0.6.0" ], @@ -12536,27 +13949,6 @@ "extsprintf": "^1.2.0" } }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -12567,41 +13959,17 @@ } }, "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "node_modules/which": { @@ -12635,9 +14003,9 @@ } }, "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "dev": true }, "node_modules/which-pm-runs": { @@ -12649,6 +14017,25 @@ "node": ">=4" } }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/why-is-node-running": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.0.tgz", @@ -12745,7 +14132,7 @@ "node_modules/windows-release/node_modules/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "dev": true, "engines": { "node": ">=0.10.0" @@ -12754,7 +14141,7 @@ "node_modules/windows-release/node_modules/npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", "dev": true, "dependencies": { "path-key": "^2.0.0" @@ -12766,7 +14153,7 @@ "node_modules/windows-release/node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, "engines": { "node": ">=4" @@ -12784,7 +14171,7 @@ "node_modules/windows-release/node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "dependencies": { "shebang-regex": "^1.0.0" @@ -12796,7 +14183,7 @@ "node_modules/windows-release/node_modules/shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, "engines": { "node": ">=0.10.0" @@ -12814,29 +14201,18 @@ "which": "bin/which" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "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": ">=8" } }, "node_modules/wrap-ansi-cjs": { @@ -12859,18 +14235,19 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/ws": { @@ -12893,18 +14270,6 @@ } } }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", @@ -13015,9810 +14380,5 @@ "node": ">=10" } } - }, - "dependencies": { - "@actions/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz", - "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", - "dev": true, - "requires": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" - }, - "dependencies": { - "@actions/http-client": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", - "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", - "dev": true, - "requires": { - "tunnel": "^0.0.6" - } - } - } - }, - "@actions/exec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.0.tgz", - "integrity": "sha512-LImpN9AY0J1R1mEYJjVJfSZWU4zYOlEcwSTgPve1rFQqK5AwrEs6uWW5Rv70gbDIQIAUwI86z6B+9mPK4w9Sbg==", - "dev": true, - "requires": { - "@actions/io": "^1.0.1" - } - }, - "@actions/github": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-2.2.0.tgz", - "integrity": "sha512-9UAZqn8ywdR70n3GwVle4N8ALosQs4z50N7XMXrSTUVOmVpaBC5kE3TRTT7qQdi3OaQV24mjGuJZsHUmhD+ZXw==", - "dev": true, - "requires": { - "@actions/http-client": "^1.0.3", - "@octokit/graphql": "^4.3.1", - "@octokit/rest": "^16.43.1" - } - }, - "@actions/http-client": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz", - "integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==", - "dev": true, - "requires": { - "tunnel": "0.0.6" - } - }, - "@actions/io": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz", - "integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.0" - } - }, - "@apidevtools/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", - "requires": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - } - }, - "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", - "dev": true - }, - "@babel/core": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz", - "integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.9", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.9", - "@babel/parser": "^7.17.9", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", - "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true - }, - "@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, - "requires": { - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true - }, - "@babel/helpers": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", - "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" - } - }, - "@babel/highlight": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", - "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", - "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", - "dev": true - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", - "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.16.7" - } - }, - "@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/traverse": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", - "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.9", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.9", - "@babel/types": "^7.17.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "@commitlint/cli": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-9.1.2.tgz", - "integrity": "sha512-ctRrrPqjZ8r4Vc4FXpPaScEpkPwfvB0Us3NK2SD2AnLwXGMxOLFTabDmNySU1Xc40ud2CmJsaV8lpavvzs8ZZA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.9.6", - "@commitlint/format": "^9.1.2", - "@commitlint/lint": "^9.1.2", - "@commitlint/load": "^9.1.2", - "@commitlint/read": "^9.1.2", - "chalk": "4.1.0", - "core-js": "^3.6.1", - "get-stdin": "7.0.0", - "lodash": "^4.17.19", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^15.1.0" - } - }, - "@commitlint/config-conventional": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-10.0.0.tgz", - "integrity": "sha512-M9l7hh2a1GB9nQ/Gm+aDLGPmzGdpgxqJoSmrbTxDlapJDyaL7FPe5aQf66F50Eq3j0bmaRaJihFCA6mIUBQAag==", - "dev": true, - "requires": { - "conventional-changelog-conventionalcommits": "^4.3.1" - } - }, - "@commitlint/ensure": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-9.1.2.tgz", - "integrity": "sha512-hwQICwpNSTsZgj/1/SdPvYAzhwjwgCJI4vLbT879+Jc+AJ6sj2bUDGw/F89vzgKz1VnaMm4D65bNhoWhG3pdhQ==", - "dev": true, - "requires": { - "@commitlint/types": "^9.1.2", - "lodash": "^4.17.19" - } - }, - "@commitlint/execute-rule": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-9.1.2.tgz", - "integrity": "sha512-NGbeo0KCVYo1yj9vVPFHv6RGFpIF6wcQxpFYUKGIzZVV9Vz1WyiKS689JXa99Dt1aN0cZlEJJLnTNDIgYls0Vg==", - "dev": true - }, - "@commitlint/format": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-9.1.2.tgz", - "integrity": "sha512-+ZWTOSGEU6dbn3NRh1q7sY5K5QLiSs7E2uSzuYnWHXcQk8nlTvnE0ibwMCQxdKLaOTZiN57fHM/7M9Re2gsRuw==", - "dev": true, - "requires": { - "@commitlint/types": "^9.1.2", - "chalk": "^4.0.0" - } - }, - "@commitlint/is-ignored": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-9.1.2.tgz", - "integrity": "sha512-423W/+Ro+Cc8cg81+t9gds1EscMZNjnGT31nKDvxVxJxXiXQsYYoFEQbU+nfUrRGQsUikEgEJ3ppVGr1linvcQ==", - "dev": true, - "requires": { - "@commitlint/types": "^9.1.2", - "semver": "7.3.2" - } - }, - "@commitlint/lint": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-9.1.2.tgz", - "integrity": "sha512-XvggqHZ4XSTKOgzJhCzz52cWRRO57QQnEviwGj0qnD4jdwC+8h2u9LNZwoa2tGAuaNM3nSm//wNK7FRZhgiiFA==", - "dev": true, - "requires": { - "@commitlint/is-ignored": "^9.1.2", - "@commitlint/parse": "^9.1.2", - "@commitlint/rules": "^9.1.2", - "@commitlint/types": "^9.1.2" - } - }, - "@commitlint/load": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-9.1.2.tgz", - "integrity": "sha512-FPL82xBuF7J3EJ57kLVoligQP4BFRwrknooP+vNT787AXmQ/Fddc/iYYwHwy67pNkk5N++/51UyDl/CqiHb6nA==", - "dev": true, - "requires": { - "@commitlint/execute-rule": "^9.1.2", - "@commitlint/resolve-extends": "^9.1.2", - "@commitlint/types": "^9.1.2", - "chalk": "4.1.0", - "cosmiconfig": "^6.0.0", - "lodash": "^4.17.19", - "resolve-from": "^5.0.0" - } - }, - "@commitlint/message": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-9.1.2.tgz", - "integrity": "sha512-ndlx5z7bPVLG347oYJUHuQ41eTcsw+aUYT1ZwQyci0Duy2atpuoeeSw9SuM1PjufzRCpb6ExzFEgGzcCRKAJsg==", - "dev": true - }, - "@commitlint/parse": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-9.1.2.tgz", - "integrity": "sha512-d+/VYbkotctW+lzDpus/R6xTerOqFQkW1myH+3PwnqYSE6JU/uHT4MlZNGJBv8pX9SPlR66t6X9puFobqtezEw==", - "dev": true, - "requires": { - "conventional-changelog-angular": "^5.0.0", - "conventional-commits-parser": "^3.0.0" - } - }, - "@commitlint/read": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-9.1.2.tgz", - "integrity": "sha512-C2sNBQOqeQXMxpWtRnXYKYB3D9yuybPtQNY/P67A6o8XH/UMHkFaUTyIx1KRgu0IG0yTTItRt46FGnsMWLotvA==", - "dev": true, - "requires": { - "@commitlint/top-level": "^9.1.2", - "fs-extra": "^8.1.0", - "git-raw-commits": "^2.0.0" - } - }, - "@commitlint/resolve-extends": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-9.1.2.tgz", - "integrity": "sha512-HcoL+qFGmWEu9VM4fY0HI+VzF4yHcg3x+9Hx6pYFZ+r2wLbnKs964y0v68oyMO/mS/46MVoLNXZGR8U3adpadg==", - "dev": true, - "requires": { - "import-fresh": "^3.0.0", - "lodash": "^4.17.19", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - } - }, - "@commitlint/rules": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-9.1.2.tgz", - "integrity": "sha512-1vecFuzqVqjiT57ocXq1bL8V6GEF1NZs3BR0dQzObaqHftImIxBVII299gasckTkcuxNc8M+7XxZyKxUthukpQ==", - "dev": true, - "requires": { - "@commitlint/ensure": "^9.1.2", - "@commitlint/message": "^9.1.2", - "@commitlint/to-lines": "^9.1.2", - "@commitlint/types": "^9.1.2" - } - }, - "@commitlint/to-lines": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-9.1.2.tgz", - "integrity": "sha512-o4zWcMf9EnzA3MOqx01780SgrKq5hqDJmUBPk30g6an0XcDuDy3OSZHHTJFdzsg4V9FjC4OY44sFeK7GN7NaxQ==", - "dev": true - }, - "@commitlint/top-level": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-9.1.2.tgz", - "integrity": "sha512-KMPP5xVePcz3B1dKqcZdU4FZBVOkT+bG3ip4RQX2TeCJoomMkTjd0utALs7rpTGLID6BXbwwXepZCZJREjR/Bw==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "@commitlint/types": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-9.1.2.tgz", - "integrity": "sha512-r3fwVbVH+M8W0qYlBBZFsUwKe6NT5qvz+EmU7sr8VeN1cQ63z+3cfXyTo7WGGEMEgKiT0jboNAK3b1FZp8k9LQ==", - "dev": true - }, - "@cspotcode/source-map-consumer": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", - "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true - }, - "@cspotcode/source-map-support": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", - "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "dev": true, - "requires": { - "@cspotcode/source-map-consumer": "0.8.0" - } - }, - "@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" - } - }, - "@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dev": true, - "requires": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" - } - }, - "@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - } - }, - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" - } - }, - "@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", - "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" - } - }, - "@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - } - }, - "@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz", - "integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@microsoft/tsdoc": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", - "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", - "dev": true - }, - "@microsoft/tsdoc-config": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", - "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", - "dev": true, - "requires": { - "@microsoft/tsdoc": "0.13.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - }, - "dependencies": { - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - } - } - }, - "@noble/hashes": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.5.tgz", - "integrity": "sha512-LTMZiiLc+V4v1Yi16TD6aX2gmtKszNye0pQgbaLqkvhIqP7nVsSaJsWloGQjJfJ8offaoP5GtX3yY5swbcJxxQ==" - }, - "@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==" - }, - "@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" - } - }, - "@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", - "requires": { - "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dev": true, - "peer": true, - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", - "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", - "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.1" - }, - "dependencies": { - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - } - } - }, - "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true, - "requires": {} - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", - "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.1", - "deprecation": "^2.3.1" - }, - "dependencies": { - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - } - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "16.43.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz", - "integrity": "sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==", - "dev": true, - "requires": { - "@octokit/auth-token": "^2.4.0", - "@octokit/plugin-paginate-rest": "^1.1.1", - "@octokit/plugin-request-log": "^1.0.0", - "@octokit/plugin-rest-endpoint-methods": "2.4.0", - "@octokit/request": "^5.2.0", - "@octokit/request-error": "^1.0.2", - "atob-lite": "^2.0.0", - "before-after-hook": "^2.0.0", - "btoa-lite": "^1.0.0", - "deprecation": "^2.0.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "lodash.uniq": "^4.5.0", - "octokit-pagination-methods": "^1.1.0", - "once": "^1.4.0", - "universal-user-agent": "^4.0.0" - }, - "dependencies": { - "@octokit/request-error": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", - "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - }, - "universal-user-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", - "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", - "dev": true, - "requires": { - "os-name": "^3.1.0" - } - } - } - }, - "@octokit/types": { - "version": "6.34.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", - "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^11.2.0" - } - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true - }, - "@promster/express": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@promster/express/-/express-6.0.0.tgz", - "integrity": "sha512-yeN+2XGZbeLNxG1S/FvyYtedjpbAa86txIhExSQwWvy64Ok69Xq0E5RqnVujN8If/T2J5vd/0sRruW3jWV9x0A==", - "requires": { - "@promster/metrics": "^8.0.0", - "merge-options": "3.0.4", - "tslib": "2.3.1" - } - }, - "@promster/metrics": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@promster/metrics/-/metrics-8.0.0.tgz", - "integrity": "sha512-pf39uSyU2yKL2qlkS/bJ5Hstsdlrzgd0zZ3NOSh3yGJSEJl91cpo/G+gcOhV1AXmwWdVIgGA/ovmMrF38bdFzA==", - "requires": { - "@sematext/gc-stats": "1.5.5", - "lodash.memoize": "4.1.2", - "lodash.once": "4.1.1", - "merge-options": "3.0.4", - "optional": "0.1.4", - "ts-essentials": "9.0.0", - "tslib": "2.3.1", - "url": "0.11.0", - "url-value-parser": "2.0.3" - } - }, - "@promster/server": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@promster/server/-/server-6.0.6.tgz", - "integrity": "sha512-FKNTi8wgxVxHVCVIy2NlbYn2AJy1uldtEUo7YznJbg+vve8RF2RXY4jPLUos49hzYPOh8yM348LyCyqMJ9xQzw==", - "requires": { - "@promster/metrics": "^7.0.4", - "tslib": "2.3.1" - }, - "dependencies": { - "@promster/metrics": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@promster/metrics/-/metrics-7.0.4.tgz", - "integrity": "sha512-0/7+rLskROGx7DZ5PX5uGAmQfN+is7VPodQA8lmYHSrFDIaZ9Q+Elhe8tMNKF5KDqezPliw1IM8ajN6tTfWapg==", - "requires": { - "@sematext/gc-stats": "1.5.5", - "lodash.memoize": "4.1.2", - "lodash.once": "4.1.1", - "merge-options": "3.0.4", - "optional": "0.1.4", - "ts-essentials": "9.0.0", - "tslib": "2.3.1", - "url": "0.11.0", - "url-value-parser": "2.0.3" - } - } - } - }, - "@promster/types": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@promster/types/-/types-3.2.3.tgz", - "integrity": "sha512-l5IYJ6Z5qm1iWYz4vH/T/S2yfQLnix8msM33KzzfZKCVTPSjzcSo7VuThXQIpaPX7odCNOoKhja3n+HobpwKCw==", - "requires": {} - }, - "@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==" - }, - "@scure/bip39": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", - "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", - "requires": { - "@noble/hashes": "~1.1.1", - "@scure/base": "~1.1.0" - } - }, - "@sematext/gc-stats": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@sematext/gc-stats/-/gc-stats-1.5.5.tgz", - "integrity": "sha512-OetiHJ7vVPy2xvM+qyTuGoDvnSy4B6JGEhoIRmAONhaa8oOL2NaBiBg2HEI+DQPwOpUeCTUVBV3/uiBt24Ru7Q==", - "optional": true, - "requires": { - "@mapbox/node-pre-gyp": "^1.0.5", - "nan": "^2.15.0" - } - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" - }, - "@stacks/common": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.2.tgz", - "integrity": "sha512-tnkyEIA7YgX9GIkqlHocQPPax25uaboJ4aTX5wVs6kAGXY10+XI7VamRG4o+4DqnFVKwvIHR2fGcxdhtxNb/+Q==", - "requires": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - }, - "dependencies": { - "@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" - } - } - }, - "@stacks/encryption": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/encryption/-/encryption-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-RGpmTCvhlGdaHceBqba2bRnrPgcEZHs0irXOrYVMkLB7oC1Yi0BpAH0gf7Vz0xzfD+3omJ9E4i5uSYkn/unINg==", - "requires": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@scure/bip39": "1.1.0", - "@stacks/common": "^6.5.3-pr.ae8c520.0", - "@types/node": "^18.0.4", - "base64-js": "^1.5.1", - "bs58": "^5.0.0", - "ripemd160-min": "^0.0.6", - "varuint-bitcoin": "^1.1.2" - }, - "dependencies": { - "@stacks/common": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-qagihApT66HcppJYZgeAbKpSjJnR/2rkc4pgkjg/jYeevQARo5DNfJRBvheZ3DF4dAaNwTyOGMeoDBjr0OSEbw==", - "requires": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, - "@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==" - }, - "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==" - }, - "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" - } - } - } - }, - "@stacks/eslint-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@stacks/eslint-config/-/eslint-config-1.2.0.tgz", - "integrity": "sha512-uKPmUuLU57mRuF8pA9ilinSCgc/EvWs+yPf/P88m/Zt7TgGmvZmqPvt8BlxS4MM1ROsDDCRzTZkupOzuLrksGQ==", - "dev": true, - "requires": { - "@stacks/prettier-config": "0.0.10", - "@typescript-eslint/eslint-plugin": "5.5.0", - "@typescript-eslint/parser": "5.5.0", - "eslint": "8.3.0", - "eslint-config-prettier": "^8.3.0", - "eslint-import-resolver-typescript": "2.5.0", - "eslint-plugin-import": "2.25.3", - "eslint-plugin-prettier": "4.0.0" - }, - "dependencies": { - "@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", - "integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "5.5.0", - "@typescript-eslint/scope-manager": "5.5.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz", - "integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.5.0", - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/typescript-estree": "5.5.0", - "debug": "^4.3.2" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", - "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0" - } - }, - "@typescript-eslint/types": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", - "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", - "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", - "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", - "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.0.4", - "@humanwhocodes/config-array": "^0.6.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - } - } - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "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 - }, - "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" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@stacks/network": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.2.tgz", - "integrity": "sha512-+XNneecXCitis7OGDoCMqfKp0j4SICaij6XN9JTq+pAoaCbuJqLRZrrVP/ApkWbotTzeVZIbrZPqMLqkdgGTrg==", - "requires": { - "@stacks/common": "^6.5.2", - "cross-fetch": "^3.1.5" - } - }, - "@stacks/prettier-config": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.10.tgz", - "integrity": "sha512-MrYWGEgO/mYR8TOZIKknQEHbFQZ5VyAD/s8eF2Yxr6Lgalt2alVEh+6ODehVP2uepkyXPmJzLbaQYs8/L4E78Q==", - "dev": true, - "requires": { - "prettier": "2.5" - }, - "dependencies": { - "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true - } - } - }, - "@stacks/stacking": { - "version": "6.5.3-pr.693e11b.0", - "resolved": "https://registry.npmjs.org/@stacks/stacking/-/stacking-6.5.3-pr.693e11b.0.tgz", - "integrity": "sha512-qW+9/2j+D8k1hITrML4O43M5Y6Xrsuem4JUY+gR0QcfkHSewVVHgCmMdMZCy/VHAJaoW7eB0S1slK5fA+xdTQw==", - "requires": { - "@scure/base": "1.1.1", - "@stacks/common": "^6.5.3-pr.693e11b.0", - "@stacks/encryption": "^6.5.3-pr.693e11b.0", - "@stacks/network": "^6.5.3-pr.693e11b.0", - "@stacks/stacks-blockchain-api-types": "^0.61.0", - "@stacks/transactions": "^6.5.3-pr.693e11b.0", - "bs58": "^5.0.0" - }, - "dependencies": { - "@stacks/common": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/common/-/common-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-qagihApT66HcppJYZgeAbKpSjJnR/2rkc4pgkjg/jYeevQARo5DNfJRBvheZ3DF4dAaNwTyOGMeoDBjr0OSEbw==", - "requires": { - "@types/bn.js": "^5.1.0", - "@types/node": "^18.0.4" - } - }, - "@stacks/network": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/network/-/network-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-C4PFAjLQam7OF19WIrcDs+BgiZB8+EI/uQqnli2tw6gwwJfZVypXpV1EoieLQQ6ST8vXtkYbUcr1megN6QAdNw==", - "requires": { - "@stacks/common": "^6.5.3-pr.ae8c520.0", - "cross-fetch": "^3.1.5" - } - }, - "@stacks/transactions": { - "version": "6.5.3-pr.ae8c520.0", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.5.3-pr.ae8c520.0.tgz", - "integrity": "sha512-DtbQ3wG/3IJPEUmwMNLqTa4fpmmoATi3oSj1hS5X5MEmOFqaMMK/uMS48EqJZfHv8D/chXkpaUVmG0qzYBfYvw==", - "requires": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.5.3-pr.ae8c520.0", - "@stacks/network": "^6.5.3-pr.ae8c520.0", - "c32check": "^2.0.0", - "lodash.clonedeep": "^4.5.0" - } - }, - "@types/node": { - "version": "18.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.5.tgz", - "integrity": "sha512-seOA34WMo9KB+UA78qaJoCO20RJzZGVXQ5Sh6FWu0g/hfT44nKXnej3/tCQl7FL97idFpBhisLYCTB50S0EirA==" - }, - "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==" - }, - "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" - } - }, - "c32check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", - "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", - "requires": { - "@noble/hashes": "^1.1.2", - "base-x": "^4.0.0" - } - } - } - }, - "@stacks/stacks-blockchain-api-types": { - "version": "0.61.0", - "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-0.61.0.tgz", - "integrity": "sha512-yPOfTUboo5eA9BZL/hqMcM71GstrFs9YWzOrJFPeP4cOO1wgYvAcckgBRbgiE3NqeX0A7SLZLDAXLZbATuRq9w==" - }, - "@stacks/transactions": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@stacks/transactions/-/transactions-6.5.2.tgz", - "integrity": "sha512-xL4XF4xSFFJ+VMzeahBenGdg1T+y0Q0fSNA09jz7knTnnXvdAzzC+RP59xzuIjrAY/IWYO3X1sf0MGm9IIhYOg==", - "requires": { - "@noble/hashes": "1.1.5", - "@noble/secp256k1": "1.7.1", - "@stacks/common": "^6.5.2", - "@stacks/network": "^6.5.2", - "c32check": "^2.0.0", - "lodash.clonedeep": "^4.5.0" - }, - "dependencies": { - "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==" - }, - "c32check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-2.0.0.tgz", - "integrity": "sha512-rpwfAcS/CMqo0oCqDf3r9eeLgScRE3l/xHDCXhM3UyrfvIn7PrLq63uHh7yYbv8NzaZn5MVsVhIRpQ+5GZ5HyA==", - "requires": { - "@noble/hashes": "^1.1.2", - "base-x": "^4.0.0" - } - } - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true - }, - "@types/ajv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/ajv/-/ajv-1.0.0.tgz", - "integrity": "sha1-T7JEB0Ly9sMOf7B5e4OfxvaWaCo=", - "dev": true, - "requires": { - "ajv": "*" - } - }, - "@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true - }, - "@types/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", - "requires": { - "@types/node": "*" - } - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" - }, - "@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", - "dev": true - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "@types/dotenv-flow": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@types/dotenv-flow/-/dotenv-flow-3.2.0.tgz", - "integrity": "sha512-A79hbPwocbYkcTwGcDOFbKDuqyVo5mLAz/6Iq465YZ7R7Go5bT1PIM8I2jlPQkaD9u9fbotGVLkUPhX+9XUHfw==", - "dev": true - }, - "@types/elliptic": { - "version": "6.4.14", - "resolved": "https://registry.npmjs.org/@types/elliptic/-/elliptic-6.4.14.tgz", - "integrity": "sha512-z4OBcDAU0GVwDTuwJzQCiL6188QvZMkvoERgcVjq0/mPM8jCfdwZ3x5zQEVoL9WCAru3aG5wl3Z5Ww5wBWn7ZQ==", - "dev": true, - "requires": { - "@types/bn.js": "*" - } - }, - "@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-list-endpoints": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/express-list-endpoints/-/express-list-endpoints-4.0.1.tgz", - "integrity": "sha512-hWeurpN0+u8JUTbLpSzQLxQbrOszRkba7LKlLPj8L8YH4DUlGgbIzzNwrc7563CV+Hr10QrpZKlQBAasK6x9KQ==", - "requires": { - "@types/express": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.28", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", - "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/http-proxy": { - "version": "1.17.8", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz", - "integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==", - "requires": { - "@types/node": "*" - } - }, - "@types/is-ci": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/is-ci/-/is-ci-3.0.0.tgz", - "integrity": "sha512-Q0Op0hdWbYd1iahB+IFNQcWXFq4O0Q5MwQP7uN0souuQ4rPg1vEYcnIOfr1gY+M+6rc8FGoRaBO1mOOvL29sEQ==", - "dev": true, - "requires": { - "ci-info": "^3.1.0" - } - }, - "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "*" - } - }, - "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "requires": { - "@types/istanbul-lib-report": "*" - } - }, - "@types/jest": { - "version": "27.4.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.4.1.tgz", - "integrity": "sha512-23iPJADSmicDVrWk+HT58LMJtzLAnB2AgIzplQuq/bSrGaxCrlvRFjGbXmamnnk/mAmCdLStiGqggu28ocUyiw==", - "dev": true, - "requires": { - "jest-matcher-utils": "^27.0.0", - "pretty-format": "^27.0.0" - } - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" - }, - "@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" - }, - "@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/node": { - "version": "16.11.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.17.tgz", - "integrity": "sha512-C1vTZME8cFo8uxY2ui41xcynEotVkczIVI5AjLmy5pkpBv/FtG+jhtOlfcPysI8VRVwoOMv6NJm44LGnoMSWkw==" - }, - "@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", - "dev": true, - "requires": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/pg": { - "version": "7.14.11", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-7.14.11.tgz", - "integrity": "sha512-EnZkZ1OMw9DvNfQkn2MTJrwKmhJYDEs5ujWrPfvseWNoI95N8B4HzU/Ltrq5ZfYxDX/Zg8mTzwr6UAyTjjFvXA==", - "dev": true, - "requires": { - "@types/node": "*", - "pg-protocol": "^1.2.0", - "pg-types": "^2.2.0" - } - }, - "@types/pg-copy-streams": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/pg-copy-streams/-/pg-copy-streams-1.2.1.tgz", - "integrity": "sha512-7gsqXeYd4CypX4ZslvOhCuquL6Uo6B/ariCxw67fw6k+YL/Y1XncraDN/7qVlbM5WE5tmhxPxmacufrZ1/iloQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/pg": "*" - } - }, - "@types/prettier": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", - "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "@types/request": { - "version": "2.48.8", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.8.tgz", - "integrity": "sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ==", - "requires": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" - }, - "dependencies": { - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - } - } - }, - "@types/request-promise-native": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/@types/request-promise-native/-/request-promise-native-1.0.18.tgz", - "integrity": "sha512-tPnODeISFc/c1LjWyLuZUY+Z0uLB3+IMfNoQyDEi395+j6kTFTTRAqjENjoPJUid4vHRGEozoTrcTrfZM+AcbA==", - "requires": { - "@types/request": "*" - } - }, - "@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/source-map-support": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.4.tgz", - "integrity": "sha512-9zGujX1sOPg32XLyfgEB/0G9ZnrjthL/Iv1ZfuAjj8LEilHZEpQSQs1scpRXPhHzGYgWiLz9ldF1cI8JhL+yMw==", - "dev": true, - "requires": { - "source-map": "^0.6.0" - } - }, - "@types/split2": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@types/split2/-/split2-2.1.6.tgz", - "integrity": "sha512-ddaFSOMuy2Rp97l6q/LEteQygvTQJuEZ+SRhxFKR0uXGsdbFDqX/QF2xoGcOqLQ8XV91v01SnAv2vpgihNgW/Q==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "@types/superagent": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz", - "integrity": "sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ==", - "dev": true, - "requires": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "@types/supertest": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.11.tgz", - "integrity": "sha512-uci4Esokrw9qGb9bvhhSVEjd6rkny/dk5PK/Qz4yxKiyppEI+dOPlNrZBahE3i+PoKFYyDxChVXZ/ysS/nrm1Q==", - "dev": true, - "requires": { - "@types/superagent": "*" - } - }, - "@types/tiny-secp256k1": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/tiny-secp256k1/-/tiny-secp256k1-2.0.1.tgz", - "integrity": "sha512-3UmSOVZR8nqCk50r/ODnT58+FutNzf1NpJHSW69Lc33ZDvOVciKHYOcBN/BXPzYWzWvM0GvHVnxv6HNHxOKXbg==", - "dev": true, - "requires": { - "tiny-secp256k1": "*" - } - }, - "@types/tough-cookie": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.1.tgz", - "integrity": "sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==" - }, - "@types/uuid": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-7.0.5.tgz", - "integrity": "sha512-hKB88y3YHL8oPOs/CNlaXtjWn93+Bs48sDQR37ZUqG2tLeCS7EA1cmnkKsuQsub9OKEB/y/Rw9zqJqqNSbqVlQ==", - "dev": true - }, - "@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "requires": { - "@types/node": "*" - } - }, - "@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.15.0.tgz", - "integrity": "sha512-u6Db5JfF0Esn3tiAKELvoU5TpXVSkOpZ78cEGn/wXtT2RVqs2vkt4ge6N8cRCyw7YVKhmmLDbwI2pg92mlv7cA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/type-utils": "5.15.0", - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/experimental-utils": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz", - "integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.5.0", - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/typescript-estree": "5.5.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", - "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0" - } - }, - "@typescript-eslint/types": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", - "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", - "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", - "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.15.0.tgz", - "integrity": "sha512-NGAYP/+RDM2sVfmKiKOCgJYPstAO40vPAgACoWPO/+yoYKSgAXIFaBKsV8P0Cc7fwKgvj27SjRNX4L7f4/jCKQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", - "debug": "^4.3.2" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.15.0.tgz", - "integrity": "sha512-EFiZcSKrHh4kWk0pZaa+YNJosvKE50EnmN4IfgjkA3bTHElPtYcd2U37QQkNTqwMCS7LXeDeZzEqnsOH8chjSg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.15.0.tgz", - "integrity": "sha512-KGeDoEQ7gHieLydujGEFLyLofipe9PIzfvA/41urz4hv+xVxPEbmMQonKSynZ0Ks2xDhJQ4VYjB3DnRiywvKDA==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "5.15.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.15.0.tgz", - "integrity": "sha512-yEiTN4MDy23vvsIksrShjNwQl2vl6kJeG9YkVJXjXZnkJElzVK8nfPsWKYxcsGWG8GhurYXP4/KGj3aZAxbeOA==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.15.0.tgz", - "integrity": "sha512-Hb0e3dGc35b75xLzixM3cSbG1sSbrTBQDfIScqdyvrfJZVEi4XWAT+UL/HMxEdrJNB8Yk28SKxPLtAhfCbBInA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/visitor-keys": "5.15.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/utils": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.15.0.tgz", - "integrity": "sha512-081rWu2IPKOgTOhHUk/QfxuFog8m4wxW43sXNOMSCdh578tGJ1PAaWPsj42LOa7pguh173tNlMigsbrHvh/mtA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.15.0", - "@typescript-eslint/types": "5.15.0", - "@typescript-eslint/typescript-estree": "5.15.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.15.0.tgz", - "integrity": "sha512-+vX5FKtgvyHbmIJdxMJ2jKm9z2BIlXJiuewI8dsDYMp5LzPUcuTT78Ya5iwvQg3VqSVdmxyM8Anj1Jeq7733ZQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.15.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", - "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", - "requires": { - "debug": "^4.1.0", - "depd": "^2.0.0", - "humanize-ms": "^1.2.1" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "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-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - }, - "dependencies": { - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - } - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "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==" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", - "dev": true - }, - "array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - } - }, - "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 - }, - "array.prototype.flat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", - "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "atob-lite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", - "dev": true - }, - "atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dev": true, - "requires": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - } - }, - "babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - }, - "before-after-hook": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", - "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==", - "dev": true - }, - "bignumber.js": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", - "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "bintrees": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", - "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" - }, - "bip174": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.0.tgz", - "integrity": "sha512-lkc0XyiX9E9KiVAS1ZiOqK1xfiwvf4FXDDdkDq5crcDzOq+xGytY+14qCsqz7kCiy8rpN1CRNfacRhf9G3JNSA==" - }, - "bitcoinjs-lib": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.0.tgz", - "integrity": "sha512-eupi1FBTJmPuAZdChnzTXLv2HBqFW2AICpzXZQLniP0V9FWWeeUQSMKES6sP8isy/xO0ijDexbgkdEyFVrsuJw==", - "requires": { - "bech32": "^2.0.0", - "bip174": "^2.1.0", - "bs58check": "^2.1.2", - "create-hash": "^1.1.0", - "ripemd160": "^2.0.2", - "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.1.2", - "wif": "^2.0.1" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", - "escalade": "^3.1.1", - "node-releases": "^2.0.2", - "picocolors": "^1.0.0" - } - }, - "bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "requires": { - "fast-json-stable-stringify": "2.x" - } - }, - "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "requires": { - "base-x": "^3.0.2" - } - }, - "bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "requires": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, - "btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", - "dev": true - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" - }, - "bufferutil": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", - "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", - "optional": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "c32check": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/c32check/-/c32check-1.1.3.tgz", - "integrity": "sha512-ADADE/PjAbJRlwpG3ShaOMbBUlJJZO7xaYSRD5Tub6PixQlgR4s36y9cvMf/YRGpkqX+QOxIdMw216iC320q9A==", - "requires": { - "base-x": "^3.0.8", - "buffer": "^5.6.0", - "cross-sha256": "^1.2.0" - } - }, - "cacache": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.3.tgz", - "integrity": "sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==", - "requires": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "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==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "fs-minipass": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz", - "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==", - "requires": { - "minipass": "^5.0.0" - } - }, - "glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - } - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "caniuse-lite": { - "version": "1.0.30001328", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001328.tgz", - "integrity": "sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "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" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "ci-info": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", - "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", - "dev": true - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "coinselect": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/coinselect/-/coinselect-3.1.12.tgz", - "integrity": "sha512-XKnm9wwZzJRGuvR1BGNbFZEfa4SEr38do8Z5riq0797QwMT836EqhdPuhtbn8uAX8vCMqJ7+gS4CHa1G9M5xhw==" - }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "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==", - "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==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "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" - } - }, - "compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concurrently": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.3.0.tgz", - "integrity": "sha512-IiDwm+8DOcFEInca494A8V402tNTQlJaYq78RF2rijOrKEk/AOHTxhN4U1cp7GYKYX5Q6Ymh1dLTBlzIMN0ikA==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "date-fns": "^2.16.1", - "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", - "tree-kill": "^1.2.2", - "yargs": "^17.3.1" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "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.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - } - }, - "conventional-changelog-conventionalcommits": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz", - "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - } - }, - "conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "requires": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - } - }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "dev": true - }, - "core-js": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz", - "integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "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-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "requires": { - "node-fetch": "2.6.7" - } - }, - "cross-sha256": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/cross-sha256/-/cross-sha256-1.2.0.tgz", - "integrity": "sha512-KViLNMDZKV7jwFqjFx+rNhG26amnFYYQ0S+VaFlVvpk8tM+2XbFia/don/SjGHg9WQxnFVi6z64CGPuF3T+nNw==", - "requires": { - "buffer": "^5.6.0" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "date-fns": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", - "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", - "dev": true - }, - "dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - } - } - }, - "decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "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 - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" - }, - "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "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" - } - }, - "docker-compose": { - "version": "0.23.14", - "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.23.14.tgz", - "integrity": "sha512-n4y10yvZEGtwW4EvpDpiWal2elr6D14Bt8oP3nvlLAxryblEVub689lYhpu8lr54OlTiW9X64BH9SLd9AqljNw==", - "dev": true, - "requires": { - "yaml": "^1.10.2" - } - }, - "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" - } - }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" - }, - "dotenv-flow": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/dotenv-flow/-/dotenv-flow-3.2.0.tgz", - "integrity": "sha512-GEB6RrR4AbqDJvNSFrYHqZ33IKKbzkvLYiD5eo4+9aFXr4Y4G+QaFrB/fNp0y6McWBmvaPn3ZNjIufnj8irCtg==", - "requires": { - "dotenv": "^8.0.0" - } - }, - "duckdb": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/duckdb/-/duckdb-0.8.1.tgz", - "integrity": "sha512-a2SJDuvBVKy5muYFxXTANlqdNX1daF3NHzpqRdrk0Qx5n3Sh7BxL66O+WY9epaDFukiXEpz45sds5T1LaPaHog==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "*", - "node-gyp": "^9.3.0" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ecpair": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.1.0.tgz", - "integrity": "sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==", - "requires": { - "randombytes": "^2.1.0", - "typeforce": "^1.18.0", - "wif": "^2.0.6" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "electron-to-chromium": { - "version": "1.4.107", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.107.tgz", - "integrity": "sha512-Huen6taaVrUrSy8o7mGStByba8PfOWWluHNxSHGBrCgEdFVLtvdQDBr9LBCF9Uci8SYxh28QNNMO0oC17wbGAg==", - "dev": true - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.2.tgz", - "integrity": "sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg==", - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.11.0" - }, - "dependencies": { - "ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "requires": {} - } - } - }, - "engine.io-client": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", - "integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==", - "dev": true, - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3", - "xmlhttprequest-ssl": "~2.0.0" - }, - "dependencies": { - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "dev": true, - "requires": {} - } - } - }, - "engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.3.tgz", - "integrity": "sha512-4axXLNovnMYf0+csS5rVnS5hLmV1ek+ecx9MuCjByL1E5Nn54avf6CHQxIjgQIHBnfX9AMxTRIy0q+Yu5J/fXA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - } - }, - "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-goat": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", - "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "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 - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "eslint": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.11.0.tgz", - "integrity": "sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "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-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "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 - }, - "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" - } - } - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", - "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-import-resolver-typescript": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz", - "integrity": "sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==", - "dev": true, - "requires": { - "debug": "^4.3.1", - "glob": "^7.1.7", - "is-glob": "^4.0.1", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" - } - }, - "eslint-module-utils": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", - "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz", - "integrity": "sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.1", - "has": "^1.0.3", - "is-core-module": "^2.8.0", - "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.11.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-plugin-tsdoc": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", - "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", - "dev": true, - "requires": { - "@microsoft/tsdoc": "0.13.2", - "@microsoft/tsdoc-config": "0.15.2" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.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 - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "evt": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/evt/-/evt-1.10.1.tgz", - "integrity": "sha512-0vkCFzH3Q2Qb9gs3yav4p3uu+l4mcIfKPTRFTO1WHYZd0+O/ZR7BgzpuF+FbqOJ6r9q20/sDL/5TQM+de0/hyg==", - "requires": { - "minimal-polyfills": "^2.1.5", - "run-exclusive": "^2.2.14" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" - } - }, - "exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==" - }, - "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - } - } - }, - "express-list-endpoints": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/express-list-endpoints/-/express-list-endpoints-5.0.0.tgz", - "integrity": "sha512-bjypzWA7AQ64VNLbQ3GqwDzLxqK1NIHFRJvFDb7wg0S7YwquI8l8XZsmF0yiEA22gN+p+G6+1KDcXxb6Dn3OaA==" - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" - }, - "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==" - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fast-redact": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.2.tgz", - "integrity": "sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==" - }, - "fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "requires": { - "bser": "2.1.1" - } - }, - "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==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "find-versions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", - "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", - "dev": true, - "requires": { - "semver-regex": "^3.1.2" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "follow-redirects": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", - "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", - "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==" - } - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "dev": true - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "getopts": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", - "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "requires": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - } - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "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" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "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==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "requires": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - }, - "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==", - "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==", - "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==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http-proxy-middleware": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz", - "integrity": "sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==", - "requires": { - "@types/http-proxy": "^1.17.5", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "requires": { - "ms": "^2.0.0" - } - }, - "husky": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.8.tgz", - "integrity": "sha512-LCqqsB0PzJQ/AlCgfrfzRe3e3+NvmefAdKQhRYpxS4u6clblBoDdzzvHi8fmxKRzvMxPY/1WZWzomPZww0Anow==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "ci-info": "^2.0.0", - "compare-versions": "^3.6.0", - "cosmiconfig": "^7.0.0", - "find-versions": "^4.0.0", - "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^5.0.0", - "please-upgrade-node": "^3.2.0", - "slash": "^3.0.0", - "which-pm-runs": "^1.0.0" - }, - "dependencies": { - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - } - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "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 - } - } - }, - "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "dependencies": { - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true - }, - "is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "requires": { - "ci-info": "^3.2.0" - } - }, - "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", - "dev": true, - "requires": { - "text-extensions": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "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==", - "dev": true, - "requires": {} - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jackspeak": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", - "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "import-local": "^3.0.2", - "jest-cli": "^27.5.1" - } - }, - "jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" - } - }, - "jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - } - }, - "jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dev": true, - "requires": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - }, - "dependencies": { - "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" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "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" - } - } - } - }, - "jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dev": true, - "requires": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - } - }, - "jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", - "dev": true, - "requires": { - "detect-newline": "^3.0.0" - } - }, - "jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - } - }, - "jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - } - }, - "jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "dev": true - }, - "jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - } - }, - "jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - } - }, - "jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", - "dev": true, - "requires": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - } - }, - "jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*" - } - }, - "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} - }, - "jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "dev": true - }, - "jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - } - }, - "jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - }, - "jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dev": true, - "requires": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - } - }, - "jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dev": true, - "requires": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - } - }, - "jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dev": true, - "requires": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", - "dev": true - }, - "joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "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==" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true - }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "jsonrpc-lite": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jsonrpc-lite/-/jsonrpc-lite-2.2.0.tgz", - "integrity": "sha512-/cbbSxtZWs1O7R4tWqabrCM/t3N8qKUZMAg9IUqpPvUs6UyRvm6pCNYkskyKN/XU0UgffW+NY2ZRr8t0AknX7g==" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "macos-release": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", - "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", - "dev": true - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "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 - }, - "make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - } - } - }, - "makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "requires": { - "tmpl": "1.0.5" - } - }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "merge-options": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", - "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", - "requires": { - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "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==" - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micro-base58": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/micro-base58/-/micro-base58-0.5.1.tgz", - "integrity": "sha512-iwqAmg66VjB2LA3BcUxyrOyqck4HLLtSzKnx2VQSnN5piQji598N15P8RRx2d6lPvJ98B1b0cl2VbvQeFeWdig==" - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.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" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimal-polyfills": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/minimal-polyfills/-/minimal-polyfills-2.2.1.tgz", - "integrity": "sha512-WLmHQrsZob4rVYf8yHapZPNJZ3sspGa/sN8abuSD59b0FifDEE7HMfLUi24z7mPZqTpBXy4Svp+iGvAmclCmXg==" - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "dependencies": { - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - } - } - }, - "minipass": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", - "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz", - "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==", - "requires": { - "encoding": "^0.1.13", - "minipass": "^5.0.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "dependencies": { - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - } - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "optional": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "nock": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.2.1.tgz", - "integrity": "sha512-CoHAabbqq/xZEknubuyQMjq6Lfi5b7RtK6SoNK6m40lebGp3yiMagWtIoYaw2s9sISD7wPuCfwFpivVHX/35RA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash.set": "^4.3.2", - "propagate": "^2.0.0" - } - }, - "node-addon-api": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", - "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - }, - "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, - "node-gyp": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", - "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", - "requires": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "requires": { - "abbrev": "^1.0.0" - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "node-gyp-build": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", - "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", - "optional": true - }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node-pg-migrate": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/node-pg-migrate/-/node-pg-migrate-6.2.1.tgz", - "integrity": "sha512-EsIOAWFBSBa/2g4BjA1tjRtPOEjOiZ/gqpjjxtsUyQRau0O2s1SVwyRW1HRA2qXZDMT/sA8GxcwLWqkK6BaGxA==", - "requires": { - "@types/pg": "^8.0.0", - "decamelize": "^5.0.0", - "mkdirp": "~1.0.0", - "yargs": "~17.3.0" - }, - "dependencies": { - "@types/pg": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.5.tgz", - "integrity": "sha512-tOkGtAqRVkHa/PVZicq67zuujI4Oorfglsr2IbKofDwBSysnaqSx7W1mDqFqdkGE6Fbgh+PZAl0r/BWON/mozw==", - "requires": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yargs": { - "version": "17.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", - "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" - } - } - }, - "node-releases": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.3.tgz", - "integrity": "sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw==", - "dev": true - }, - "nodemon": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.19.tgz", - "integrity": "sha512-4pv1f2bMDj0Eeg/MhGqxrtveeQ5/G/UVe9iO6uTZzjnRluSA4PVWf8CW99LUPwGB3eNIA7zUFoP77YuI7hOc0A==", - "dev": true, - "requires": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "simple-update-notifier": "^1.0.7", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - }, - "octokit-pagination-methods": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", - "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", - "dev": true - }, - "on-exit-leak-free": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", - "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "opencollective-postinstall": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", - "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", - "dev": true - }, - "optional": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/optional/-/optional-0.1.4.tgz", - "integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==" - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "os-name": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", - "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", - "dev": true, - "requires": { - "macos-release": "^2.2.0", - "windows-release": "^3.1.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", - "requires": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" - } - }, - "p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "requires": { - "p-finally": "^1.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", - "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz", - "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==" - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - } - } - }, - "path-to-regexp": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz", - "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==" - }, - "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 - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pg": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz", - "integrity": "sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==", - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.4.1", - "pg-protocol": "^1.5.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" - }, - "pg-copy-streams": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/pg-copy-streams/-/pg-copy-streams-5.1.1.tgz", - "integrity": "sha512-ieW6JuiIo/4WQ7n+Wevr9zYvpM1AwUs6EwNCCA0VgKZ6ZQ7Y9k3IW00vqc6svX9FtENhbaTbLN7MxekraCrbfg==", - "requires": { - "obuf": "^1.1.2" - } - }, - "pg-cursor": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.7.1.tgz", - "integrity": "sha512-dtxtyvx4BcSammddki27KPBVA0sZ8AguLabgs7++gqaefX7dlQ5zaRlk1Gi5mvyO25aCmHFAZyNq9zYtPDwFTA==", - "requires": {} - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" - }, - "pg-pool": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz", - "integrity": "sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ==", - "requires": {} - }, - "pg-protocol": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", - "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "requires": { - "split2": "^4.1.0" - }, - "dependencies": { - "split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==" - } - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pino": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.11.0.tgz", - "integrity": "sha512-Z2eKSvlrl2rH8p5eveNUnTdd4AjJk8tAsLkHYZQKGHP4WTh2Gi1cOSOs3eWPqaj+niS3gj4UkoreoaWgF3ZWYg==", - "requires": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "v1.0.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.1.0", - "thread-stream": "^2.0.0" - } - }, - "pino-abstract-transport": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", - "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", - "requires": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "readable-stream": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz", - "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10" - } - }, - "split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" - } - } - }, - "pino-http": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-8.3.3.tgz", - "integrity": "sha512-p4umsNIXXVu95HD2C8wie/vXH7db5iGRpc+yj1/ZQ3sRtTQLXNjoS6Be5+eI+rQbqCRxen/7k/KSN+qiZubGDw==", - "requires": { - "get-caller-file": "^2.0.5", - "pino": "^8.0.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0" - } - }, - "pino-pretty": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.0.tgz", - "integrity": "sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q==", - "requires": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "readable-stream": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz", - "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10" - } - } - } - }, - "pino-std-serializers": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.0.tgz", - "integrity": "sha512-IWgSzUL8X1w4BIWTwErRgtV8PyOGOOi60uqv0oKuS/fOA8Nco/OeI6lBuc4dyP8MMfdFwyHqTMcBIA7nDiqEqA==" - }, - "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true - }, - "pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - }, - "dependencies": { - "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" - } - }, - "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" - } - }, - "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" - } - } - } - }, - "please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "requires": { - "semver-compare": "^1.0.0" - } - }, - "postgres": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.3.1.tgz", - "integrity": "sha512-ak/xXToZYwRvQlZIUtLgPUIggz62eIIbPTgxl/Yl4oTu0TgNOd1CrzTCifsvZ89jBwLvnX6+Ky5frp5HzIBoaw==" - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" - }, - "postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "requires": { - "xtend": "^4.0.0" - } - }, - "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.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - } - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "process-warning": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.2.0.tgz", - "integrity": "sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "prom-client": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.0.1.tgz", - "integrity": "sha512-HxTArb6fkOntQHoRGvv4qd/BkorjliiuO2uSWC2KC17MUTKYttWdDoXX/vxOhQdkoECEM9BBH0pj2l8G8kev6w==", - "requires": { - "tdigest": "^0.1.1" - } - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "dev": true - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==" - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "requires": { - "lodash": "^4.17.19" - } - }, - "request-promise-native": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", - "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", - "requires": { - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "dependencies": { - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "requires": { - "global-dirs": "^0.1.1" - } - }, - "resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", - "dev": true - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", - "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", - "dev": true, - "requires": { - "glob": "^10.0.0" - }, - "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": "10.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.0.0.tgz", - "integrity": "sha512-zmp9ZDC6NpDNLujV2W2n+3lH+BafIVZ4/ct+Yj3BMZTH/+bgm/eVjHzeFLwxJrrIGgjjS2eiQLlpurHsNlEAtQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.6.4" - } - }, - "minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - } - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "ripemd160-min": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/ripemd160-min/-/ripemd160-min-0.0.6.tgz", - "integrity": "sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==" - }, - "rpc-bitcoin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rpc-bitcoin/-/rpc-bitcoin-2.0.0.tgz", - "integrity": "sha512-o+DJHCuuuTJIJgWD1De3fGWd/ulpHb/Nn87qSh0Zn6+ur1pvyJU6TzvIlYAW6EWtCCyZdwbEXL3+Jpmh3/7EvQ==", - "requires": { - "rpc-request": "^4.0.9" - } - }, - "rpc-request": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/rpc-request/-/rpc-request-4.0.10.tgz", - "integrity": "sha512-VQIogs0wYpRBxmliXxOK6sDj+BCS/AFwPjroffwg7l5Dxur0l1YkljtB/pdYj0p31U0seEiwKeYr0j7xTY0Clg==", - "requires": { - "@types/request-promise-native": "^1.0.17", - "request": "^2.88.2", - "request-promise-native": "^1.0.9" - } - }, - "rpc-websocket-client": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/rpc-websocket-client/-/rpc-websocket-client-1.1.4.tgz", - "integrity": "sha512-UDMVcsNDJ3WET+0EFdmseYX+60MOCA3BpgpZ5dbtiGsqHo+9uWfgNbPZ4iGDtNcX+EUhCt/Y7C0fTmUU3CkkWA==", - "dev": true, - "requires": { - "isomorphic-ws": "^4.0.1", - "uuid": "^3.3.3", - "ws": "^7.1.2" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "run-exclusive": { - "version": "2.2.14", - "resolved": "https://registry.npmjs.org/run-exclusive/-/run-exclusive-2.2.14.tgz", - "integrity": "sha512-NHaQfB3zPJFx7p4M06AcmoK8xz/h8YDMCdy3jxfyoC9VqIbl1U+DiVjUuAYZBRMwvj5qkQnOUGfsmyUC4k46dg==", - "requires": { - "minimal-polyfills": "^2.1.5" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", - "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "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==" - }, - "safe-stable-stringify": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", - "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "semver-regex": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz", - "integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==", - "dev": true - }, - "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "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==" - }, - "shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "simple-update-notifier": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", - "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", - "dev": true, - "requires": { - "semver": "~7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" - }, - "socket.io": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", - "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.4.1", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.1" - } - }, - "socket.io-adapter": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", - "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", - "requires": { - "ws": "~8.11.0" - }, - "dependencies": { - "ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "requires": {} - } - } - }, - "socket.io-client": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.4.tgz", - "integrity": "sha512-ZpKteoA06RzkD32IbqILZ+Cnst4xewU7ZYK12aS1mzHftFFjpoMz69IuhP/nL25pJfao/amoPI527KnuhFm01g==", - "dev": true, - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.2.3", - "socket.io-parser": "~4.2.1" - } - }, - "socket.io-parser": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz", - "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==", - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - } - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "sonic-boom": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", - "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", - "requires": { - "atomic-sleep": "^1.0.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", - "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", - "dev": true - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "requires": { - "readable-stream": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz", - "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==", - "requires": { - "minipass": "^5.0.0" - }, - "dependencies": { - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - } - } - }, - "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - } - } - }, - "stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha1-Gsig2Ug4SNFpXkGLbQMaPDzmjjs=", - "dev": true - }, - "stacks-encoding-native-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stacks-encoding-native-js/-/stacks-encoding-native-js-1.0.0.tgz", - "integrity": "sha512-7lbcU98ozN+/XvMViXc1cZe72PB3Lz/Fcw5Lv4xcRbDfZDqdT4LqNzDfApb0TrrPWDf1moT2jtR5Lq0pSm1byQ==", - "requires": { - "@types/node": "^16.11.26", - "detect-libc": "^2.0.1" - }, - "dependencies": { - "@types/node": { - "version": "16.11.49", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.49.tgz", - "integrity": "sha512-Abq9fBviLV93OiXMu+f6r0elxCzRwc0RC5f99cU892uBITL44pTvgvEqlRlPRi8EGcO1z7Cp8A4d0s/p3J/+Nw==" - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" - }, - "strict-event-emitter-types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", - "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "tdigest": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", - "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", - "requires": { - "bintrees": "1.0.1" - } - }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thread-stream": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.3.0.tgz", - "integrity": "sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==", - "requires": { - "real-require": "^0.2.0" - } - }, - "throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - } - }, - "tiny-secp256k1": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", - "integrity": "sha512-/U4xfVqnVxJXN4YVsru0E6t5wVncu2uunB8+RVR40fYUxkKYUPS10f+ePQZgFBoE/Jbf9H1NBveupF2VmB58Ng==", - "requires": { - "uint8array-tools": "0.0.7" - } - }, - "tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-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==", - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "requires": { - "nopt": "~1.0.10" - }, - "dependencies": { - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1" - } - } - } - }, - "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true - }, - "ts-essentials": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.0.0.tgz", - "integrity": "sha512-pow5YBSknf/PyoDhr8vsb93+hZah/jSzhdHA3GMjSzUuZIDZH+rV7tvN5DCbN4hi7QJXdteDv8D9HdDCSwXBUw==", - "requires": {} - }, - "ts-jest": { - "version": "27.1.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.3.tgz", - "integrity": "sha512-6Nlura7s6uM9BVUAoqLH7JHyMXjz8gluryjpPXxr3IxZdAXnU6FhjvVLHFtfd1vsE1p8zD1OJfskkc0jhTSnkA==", - "dev": true, - "requires": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" - } - }, - "ts-node": { - "version": "10.7.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz", - "integrity": "sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "0.7.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.0", - "yn": "3.1.1" - }, - "dependencies": { - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - } - } - }, - "ts-unused-exports": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-unused-exports/-/ts-unused-exports-7.0.3.tgz", - "integrity": "sha512-D0VdTiTfrmZM7tViQEMuzG0+giU5z5crn4vjK+f1dnxTKcNx23Vc2lpMgd1vP3lYrwnvJofZmCnvEuJ7XUeV2Q==", - "requires": { - "chalk": "^4.0.0", - "tsconfig-paths": "^3.9.0" - } - }, - "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - } - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "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 - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, - "typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==" - }, - "uint8array-tools": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz", - "integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==" - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true - }, - "unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "requires": { - "unique-slug": "^4.0.0" - } - }, - "unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - } - } - }, - "url-value-parser": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/url-value-parser/-/url-value-parser-2.0.3.tgz", - "integrity": "sha512-FjIX+Q9lYmDM9uYIGdMYfQW0uLbWVwN2NrL2ayAI7BTOvEwzH+VoDdNquwB9h4dFAx+u6mb0ONLa3sHD5DvyvA==" - }, - "utf-8-validate": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", - "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", - "optional": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8-compile-cache-lib": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz", - "integrity": "sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==", - "dev": true - }, - "v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "varuint-bitcoin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz", - "integrity": "sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw==", - "requires": { - "safe-buffer": "^5.1.1" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "requires": { - "makeerror": "1.0.12" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "which-pm-runs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", - "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", - "dev": true - }, - "why-is-node-running": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.0.tgz", - "integrity": "sha512-rxtN9D0lJaYyP92BR5yoyWecK2txBKmBIuS7GRbOPP5bXsT37/hBqcmTrlrt25DBr9p4WJb6c9LuYSJd89vHRQ==", - "dev": true, - "requires": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "requires": { - "bs58check": "<3.0.0" - } - }, - "windows-release": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz", - "integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==", - "dev": true, - "requires": { - "execa": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "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": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "requires": {} - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "dependencies": { - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "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 - }, - "zone-file": { - "version": "2.0.0-beta.3", - "resolved": "https://registry.npmjs.org/zone-file/-/zone-file-2.0.0-beta.3.tgz", - "integrity": "sha512-6tE3PSRcpN5lbTTLlkLez40WkNPc9vw/u1J2j6DBiy0jcVX48nCkWrx2EC+bWHqC2SLp069Xw4AdnYn/qp/W5g==" - } } } diff --git a/package.json b/package.json index f304f73a26..defce13e92 100644 --- a/package.json +++ b/package.json @@ -7,36 +7,36 @@ "dev:watch": "cross-env NODE_ENV=development nodemon -e ts -x 'ts-node-transpile-only src/index.ts'", "dev:integrated": "npm run devenv:build && concurrently npm:dev npm:devenv:deploy", "dev:follower": "npm run devenv:build && concurrently npm:dev npm:devenv:follower", - "test": "cross-env NODE_ENV=development jest --config ./tests/jest.config.js --coverage --runInBand", - "test:subnets": "cross-env NODE_ENV=development jest --config ./tests/jest.config.subnets.js --coverage --runInBand", - "test:2.4": "cross-env NODE_ENV=development jest --config ./tests/jest.config.2.4.js --coverage --runInBand", - "test:rosetta": "cross-env NODE_ENV=development jest --config ./tests/jest.config.rosetta.js --coverage --runInBand", - "test:rosetta-construction": "cross-env NODE_ENV=development jest --config ./tests/jest.config.rosetta-construction.js --coverage --runInBand", - "test:rosetta-cli:data": "cross-env NODE_ENV=development STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-data.js --coverage --runInBand", - "test:rosetta-cli:construction": "cross-env NODE_ENV=development STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-construction.js --coverage --runInBand", - "test:bns": "cross-env NODE_ENV=development jest --config ./tests/jest.config.bns.js --coverage --runInBand", - "test:bns-e2e": "cross-env NODE_ENV=development jest --config ./tests/jest.config.bns-e2e.js --coverage --runInBand", - "test:rpc": "cross-env NODE_ENV=development jest --config ./tests/jest.config.rpc.js --coverage --runInBand", - "test:event-replay": "cross-env NODE_ENV=development jest --config ./tests/jest.config.event-replay.js --coverage --runInBand", - "test:btc-faucet": "cross-env NODE_ENV=development jest --config ./tests/jest.config.btc-faucet.js --coverage --runInBand", - "test:tokens-metadata": "cross-env NODE_ENV=development jest --config ./tests/jest.config.tokens-metadata.js --coverage --runInBand", - "test:tokens-strict": "cross-env NODE_ENV=development jest --config ./tests/jest.config.tokens-strict.js --coverage --runInBand", - "test:watch": "cross-env NODE_ENV=development jest --config ./tests/jest.config.js --watch", - "test:integration": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.js --no-cache --runInBand; npm run devenv:stop:pg\"", - "test:integration:subnets": "concurrently --hide \"devenv:deploy:subnets\" \"npm:devenv:deploy:subnets\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.subnets.js --no-cache --runInBand; npm run devenv:stop:subnets\"", - "test:integration:2.4": "concurrently --hide \"devenv:deploy-krypton\" \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.2.4.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:rosetta": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.rosetta.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:rosetta-construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.rosetta-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:rosetta-cli:data": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-data.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:rosetta-cli:construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:bns": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.bns.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:bns-e2e": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.bns-e2e.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:tokens-strict": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.tokens-strict.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:tokens-metadata": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.tokens-metadata.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:rpc": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.rpc.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:event-replay": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.event-replay.js --no-cache --runInBand; npm run devenv:stop\"", - "test:integration:btc-faucet": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.bitcoind.yml up --force-recreate -V\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.btc-faucet.js --no-cache --runInBand; npm run devenv:stop\"", - "generate:git-info": "node ./git-info-generator.mjs", + "test": "cross-env NODE_ENV=test jest --config ./tests/jest.config.js --coverage --runInBand", + "test:subnets": "cross-env NODE_ENV=test jest --config ./tests/jest.config.subnets.js --coverage --runInBand", + "test:2.4": "cross-env NODE_ENV=test jest --config ./tests/jest.config.2.4.js --coverage --runInBand", + "test:rosetta": "cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta.js --coverage --runInBand", + "test:rosetta-construction": "cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta-construction.js --coverage --runInBand", + "test:rosetta-cli:data": "cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-data.js --coverage --runInBand", + "test:rosetta-cli:construction": "cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-construction.js --coverage --runInBand", + "test:bns": "cross-env NODE_ENV=test jest --config ./tests/jest.config.bns.js --coverage --runInBand", + "test:bns-e2e": "cross-env NODE_ENV=test jest --config ./tests/jest.config.bns-e2e.js --coverage --runInBand", + "test:rpc": "cross-env NODE_ENV=test jest --config ./tests/jest.config.rpc.js --coverage --runInBand", + "test:event-replay": "cross-env NODE_ENV=test jest --config ./tests/jest.config.event-replay.js --coverage --runInBand", + "test:btc-faucet": "cross-env NODE_ENV=test jest --config ./tests/jest.config.btc-faucet.js --coverage --runInBand", + "test:tokens-metadata": "cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-metadata.js --coverage --runInBand", + "test:tokens-strict": "cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-strict.js --coverage --runInBand", + "test:watch": "cross-env NODE_ENV=test jest --config ./tests/jest.config.js --watch", + "test:integration": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.js --no-cache --runInBand; npm run devenv:stop:pg\"", + "test:integration:subnets": "concurrently --hide \"devenv:deploy:subnets\" \"npm:devenv:deploy:subnets\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.subnets.js --no-cache --runInBand; npm run devenv:stop:subnets\"", + "test:integration:2.4": "concurrently --hide \"devenv:deploy-krypton\" \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.2.4.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:rosetta": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:rosetta-construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:rosetta-cli:data": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-data.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:rosetta-cli:construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:bns": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.bns.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:bns-e2e": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.bns-e2e.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:tokens-strict": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-strict.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:tokens-metadata": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-metadata.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:rpc": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.rpc.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:event-replay": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.event-replay.js --no-cache --runInBand; npm run devenv:stop\"", + "test:integration:btc-faucet": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.bitcoind.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.btc-faucet.js --no-cache --runInBand; npm run devenv:stop\"", + "generate:git-info": "rimraf .git-info && api-toolkit-git-info", "build": "npm run generate:git-info && rimraf ./lib && tsc -p tsconfig.build.json", "build:tests": "tsc -p tsconfig.json", "build:docs": "npm ci --prefix docs && npm run build --prefix docs && npm ci --prefix client && npm run generate:docs --prefix client", @@ -72,60 +72,9 @@ "homepage": "https://github.com/hirosystems/stacks-blockchain-api#readme", "prettier": "@stacks/prettier-config", "engines": { - "node": ">=16" + "node": ">=18" }, "engineStrict": true, - "release": { - "branches": [ - "master", - { - "name": "beta", - "channel": "beta", - "prerelease": true - }, - { - "name": "stacks-2.4", - "channel": "stacks-2.4", - "prerelease": true - } - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits" - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits" - } - ], - [ - "@semantic-release/exec", - { - "execCwd": "client", - "prepareCmd": "npm ci" - } - ], - [ - "@semantic-release/npm", - { - "pkgRoot": "./docs" - } - ], - [ - "@semantic-release/npm", - { - "pkgRoot": "./client" - } - ], - "@semantic-release/github", - "@semantic-release/changelog", - "@semantic-release/git" - ] - }, "commitlint": { "extends": [ "@commitlint/config-conventional" @@ -138,14 +87,15 @@ }, "dependencies": { "@apidevtools/json-schema-ref-parser": "9.0.9", + "@hirosystems/api-toolkit": "1.2.2", "@promster/express": "6.0.0", "@promster/server": "6.0.6", "@promster/types": "3.2.3", "@scure/base": "1.1.1", - "@stacks/common": "6.5.2", - "@stacks/network": "6.5.2", - "@stacks/stacking": "6.5.3-pr.693e11b.0", - "@stacks/transactions": "6.5.2", + "@stacks/common": "6.8.1", + "@stacks/network": "6.8.1", + "@stacks/stacking": "6.9.0", + "@stacks/transactions": "6.9.0", "@types/express-list-endpoints": "4.0.1", "@types/lru-cache": "5.1.1", "@types/ws": "7.4.7", @@ -193,7 +143,6 @@ "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", - "typescript": "4.6.2", "uuid": "8.3.2", "ws": "7.5.9", "zone-file": "2.0.0-beta.3" @@ -206,7 +155,6 @@ "@commitlint/cli": "9.1.2", "@commitlint/config-conventional": "10.0.0", "@stacks/eslint-config": "1.2.0", - "@stacks/prettier-config": "0.0.10", "@types/ajv": "1.0.0", "@types/bluebird": "3.5.36", "@types/cors": "2.8.12", @@ -214,8 +162,8 @@ "@types/elliptic": "6.4.14", "@types/express": "4.17.13", "@types/is-ci": "3.0.0", - "@types/jest": "27.4.1", - "@types/node": "16.11.17", + "@types/jest": "29.5.6", + "@types/node": "18.13.0", "@types/node-fetch": "2.5.12", "@types/pg": "7.14.11", "@types/pg-copy-streams": "1.2.1", @@ -224,27 +172,28 @@ "@types/supertest": "2.0.11", "@types/tiny-secp256k1": "2.0.1", "@types/uuid": "7.0.5", - "@typescript-eslint/eslint-plugin": "5.15.0", - "@typescript-eslint/parser": "5.15.0", + "@typescript-eslint/eslint-plugin": "5.46.1", + "@typescript-eslint/parser": "5.51.0", "concurrently": "7.3.0", "docker-compose": "0.23.14", - "eslint": "8.11.0", - "eslint-config-prettier": "8.5.0", - "eslint-plugin-prettier": "4.0.0", - "eslint-plugin-tsdoc": "0.2.14", + "eslint": "8.29.0", + "eslint-plugin-prettier": "4.2.1", + "eslint-plugin-tsdoc": "0.2.17", + "fastify": "4.15.0", "husky": "4.3.8", "is-ci": "3.0.1", - "jest": "27.5.1", + "jest": "29.7.0", "nock": "13.2.1", "nodemon": "2.0.19", "pg-connection-string": "2.5.0", - "prettier": "2.2.1", + "prettier": "2.8.8", "rimraf": "5.0.0", "rpc-websocket-client": "1.1.4", "socket.io-client": "4.5.4", "supertest": "4.0.2", - "ts-jest": "27.1.3", - "ts-node": "10.7.0", + "ts-jest": "29.1.1", + "ts-node": "10.8.2", + "typescript": "4.7.4", "why-is-node-running": "2.2.0" }, "optionalDependencies": { diff --git a/running_api_from_source.md b/running_api_from_source.md index d9a19dd3a6..8abfc82ee9 100644 --- a/running_api_from_source.md +++ b/running_api_from_source.md @@ -96,7 +96,6 @@ $ sudo systemctl stop postgresql ```bash $ git clone https://github.com/hirosystems/stacks-blockchain-api /stacks-node/stacks-blockchain-api && cd /stacks-node/stacks-blockchain-api \ && echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env \ - && npm config set unsafe-perm true \ && npm install \ && npm run build \ && npm prune --production diff --git a/src/api/controllers/cache-controller.ts b/src/api/controllers/cache-controller.ts index b8d6e6d8df..6d2f84fc77 100644 --- a/src/api/controllers/cache-controller.ts +++ b/src/api/controllers/cache-controller.ts @@ -1,9 +1,10 @@ import { RequestHandler, Request, Response } from 'express'; import * as prom from 'prom-client'; -import { normalizeHashString, sha256 } from '../../helpers'; +import { normalizeHashString } from '../../helpers'; import { asyncHandler } from '../async-handler'; import { PgStore } from '../../datastore/pg-store'; import { logger } from '../../logger'; +import { sha256 } from '@hirosystems/api-toolkit'; const CACHE_OK = Symbol('cache_ok'); diff --git a/src/api/init.ts b/src/api/init.ts index d8bdac6b18..f549296ac0 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -19,7 +19,7 @@ import { createRosettaMempoolRouter } from './routes/rosetta/mempool'; import { createRosettaBlockRouter } from './routes/rosetta/block'; import { createRosettaAccountRouter } from './routes/rosetta/account'; import { createRosettaConstructionRouter } from './routes/rosetta/construction'; -import { ChainID, apiDocumentationUrl, getChainIDNetwork, isProdEnv, waiter } from '../helpers'; +import { ChainID, apiDocumentationUrl, getChainIDNetwork } from '../helpers'; import { InvalidRequestError } from '../errors'; import { createBurnchainRouter } from './routes/burnchain'; import { createBnsNamespacesRouter } from './routes/bns/namespaces'; @@ -42,9 +42,9 @@ import { PgWriteStore } from '../datastore/pg-write-store'; import { WebSocketTransmitter } from './routes/ws/web-socket-transmitter'; import { createPox2EventsRouter } from './routes/pox2'; import { createPox3EventsRouter } from './routes/pox3'; -import { isPgConnectionError } from '../datastore/helpers'; import { createStackingRouter } from './routes/stacking'; import { logger, loggerMiddleware } from '../logger'; +import { SERVER_VERSION, isPgConnectionError, isProdEnv, waiter } from '@hirosystems/api-toolkit'; export interface ApiServer { expressApp: express.Express; @@ -56,9 +56,6 @@ export interface ApiServer { forceKill: () => Promise; } -/** API version as given by .git-info */ -export const API_VERSION: { branch?: string; commit?: string; tag?: string } = {}; - export async function startApiServer(opts: { datastore: PgStore; writeDatastore?: PgWriteStore; @@ -69,16 +66,6 @@ export async function startApiServer(opts: { serverPort?: number; }): Promise { const { datastore, writeDatastore, chainId, serverHost, serverPort } = opts; - - try { - const [branch, commit, tag] = fs.readFileSync('.git-info', 'utf-8').split('\n'); - API_VERSION.branch = branch; - API_VERSION.commit = commit; - API_VERSION.tag = tag; - } catch (error) { - logger.error(error, `Unable to read API version from .git-info`); - } - const app = express(); const apiHost = serverHost ?? process.env['STACKS_BLOCKCHAIN_API_HOST']; const apiPort = serverPort ?? parseInt(process.env['STACKS_BLOCKCHAIN_API_PORT'] ?? ''); @@ -94,9 +81,6 @@ export async function startApiServer(opts: { ); } - // app.use(compression()); - // app.disable('x-powered-by'); - let routes: { path: string; regexp: RegExp; @@ -141,7 +125,7 @@ export async function startApiServer(opts: { app.use((_, res, next) => { res.setHeader( 'X-API-Version', - `${API_VERSION.tag} (${API_VERSION.branch}:${API_VERSION.commit})` + `${SERVER_VERSION.tag} (${SERVER_VERSION.branch}:${SERVER_VERSION.commit})` ); res.append('Access-Control-Expose-Headers', 'X-API-Version'); next(); diff --git a/src/api/query-helpers.ts b/src/api/query-helpers.ts index 56f938f3dd..fa365535a8 100644 --- a/src/api/query-helpers.ts +++ b/src/api/query-helpers.ts @@ -1,8 +1,9 @@ import { ClarityAbi } from '@stacks/transactions'; import { NextFunction, Request, Response } from 'express'; -import { has0xPrefix, hexToBuffer, parseEventTypeStrings, isValidPrincipal } from './../helpers'; +import { parseEventTypeStrings, isValidPrincipal } from './../helpers'; import { InvalidRequestError, InvalidRequestErrorType } from '../errors'; import { DbEventTypeId } from './../datastore/common'; +import { has0xPrefix, hexToBuffer } from '@hirosystems/api-toolkit'; function handleBadRequest(res: Response, next: NextFunction, errorMessage: string): never { const error = new InvalidRequestError(errorMessage, InvalidRequestErrorType.bad_request); diff --git a/src/api/rosetta-validate.ts b/src/api/rosetta-validate.ts index 8638d956e8..d35179d607 100644 --- a/src/api/rosetta-validate.ts +++ b/src/api/rosetta-validate.ts @@ -1,5 +1,5 @@ import * as Ajv from 'ajv'; -import { hexToBuffer, has0xPrefix, isValidC32Address, isValidPrincipal } from '../helpers'; +import { isValidPrincipal } from '../helpers'; import { RosettaConstants, RosettaErrors, @@ -13,6 +13,7 @@ import * as T from '@stacks/stacks-blockchain-api-types'; import { dereferenceSchema, getDocSchemaFile } from './validate'; import { ChainID } from '@stacks/transactions'; import { logger } from '../logger'; +import { has0xPrefix, hexToBuffer } from '@hirosystems/api-toolkit'; export interface ValidSchema { valid: boolean; diff --git a/src/api/routes/address.ts b/src/api/routes/address.ts index 0245260c0e..7ef60c2361 100644 --- a/src/api/routes/address.ts +++ b/src/api/routes/address.ts @@ -9,15 +9,7 @@ import { parseUntilBlockQuery, validatePrincipal, } from '../query-helpers'; -import { - ChainID, - formatMapToObject, - getSendManyContract, - has0xPrefix, - isProdEnv, - isValidC32Address, - isValidPrincipal, -} from '../../helpers'; +import { ChainID, formatMapToObject, getSendManyContract, isValidPrincipal } from '../../helpers'; import { getAssetEventTypeString, getTxFromDataStore, @@ -50,6 +42,7 @@ import { } from '../controllers/cache-controller'; import { PgStore } from '../../datastore/pg-store'; import { logger } from '../../logger'; +import { has0xPrefix, isProdEnv } from '@hirosystems/api-toolkit'; async function getBlockHeight( untilBlock: number | string | undefined, @@ -612,7 +605,7 @@ export function createAddressRouter(db: PgStore, chainId: ChainID): express.Rout last_executed_tx_nonce: nonceQuery.result.lastExecutedTxNonce as number, possible_next_nonce: nonceQuery.result.possibleNextNonce, // Note: OpenAPI type generator doesn't support `nullable: true` so force cast it here - last_mempool_tx_nonce: (null as unknown) as number, + last_mempool_tx_nonce: null as unknown as number, detected_missing_nonces: [], detected_mempool_nonces: [], }; diff --git a/src/api/routes/block.ts b/src/api/routes/block.ts index c9bcc62d15..b603990983 100644 --- a/src/api/routes/block.ts +++ b/src/api/routes/block.ts @@ -1,13 +1,13 @@ import * as express from 'express'; import { BlockListResponse } from '@stacks/stacks-blockchain-api-types'; import { getBlockFromDataStore, getBlocksWithMetadata } from '../controllers/db-controller'; -import { has0xPrefix } from '../../helpers'; import { InvalidRequestError, InvalidRequestErrorType } from '../../errors'; import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; import { getBlockHeightPathParam, validateRequestHexInput } from '../query-helpers'; import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; import { asyncHandler } from '../async-handler'; import { PgStore } from '../../datastore/pg-store'; +import { has0xPrefix } from '@hirosystems/api-toolkit'; export function createBlockRouter(db: PgStore): express.Router { const router = express.Router(); diff --git a/src/api/routes/core-node-rpc-proxy.ts b/src/api/routes/core-node-rpc-proxy.ts index c14f3a5e61..2f04fabc77 100644 --- a/src/api/routes/core-node-rpc-proxy.ts +++ b/src/api/routes/core-node-rpc-proxy.ts @@ -43,7 +43,7 @@ export function createCoreNodeRpcProxyRouter(db: PgStore): express.Router { const PROXY_CACHE_CONTROL_FILE_ENV_VAR = 'STACKS_API_PROXY_CACHE_CONTROL_FILE'; let proxyCacheControlFile = '.proxy-cache-control.json'; if (process.env[PROXY_CACHE_CONTROL_FILE_ENV_VAR]) { - proxyCacheControlFile = process.env[PROXY_CACHE_CONTROL_FILE_ENV_VAR] as string; + proxyCacheControlFile = process.env[PROXY_CACHE_CONTROL_FILE_ENV_VAR]; logger.info(`Using ${proxyCacheControlFile}`); } const cacheControlFileWatcher = chokidar.watch(proxyCacheControlFile, { diff --git a/src/api/routes/debug.ts b/src/api/routes/debug.ts index abb600d31c..bf4587d773 100644 --- a/src/api/routes/debug.ts +++ b/src/api/routes/debug.ts @@ -95,19 +95,17 @@ export const testnetKeys: SeededAccount[] = testnetAccounts.map(t => ({ pubKey: publicKeyToString(pubKeyfromPrivKey(t.secretKey)), })); -const testnetKeyMap: Record< - string, - { address: string; secretKey: string; pubKey: string } -> = Object.fromEntries( - testnetKeys.map(t => [ - t.stacksAddress, - { - address: t.stacksAddress, - secretKey: t.secretKey, - pubKey: t.pubKey, - }, - ]) -); +const testnetKeyMap: Record = + Object.fromEntries( + testnetKeys.map(t => [ + t.stacksAddress, + { + address: t.stacksAddress, + secretKey: t.secretKey, + pubKey: t.pubKey, + }, + ]) + ); export function getStacksTestnetNetwork() { return new StacksTestnet({ @@ -135,7 +133,7 @@ export function createDebugRouter(db: PgStore): express.Router { } router.get('/broadcast', (req, res) => { - const endpoints = listEndpoints((router as unknown) as express.Express); + const endpoints = listEndpoints(router as unknown as express.Express); const paths: Set = new Set(); endpoints.forEach(e => { if (e.methods.includes('GET')) { diff --git a/src/api/routes/info.ts b/src/api/routes/info.ts index b9c8287396..6f7fb50dc9 100644 --- a/src/api/routes/info.ts +++ b/src/api/routes/info.ts @@ -1,13 +1,13 @@ import * as express from 'express'; import { asyncHandler } from '../async-handler'; import { validate } from '../validate'; -import { isProdEnv } from '../../helpers'; import { InvalidRequestError, InvalidRequestErrorType } from '../../errors'; import { NetworkBlockTimesResponse, NetworkBlockTimeResponse, } from '@stacks/stacks-blockchain-api-types'; import { PgStore } from '../../datastore/pg-store'; +import { isProdEnv } from '@hirosystems/api-toolkit'; const enum TargetBlockTime { /** diff --git a/src/api/routes/microblock.ts b/src/api/routes/microblock.ts index f5a36334ed..4d53196972 100644 --- a/src/api/routes/microblock.ts +++ b/src/api/routes/microblock.ts @@ -10,10 +10,10 @@ import { getMicroblocksFromDataStore, getUnanchoredTxsFromDataStore, } from '../controllers/db-controller'; -import { has0xPrefix } from '../../helpers'; import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; import { validateRequestHexInput } from '../query-helpers'; import { PgStore } from '../../datastore/pg-store'; +import { has0xPrefix } from '@hirosystems/api-toolkit'; export function createMicroblockRouter(db: PgStore): express.Router { const router = express.Router(); diff --git a/src/api/routes/rosetta/account.ts b/src/api/routes/rosetta/account.ts index be01d0e7cb..c333e5f455 100644 --- a/src/api/routes/rosetta/account.ts +++ b/src/api/routes/rosetta/account.ts @@ -2,7 +2,7 @@ import * as express from 'express'; import { asyncHandler } from '../../async-handler'; import { DbBlock } from '../../../datastore/common'; import { PgStore } from '../../../datastore/pg-store'; -import { has0xPrefix, FoundOrNot, ChainID } from '../../../helpers'; +import { FoundOrNot, ChainID } from '../../../helpers'; import { RosettaAccount, RosettaBlockIdentifier, @@ -15,6 +15,7 @@ import { RosettaErrors, RosettaConstants, RosettaErrorsTypes } from '../../roset import { rosettaValidateRequest, ValidSchema, makeRosettaError } from '../../rosetta-validate'; import { getValidatedFtMetadata } from '../../../rosetta-helpers'; import { isFtMetadataEnabled } from '../../../token-metadata/helpers'; +import { has0xPrefix } from '@hirosystems/api-toolkit'; export function createRosettaAccountRouter(db: PgStore, chainId: ChainID): express.Router { const router = express.Router(); diff --git a/src/api/routes/rosetta/block.ts b/src/api/routes/rosetta/block.ts index dd635f6e62..f99bb670ae 100644 --- a/src/api/routes/rosetta/block.ts +++ b/src/api/routes/rosetta/block.ts @@ -6,9 +6,10 @@ import { getRosettaTransactionFromDataStore, getRosettaBlockFromDataStore, } from '../../controllers/db-controller'; -import { ChainID, has0xPrefix } from '../../../helpers'; +import { ChainID } from '../../../helpers'; import { RosettaErrors, RosettaErrorsTypes } from '../../rosetta-constants'; import { rosettaValidateRequest, ValidSchema, makeRosettaError } from '../../rosetta-validate'; +import { has0xPrefix } from '@hirosystems/api-toolkit'; export function createRosettaBlockRouter(db: PgStore, chainId: ChainID): express.Router { const router = express.Router(); diff --git a/src/api/routes/rosetta/construction.ts b/src/api/routes/rosetta/construction.ts index c570bccb91..49a9e2f074 100644 --- a/src/api/routes/rosetta/construction.ts +++ b/src/api/routes/rosetta/construction.ts @@ -57,8 +57,6 @@ import { doesThrow, FoundOrNot, getChainIDNetwork, - has0xPrefix, - hexToBuffer, isValidC32Address, } from '../../../helpers'; import { asyncHandler } from '../../async-handler'; @@ -84,6 +82,7 @@ import { verifySignature, } from './../../../rosetta-helpers'; import { makeRosettaError, rosettaValidateRequest, ValidSchema } from './../../rosetta-validate'; +import { has0xPrefix, hexToBuffer } from '@hirosystems/api-toolkit'; export function createRosettaConstructionRouter(db: PgStore, chainId: ChainID): express.Router { const router = express.Router(); diff --git a/src/api/routes/rosetta/mempool.ts b/src/api/routes/rosetta/mempool.ts index ef3cef772e..657fcaef2f 100644 --- a/src/api/routes/rosetta/mempool.ts +++ b/src/api/routes/rosetta/mempool.ts @@ -1,7 +1,7 @@ import * as express from 'express'; import { asyncHandler } from '../../async-handler'; import { PgStore } from '../../../datastore/pg-store'; -import { ChainID, has0xPrefix } from '../../../helpers'; +import { ChainID } from '../../../helpers'; import { rosettaValidateRequest, ValidSchema, makeRosettaError } from '../../rosetta-validate'; import { RosettaMempoolResponse, @@ -10,6 +10,7 @@ import { } from '@stacks/stacks-blockchain-api-types'; import { getOperations, parseTransactionMemo } from '../../../rosetta-helpers'; import { RosettaErrors, RosettaErrorsTypes } from '../../rosetta-constants'; +import { has0xPrefix } from '@hirosystems/api-toolkit'; export function createRosettaMempoolRouter(db: PgStore, chainId: ChainID): express.Router { const router = express.Router(); diff --git a/src/api/routes/search.ts b/src/api/routes/search.ts index ad4db3eebd..2a29b38f50 100644 --- a/src/api/routes/search.ts +++ b/src/api/routes/search.ts @@ -7,7 +7,7 @@ import { DbSearchResult, DbSearchResultWithMetadata, } from '../../datastore/common'; -import { isValidPrincipal, has0xPrefix, FoundOrNot } from '../../helpers'; +import { isValidPrincipal, FoundOrNot } from '../../helpers'; import { Block, SearchResult, @@ -27,6 +27,7 @@ import { } from '../controllers/db-controller'; import { booleanValueForParam } from '../query-helpers'; import { PgStore } from '../../datastore/pg-store'; +import { has0xPrefix } from '@hirosystems/api-toolkit'; const enum SearchResultType { TxId = 'tx_id', diff --git a/src/api/routes/status.ts b/src/api/routes/status.ts index 3c8f7c415f..eb2cadfccc 100644 --- a/src/api/routes/status.ts +++ b/src/api/routes/status.ts @@ -2,7 +2,7 @@ import * as express from 'express'; import { ServerStatusResponse } from '@stacks/stacks-blockchain-api-types'; import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; import { PgStore } from '../../datastore/pg-store'; -import { API_VERSION } from '../init'; +import { SERVER_VERSION } from '@hirosystems/api-toolkit'; export function createStatusRouter(db: PgStore): express.Router { const router = express.Router(); @@ -10,7 +10,7 @@ export function createStatusRouter(db: PgStore): express.Router { const statusHandler = async (_: Request, res: any) => { try { const response: ServerStatusResponse = { - server_version: `stacks-blockchain-api ${API_VERSION.tag} (${API_VERSION.branch}:${API_VERSION.commit})`, + server_version: `stacks-blockchain-api ${SERVER_VERSION.tag} (${SERVER_VERSION.branch}:${SERVER_VERSION.commit})`, status: 'ready', }; const poxForceUnlockHeights = await db.getPoxForceUnlockHeights(); diff --git a/src/api/routes/tokens/tokens.ts b/src/api/routes/tokens/tokens.ts index 500e949171..ba365a4949 100644 --- a/src/api/routes/tokens/tokens.ts +++ b/src/api/routes/tokens/tokens.ts @@ -14,12 +14,13 @@ import { } from '@stacks/stacks-blockchain-api-types'; import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from './../../pagination'; import { isFtMetadataEnabled, isNftMetadataEnabled } from '../../../token-metadata/helpers'; -import { has0xPrefix, isValidPrincipal } from '../../../helpers'; +import { isValidPrincipal } from '../../../helpers'; import { booleanValueForParam, isUnanchoredRequest } from '../../../api/query-helpers'; import { decodeClarityValueToRepr } from 'stacks-encoding-native-js'; import { getAssetEventTypeString, parseDbTx } from '../../controllers/db-controller'; import { getETagCacheHandler, setETagCacheHeaders } from '../../controllers/cache-controller'; import { PgStore } from '../../../datastore/pg-store'; +import { has0xPrefix } from '@hirosystems/api-toolkit'; export function createTokenRouter(db: PgStore): express.Router { const router = express.Router(); diff --git a/src/api/routes/tx.ts b/src/api/routes/tx.ts index 40e7969b9e..f23d5fc81f 100644 --- a/src/api/routes/tx.ts +++ b/src/api/routes/tx.ts @@ -8,7 +8,7 @@ import { parseDbTx, parseDbEvent, } from '../controllers/db-controller'; -import { has0xPrefix, isProdEnv, isValidC32Address, isValidPrincipal } from '../../helpers'; +import { isValidC32Address, isValidPrincipal } from '../../helpers'; import { InvalidRequestError, InvalidRequestErrorType } from '../../errors'; import { isUnanchoredRequest, @@ -31,6 +31,7 @@ import { setETagCacheHeaders, } from '../controllers/cache-controller'; import { PgStore } from '../../datastore/pg-store'; +import { has0xPrefix, isProdEnv } from '@hirosystems/api-toolkit'; export function createTxRouter(db: PgStore): express.Router { const router = express.Router(); diff --git a/src/api/routes/ws/channels/socket-io-channel.ts b/src/api/routes/ws/channels/socket-io-channel.ts index f8b0a7d487..bcc0280861 100644 --- a/src/api/routes/ws/channels/socket-io-channel.ts +++ b/src/api/routes/ws/channels/socket-io-channel.ts @@ -9,7 +9,7 @@ import * as http from 'http'; import { Server as SocketIOServer } from 'socket.io'; import { Adapter } from 'socket.io-adapter'; import { isValidTxId } from '../../../../api/query-helpers'; -import { isProdEnv, isValidPrincipal } from '../../../../helpers'; +import { isValidPrincipal } from '../../../../helpers'; import { WebSocketPrometheus } from '../web-socket-prometheus'; import { ListenerType, @@ -23,6 +23,7 @@ import { getWsPingTimeoutMs, } from '../web-socket-transmitter'; import { logger } from '../../../../logger'; +import { isProdEnv } from '@hirosystems/api-toolkit'; const component = { component: 'socket-io' }; diff --git a/src/api/routes/ws/channels/ws-rpc-channel.ts b/src/api/routes/ws/channels/ws-rpc-channel.ts index 86e19384fc..f26aa71ade 100644 --- a/src/api/routes/ws/channels/ws-rpc-channel.ts +++ b/src/api/routes/ws/channels/ws-rpc-channel.ts @@ -1,12 +1,7 @@ import * as http from 'http'; import * as WebSocket from 'ws'; import * as net from 'net'; -import { - isProdEnv, - isValidPrincipal, - normalizeHashString, - resolveOrTimeout, -} from '../../../../helpers'; +import { isValidPrincipal, normalizeHashString } from '../../../../helpers'; import { WebSocketPrometheus } from '../web-socket-prometheus'; import { ListenerType, @@ -43,6 +38,7 @@ import { } from '@stacks/stacks-blockchain-api-types'; import { getWsMessageTimeoutMs, getWsPingIntervalMs } from '../web-socket-transmitter'; import { logger } from '../../../../logger'; +import { isProdEnv, resolveOrTimeout } from '@hirosystems/api-toolkit'; type Subscription = | RpcTxUpdateSubscriptionParams diff --git a/src/btc-faucet.ts b/src/btc-faucet.ts index ee8bdd5b43..58d23f92d6 100644 --- a/src/btc-faucet.ts +++ b/src/btc-faucet.ts @@ -2,11 +2,12 @@ import { RPCClient } from 'rpc-bitcoin'; import * as btc from 'bitcoinjs-lib'; import * as ecc from 'tiny-secp256k1'; import * as Bluebird from 'bluebird'; -import { parsePort, time } from './helpers'; +import { parsePort } from './helpers'; import * as coinselect from 'coinselect'; import { ECPair, ECPairInterface, validateSigFunction } from './ec-helpers'; import { BtcFaucetConfigError } from './errors'; import { logger } from './logger'; +import { time } from '@hirosystems/api-toolkit'; function getFaucetPk(): string { const { BTC_FAUCET_PK } = process.env; diff --git a/src/core-rpc/client.ts b/src/core-rpc/client.ts index 83bcb30ed1..422ea83850 100644 --- a/src/core-rpc/client.ts +++ b/src/core-rpc/client.ts @@ -1,9 +1,10 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import fetch, { RequestInit } from 'node-fetch'; -import { parsePort, stopwatch, timeout } from '../helpers'; +import { parsePort } from '../helpers'; import { CoreNodeFeeResponse } from '@stacks/stacks-blockchain-api-types'; import { ClarityValue, cvToHex } from '@stacks/transactions'; import { logger } from '../logger'; +import { stopwatch, timeout } from '@hirosystems/api-toolkit'; interface CoreRpcAccountInfo { /** Hex-prefixed uint128. */ diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 6d60242b22..18b974d923 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -1,7 +1,7 @@ import { ClarityAbi } from '@stacks/transactions'; import { Block } from '@stacks/stacks-blockchain-api-types'; -import { PgBytea, PgJsonb, PgNumeric } from './connection'; import { Pox2EventName } from '../pox-helpers'; +import { PgBytea, PgJsonb, PgNumeric } from '@hirosystems/api-toolkit'; export interface DbBlock { block_hash: string; diff --git a/src/datastore/connection.ts b/src/datastore/connection.ts index f0daae4e8a..c1ff99cdeb 100644 --- a/src/datastore/connection.ts +++ b/src/datastore/connection.ts @@ -1,9 +1,4 @@ -import { parseArgBoolean, parsePort, stopwatch, timeout } from '../helpers'; -import * as postgres from 'postgres'; -import { isPgConnectionError } from './helpers'; -import { logger } from '../logger'; - -export type PgSqlClient = postgres.Sql | postgres.TransactionSql; +import { PgConnectionArgs, PgConnectionOptions } from '@hirosystems/api-toolkit'; /** * The postgres server being used for a particular connection, transaction or query. @@ -15,107 +10,6 @@ export enum PgServer { primary, } -const PG_TYPE_MAPPINGS = { - // Make both `string` and `Buffer` be compatible with a `bytea` columns. - // * Buffers and strings with `0x` prefixes will be transformed to hex format (`\x`). - // * Other strings will be passed as-is. - // From postgres, all values will be returned as strings with `0x` prefix. - bytea: { - to: 17, - from: [17], - serialize: (x: any) => { - if (typeof x === 'string') { - if (/^(0x|0X)[a-fA-F0-9]*$/.test(x)) { - // hex string with "0x" prefix - if (x.length % 2 !== 0) { - throw new Error(`Hex string is an odd number of digits: "${x}"`); - } - return '\\x' + x.slice(2); - } else if (x.length === 0) { - return '\\x'; - } else if (/^\\x[a-fA-F0-9]*$/.test(x)) { - // hex string with "\x" prefix (already encoded for postgres) - if (x.length % 2 !== 0) { - throw new Error(`Hex string is an odd number of digits: "${x}"`); - } - return x; - } else { - throw new Error(`String value for bytea column does not have 0x prefix: "${x}"`); - } - } else if (Buffer.isBuffer(x)) { - return '\\x' + x.toString('hex'); - } else if (ArrayBuffer.isView(x)) { - return '\\x' + Buffer.from(x.buffer, x.byteOffset, x.byteLength).toString('hex'); - } else { - throw new Error( - `Cannot serialize unexpected type "${x.constructor.name}" to bytea hex string` - ); - } - }, - parse: (x: any) => `0x${x.slice(2)}`, - }, -}; -/** Values will be automatically converted into a `bytea` compatible string before sending to pg. */ -export type PgBytea = string | Buffer; -/** The `string` type guarantees the value will fit into the `numeric` pg type. */ -export type PgNumeric = string; -/** JSON objects will be automatically stringified before insertion. */ -export type PgJsonb = any; - -/** - * Connects to Postgres. This function will also test the connection first to make sure - * all connection parameters are specified correctly in `.env`. - * @param args - Connection options - * @returns configured `Pool` object - */ -export async function connectPostgres({ - usageName, - pgServer, -}: { - usageName: string; - pgServer: PgServer; -}): Promise { - const initTimer = stopwatch(); - let connectionError: Error | undefined; - let connectionOkay = false; - let lastElapsedLog = 0; - do { - const testSql = getPostgres({ - usageName: `${usageName};conn-poll`, - pgServer: pgServer, - }); - try { - await testSql`SELECT version()`; - connectionOkay = true; - break; - } catch (error: any) { - if (isPgConnectionError(error) || error instanceof postgres.PostgresError) { - const timeElapsed = initTimer.getElapsed(); - if (timeElapsed - lastElapsedLog > 2000) { - lastElapsedLog = timeElapsed; - logger.error(error, 'Pg connection failed. Retrying..'); - } - connectionError = error; - await timeout(100); - } else { - logger.error(error, 'Cannot connect to pg'); - throw error; - } - } finally { - await testSql.end(); - } - } while (initTimer.getElapsed() < Number.MAX_SAFE_INTEGER); - if (!connectionOkay) { - connectionError = connectionError ?? new Error('Error connecting to database'); - throw connectionError; - } - const sql = getPostgres({ - usageName: `${usageName};datastore-crud`, - pgServer: pgServer, - }); - return sql; -} - /** * Retrieve a postgres ENV value depending on the target database server (read-replica/default or * primary). We will fall back to read-replica values if a primary value was not given. See the @@ -125,80 +19,33 @@ export function getPgConnectionEnvValue( name: string, pgServer: PgServer = PgServer.default ): string | undefined { + const defaultVal = process.env[`PG_${name}`] ?? process.env[`PG${name}`]; return pgServer === PgServer.primary - ? process.env[`PG_PRIMARY_${name}`] ?? process.env[`PG_${name}`] - : process.env[`PG_${name}`]; + ? process.env[`PG_PRIMARY_${name}`] ?? defaultVal + : defaultVal; +} + +export function getConnectionArgs(server: PgServer = PgServer.default): PgConnectionArgs { + return ( + getPgConnectionEnvValue('CONNECTION_URI', server) ?? { + database: getPgConnectionEnvValue('DATABASE', server), + user: getPgConnectionEnvValue('USER', server), + password: getPgConnectionEnvValue('PASSWORD', server), + host: getPgConnectionEnvValue('HOST', server), + port: parseInt(getPgConnectionEnvValue('PORT', server) ?? '5432'), + ssl: getPgConnectionEnvValue('SSL', server) == 'true', + schema: getPgConnectionEnvValue('SCHEMA', server), + application_name: getPgConnectionEnvValue('APPLICATION_NAME', server), + } + ); } -export function getPostgres({ - usageName, - pgServer, -}: { - usageName: string; - pgServer?: PgServer; -}): PgSqlClient { - const pgEnvVars = { - database: getPgConnectionEnvValue('DATABASE', pgServer), - user: getPgConnectionEnvValue('USER', pgServer), - password: getPgConnectionEnvValue('PASSWORD', pgServer), - host: getPgConnectionEnvValue('HOST', pgServer), - port: getPgConnectionEnvValue('PORT', pgServer), - ssl: getPgConnectionEnvValue('SSL', pgServer), - schema: getPgConnectionEnvValue('SCHEMA', pgServer), - applicationName: getPgConnectionEnvValue('APPLICATION_NAME', pgServer), - idleTimeout: parseInt(getPgConnectionEnvValue('IDLE_TIMEOUT', pgServer) ?? '30'), - maxLifetime: parseInt(getPgConnectionEnvValue('MAX_LIFETIME', pgServer) ?? '60'), - poolMax: parseInt(process.env['PG_CONNECTION_POOL_MAX'] ?? '10'), +export function getConnectionConfig(server: PgServer = PgServer.default): PgConnectionOptions { + const statementTimeout = getPgConnectionEnvValue('STATEMENT_TIMEOUT', server); + return { + idleTimeout: parseInt(getPgConnectionEnvValue('IDLE_TIMEOUT', server) ?? '30'), + maxLifetime: parseInt(getPgConnectionEnvValue('MAX_LIFETIME', server) ?? '60'), + poolMax: parseInt(getPgConnectionEnvValue('CONNECTION_POOL_MAX', server) ?? '10'), + statementTimeout: statementTimeout ? parseInt(statementTimeout) : undefined, }; - const defaultAppName = 'stacks-blockchain-api'; - const pgConnectionUri = getPgConnectionEnvValue('CONNECTION_URI', pgServer); - const pgConfigEnvVar = Object.entries(pgEnvVars).find(([, v]) => typeof v === 'string')?.[0]; - if (pgConfigEnvVar && pgConnectionUri) { - throw new Error( - `Both PG_CONNECTION_URI and ${pgConfigEnvVar} environmental variables are defined. PG_CONNECTION_URI must be defined without others or omitted.` - ); - } - let sql: PgSqlClient; - if (pgConnectionUri) { - const uri = new URL(pgConnectionUri); - const searchParams = Object.fromEntries( - [...uri.searchParams.entries()].map(([k, v]) => [k.toLowerCase(), v]) - ); - // Not really standardized - const schema: string | undefined = - searchParams['currentschema'] ?? - searchParams['current_schema'] ?? - searchParams['searchpath'] ?? - searchParams['search_path'] ?? - searchParams['schema']; - const appName = `${uri.searchParams.get('application_name') ?? defaultAppName}:${usageName}`; - uri.searchParams.set('application_name', appName); - sql = postgres(uri.toString(), { - types: PG_TYPE_MAPPINGS, - max: pgEnvVars.poolMax, - connection: { - application_name: appName, - search_path: schema, - }, - }); - } else { - const appName = `${pgEnvVars.applicationName ?? defaultAppName}:${usageName}`; - sql = postgres({ - database: pgEnvVars.database, - user: pgEnvVars.user, - password: pgEnvVars.password, - host: pgEnvVars.host, - port: parsePort(pgEnvVars.port), - ssl: parseArgBoolean(pgEnvVars.ssl), - idle_timeout: pgEnvVars.idleTimeout, - max_lifetime: pgEnvVars.maxLifetime, - max: pgEnvVars.poolMax, - types: PG_TYPE_MAPPINGS, - connection: { - application_name: appName, - search_path: pgEnvVars.schema, - }, - }); - } - return sql; } diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index 8af1ddc920..7eafa68fc7 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -1,4 +1,4 @@ -import { hexToBuffer, parseEnum, unwrapOptionalProp } from '../helpers'; +import { parseEnum, unwrapOptionalProp } from '../helpers'; import { BlockQueryResult, ContractTxQueryResult, @@ -57,12 +57,12 @@ import { import { getTxSenderAddress } from '../event-stream/reader'; import postgres = require('postgres'); import * as prom from 'prom-client'; -import { PgSqlClient } from './connection'; import { NftEvent } from 'docs/generated'; import { getAssetEventTypeString } from '../api/controllers/db-controller'; import { PgStoreEventEmitter } from './pg-store-event-emitter'; import { Pox2EventName } from '../pox-helpers'; import { logger } from '../logger'; +import { PgSqlClient } from '@hirosystems/api-toolkit'; export const TX_COLUMNS = [ 'tx_id', @@ -229,50 +229,6 @@ export const POX2_EVENT_COLUMNS = [ export const POX3_EVENT_COLUMNS = POX2_EVENT_COLUMNS; -/** - * Checks if a given error from the pg lib is a connection error (i.e. the query is retryable). - * If true then returns a normalized error message, otherwise returns false. - */ -export function isPgConnectionError(error: any): string | false { - if (error.code === 'ECONNREFUSED') { - return 'Postgres connection ECONNREFUSED'; - } else if (error.code === 'ETIMEDOUT') { - return 'Postgres connection ETIMEDOUT'; - } else if (error.code === 'ENOTFOUND') { - return 'Postgres connection ENOTFOUND'; - } else if (error.code === 'ECONNRESET') { - return 'Postgres connection ECONNRESET'; - } else if (error.code === 'CONNECTION_CLOSED') { - return 'Postgres connection CONNECTION_CLOSED'; - } else if (error.code === 'CONNECTION_ENDED') { - return 'Postgres connection CONNECTION_ENDED'; - } else if (error.code === 'CONNECTION_DESTROYED') { - return 'Postgres connection CONNECTION_DESTROYED'; - } else if (error.code === 'CONNECTION_CONNECT_TIMEOUT') { - return 'Postgres connection CONNECTION_CONNECT_TIMEOUT'; - } else if (error.code === 'CONNECT_TIMEOUT') { - return 'Postgres connection CONNECT_TIMEOUT'; - } else if (error.message) { - const msg = (error as Error).message.toLowerCase(); - if (msg.includes('database system is starting up')) { - return 'Postgres connection failed while database system is starting up'; - } else if (msg.includes('database system is shutting down')) { - return 'Postgres connection failed while database system is shutting down'; - } else if (msg.includes('connection terminated unexpectedly')) { - return 'Postgres connection terminated unexpectedly'; - } else if (msg.includes('connection terminated')) { - return 'Postgres connection terminated'; - } else if (msg.includes('connection error')) { - return 'Postgres client has encountered a connection error and is not queryable'; - } else if (msg.includes('terminating connection due to unexpected postmaster exit')) { - return 'Postgres connection terminating due to unexpected postmaster exit'; - } else if (msg.includes('getaddrinfo eai_again')) { - return 'Postgres connection failed due to a DNS lookup error'; - } - } - return false; -} - /** * Adds a table name prefix to an array of column names. * @param columns - array of column names diff --git a/src/datastore/migrations.ts b/src/datastore/migrations.ts deleted file mode 100644 index 9cc7f45e30..0000000000 --- a/src/datastore/migrations.ts +++ /dev/null @@ -1,102 +0,0 @@ -import * as path from 'path'; -import PgMigrate, { RunnerOption } from 'node-pg-migrate'; -import { Client } from 'pg'; -import { APP_DIR, isDevEnv, isTestEnv, REPO_DIR } from '../helpers'; -import { getPgClientConfig, PgClientConfig } from './connection-legacy'; -import { connectPostgres, PgServer } from './connection'; -import { databaseHasData } from './event-requests'; -import { logger } from '../logger'; - -const MIGRATIONS_TABLE = 'pgmigrations'; -const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); - -export async function runMigrations( - clientConfig: PgClientConfig = getPgClientConfig({ usageName: 'schema-migrations' }), - direction: 'up' | 'down' = 'up', - opts?: { - // Bypass the NODE_ENV check when performing a "down" migration which irreversibly drops data. - dangerousAllowDataLoss?: boolean; - } -): Promise { - if (!opts?.dangerousAllowDataLoss && direction !== 'up' && !isTestEnv && !isDevEnv) { - throw new Error( - 'Whoa there! This is a testing function that will drop all data from PG. ' + - 'Set NODE_ENV to "test" or "development" to enable migration testing.' - ); - } - const client = new Client(clientConfig); - try { - await client.connect(); - const runnerOpts: RunnerOption = { - dbClient: client, - ignorePattern: '.*map', - dir: MIGRATIONS_DIR, - direction: direction, - migrationsTable: MIGRATIONS_TABLE, - count: Infinity, - logger: { - info: msg => {}, - warn: msg => logger.warn(msg), - error: msg => logger.error(msg), - }, - }; - if (clientConfig.schema) { - runnerOpts.schema = clientConfig.schema; - } - await PgMigrate(runnerOpts); - } catch (error) { - logger.error(error, 'Error running pg-migrate'); - throw error; - } finally { - await client.end(); - } -} - -export async function cycleMigrations(opts?: { - // Bypass the NODE_ENV check when performing a "down" migration which irreversibly drops data. - dangerousAllowDataLoss?: boolean; - checkForEmptyData?: boolean; -}): Promise { - const clientConfig = getPgClientConfig({ usageName: 'cycle-migrations' }); - - await runMigrations(clientConfig, 'down', opts); - if (opts?.checkForEmptyData && (await databaseHasData({ ignoreMigrationTables: true }))) { - throw new Error('Migration down process did not completely remove DB tables'); - } - await runMigrations(clientConfig, 'up', opts); -} - -export async function dangerousDropAllTables(opts?: { - acknowledgePotentialCatastrophicConsequences?: 'yes'; -}) { - if (opts?.acknowledgePotentialCatastrophicConsequences !== 'yes') { - throw new Error('Dangerous usage error.'); - } - const sql = await connectPostgres({ - usageName: 'dangerous-drop-all-tables', - pgServer: PgServer.primary, - }); - const schema = sql.options.connection.search_path; - try { - await sql.begin(async sql => { - const relNamesQuery = async (kind: string) => sql<{ relname: string }[]>` - SELECT relname - FROM pg_class c - JOIN pg_namespace s ON s.oid = c.relnamespace - WHERE s.nspname = ${schema} AND c.relkind = ${kind} - `; - // Remove materialized views first and tables second. - // Using CASCADE in these DROP statements also removes associated indexes and constraints. - const views = await relNamesQuery('m'); - for (const view of views) { - await sql`DROP MATERIALIZED VIEW IF EXISTS ${sql(view.relname)} CASCADE`; - } - const tables = await relNamesQuery('r'); - for (const table of tables) { - await sql`DROP TABLE IF EXISTS ${sql(table.relname)} CASCADE`; - } - }); - } finally { - await sql.end(); - } -} diff --git a/src/datastore/pg-notifier.ts b/src/datastore/pg-notifier.ts index 28b2758cd9..8d60d3c6e0 100644 --- a/src/datastore/pg-notifier.ts +++ b/src/datastore/pg-notifier.ts @@ -1,7 +1,8 @@ import * as postgres from 'postgres'; import { logger } from '../logger'; import { DbConfigState } from './common'; -import { connectPostgres, PgServer, PgSqlClient } from './connection'; +import { PgSqlClient, connectPostgres } from '@hirosystems/api-toolkit'; +import { PgServer, getConnectionArgs, getConnectionConfig } from './connection'; type PgTxNotificationPayload = { txId: string; @@ -46,7 +47,7 @@ type PgTokensNotificationPayload = { contractID: string; }; -export type PgConfigStateNotificationPayload = DbConfigState; +type PgConfigStateNotificationPayload = DbConfigState; /** * API notifications to be sent via Postgres `NOTIFY` queries. @@ -77,7 +78,11 @@ export class PgNotifier { listener?: postgres.ListenMeta; static async create(usageName: string) { - const sql = await connectPostgres({ usageName: usageName, pgServer: PgServer.primary }); + const sql = await connectPostgres({ + usageName: usageName, + connectionArgs: getConnectionArgs(PgServer.primary), + connectionConfig: getConnectionConfig(PgServer.primary), + }); return new PgNotifier(sql); } diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 29ab013922..2dade8833e 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -14,6 +14,7 @@ import { getBnsSmartContractId, bnsNameFromSubdomain, ChainID, + REPO_DIR, } from '../helpers'; import { PgStoreEventEmitter } from './pg-store-event-emitter'; import { @@ -30,7 +31,6 @@ import { DbBnsZoneFile, DbBurnchainReward, DbChainTip, - DbConfigState, DbEvent, DbEventTypeId, DbFtBalance, @@ -77,7 +77,6 @@ import { StxUnlockEvent, TransferQueryResult, } from './common'; -import { connectPostgres, getPgConnectionEnvValue, PgServer, PgSqlClient } from './connection'; import { abiColumn, BLOCK_COLUMNS, @@ -99,25 +98,18 @@ import { unsafeCols, validateZonefileHash, } from './helpers'; -import { PgConfigStateNotificationPayload, PgNotifier } from './pg-notifier'; -import { AsyncLocalStorage } from 'async_hooks'; +import { PgNotifier } from './pg-notifier'; import { Pox2EventName } from '../pox-helpers'; +import { BasePgStore, PgSqlClient, connectPostgres } from '@hirosystems/api-toolkit'; +import { + PgServer, + getConnectionArgs, + getConnectionConfig, + getPgConnectionEnvValue, +} from './connection'; +import * as path from 'path'; -export type UnwrapPromiseArray = T extends any[] - ? { - [k in keyof T]: T[k] extends Promise ? R : T[k]; - } - : T; - -type SqlTransactionContext = { - usageName: string; - sql: PgSqlClient; -}; -/** - * AsyncLocalStorage which determines if the current async context is running inside a SQL - * transaction. - */ -export const sqlTransactionContext = new AsyncLocalStorage(); +export const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); /** * This is the main interface between the API and the Postgres database. It contains all methods that @@ -125,25 +117,12 @@ export const sqlTransactionContext = new AsyncLocalStorage { - const sql = await connectPostgres({ usageName: usageName, pgServer: PgServer.default }); + const sql = await connectPostgres({ + usageName: usageName, + connectionArgs: getConnectionArgs(), + connectionConfig: getConnectionConfig(), + }); const notifier = withNotifier ? await PgNotifier.create(usageName) : undefined; const store = new PgStore(sql, notifier); await store.connectPgNotifier(); @@ -164,44 +147,11 @@ export class PgStore { async close(): Promise { await this.notifier?.close(); - await this.sql.end({ timeout: this.closeTimeout }); - } - - /** - * Start a SQL transaction. If any SQL client used within the callback was already scoped inside a - * `BEGIN` transaction, no new transaction will be opened. This flexibility allows us to avoid - * repeating code while making sure we don't arrive at SQL errors such as - * `WARNING: there is already a transaction in progress` which may cause result inconsistencies. - * @param callback - Callback with a scoped SQL client - * @param readOnly - If a `BEGIN` transaction should be marked as `READ ONLY` - * @returns Transaction results - */ - async sqlTransaction( - callback: (sql: PgSqlClient) => T | Promise, - readOnly = true - ): Promise> { - // Do we have a scoped client already? Use it directly. - const sqlContext = sqlTransactionContext.getStore(); - if (sqlContext) { - return callback(sqlContext.sql) as UnwrapPromiseArray; - } - // Otherwise, start a transaction and store the scoped connection in the current async context. - const usageName = this._sql.options.connection.application_name ?? ''; - return this._sql.begin(readOnly ? 'read only' : 'read write', sql => { - return sqlTransactionContext.run({ usageName, sql }, () => callback(sql)); + await super.close({ + timeout: parseInt(getPgConnectionEnvValue('CLOSE_TIMEOUT', PgServer.default) ?? '5'), }); } - /** - * Get `application_name` for current connection (each connection has a unique PID) - */ - async getConnectionApplicationName(): Promise { - const result = await this.sql<{ application_name: string }[]>` - SELECT application_name FROM pg_stat_activity WHERE pid = pg_backend_pid() - `; - return result[0].application_name; - } - /** * Connects to the `PgNotifier`. Its messages will be forwarded to the rest of the API components * though the EventEmitter. @@ -258,9 +208,7 @@ export class PgStore { }); } - async getChainTip( - sql: PgSqlClient - ): Promise<{ + async getChainTip(sql: PgSqlClient): Promise<{ blockHeight: number; blockHash: string; indexBlockHash: string; @@ -730,9 +678,7 @@ export class PgStore { }); } - async getAddressNonces(args: { - stxAddress: string; - }): Promise<{ + async getAddressNonces(args: { stxAddress: string }): Promise<{ lastExecutedTxNonce: number | null; lastMempoolTxNonce: number | null; possibleNextNonce: number; diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 5d843beed8..ef8c3c7028 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -1,4 +1,4 @@ -import { getOrAdd, batchIterate, isProdEnv, I32_MAX, getIbdBlockHeight } from '../helpers'; +import { getOrAdd, batchIterate, I32_MAX, getIbdBlockHeight } from '../helpers'; import { DbBlock, DbTx, @@ -9,7 +9,6 @@ import { DbSmartContractEvent, DbSmartContract, DataStoreBlockUpdateData, - DbMempoolTx, DbStxLockEvent, DbMinerReward, DbBurnchainReward, @@ -81,21 +80,20 @@ import { validateZonefileHash, } from './helpers'; import { PgNotifier } from './pg-notifier'; -import { PgStore, UnwrapPromiseArray } from './pg-store'; -import { - connectPostgres, - getPgConnectionEnvValue, - PgJsonb, - PgServer, - PgSqlClient, -} from './connection'; -import { runMigrations } from './migrations'; -import { getPgClientConfig } from './connection-legacy'; +import { MIGRATIONS_DIR, PgStore } from './pg-store'; import { isProcessableTokenMetadata } from '../token-metadata/helpers'; import * as zoneFileParser from 'zone-file'; import { parseResolver, parseZoneFileTxt } from '../event-stream/bns/bns-helpers'; import { Pox2EventName } from '../pox-helpers'; import { logger } from '../logger'; +import { + PgJsonb, + PgSqlClient, + connectPostgres, + isProdEnv, + runMigrations, +} from '@hirosystems/api-toolkit'; +import { PgServer, getConnectionArgs, getConnectionConfig } from './connection'; const MIGRATIONS_TABLE = 'pgmigrations'; @@ -115,9 +113,6 @@ class MicroblockGapError extends Error { export class PgWriteStore extends PgStore { readonly isEventReplay: boolean; protected isIbdBlockHeightReached = false; - protected get closeTimeout(): number { - return parseInt(getPgConnectionEnvValue('CLOSE_TIMEOUT', PgServer.primary) ?? '5'); - } constructor( sql: PgSqlClient, @@ -139,14 +134,13 @@ export class PgWriteStore extends PgStore { withNotifier?: boolean; isEventReplay?: boolean; }): Promise { - const sql = await connectPostgres({ usageName: usageName, pgServer: PgServer.primary }); + const sql = await connectPostgres({ + usageName: usageName, + connectionArgs: getConnectionArgs(PgServer.primary), + connectionConfig: getConnectionConfig(PgServer.primary), + }); if (!skipMigrations) { - await runMigrations( - getPgClientConfig({ - usageName: `${usageName}:schema-migrations`, - pgServer: PgServer.primary, - }) - ); + await runMigrations(MIGRATIONS_DIR, 'up', getConnectionArgs(PgServer.primary)); } const notifier = withNotifier ? await PgNotifier.create(usageName) : undefined; const store = new PgWriteStore(sql, notifier, isEventReplay); @@ -154,12 +148,6 @@ export class PgWriteStore extends PgStore { return store; } - async sqlWriteTransaction( - callback: (sql: PgSqlClient) => T | Promise - ): Promise> { - return super.sqlTransaction(callback, false); - } - async getChainTip(sql: PgSqlClient, useMaterializedView = true): Promise { if (!this.isEventReplay && useMaterializedView) { return super.getChainTip(sql); diff --git a/src/ec-helpers.ts b/src/ec-helpers.ts index c2c0b279b7..672e16d14a 100644 --- a/src/ec-helpers.ts +++ b/src/ec-helpers.ts @@ -1,7 +1,7 @@ import * as bitcoin from 'bitcoinjs-lib'; import * as ecc from 'tiny-secp256k1'; import { ECPairAPI, ECPairFactory, ECPairInterface } from 'ecpair'; -import { coerceToBuffer } from './helpers'; +import { coerceToBuffer } from '@hirosystems/api-toolkit'; export { ECPairInterface }; diff --git a/src/datastore/connection-legacy.ts b/src/event-replay/connection-legacy.ts similarity index 91% rename from src/datastore/connection-legacy.ts rename to src/event-replay/connection-legacy.ts index 09037e86f3..19564f9e5d 100644 --- a/src/datastore/connection-legacy.ts +++ b/src/event-replay/connection-legacy.ts @@ -1,10 +1,13 @@ +// TODO: This file exists because we use the old `pg` library to stream node events during replays. +// we should migrate replays into `postgres.js` and delete this file. + import { Client, ClientConfig, Pool, PoolClient, PoolConfig } from 'pg'; -import { parseArgBoolean, parsePort, stopwatch, timeout } from '../helpers'; -import { PgServer } from './connection'; -import { isPgConnectionError } from './helpers'; +import { PgServer } from '../datastore/connection'; import { logger } from '../logger'; +import { isPgConnectionError, parseBoolean, stopwatch, timeout } from '@hirosystems/api-toolkit'; +import { parsePort } from '../helpers'; -export type PgClientConfig = ClientConfig & { schema?: string }; +type PgClientConfig = ClientConfig & { schema?: string }; type PgPoolConfig = PoolConfig & { schema?: string }; /** @@ -70,7 +73,7 @@ export async function connectPgPool({ /** * @typeParam TGetPoolConfig - If specified as true, returns a PoolConfig object where max connections are configured. Otherwise, returns a regular ClientConfig. */ -export function getPgClientConfig({ +function getPgClientConfig({ usageName, pgServer, getPoolConfig, @@ -131,7 +134,7 @@ export function getPgClientConfig({ password: pgEnvVars.password, host: pgEnvVars.host, port: parsePort(pgEnvVars.port), - ssl: parseArgBoolean(pgEnvVars.ssl), + ssl: parseBoolean(pgEnvVars.ssl), schema: pgEnvVars.schema, application_name: appName, }; diff --git a/src/event-replay/event-replay.ts b/src/event-replay/event-replay.ts index 53cb077509..4378d30243 100644 --- a/src/event-replay/event-replay.ts +++ b/src/event-replay/event-replay.ts @@ -1,17 +1,15 @@ import * as fs from 'fs'; import * as path from 'path'; -import { - databaseHasData, - exportRawEventRequests, - getRawEventRequests, -} from '../datastore/event-requests'; -import { cycleMigrations, dangerousDropAllTables } from '../datastore/migrations'; +import { exportRawEventRequests, getRawEventRequests } from './event-requests'; import { PgWriteStore } from '../datastore/pg-write-store'; import { startEventServer } from '../event-stream/event-server'; import { getApiConfiguredChainID, HttpClientResponse, httpPostRequest } from '../helpers'; import { importV1TokenOfferingData } from '../import-v1'; import { findTsvBlockHeight, getDbBlockHeight } from './helpers'; import { logger } from '../logger'; +import { cycleMigrations, dangerousDropAllTables, databaseHasData } from '@hirosystems/api-toolkit'; +import { MIGRATIONS_DIR } from '../datastore/pg-store'; +import { PgServer, getConnectionArgs } from '../datastore/connection'; enum EventImportMode { /** @@ -86,16 +84,22 @@ export async function importEventsFromTsv( default: throw new Error(`Invalid event import mode: ${importMode}`); } - const hasData = await databaseHasData(); + const connectionArgs = getConnectionArgs(PgServer.primary); + const hasData = await databaseHasData(connectionArgs); if (!wipeDb && hasData) { throw new Error(`Database contains existing data. Add --wipe-db to drop the existing tables.`); } if (force) { - await dangerousDropAllTables({ acknowledgePotentialCatastrophicConsequences: 'yes' }); + await dangerousDropAllTables(connectionArgs, { + acknowledgePotentialCatastrophicConsequences: 'yes', + }); } try { - await cycleMigrations({ dangerousAllowDataLoss: true, checkForEmptyData: true }); + await cycleMigrations(MIGRATIONS_DIR, connectionArgs, { + dangerousAllowDataLoss: true, + checkForEmptyData: true, + }); } catch (error) { logger.error(error); throw new Error( diff --git a/src/datastore/event-requests.ts b/src/event-replay/event-requests.ts similarity index 76% rename from src/datastore/event-requests.ts rename to src/event-replay/event-requests.ts index 45f68eae5b..eb789f523e 100644 --- a/src/datastore/event-requests.ts +++ b/src/event-replay/event-requests.ts @@ -1,7 +1,7 @@ import { pipelineAsync } from '../helpers'; import { Readable, Writable } from 'stream'; -import { DbRawEventRequest } from './common'; -import { connectPostgres, PgServer } from './connection'; +import { DbRawEventRequest } from '../datastore/common'; +import { PgServer } from '../datastore/connection'; import { connectPgPool, connectWithRetry } from './connection-legacy'; import * as pgCopyStreams from 'pg-copy-streams'; import * as PgCursor from 'pg-cursor'; @@ -118,37 +118,3 @@ export async function* getRawEventRequests( await pool.end(); } } - -/** - * Check the `pg_class` table for any data structures contained in the database. We will consider - * any and all results here as "data" contained in the DB, since anything that is not a completely - * empty DB could lead to strange errors when running the API. See: - * https://www.postgresql.org/docs/current/catalog-pg-class.html - * @returns `boolean` if the DB has data - */ -export async function databaseHasData(args?: { - ignoreMigrationTables?: boolean; -}): Promise { - const sql = await connectPostgres({ - usageName: 'contains-data-check', - pgServer: PgServer.primary, - }); - try { - const ignoreMigrationTables = args?.ignoreMigrationTables ?? false; - const result = await sql<{ count: number }[]>` - SELECT COUNT(*) - FROM pg_class c - JOIN pg_namespace s ON s.oid = c.relnamespace - WHERE s.nspname = ${sql.options.connection.search_path} - ${ignoreMigrationTables ? sql`AND c.relname NOT LIKE 'pgmigrations%'` : sql``} - `; - return result.count > 0 && result[0].count > 0; - } catch (error: any) { - if (error.message?.includes('does not exist')) { - return false; - } - throw error; - } finally { - await sql.end(); - } -} diff --git a/src/event-replay/helpers.ts b/src/event-replay/helpers.ts index 075789aaf9..3cec50ea4b 100644 --- a/src/event-replay/helpers.ts +++ b/src/event-replay/helpers.ts @@ -38,28 +38,6 @@ export async function findTsvBlockHeight(filePath: string): Promise { return blockHeight; } -export async function getGenesisBlockData(filePath: string): Promise { - const rl = readline.createInterface({ - input: fs.createReadStream(filePath), - crlfDelay: Infinity, - }); - try { - for await (const line of rl) { - const columns = line.split('\t'); - const eventName = columns[2]; - if (eventName === '/new_block') { - const blockMessage = JSON.parse(columns[3]); - if (blockMessage.block_height === 0 || blockMessage.block_height === 1) { - return blockMessage as CoreNodeBlockMessage; - } - } - } - } finally { - rl.close(); - } - throw new Error('Genesis block data not found'); -} - export async function getBnsGenesisBlockFromBlockMessage( db: PgWriteStore ): Promise { diff --git a/src/event-replay/parquet-based/helpers.ts b/src/event-replay/parquet-based/helpers.ts index 63ccddfed9..c58a7b4966 100644 --- a/src/event-replay/parquet-based/helpers.ts +++ b/src/event-replay/parquet-based/helpers.ts @@ -6,9 +6,7 @@ import { DatasetStore } from './dataset/store'; interface TimeTracker { track(name: string, fn: () => Promise): Promise; trackSync(name: string, fn: () => T): T; - getDurations: ( - roundDecimals?: number - ) => { + getDurations: (roundDecimals?: number) => { name: string; seconds: string; }[]; diff --git a/src/event-replay/parquet-based/replay-controller.ts b/src/event-replay/parquet-based/replay-controller.ts index 323f8b7260..b011bd97f5 100644 --- a/src/event-replay/parquet-based/replay-controller.ts +++ b/src/event-replay/parquet-based/replay-controller.ts @@ -8,15 +8,17 @@ import { processAttachmentNewEvents } from './importers/attachment-new-importer' import { processRawEvents } from './importers/raw-importer'; import { processRemainderEvents } from './importers/remainder-importer'; import { DatasetStore } from './dataset/store'; -import { cycleMigrations, dangerousDropAllTables } from '../../datastore/migrations'; import { IndexesState } from '../../datastore/common'; import { importV1TokenOfferingData } from '../../import-v1'; import * as _cluster from 'cluster'; -const cluster = (_cluster as unknown) as _cluster.Cluster; // typings fix +const cluster = _cluster as unknown as _cluster.Cluster; // typings fix import { FILE_PATH as raw_worker_path } from './workers/raw-worker'; import { FILE_PATH as new_block_worker_path } from './workers/new-block-worker'; +import { cycleMigrations, dangerousDropAllTables } from '@hirosystems/api-toolkit'; +import { PgServer, getConnectionArgs } from 'src/datastore/connection'; +import { MIGRATIONS_DIR } from '../../datastore/pg-store'; /** * This class is an entry point for the event-replay based on parquet files, @@ -220,12 +222,16 @@ export class ReplayController { * */ prepare = async () => { + const args = getConnectionArgs(PgServer.primary); logger.info({ component: 'event-replay' }, 'Cleaning up the Database'); - await dangerousDropAllTables({ acknowledgePotentialCatastrophicConsequences: 'yes' }); + await dangerousDropAllTables(args, { acknowledgePotentialCatastrophicConsequences: 'yes' }); logger.info({ component: 'event-replay' }, 'Migrating tables'); try { - await cycleMigrations({ dangerousAllowDataLoss: true, checkForEmptyData: true }); + await cycleMigrations(MIGRATIONS_DIR, args, { + dangerousAllowDataLoss: true, + checkForEmptyData: true, + }); } catch (error) { logger.error(error); throw new Error('DB migration cycle failed'); diff --git a/src/event-stream/bns/bns-helpers.ts b/src/event-stream/bns/bns-helpers.ts index 6498d81310..9dd35db5c6 100644 --- a/src/event-stream/bns/bns-helpers.ts +++ b/src/event-stream/bns/bns-helpers.ts @@ -1,10 +1,9 @@ -import { BufferCV, ClarityType, hexToCV, StringAsciiCV } from '@stacks/transactions'; -import { bnsNameCV, ChainID, getChainIDNetwork, hexToBuffer, hexToUtf8String } from '../../helpers'; +import { BufferCV, ClarityType, hexToCV } from '@stacks/transactions'; +import { bnsNameCV, ChainID, getChainIDNetwork } from '../../helpers'; import { CoreNodeEvent, CoreNodeEventType, CoreNodeParsedTxMessage, - NftTransferEvent, } from '../../event-stream/core-node-message'; import { getCoreNodeEndpoint } from '../../core-rpc/client'; import { StacksMainnet, StacksTestnet } from '@stacks/network'; @@ -25,6 +24,7 @@ import { } from 'stacks-encoding-native-js'; import { SmartContractEvent } from '../core-node-message'; import { DbBnsNamespace, DbBnsName } from '../../datastore/common'; +import { hexToBuffer, hexToUtf8String } from '@hirosystems/api-toolkit'; interface Attachment { attachment: { diff --git a/src/event-stream/core-node-message.ts b/src/event-stream/core-node-message.ts index 4c9c436049..e23e569968 100644 --- a/src/event-stream/core-node-message.ts +++ b/src/event-stream/core-node-message.ts @@ -80,7 +80,7 @@ export interface StxLockEvent extends CoreNodeEventBase { }; } -export interface NftTransferEvent extends CoreNodeEventBase { +interface NftTransferEvent extends CoreNodeEventBase { type: CoreNodeEventType.NftTransferEvent; nft_transfer_event: { /** Fully qualified asset ID, e.g. "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH.contract-name.asset-name" */ @@ -199,7 +199,7 @@ export interface CoreNodeTxMessage { burnchain_op?: BurnchainOp | null; } -export interface CoreNodeMicroblockTxMessage extends CoreNodeTxMessage { +interface CoreNodeMicroblockTxMessage extends CoreNodeTxMessage { microblock_sequence: number; microblock_hash: string; microblock_parent_hash: string; diff --git a/src/event-stream/event-server.ts b/src/event-stream/event-server.ts index 02d3e9f619..c767a44163 100644 --- a/src/event-stream/event-server.ts +++ b/src/event-stream/event-server.ts @@ -6,14 +6,7 @@ import * as bodyParser from 'body-parser'; import { asyncHandler } from '../api/async-handler'; import PQueue from 'p-queue'; import * as prom from 'prom-client'; -import { - ChainID, - getChainIDNetwork, - getIbdBlockHeight, - hexToBuffer, - isProdEnv, - stopwatch, -} from '../helpers'; +import { ChainID, getChainIDNetwork, getIbdBlockHeight } from '../helpers'; import { CoreNodeBlockMessage, CoreNodeEventType, @@ -45,7 +38,6 @@ import { DbPox2Event, DbTxStatus, DbBnsSubdomain, - DataStoreBnsBlockData, } from '../datastore/common'; import { getTxSenderAddress, @@ -78,12 +70,12 @@ import { getTxDbStatus, } from '../datastore/helpers'; import { handleBnsImport } from '../import-v1'; -import { Pox2ContractIdentifer } from '../pox-helpers'; import { decodePox2PrintEvent } from './pox2-event-parsing'; import { logger, loggerMiddleware } from '../logger'; import * as zoneFileParser from 'zone-file'; +import { hexToBuffer, isProdEnv, stopwatch } from '@hirosystems/api-toolkit'; -export const IBD_PRUNABLE_ROUTES = ['/new_mempool_tx', '/drop_mempool_tx', '/new_microblocks']; +const IBD_PRUNABLE_ROUTES = ['/new_mempool_tx', '/drop_mempool_tx', '/new_microblocks']; async function handleRawEventRequest( eventPath: string, diff --git a/src/event-stream/pox2-event-parsing.ts b/src/event-stream/pox2-event-parsing.ts index 653284d60a..66e4e27525 100644 --- a/src/event-stream/pox2-event-parsing.ts +++ b/src/event-stream/pox2-event-parsing.ts @@ -13,8 +13,6 @@ import { DbPox2StackIncreaseEvent, DbPox2StackStxEvent, } from '../datastore/common'; -import { bufferToHexPrefixString, coerceToBuffer, has0xPrefix } from '../helpers'; - import { ClarityTypeID, ClarityValue, @@ -33,10 +31,11 @@ import { import { poxAddressToBtcAddress } from '@stacks/stacking'; import { Pox2EventName } from '../pox-helpers'; import { logger } from '../logger'; +import { bufferToHex, coerceToBuffer } from '@hirosystems/api-toolkit'; function tryClarityPoxAddressToBtcAddress( poxAddr: Pox2Addr | ClarityValueOptionalSome | ClarityValueOptionalNone, - network: 'mainnet' | 'testnet' | 'regtest' + network: 'mainnet' | 'testnet' | 'devnet' | 'mocknet' ): { btcAddr: string | null; raw: Buffer } { let btcAddr: string | null = null; if (poxAddr.type_id === ClarityTypeID.OptionalNone) { @@ -166,7 +165,7 @@ const PATCH_EVENT_BALANCES = true; export function decodePox2PrintEvent( rawClarityData: string, - network: 'mainnet' | 'testnet' | 'regtest' + network: 'mainnet' | 'testnet' | 'devnet' | 'mocknet' ): DbPox2EventData | null { const decoded = decodeClarityValue(rawClarityData); if (decoded.type_id === ClarityTypeID.ResponseError) { @@ -216,7 +215,7 @@ export function decodePox2PrintEvent( | ClarityValueOptionalNone; const encodedArr = tryClarityPoxAddressToBtcAddress(eventPoxAddr, network); baseEventData.pox_addr = encodedArr.btcAddr; - baseEventData.pox_addr_raw = bufferToHexPrefixString(encodedArr.raw); + baseEventData.pox_addr_raw = bufferToHex(encodedArr.raw); } switch (eventName) { diff --git a/src/event-stream/reader.ts b/src/event-stream/reader.ts index cca558e797..58107ffe17 100644 --- a/src/event-stream/reader.ts +++ b/src/event-stream/reader.ts @@ -1,9 +1,7 @@ import { BurnchainOp, - CoreNodeBlockMessage, CoreNodeEvent, CoreNodeEventType, - CoreNodeMicroblockTxMessage, CoreNodeParsedTxMessage, CoreNodeTxMessage, FtMintEvent, @@ -43,8 +41,6 @@ import { NotImplementedError } from '../errors'; import { getEnumDescription, I32_MAX, - bufferToHexPrefixString, - hexToBuffer, SubnetContractIdentifer, getChainIDNetwork, ChainID, @@ -53,15 +49,12 @@ import { import { TransactionVersion, uintCV, - tupleCV, bufferCV, serializeCV, noneCV, someCV, OptionalCV, TupleCV, - BufferCV, - SomeCV, NoneCV, UIntCV, stringAsciiCV, @@ -70,9 +63,10 @@ import { import { poxAddressToTuple } from '@stacks/stacking'; import { c32ToB58 } from 'c32check'; import { decodePox2PrintEvent } from './pox2-event-parsing'; -import { Pox2ContractIdentifer, Pox2EventName } from '../pox-helpers'; +import { Pox2EventName } from '../pox-helpers'; import { principalCV } from '@stacks/transactions/dist/clarity/types/principalCV'; import { logger } from '../logger'; +import { bufferToHex, hexToBuffer } from '@hirosystems/api-toolkit'; export function getTxSenderAddress(tx: DecodedTxResult): string { const txSender = tx.auth.origin_condition.signer.address; @@ -128,9 +122,7 @@ function createSubnetTransactionFromL1RegisterAsset( const fnLenBuffer = Buffer.alloc(4); fnLenBuffer.writeUInt32BE(legacyClarityVals.length); const serializedClarityValues = legacyClarityVals.map(c => serializeCV(c)); - const rawFnArgs = bufferToHexPrefixString( - Buffer.concat([fnLenBuffer, ...serializedClarityValues]) - ); + const rawFnArgs = bufferToHex(Buffer.concat([fnLenBuffer, ...serializedClarityValues])); const clarityFnArgs = decodeClarityValueList(rawFnArgs); const tx: DecodedTxResult = { @@ -190,9 +182,7 @@ function createSubnetTransactionFromL1NftDeposit( const fnLenBuffer = Buffer.alloc(4); fnLenBuffer.writeUInt32BE(legacyClarityVals.length); const serializedClarityValues = legacyClarityVals.map(c => serializeCV(c)); - const rawFnArgs = bufferToHexPrefixString( - Buffer.concat([fnLenBuffer, ...serializedClarityValues]) - ); + const rawFnArgs = bufferToHex(Buffer.concat([fnLenBuffer, ...serializedClarityValues])); const clarityFnArgs = decodeClarityValueList(rawFnArgs); const tx: DecodedTxResult = { @@ -252,9 +242,7 @@ function createSubnetTransactionFromL1FtDeposit( const fnLenBuffer = Buffer.alloc(4); fnLenBuffer.writeUInt32BE(legacyClarityVals.length); const serializedClarityValues = legacyClarityVals.map(c => serializeCV(c)); - const rawFnArgs = bufferToHexPrefixString( - Buffer.concat([fnLenBuffer, ...serializedClarityValues]) - ); + const rawFnArgs = bufferToHex(Buffer.concat([fnLenBuffer, ...serializedClarityValues])); const clarityFnArgs = decodeClarityValueList(rawFnArgs); const tx: DecodedTxResult = { @@ -402,9 +390,7 @@ function createTransactionFromCoreBtcStxLockEvent( const fnLenBuffer = Buffer.alloc(4); fnLenBuffer.writeUInt32BE(legacyClarityVals.length); const serializedClarityValues = legacyClarityVals.map(c => serializeCV(c)); - const rawFnArgs = bufferToHexPrefixString( - Buffer.concat([fnLenBuffer, ...serializedClarityValues]) - ); + const rawFnArgs = bufferToHex(Buffer.concat([fnLenBuffer, ...serializedClarityValues])); const clarityFnArgs = decodeClarityValueList(rawFnArgs); const tx: DecodedTxResult = { @@ -500,9 +486,7 @@ function createTransactionFromCoreBtcDelegateStxEvent( const fnLenBuffer = Buffer.alloc(4); fnLenBuffer.writeUInt32BE(legacyClarityVals.length); const serializedClarityValues = legacyClarityVals.map(c => serializeCV(c)); - const rawFnArgs = bufferToHexPrefixString( - Buffer.concat([fnLenBuffer, ...serializedClarityValues]) - ); + const rawFnArgs = bufferToHex(Buffer.concat([fnLenBuffer, ...serializedClarityValues])); const clarityFnArgs = decodeClarityValueList(rawFnArgs); const tx: DecodedTxResult = { diff --git a/src/helpers.ts b/src/helpers.ts index 358c34ff90..41e30ee0c1 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,10 +1,8 @@ import { BufferCV, bufferCV, cvToHex, hexToCV, TupleCV, tupleCV } from '@stacks/transactions'; import BigNumber from 'bignumber.js'; import * as btc from 'bitcoinjs-lib'; -import { execSync } from 'child_process'; import * as dotenv from 'dotenv-flow'; import * as http from 'http'; -import { isArrayBufferView } from 'node:util/types'; import * as path from 'path'; import { isValidStacksAddress, stacksToBitcoinAddress } from 'stacks-encoding-native-js'; import * as stream from 'stream'; @@ -12,19 +10,11 @@ import * as ecc from 'tiny-secp256k1'; import * as util from 'util'; import { StacksCoreRpcClient } from './core-rpc/client'; import { DbEventTypeId } from './datastore/common'; -import { createHash } from 'node:crypto'; import { logger } from './logger'; +import { has0xPrefix, isDevEnv, numberToHex } from '@hirosystems/api-toolkit'; -export const isDevEnv = process.env.NODE_ENV === 'development'; -export const isTestEnv = process.env.NODE_ENV === 'test'; -export const isProdEnv = - process.env.NODE_ENV === 'production' || - process.env.NODE_ENV === 'prod' || - !process.env.NODE_ENV || - (!isTestEnv && !isDevEnv); export const apiDocumentationUrl = process.env.API_DOCS_URL; -export const APP_DIR = __dirname; export const REPO_DIR = path.dirname(__dirname); export const I32_MAX = 0x7fffffff; @@ -41,13 +31,9 @@ export function getIbdBlockHeight(): number | undefined { } } -export function sha256(content: string) { - return createHash('sha256').update(content).digest('hex'); -} - -function createEnumChecker( - enumVariable: { [key in T]: TEnumValue } -): (value: number) => value is TEnumValue { +function createEnumChecker(enumVariable: { + [key in T]: TEnumValue; +}): (value: number) => value is TEnumValue { // Create a set of valid enum number values. const enumValues = Object.values(enumVariable).filter(v => typeof v === 'number'); const enumValueSet = new Set(enumValues); @@ -364,35 +350,6 @@ export async function httpGetRequest(url: string, opts?: http.RequestOptions) { }); } -/** - * Parses a boolean string using conventions from CLI arguments, URL query params, and environmental variables. - * If the input is defined but empty string then true is returned. If the input is undefined or null than false is returned. - * For example, if the input comes from a CLI arg like `--enable_thing` or URL query param like `?enable_thing`, then - * this function expects to receive a defined but empty string, and returns true. - * Otherwise, it checks or values like `true`, `1`, `on`, `yes` (and the inverses). - * Throws if an unexpected input value is provided. - */ -export function parseArgBoolean(val: string | undefined | null): boolean { - if (typeof val === 'undefined' || val === null) { - return false; - } - switch (val.trim().toLowerCase()) { - case '': - case 'true': - case '1': - case 'on': - case 'yes': - return true; - case 'false': - case '0': - case 'off': - case 'no': - return false; - default: - throw new Error(`Cannot parse boolean from "${val}"`); - } -} - export function parsePort(portVal: number | string | undefined): number | undefined { if (portVal === undefined) { return undefined; @@ -419,105 +376,6 @@ export function unixEpochToIso(timestamp: number): string { } } -export function getCurrentGitTag(): string { - const tagEnvVar = (process.env.GIT_TAG || '').trim(); - if (tagEnvVar) { - return tagEnvVar; - } - - if (!isDevEnv && !isTestEnv) { - if (!tagEnvVar) { - const error = - 'Production requires the GIT_TAG env var to be set. Set `NODE_ENV=development` to use the current git tag'; - console.error(error); - throw new Error(error); - } - return tagEnvVar; - } - - try { - const gitTag = (execSync('git tag --points-at HEAD', { encoding: 'utf8' }) ?? '').trim(); - const gitCommit = (execSync('git rev-parse --short HEAD', { encoding: 'utf8' }) ?? '').trim(); - const result = gitTag || gitCommit; - if (!result) { - throw new Error('no git tag or commit hash available'); - } - return result; - } catch (error) { - console.error(error); - throw error; - } -} - -/** - * Encodes a buffer as a `0x` prefixed lower-case hex string. - * Returns an empty string if the buffer is zero length. - */ -export function bufferToHexPrefixString(buff: Buffer): string { - if (buff.length === 0) { - return ''; - } - return '0x' + buff.toString('hex'); -} - -/** - * Decodes a `0x` prefixed hex string to a buffer. - * @param hex - A hex string with a `0x` prefix. - */ -export function hexToBuffer(hex: string): Buffer { - if (hex.length === 0) { - return Buffer.alloc(0); - } - if (!hex.startsWith('0x')) { - throw new Error(`Hex string is missing the "0x" prefix: "${hex}"`); - } - if (hex.length % 2 !== 0) { - throw new Error(`Hex string is an odd number of digits: ${hex}`); - } - return Buffer.from(hex.substring(2), 'hex'); -} - -/** - * Decodes a hex string to a Buffer, trims the 0x-prefix if exists. - * If already a buffer, returns the input immediately. - */ -export function coerceToBuffer(hex: string | Buffer | ArrayBufferView): Buffer { - if (typeof hex === 'string') { - if (hex.startsWith('0x')) { - hex = hex.substring(2); - } - if (hex.length % 2 !== 0) { - throw new Error(`Hex string is an odd number of characters: ${hex}`); - } - if (!/^[0-9a-fA-F]*$/.test(hex)) { - throw new Error(`Hex string contains non-hexadecimal characters: ${hex}`); - } - return Buffer.from(hex, 'hex'); - } else if (Buffer.isBuffer(hex)) { - return hex; - } else if (isArrayBufferView(hex)) { - return Buffer.from(hex.buffer, hex.byteOffset, hex.byteLength); - } else { - throw new Error(`Cannot convert to Buffer, unexpected type: ${hex.constructor.name}`); - } -} - -export function hexToUtf8String(hex: string): string { - const buffer = hexToBuffer(hex); - return buffer.toString('utf8'); -} - -export function numberToHex(number: number, paddingBytes: number = 4): string { - let result = number.toString(16); - if (result.length % 2 > 0) { - result = '0' + result; - } - if (paddingBytes && result.length / 2 < paddingBytes) { - result = '00'.repeat(paddingBytes - result.length / 2) + result; - } - return '0x' + result; -} - export function unwrapOptional( val: T | null, onNullish?: () => string @@ -693,125 +551,6 @@ export async function getOrAddAsync( export type FoundOrNot = { found: true; result: T } | { found: false; result?: T }; -export function timeout(ms: number, abortController?: AbortController): Promise { - return new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - resolve(); - }, ms); - abortController?.signal.addEventListener( - 'abort', - () => { - clearTimeout(timeout); - reject(new Error(`Timeout aborted`)); - }, - { once: true } - ); - }); -} - -/** - * Set an execution time limit for a promise. - * @param promise - The promise being capped to `timeoutMs` max execution time - * @param timeoutMs - Timeout limit in milliseconds - * @param wait - If we should wait another `timeoutMs` period for `promise` to resolve - * @param waitHandler - If `wait` is `true`, this closure will be executed before waiting another `timeoutMs` cycle - * @returns `true` if `promise` ended gracefully, `false` if timeout was reached - */ -export async function resolveOrTimeout( - promise: Promise, - timeoutMs: number, - wait: boolean = false, - waitHandler?: () => void -) { - let timer: NodeJS.Timeout; - const result = await Promise.race([ - new Promise((resolve, reject) => { - promise - .then(() => resolve(true)) - .catch(error => reject(error)) - .finally(() => clearTimeout(timer)); - }), - new Promise((resolve, _) => { - timer = setInterval(() => { - if (!wait) { - clearTimeout(timer); - resolve(false); - return; - } - if (waitHandler) { - waitHandler(); - } - }, timeoutMs); - }), - ]); - return result; -} - -export type Waiter = Promise & { - finish: (result: T) => void; - isFinished: boolean; -}; - -export function waiter(): Waiter { - let resolveFn: (result: T) => void; - const promise = new Promise(resolve => { - resolveFn = resolve; - }); - const completer = { - finish: (result: T) => { - completer.isFinished = true; - resolveFn(result); - }, - isFinished: false, - }; - return Object.assign(promise, completer); -} - -export interface Stopwatch { - /** Milliseconds since stopwatch was created. */ - getElapsed: () => number; - /** Seconds since stopwatch was created. */ - getElapsedSeconds: () => number; - getElapsedAndRestart: () => number; - restart(): void; -} - -export function stopwatch(): Stopwatch { - let start = process.hrtime.bigint(); - const result: Stopwatch = { - getElapsedSeconds: () => { - const elapsedMs = result.getElapsed(); - return elapsedMs / 1000; - }, - getElapsed: () => { - const end = process.hrtime.bigint(); - return Number((end - start) / 1_000_000n); - }, - getElapsedAndRestart: () => { - const end = process.hrtime.bigint(); - const result = Number((end - start) / 1_000_000n); - start = process.hrtime.bigint(); - return result; - }, - restart: () => { - start = process.hrtime.bigint(); - }, - }; - return result; -} - -export async function time( - fn: () => Promise, - onFinish: (elapsedMs: number) => void -): Promise { - const watch = stopwatch(); - try { - return await fn(); - } finally { - onFinish(watch.getElapsed()); - } -} - /** * Escape a string for use as a css selector name. * From https://github.com/mathiasbynens/CSS.escape/blob/master/css.escape.js @@ -887,8 +626,6 @@ export function cssEscape(value: string): string { return result; } -export const has0xPrefix = (id: string) => id.substr(0, 2).toLowerCase() === '0x'; - /** * Check if the input is a valid 32-byte hex string. If valid, returns a * lowercase and 0x-prefixed hex string. If invalid, returns false. @@ -919,7 +656,8 @@ export function parseDataUrl( if (url.protocol !== 'data:') { return false; } - const validDataUrlRegex = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()|~`]+)*)?(;base64)?,(.*)$/i; + const validDataUrlRegex = + /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()|~`]+)*)?(;base64)?,(.*)$/i; const parts = validDataUrlRegex.exec(s.trim()); if (parts === null) { return false; diff --git a/src/import-v1/index.ts b/src/import-v1/index.ts index 7acb01d369..327e0de4d0 100644 --- a/src/import-v1/index.ts +++ b/src/import-v1/index.ts @@ -16,9 +16,9 @@ import { } from '../datastore/common'; import { asyncBatchIterate, asyncIterableToGenerator, I32_MAX, REPO_DIR } from '../helpers'; import { BnsGenesisBlock, getBnsGenesisBlockFromBlockMessage } from '../event-replay/helpers'; -import { PgSqlClient } from '../datastore/connection'; import { PgWriteStore } from '../datastore/pg-write-store'; import { logger } from '../logger'; +import { PgSqlClient } from '@hirosystems/api-toolkit'; const finished = util.promisify(stream.finished); const pipeline = util.promisify(stream.pipeline); diff --git a/src/index.ts b/src/index.ts index 83516e234b..0e94cc7c9f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,5 @@ import { loadDotEnv, - timeout, - isProdEnv, - numberToHex, - parseArgBoolean, getApiConfiguredChainID, getStacksNodeChainID, chainIdConfigurationCheck, @@ -14,7 +10,6 @@ import { startProfilerServer } from './inspector-util'; import { startEventServer } from './event-stream/event-server'; import { StacksCoreRpcClient } from './core-rpc/client'; import { createServer as createPrometheusServer } from '@promster/server'; -import { registerShutdownConfig } from './shutdown-handler'; import { OfflineDummyStore } from './datastore/offline-dummy-store'; import { Socket } from 'net'; import * as getopts from 'getopts'; @@ -28,6 +23,13 @@ import { TokensProcessorQueue } from './token-metadata/tokens-processor-queue'; import { registerMempoolPromStats } from './datastore/helpers'; import { logger } from './logger'; import { ReplayController } from './event-replay/parquet-based/replay-controller'; +import { + isProdEnv, + numberToHex, + parseBoolean, + registerShutdownConfig, + timeout, +} from '@hirosystems/api-toolkit'; enum StacksApiMode { /** @@ -65,10 +67,10 @@ function getApiMode(): StacksApiMode { break; } // Make sure we're backwards compatible if `STACKS_API_MODE` is not specified. - if (parseArgBoolean(process.env['STACKS_READ_ONLY_MODE'])) { + if (parseBoolean(process.env['STACKS_READ_ONLY_MODE'])) { return StacksApiMode.readOnly; } - if (parseArgBoolean(process.env['STACKS_API_OFFLINE_MODE'])) { + if (parseBoolean(process.env['STACKS_API_OFFLINE_MODE'])) { return StacksApiMode.offline; } return StacksApiMode.default; @@ -144,7 +146,7 @@ async function init(): Promise { forceKillable: false, }); - const skipChainIdCheck = parseArgBoolean(process.env['SKIP_STACKS_CHAIN_ID_CHECK']); + const skipChainIdCheck = parseBoolean(process.env['SKIP_STACKS_CHAIN_ID_CHECK']); if (!skipChainIdCheck) { const networkChainId = await getStacksNodeChainID(); if (networkChainId !== configuredChainID) { diff --git a/src/inspector-util.ts b/src/inspector-util.ts index eb41fa1c7e..be456661af 100644 --- a/src/inspector-util.ts +++ b/src/inspector-util.ts @@ -4,13 +4,14 @@ import { once } from 'events'; import { createServer, Server } from 'http'; import * as express from 'express'; import { asyncHandler } from './api/async-handler'; -import { parsePort, stopwatch, timeout, pipelineAsync, Stopwatch } from './helpers'; +import { parsePort, pipelineAsync } from './helpers'; import { Socket } from 'net'; import * as os from 'os'; import * as path from 'path'; import * as fs from 'fs'; -import { createProfiler, startProfiler, stopProfiler } from 'stacks-encoding-native-js'; +import { startProfiler, stopProfiler } from 'stacks-encoding-native-js'; import { logger } from './logger'; +import { stopwatch, Stopwatch, timeout } from '@hirosystems/api-toolkit'; type CpuProfileResult = inspector.Profiler.Profile; @@ -283,9 +284,7 @@ function initHeapSnapshot( return { start, stop, dispose, session, sessionType: 'memory', stopwatch: sw }; } -export async function startProfilerServer( - httpServerPort?: number | string -): Promise<{ +export async function startProfilerServer(httpServerPort?: number | string): Promise<{ server: Server; address: string; close: () => Promise; @@ -443,7 +442,9 @@ export async function startProfilerServer( const elapsedSeconds = existingSession.instance.stopwatch.getElapsedSeconds(); const timestampSeconds = Math.round(Date.now() / 1000); const filename = `cpu_${timestampSeconds}_${elapsedSeconds}-seconds.cpuprofile`; - const result = await (existingSession.instance as ProfilerInstance).stop(); + const result = await ( + existingSession.instance as ProfilerInstance + ).stop(); const resultString = JSON.stringify(result); logger.info( `[CpuProfiler] Completed, total profile report JSON string length: ${resultString.length}` diff --git a/src/rosetta-helpers.ts b/src/rosetta-helpers.ts index 945903d4f6..50cb6f9f6b 100644 --- a/src/rosetta-helpers.ts +++ b/src/rosetta-helpers.ts @@ -55,7 +55,7 @@ import { StxUnlockEvent, } from './datastore/common'; import { getTxSenderAddress, getTxSponsorAddress } from './event-stream/reader'; -import { unwrapOptional, hexToBuffer, getSendManyContract } from './helpers'; +import { unwrapOptional, getSendManyContract } from './helpers'; import { getCoreNodeEndpoint } from './core-rpc/client'; import { TokenMetadataErrorMode } from './token-metadata/tokens-contract-handler'; @@ -81,6 +81,7 @@ import { isFtMetadataEnabled, tokenMetadataErrorMode } from './token-metadata/he import { poxAddressToBtcAddress } from '@stacks/stacking'; import { parseRecoverableSignatureVrs } from '@stacks/common'; import { logger } from './logger'; +import { hexToBuffer } from '@hirosystems/api-toolkit'; enum CoinAction { CoinSpent = 'coin_spent', diff --git a/src/shutdown-handler.ts b/src/shutdown-handler.ts deleted file mode 100644 index 58e1a84714..0000000000 --- a/src/shutdown-handler.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { resolveOrTimeout } from './helpers'; -import { logger } from './logger'; - -const SHUTDOWN_SIGNALS = ['SIGINT', 'SIGTERM'] as const; - -type ShutdownHandler = () => void | PromiseLike; -type ShutdownConfig = { - name: string; - handler: ShutdownHandler; - forceKillable: boolean; - forceKillHandler?: ShutdownHandler; -}; - -const shutdownConfigs: ShutdownConfig[] = []; - -let isShuttingDown = false; - -async function startShutdown() { - if (isShuttingDown) { - return; - } - isShuttingDown = true; - const timeoutMs = parseInt(process.env['STACKS_SHUTDOWN_FORCE_KILL_TIMEOUT'] ?? '60') * 1000; - let errorEncountered = false; - for (const config of shutdownConfigs) { - try { - logger.info(`Closing ${config.name}...`); - const gracefulShutdown = await resolveOrTimeout( - Promise.resolve(config.handler()), - timeoutMs, - !config.forceKillable, - () => - logger.error( - `${config.name} is taking longer than expected to shutdown, possibly hanging indefinitely` - ) - ); - if (!gracefulShutdown) { - if (config.forceKillable && config.forceKillHandler) { - await Promise.resolve(config.forceKillHandler()); - } - logger.error( - `${config.name} was force killed after taking longer than ${timeoutMs}ms to shutdown` - ); - } else { - logger.info(`${config.name} closed`); - } - } catch (error) { - errorEncountered = true; - logger.error(`Error running ${config.name} shutdown handler`, error); - } - } - if (errorEncountered) { - process.exit(1); - } else { - logger.info('App shutdown successful.'); - process.exit(); - } -} - -let shutdownSignalsRegistered = false; -function registerShutdownSignals() { - if (shutdownSignalsRegistered) { - return; - } - shutdownSignalsRegistered = true; - - SHUTDOWN_SIGNALS.forEach(sig => { - process.once(sig, () => { - logger.info(`Shutting down... received signal: ${sig}`); - void startShutdown(); - }); - }); - process.once('unhandledRejection', error => { - logger.error(error, 'unhandledRejection'); - logger.error(`Shutting down... received unhandledRejection.`); - void startShutdown(); - }); - process.once('uncaughtException', error => { - logger.error(`Received uncaughtException: ${error}`, error); - logger.error(`Shutting down... received uncaughtException.`); - void startShutdown(); - }); - process.once('beforeExit', () => { - logger.info(`Shutting down... received beforeExit.`); - void startShutdown(); - }); -} - -export function registerShutdownConfig(...configs: ShutdownConfig[]) { - registerShutdownSignals(); - shutdownConfigs.push(...configs); -} diff --git a/src/test-utils/shared-setup.ts b/src/test-utils/shared-setup.ts index 1e9ffc62fb..b842d1276d 100644 --- a/src/test-utils/shared-setup.ts +++ b/src/test-utils/shared-setup.ts @@ -1,6 +1,5 @@ -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { StacksCoreRpcClient } from '../core-rpc/client'; -import { loadDotEnv, timeout } from '../helpers'; +import { loadDotEnv } from '../helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; import { DummyEventMessageHandler, @@ -9,6 +8,8 @@ import { } from '../event-stream/event-server'; import { ChainID } from '@stacks/common'; import * as isCI from 'is-ci'; +import { migrate } from './test-helpers'; +import { timeout } from '@hirosystems/api-toolkit'; interface GlobalTestEnv { db: PgWriteStore; @@ -42,7 +43,7 @@ export async function defaultSetupInit( process.env.PG_DATABASE = 'postgres'; process.env.STACKS_CHAIN_ID = '0x80000000'; - await cycleMigrations(); + await migrate('up'); const db = await PgWriteStore.connect({ usageName: 'tests' }); const eventServer = await startEventServer({ datastore: db, @@ -64,7 +65,7 @@ export async function defaultSetupTeardown() { const testEnv: GlobalTestEnv = (global as any).globalTestEnv; await testEnv.eventServer.closeAsync(); await testEnv.db.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); // If running in CI setup the "why am I still running?" log to detect stuck Jest tests if (isCI) { diff --git a/src/test-utils/test-builders.ts b/src/test-utils/test-builders.ts index 700dbe790f..b7f165a393 100644 --- a/src/test-utils/test-builders.ts +++ b/src/test-utils/test-builders.ts @@ -30,7 +30,7 @@ import { } from '../datastore/common'; import { bufferCV, bufferCVFromString, serializeCV, uintCV } from '@stacks/transactions'; import { createClarityValueArray } from '../stacks-encoding-helpers'; -import { bufferToHexPrefixString } from '../helpers'; +import { bufferToHex } from '@hirosystems/api-toolkit'; // Default values when none given. Useful when they are irrelevant for a particular test. const BLOCK_HEIGHT = 1; @@ -211,7 +211,7 @@ function testTx(args?: TestTxArgs): DataStoreTxEventData { sponsor_address: undefined, sender_address: args?.sender_address ?? SENDER_ADDRESS, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), coinbase_alt_recipient: args?.coinbase_alt_recipient, event_count: 0, parent_index_block_hash: args?.parent_index_block_hash ?? INDEX_BLOCK_HASH, @@ -295,8 +295,7 @@ export function testMempoolTx(args?: TestMempoolTxArgs): DbMempoolTxRaw { contract_call_contract_id: args?.contract_call_contract_id ?? CONTRACT_ID, contract_call_function_name: args?.contract_call_function_name ?? CONTRACT_CALL_FUNCTION_NAME, contract_call_function_args: - args?.contract_call_function_args ?? - bufferToHexPrefixString(createClarityValueArray(uintCV(123456))), + args?.contract_call_function_args ?? bufferToHex(createClarityValueArray(uintCV(123456))), }; } @@ -362,9 +361,7 @@ function testNftEvent(args?: TestNftEventArgs): DbNftEvent { sender: args?.sender, // No default as this can be undefined. tx_id: args?.tx_id ?? TX_ID, tx_index: args?.tx_index ?? 0, - value: - args?.value ?? - bufferToHexPrefixString(Buffer.from(serializeCV(bufferCV(Buffer.from([2051]))))), + value: args?.value ?? bufferToHex(Buffer.from(serializeCV(bufferCV(Buffer.from([2051]))))), }; } @@ -428,9 +425,7 @@ function testSmartContractLogEvent(args?: TestSmartContractLogEventArgs): DbSmar event_type: DbEventTypeId.SmartContractLog, contract_identifier: args?.contract_identifier ?? CONTRACT_ID, topic: args?.topic ?? 'some-topic', - value: - args?.value ?? - bufferToHexPrefixString(Buffer.from(serializeCV(bufferCVFromString('some val')))), + value: args?.value ?? bufferToHex(Buffer.from(serializeCV(bufferCVFromString('some val')))), }; } diff --git a/src/test-utils/test-helpers.ts b/src/test-utils/test-helpers.ts index ea64513600..4e70d5696a 100644 --- a/src/test-utils/test-helpers.ts +++ b/src/test-utils/test-helpers.ts @@ -49,8 +49,14 @@ import { CoreRpcPoxInfo, StacksCoreRpcClient } from '../core-rpc/client'; import { DbBlock, DbTx, DbTxStatus } from '../datastore/common'; import { PgWriteStore } from '../datastore/pg-write-store'; import { BitcoinAddressFormat, ECPair, getBitcoinAddressFromKey } from '../ec-helpers'; -import { I32_MAX, coerceToBuffer, hexToBuffer, timeout } from '../helpers'; import { b58ToC32 } from 'c32check'; +import { coerceToBuffer, hexToBuffer, runMigrations, timeout } from '@hirosystems/api-toolkit'; +import { MIGRATIONS_DIR } from '../datastore/pg-store'; +import { getConnectionArgs } from '../datastore/connection'; + +export async function migrate(direction: 'up' | 'down') { + await runMigrations(MIGRATIONS_DIR, direction, getConnectionArgs()); +} export interface TestEnvContext { db: PgWriteStore; @@ -594,9 +600,7 @@ export async function stackStxWithRosetta(opts: { }; } -export function decodePoxAddrArg( - argHex: string -): { +export function decodePoxAddrArg(argHex: string): { btcAddr: string; stxAddr: string; hash160: string; @@ -610,7 +614,7 @@ export function decodePoxAddrArg( const btcAddr = poxAddressToBtcAddress( hexToBuffer(addressCV.data.version.buffer)[0], hexToBuffer(addressCV.data.hashbytes.buffer), - 'regtest' + 'mocknet' ); const stxAddr = b58ToC32(btcAddr); return { btcAddr, stxAddr, hash160: addressCV.data.hashbytes.buffer }; diff --git a/src/tests-2.4/global-setup.ts b/src/tests-2.4/global-setup.ts index e989445f77..2ab33c8fb7 100644 --- a/src/tests-2.4/global-setup.ts +++ b/src/tests-2.4/global-setup.ts @@ -1,11 +1,10 @@ -import { loadDotEnv, timeout } from '../helpers'; +import { loadDotEnv } from '../helpers'; import { StacksCoreRpcClient } from '../core-rpc/client'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { EventStreamServer, startEventServer } from '../event-stream/event-server'; -import { ApiServer, startApiServer } from '../api/init'; import { ChainID } from '@stacks/transactions'; -import { StacksNetwork, StacksTestnet } from '@stacks/network'; +import { migrate } from '../test-utils/test-helpers'; +import { timeout } from '@hirosystems/api-toolkit'; export interface GlobalTestEnv { db: PgWriteStore; @@ -41,7 +40,7 @@ export default async (): Promise => { process.env.PG_DATABASE = 'postgres'; process.env.STACKS_CHAIN_ID = '0x80000000'; - await cycleMigrations(); + await migrate('up'); const db = await PgWriteStore.connect({ usageName: 'tests' }); const eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); diff --git a/src/tests-2.4/global-teardown.ts b/src/tests-2.4/global-teardown.ts index 861975b64f..abfa739b23 100644 --- a/src/tests-2.4/global-teardown.ts +++ b/src/tests-2.4/global-teardown.ts @@ -1,3 +1,4 @@ +import { migrate } from '../test-utils/test-helpers'; import type { GlobalTestEnv } from './global-setup'; // ts-unused-exports:disable-next-line @@ -5,6 +6,7 @@ export default async (): Promise => { console.log('Jest - global teardown..'); const testEnv: GlobalTestEnv = (global as any).globalTestEnv; + await migrate('down'); await testEnv.eventServer.closeAsync(); await testEnv.db.close(); diff --git a/src/tests-2.4/pox-3-btc-address-formats.ts b/src/tests-2.4/pox-3-btc-address-formats.ts index da9afc8a80..1a80bf4592 100644 --- a/src/tests-2.4/pox-3-btc-address-formats.ts +++ b/src/tests-2.4/pox-3-btc-address-formats.ts @@ -12,15 +12,14 @@ import { testnetKeys } from '../api/routes/debug'; import { CoreRpcPoxInfo } from '../core-rpc/client'; import { DbEventTypeId, DbStxLockEvent } from '../datastore/common'; import { getBitcoinAddressFromKey, privateToPublicKey, VerboseKeyOutput } from '../ec-helpers'; -import { hexToBuffer } from '../helpers'; import { fetchGet, - standByForNextPoxCycle, standByForPoxCycle, standByForTxSuccess, standByUntilBurnBlock, testEnv, } from '../test-utils/test-helpers'; +import { hexToBuffer } from '@hirosystems/api-toolkit'; describe('PoX-3 - Stack using supported bitcoin address formats', () => { test('Standby for next cycle', async () => { diff --git a/src/tests-2.4/pox-3-burnchain-delegate-stx.ts b/src/tests-2.4/pox-3-burnchain-delegate-stx.ts index 723dcde3d4..4d1fa5e813 100644 --- a/src/tests-2.4/pox-3-burnchain-delegate-stx.ts +++ b/src/tests-2.4/pox-3-burnchain-delegate-stx.ts @@ -14,8 +14,8 @@ import { } from '@stacks/transactions'; import { testnetKeys } from '../api/routes/debug'; import { StacksCoreRpcClient } from '../core-rpc/client'; -import { ECPair, getBitcoinAddressFromKey } from '../ec-helpers'; -import { BootContractAddress, timeout } from '../helpers'; +import { ECPair } from '../ec-helpers'; +import { BootContractAddress } from '../helpers'; import { Account, accountFromKey, @@ -37,7 +37,8 @@ import { RPCClient } from 'rpc-bitcoin'; import * as supertest from 'supertest'; import { Pox2ContractIdentifer } from '../pox-helpers'; import { ClarityValueUInt, decodeClarityValue } from 'stacks-encoding-native-js'; -import { decodeBtcAddress, poxAddressToBtcAddress } from '@stacks/stacking'; +import { decodeBtcAddress } from '@stacks/stacking'; +import { timeout } from '@hirosystems/api-toolkit'; // Perform Delegate-STX operation on Bitcoin. // See https://github.com/stacksgov/sips/blob/a7f2e58ec90c12ee1296145562eec75029b89c48/sips/sip-015/sip-015-network-upgrade.md#new-burnchain-transaction-delegate-stx @@ -374,8 +375,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { type: '(optional uint)', }, { - hex: - '0x0a0c000000020968617368627974657302000000204d4daaf0776c1bbeb4c6bb14e7499acc72c250bde7146ef79c8b051eb4cb85930776657273696f6e020000000106', + hex: '0x0a0c000000020968617368627974657302000000204d4daaf0776c1bbeb4c6bb14e7499acc72c250bde7146ef79c8b051eb4cb85930776657273696f6e020000000106', repr: expectedPoxPayoutAddrRepr, name: 'pox-addr', type: '(optional (tuple (hashbytes (buff 32)) (version (buff 1))))', diff --git a/src/tests-2.4/pox-3-burnchain-stack-stx.ts b/src/tests-2.4/pox-3-burnchain-stack-stx.ts index b93de53f9e..d129bdbc9c 100644 --- a/src/tests-2.4/pox-3-burnchain-stack-stx.ts +++ b/src/tests-2.4/pox-3-burnchain-stack-stx.ts @@ -9,11 +9,10 @@ import { AnchorMode, makeSTXTokenTransfer } from '@stacks/transactions'; import { testnetKeys } from '../api/routes/debug'; import { StacksCoreRpcClient } from '../core-rpc/client'; import { ECPair } from '../ec-helpers'; -import { BootContractAddress, timeout } from '../helpers'; +import { BootContractAddress } from '../helpers'; import { Account, accountFromKey, - decodePoxAddrArg, fetchGet, getRosettaAccountBalance, standByForTxSuccess, @@ -29,9 +28,9 @@ import { ApiServer } from '../api/init'; import { StacksNetwork } from '@stacks/network'; import { RPCClient } from 'rpc-bitcoin'; import * as supertest from 'supertest'; -import { Pox2ContractIdentifer } from '../pox-helpers'; import { ClarityValueUInt, decodeClarityValue } from 'stacks-encoding-native-js'; import { decodeBtcAddress } from '@stacks/stacking'; +import { timeout } from '@hirosystems/api-toolkit'; // Perform Stack-STX operation on Bitcoin. // See https://github.com/stacksgov/sips/blob/0da29c6911c49c45e4125dbeaed58069854591eb/sips/sip-007/sip-007-stacking-consensus.md#stx-operations-on-bitcoin diff --git a/src/tests-2.4/pox-3-rosetta-segwit.ts b/src/tests-2.4/pox-3-rosetta-segwit.ts index 9cbd6d707b..c878423635 100644 --- a/src/tests-2.4/pox-3-rosetta-segwit.ts +++ b/src/tests-2.4/pox-3-rosetta-segwit.ts @@ -13,7 +13,6 @@ import bignumber from 'bignumber.js'; import { testnetKeys } from '../api/routes/debug'; import { CoreRpcPoxInfo } from '../core-rpc/client'; import { ECPair, getBitcoinAddressFromKey } from '../ec-helpers'; -import { hexToBuffer } from '../helpers'; import { fetchGet, getRosettaAccountBalance, @@ -26,6 +25,7 @@ import { standByUntilBurnBlock, testEnv, } from '../test-utils/test-helpers'; +import { hexToBuffer } from '@hirosystems/api-toolkit'; describe('PoX-3 - Rosetta - Stacking with segwit', () => { let btcAddr: string; diff --git a/src/tests-2.4/pox-3-stack-extend-increase.ts b/src/tests-2.4/pox-3-stack-extend-increase.ts index 0f9e0c9ac0..ba18676e09 100644 --- a/src/tests-2.4/pox-3-stack-extend-increase.ts +++ b/src/tests-2.4/pox-3-stack-extend-increase.ts @@ -11,7 +11,6 @@ import { import { AnchorMode, bufferCV, makeContractCall, tupleCV, uintCV } from '@stacks/transactions'; import bignumber from 'bignumber.js'; import { DbEventTypeId, DbStxLockEvent } from '../datastore/common'; -import { hexToBuffer } from '../helpers'; import { fetchGet, standByForPoxCycle, @@ -20,6 +19,7 @@ import { testEnv, } from '../test-utils/test-helpers'; import { decodeBtcAddress } from '@stacks/stacking'; +import { hexToBuffer } from '@hirosystems/api-toolkit'; describe('PoX-3 - Stack extend and increase operations', () => { const account = testnetKeys[1]; @@ -66,12 +66,10 @@ describe('PoX-3 - Stack extend and increase operations', () => { label: btcRegtestAccount.address, rescan: false, }); - const btcWalletAddrs: Record< - string, - unknown - > = await testEnv.bitcoinRpcClient.getaddressesbylabel({ - label: btcRegtestAccount.address, - }); + const btcWalletAddrs: Record = + await testEnv.bitcoinRpcClient.getaddressesbylabel({ + label: btcRegtestAccount.address, + }); const expectedAddrs = { P2PKH: getBitcoinAddressFromKey({ diff --git a/src/tests-bns-e2e/bns-integration-tests.ts b/src/tests-bns-e2e/bns-integration-tests.ts index dc776ea63c..0b6cfff928 100644 --- a/src/tests-bns-e2e/bns-integration-tests.ts +++ b/src/tests-bns-e2e/bns-integration-tests.ts @@ -17,7 +17,6 @@ import { import { logger } from '../logger'; import { testnetKeys } from '../api/routes/debug'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { runMigrations } from '../datastore/migrations'; import { standByForTx as standByForTxShared } from '../test-utils/test-helpers'; function hash160(bfr: Buffer): Buffer { @@ -27,7 +26,9 @@ function hash160(bfr: Buffer): Buffer { return Buffer.from(hash160, 'hex'); } -const network = new StacksMocknet(); +const network = new StacksMocknet({ + url: `http://${process.env['STACKS_BLOCKCHAIN_API_HOST']}:${process.env['STACKS_BLOCKCHAIN_API_PORT']}`, +}); const deployedTo = 'ST000000000000000000002AMW42H'; const deployedName = 'bns'; @@ -331,11 +332,15 @@ describe('BNS integration tests', () => { } beforeAll(async () => { - process.env.PG_DATABASE = 'postgres'; db = await PgWriteStore.connect({ usageName: 'tests', skipMigrations: true }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterAll(async () => { + await api.terminate(); + await db?.close(); + }); + test('name-import/ready/update contract call', async () => { const namespace = 'name-import'; const name = 'alice'; @@ -595,10 +600,4 @@ describe('BNS integration tests', () => { expect(query3.type).toBe('application/json'); expect(query3.body.expire_block > prevExpiration).toBe(true); }); - - afterAll(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-bns/api.ts b/src/tests-bns/api.ts index b581687156..28438175c1 100644 --- a/src/tests-bns/api.ts +++ b/src/tests-bns/api.ts @@ -6,9 +6,9 @@ import * as StacksTransactions from '@stacks/transactions'; import { ChainID } from '@stacks/transactions'; import { bnsNameCV, I32_MAX } from '../helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; import { TestBlockBuilder, TestMicroblockStreamBuilder } from '../test-utils/test-builders'; +import { migrate } from '../test-utils/test-helpers'; +import { PgSqlClient } from '@hirosystems/api-toolkit'; const nameSpaceExpected = { type: StacksTransactions.ClarityType.ResponseOk, @@ -50,8 +50,7 @@ describe('BNS API tests', () => { let dbBlock: DbBlock; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests' }); client = db.sql; api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); @@ -163,6 +162,12 @@ describe('BNS API tests', () => { ); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('Success: namespaces', async () => { const query1 = await supertest(api.server).get(`/v1/namespaces`); expect(query1.status).toBe(200); @@ -1182,10 +1187,4 @@ describe('BNS API tests', () => { expect(query.body.address).toEqual(addr2); expect(query.body.last_txid).toEqual('0xf111'); }) - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-bns/event-server-tests.ts b/src/tests-bns/event-server-tests.ts index d01703375f..b84f3b3569 100644 --- a/src/tests-bns/event-server-tests.ts +++ b/src/tests-bns/event-server-tests.ts @@ -4,10 +4,8 @@ import { EventStreamServer, startEventServer } from '../event-stream/event-serve import { TestBlockBuilder, TestMicroblockStreamBuilder } from '../test-utils/test-builders'; import { DbAssetEventTypeId, DbBnsZoneFile } from '../datastore/common'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; -import { getGenesisBlockData } from '../event-replay/helpers'; -import { NextFunction } from 'express'; +import { PgSqlClient } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('BNS event server tests', () => { let db: PgWriteStore; @@ -15,8 +13,7 @@ describe('BNS event server tests', () => { let eventServer: EventStreamServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: true }); client = db.sql; eventServer = await startEventServer({ @@ -30,7 +27,7 @@ describe('BNS event server tests', () => { afterEach(async () => { await eventServer.closeAsync(); await db?.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); }); test('namespace-ready called by a contract other than BNS', async () => { diff --git a/src/tests-bns/v1-import-tests.ts b/src/tests-bns/v1-import-tests.ts index 2a178725e5..cb67dfaf39 100644 --- a/src/tests-bns/v1-import-tests.ts +++ b/src/tests-bns/v1-import-tests.ts @@ -7,7 +7,7 @@ import { TestBlockBuilder } from '../test-utils/test-builders'; import { DataStoreBlockUpdateData } from '../datastore/common'; import { BnsGenesisBlock } from '../event-replay/helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; describe('BNS V1 import', () => { let db: PgWriteStore; @@ -15,8 +15,7 @@ describe('BNS V1 import', () => { let block: DataStoreBlockUpdateData; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests' }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); @@ -27,7 +26,7 @@ describe('BNS V1 import', () => { afterEach(async () => { await api.terminate(); await db?.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); }); test('v1-import', async () => { diff --git a/src/tests-btc-faucet/faucet-btc-tests.ts b/src/tests-btc-faucet/faucet-btc-tests.ts index 78bc9f2a5e..8d8dbad4ea 100644 --- a/src/tests-btc-faucet/faucet-btc-tests.ts +++ b/src/tests-btc-faucet/faucet-btc-tests.ts @@ -12,7 +12,7 @@ import { ApiServer, startApiServer } from '../api/init'; import { ChainID } from '@stacks/transactions'; import { PgStore } from '../datastore/pg-store'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; async function getBalanceWithWalletImport(address: string): Promise { const client = getRpcClient(); @@ -107,9 +107,9 @@ describe('btc faucet', () => { let db: PgStore; let writeDb: PgWriteStore; const OLD_ENV = process.env; + beforeAll(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgStore.connect({ usageName: 'tests', withNotifier: false }); writeDb = await PgWriteStore.connect({ usageName: 'tests', @@ -123,6 +123,14 @@ describe('btc faucet', () => { }); }); + afterAll(async () => { + process.env = OLD_ENV; + await apiServer.terminate(); + await db?.close(); + await writeDb?.close(); + await migrate('down'); + }); + test('faucet http receive endpoint', async () => { const addr = getKeyAddress(ECPair.makeRandom({ network: regtest })); const response = await supertest(apiServer.server).post( @@ -161,13 +169,5 @@ describe('btc faucet', () => { const resJson = JSON.parse(response.text); expect(resJson.error).toBe('BTC Faucet is not configured.'); }); - - afterAll(async () => { - process.env = OLD_ENV; - await apiServer.terminate(); - await db?.close(); - await writeDb?.close(); - await runMigrations(undefined, 'down'); - }); }); }); diff --git a/src/tests-btc-faucet/setup.ts b/src/tests-btc-faucet/setup.ts index 54d6dc83fe..c3d10b9cf7 100644 --- a/src/tests-btc-faucet/setup.ts +++ b/src/tests-btc-faucet/setup.ts @@ -1,5 +1,6 @@ -import { loadDotEnv, timeout } from '../helpers'; +import { loadDotEnv } from '../helpers'; import { getRpcClient } from '../btc-faucet'; +import { timeout } from '@hirosystems/api-toolkit'; // ts-unused-exports:disable-next-line export default async () => { diff --git a/src/tests-event-replay/import-export-tests.ts b/src/tests-event-replay/import-export-tests.ts index ee6bd96e12..a5d52b7167 100644 --- a/src/tests-event-replay/import-export-tests.ts +++ b/src/tests-event-replay/import-export-tests.ts @@ -1,21 +1,19 @@ import { ChainID } from '@stacks/transactions'; import * as fs from 'fs'; -import { getBnsGenesisBlockFromBlockMessage, getGenesisBlockData } from '../event-replay/helpers'; -import { PgSqlClient } from '../datastore/connection'; -import { getPgClientConfig } from '../datastore/connection-legacy'; -import { databaseHasData, getRawEventRequests } from '../datastore/event-requests'; -import { cycleMigrations, dangerousDropAllTables, runMigrations } from '../datastore/migrations'; +import { getRawEventRequests } from '../event-replay/event-requests'; import { PgWriteStore } from '../datastore/pg-write-store'; import { exportEventsAsTsv, importEventsFromTsv } from '../event-replay/event-replay'; -import { IBD_PRUNABLE_ROUTES, startEventServer } from '../event-stream/event-server'; -import { getIbdBlockHeight, httpPostRequest } from '../helpers'; +import { startEventServer } from '../event-stream/event-server'; +import { httpPostRequest } from '../helpers'; import { useWithCleanup } from '../tests/test-helpers'; +import { migrate } from '../test-utils/test-helpers'; +import { PgSqlClient, dangerousDropAllTables, databaseHasData } from '@hirosystems/api-toolkit'; +import { getConnectionArgs } from '../datastore/connection'; describe('import/export tests', () => { let db: PgWriteStore; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -69,8 +67,7 @@ describe('import/export tests', () => { test('import with db wipe options', async () => { // Migrate first so we have some data. - const clientConfig = getPgClientConfig({ usageName: 'cycle-migrations' }); - await runMigrations(clientConfig, 'up', {}); + await migrate('up'); await expect( importEventsFromTsv('src/tests-event-replay/tsv/mocknet.tsv', 'archival', false, false) ).rejects.toThrowError('contains existing data'); @@ -88,21 +85,23 @@ describe('import/export tests', () => { }); test('db contains data', async () => { - const clientConfig = getPgClientConfig({ usageName: 'cycle-migrations' }); - await runMigrations(clientConfig, 'up', {}); + const args = getConnectionArgs(); + await migrate('up'); // Having tables counts as having data as this may change across major versions. - await expect(databaseHasData()).resolves.toBe(true); + await expect(databaseHasData(args)).resolves.toBe(true); // Dropping all tables removes everything. - await dangerousDropAllTables({ acknowledgePotentialCatastrophicConsequences: 'yes' }); - await expect(databaseHasData()).resolves.toBe(false); + await dangerousDropAllTables(args, { + acknowledgePotentialCatastrophicConsequences: 'yes', + }); + await expect(databaseHasData(args)).resolves.toBe(false); // Cycling migrations leaves the `pgmigrations` table. - await runMigrations(clientConfig, 'up', {}); - await runMigrations(clientConfig, 'down', {}); - await expect(databaseHasData()).resolves.toBe(true); - await expect(databaseHasData({ ignoreMigrationTables: true })).resolves.toBe(false); + await migrate('up'); + await migrate('down'); + await expect(databaseHasData(args)).resolves.toBe(true); + await expect(databaseHasData(args, { ignoreMigrationTables: true })).resolves.toBe(false); }); test('Bns import occurs (block 1 genesis)', async () => { @@ -141,8 +140,7 @@ describe('IBD', () => { let client: PgSqlClient; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -154,7 +152,7 @@ describe('IBD', () => { afterEach(async () => { process.env.IBD_MODE_UNTIL_BLOCK = undefined; await db?.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); }); const getIbdInterceptCountFromTsvEvents = async (): Promise => { diff --git a/src/tests-event-replay/poison-microblock-tests.ts b/src/tests-event-replay/poison-microblock-tests.ts index 73a40cbefa..dd6d0ef741 100644 --- a/src/tests-event-replay/poison-microblock-tests.ts +++ b/src/tests-event-replay/poison-microblock-tests.ts @@ -6,7 +6,6 @@ describe('poison microblock for height 80743', () => { let db: PgWriteStore; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, diff --git a/src/tests-event-replay/raw-event-request-tests.ts b/src/tests-event-replay/raw-event-request-tests.ts index dfa07f347c..4413fee747 100644 --- a/src/tests-event-replay/raw-event-request-tests.ts +++ b/src/tests-event-replay/raw-event-request-tests.ts @@ -1,13 +1,12 @@ import * as fs from 'fs'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { runMigrations } from '../datastore/migrations'; import { ChainID } from '@stacks/transactions'; import { httpPostRequest } from '../helpers'; import { EventStreamServer, startEventServer } from '../event-stream/event-server'; -import { cycleMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; -import { getRawEventRequests } from '../datastore/event-requests'; +import { getRawEventRequests } from '../event-replay/event-requests'; import { useWithCleanup } from '../tests/test-helpers'; +import { PgSqlClient } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('Events table', () => { let db: PgWriteStore; @@ -15,8 +14,7 @@ describe('Events table', () => { let eventServer: EventStreamServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false }); client = db.sql; eventServer = await startEventServer({ @@ -30,7 +28,7 @@ describe('Events table', () => { afterEach(async () => { await eventServer.closeAsync(); await db?.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); }); test('If there is an event request error, then the event will not be recorded in the events_observer_request table', async () => { diff --git a/src/tests-event-replay/setup.ts b/src/tests-event-replay/setup.ts index e87e72a18f..737c21ed32 100644 --- a/src/tests-event-replay/setup.ts +++ b/src/tests-event-replay/setup.ts @@ -7,5 +7,6 @@ export default (): void => { process.env.NODE_ENV = 'test'; } loadDotEnv(); + process.env.PG_DATABASE = 'postgres'; console.log('Jest - setup done'); }; diff --git a/src/tests-rosetta-cli-construction/setup.ts b/src/tests-rosetta-cli-construction/setup.ts index ec885da097..0b7b18df6e 100644 --- a/src/tests-rosetta-cli-construction/setup.ts +++ b/src/tests-rosetta-cli-construction/setup.ts @@ -12,6 +12,7 @@ export default async (): Promise => { process.env.NODE_ENV = 'test'; } loadDotEnv(); + process.env.PG_DATABASE = 'postgres'; const db = await PgWriteStore.connect({ skipMigrations: true, usageName: 'tests' }); const globalServices: GlobalServices = { db: db, diff --git a/src/tests-rosetta-cli-construction/teardown.ts b/src/tests-rosetta-cli-construction/teardown.ts index a92094ee48..5e8c1842e0 100644 --- a/src/tests-rosetta-cli-construction/teardown.ts +++ b/src/tests-rosetta-cli-construction/teardown.ts @@ -2,7 +2,7 @@ import type { GlobalServices } from './setup'; // ts-unused-exports:disable-next-line export default async (): Promise => { console.log('Jest - teardown..'); - const globalServices = (global as unknown) as GlobalServices; + const globalServices = global as unknown as GlobalServices; await globalServices.db.close(); console.log('Jest - teardown done'); }; diff --git a/src/tests-rosetta-cli-construction/validate-construction.ts b/src/tests-rosetta-cli-construction/validate-construction.ts index 3cb5c257f8..0bcea2fe94 100644 --- a/src/tests-rosetta-cli-construction/validate-construction.ts +++ b/src/tests-rosetta-cli-construction/validate-construction.ts @@ -11,12 +11,11 @@ import { import { StacksTestnet } from '@stacks/network'; import * as fs from 'fs'; import { StacksCoreRpcClient, getCoreNodeEndpoint } from '../core-rpc/client'; -import { timeout } from '../helpers'; import * as compose from 'docker-compose'; import * as path from 'path'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { runMigrations } from '../datastore/migrations'; -import { NonceJar, standByForTxSuccess } from '../test-utils/test-helpers'; +import { NonceJar, migrate, standByForTxSuccess } from '../test-utils/test-helpers'; +import { timeout } from '@hirosystems/api-toolkit'; const sender1 = { address: 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6', @@ -37,7 +36,7 @@ describe('Rosetta API', () => { let nonceJar: NonceJar; beforeAll(async () => { - process.env.PG_DATABASE = 'postgres'; + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests' }); eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); @@ -132,7 +131,7 @@ describe('Rosetta API', () => { await new Promise(resolve => eventServer.close(() => resolve(true))); await api.terminate(); await db?.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); }); }); diff --git a/src/tests-rosetta-cli-data/setup.ts b/src/tests-rosetta-cli-data/setup.ts index b686774eae..07e46a8df6 100644 --- a/src/tests-rosetta-cli-data/setup.ts +++ b/src/tests-rosetta-cli-data/setup.ts @@ -11,6 +11,7 @@ export default async (): Promise => { process.env.NODE_ENV = 'test'; } loadDotEnv(); + process.env.PG_DATABASE = 'postgres'; const db = await PgWriteStore.connect({ skipMigrations: true, usageName: 'tests' }); const globalServices: GlobalServices = { db: db, diff --git a/src/tests-rosetta-cli-data/teardown.ts b/src/tests-rosetta-cli-data/teardown.ts index a92094ee48..5e8c1842e0 100644 --- a/src/tests-rosetta-cli-data/teardown.ts +++ b/src/tests-rosetta-cli-data/teardown.ts @@ -2,7 +2,7 @@ import type { GlobalServices } from './setup'; // ts-unused-exports:disable-next-line export default async (): Promise => { console.log('Jest - teardown..'); - const globalServices = (global as unknown) as GlobalServices; + const globalServices = global as unknown as GlobalServices; await globalServices.db.close(); console.log('Jest - teardown done'); }; diff --git a/src/tests-rosetta-cli-data/validate-rosetta.ts b/src/tests-rosetta-cli-data/validate-rosetta.ts index 2446f11abc..1ae844e2ea 100644 --- a/src/tests-rosetta-cli-data/validate-rosetta.ts +++ b/src/tests-rosetta-cli-data/validate-rosetta.ts @@ -16,14 +16,13 @@ import { import { StacksTestnet } from '@stacks/network'; import * as fs from 'fs'; import { StacksCoreRpcClient, getCoreNodeEndpoint } from '../core-rpc/client'; -import { timeout, unwrapOptional } from '../helpers'; +import { unwrapOptional } from '../helpers'; import * as compose from 'docker-compose'; import * as path from 'path'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { runMigrations } from '../datastore/migrations'; import { EventStreamServer, startEventServer } from '../event-stream/event-server'; -import { NonceJar, standByForTxSuccess } from '../test-utils/test-helpers'; -import * as supertest from 'supertest'; +import { NonceJar, migrate, standByForTxSuccess } from '../test-utils/test-helpers'; +import { timeout } from '@hirosystems/api-toolkit'; const sender1 = { address: 'STF9B75ADQAVXQHNEQ6KGHXTG7JP305J2GRWF3A2', @@ -100,7 +99,7 @@ describe('Rosetta API', () => { let nonceJar: NonceJar; beforeAll(async () => { - process.env.PG_DATABASE = 'postgres'; + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests' }); eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); @@ -242,7 +241,7 @@ describe('Rosetta API', () => { await new Promise(resolve => eventServer.close(() => resolve())); await api.terminate(); await db?.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); }); }); diff --git a/src/tests-rosetta-construction/construction.ts b/src/tests-rosetta-construction/construction.ts index 12109483f8..4a6eacfa63 100644 --- a/src/tests-rosetta-construction/construction.ts +++ b/src/tests-rosetta-construction/construction.ts @@ -1,8 +1,6 @@ import { ApiServer, startApiServer } from '../api/init'; import * as supertest from 'supertest'; -import { startEventServer } from '../event-stream/event-server'; -import { Server } from 'net'; -import { DbBlock, DbTxRaw, DbTxStatus } from '../datastore/common'; +import { DbBlock } from '../datastore/common'; import * as assert from 'assert'; import { AnchorMode, @@ -27,7 +25,6 @@ import { UnsignedTokenTransferOptions, } from '@stacks/transactions'; import { StacksCoreRpcClient } from '../core-rpc/client'; -import { bufferToHexPrefixString, FoundOrNot, timeout } from '../helpers'; import { RosettaConstructionCombineRequest, RosettaConstructionCombineResponse, @@ -56,13 +53,14 @@ import { getStacksTestnetNetwork, testnetKeys } from '../api/routes/debug'; import { getSignature, getStacksNetwork } from '../rosetta-helpers'; import { makeSigHashPreSign, MessageSignature } from '@stacks/transactions'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { runMigrations } from '../datastore/migrations'; import { decodeBtcAddress } from '@stacks/stacking'; import { standByForPoxCycle, standByForTx as standByForTxShared, standByUntilBurnBlock, } from '../test-utils/test-helpers'; +import { bufferToHex, timeout } from '@hirosystems/api-toolkit'; +import { FoundOrNot } from '../helpers'; describe('Rosetta Construction', () => { let db: PgWriteStore; @@ -75,11 +73,15 @@ describe('Rosetta Construction', () => { process.env.PG_DATABASE = 'postgres'; process.env.STACKS_CHAIN_ID = '0x80000000'; db = await PgWriteStore.connect({ usageName: 'tests' }); - // eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); await new StacksCoreRpcClient().waitForConnection(60000); }); + afterAll(async () => { + await api.terminate(); + await db?.close(); + }); + /* rosetta construction api tests below */ test('construction/derive', async () => { @@ -591,7 +593,7 @@ describe('Rosetta Construction', () => { network: 'testnet', }, signed: true, - transaction: bufferToHexPrefixString(Buffer.from(testTransaction.serialize())), + transaction: bufferToHex(Buffer.from(testTransaction.serialize())), }; const result = await supertest(api.server).post(`/rosetta/v1/construction/parse`).send(request); @@ -636,7 +638,7 @@ describe('Rosetta Construction', () => { network: 'testnet', }, signed: false, - transaction: bufferToHexPrefixString(Buffer.from(testTransaction.serialize())), + transaction: bufferToHex(Buffer.from(testTransaction.serialize())), }; const result = await supertest(api.server).post(`/rosetta/v1/construction/parse`).send(request); @@ -2576,11 +2578,4 @@ describe('Rosetta Construction', () => { expect(queryResult.genesis_block_identifier).toEqual(expectResponse.genesis_block_identifier); }); }); - - afterAll(async () => { - // await new Promise(resolve => eventServer.close(() => resolve())); - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-rosetta/account-tests.ts b/src/tests-rosetta/account-tests.ts index f6196b1f83..4dbb795b3f 100644 --- a/src/tests-rosetta/account-tests.ts +++ b/src/tests-rosetta/account-tests.ts @@ -1,23 +1,27 @@ import * as supertest from 'supertest'; import { ChainID } from '@stacks/transactions'; -import { PoolClient } from 'pg'; import { ApiServer, startApiServer } from '../api/init'; import { TestBlockBuilder } from '../test-utils/test-builders'; import { DbAssetEventTypeId, DbFungibleTokenMetadata } from '../datastore/common'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; describe('/account tests', () => { let db: PgWriteStore; let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests' }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down') + }); + test('/account/balance - returns ft balances', async () => { process.env.STACKS_API_ENABLE_FT_METADATA = '1'; const addr1 = 'SP3WV3VC6GM1WF215SDHP0MESQ3BNXHB1N6TPB70S'; @@ -95,10 +99,4 @@ describe('/account tests', () => { } ]); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-rosetta/api.ts b/src/tests-rosetta/api.ts index fd2fff3dca..eaea9e563e 100644 --- a/src/tests-rosetta/api.ts +++ b/src/tests-rosetta/api.ts @@ -33,10 +33,9 @@ import { TestTxArgs, } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; -import { bufferToHexPrefixString } from '../helpers'; import * as nock from 'nock'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('Rosetta API', () => { let db: PgWriteStore; @@ -44,14 +43,19 @@ describe('Rosetta API', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; process.env.STACKS_CHAIN_ID = '0x80000000'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests' }); client = db.sql; api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('network/list', async () => { const query1 = await supertest(api.server).post(`/rosetta/v1/network/list`); expect(query1.status).toBe(200); @@ -380,7 +384,7 @@ describe('Rosetta API', () => { abi: undefined, token_transfer_recipient_address: 'STRYYQQ9M8KAF4NS7WNZQYY59X93XEKR31JP64CP', token_transfer_amount: 3852n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('test1234')).padEnd(70, '0'), + token_transfer_memo: bufferToHex(Buffer.from('test1234')).padEnd(70, '0'), } const data = new TestBlockBuilder(block).addTx(tx).build(); await db.update(data); @@ -1496,10 +1500,4 @@ describe('Rosetta API', () => { } expect(JSON.parse(result.text)).toEqual(expectResponse); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-rosetta/block-tests.ts b/src/tests-rosetta/block-tests.ts index 98e8b1504b..8d662355a4 100644 --- a/src/tests-rosetta/block-tests.ts +++ b/src/tests-rosetta/block-tests.ts @@ -5,21 +5,26 @@ import { TestBlockBuilder } from '../test-utils/test-builders'; import { DbAssetEventTypeId, DbFungibleTokenMetadata, DbTxTypeId } from '../datastore/common'; import { createClarityValueArray } from '../stacks-encoding-helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { bufferToHexPrefixString } from '../helpers'; import { principalCV } from '@stacks/transactions/dist/clarity/types/principalCV'; +import { migrate } from '../test-utils/test-helpers'; +import { bufferToHex } from '@hirosystems/api-toolkit'; describe('/block tests', () => { let db: PgWriteStore; let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests' }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('block/transaction - contract_call contains parsed metadata', async () => { const testContractAddr = 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y.hello-world'; const contractJsonAbi = { @@ -68,7 +73,7 @@ describe('/block tests', () => { sender_address: testContractAddr, contract_call_contract_id: testContractAddr, contract_call_function_name: 'test-contract-fn', - contract_call_function_args: bufferToHexPrefixString(createClarityValueArray(uintCV(123456), stringAsciiCV('hello'))), + contract_call_function_args: bufferToHex(createClarityValueArray(uintCV(123456), stringAsciiCV('hello'))), abi: JSON.stringify(contractJsonAbi), }) .build(); @@ -480,7 +485,7 @@ describe('/block tests', () => { sender_address: sendManyAddr, contract_call_contract_id: sendManyAddr, contract_call_function_name: 'send-many', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray( listCV([ tupleCV({ @@ -567,7 +572,7 @@ describe('/block tests', () => { sender_address: sendManyAddr, contract_call_contract_id: sendManyAddr, contract_call_function_name: 'send-stx-with-memo', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray( uintCV(2000), principalCV('SPG7RD94XW8HN5NS7V68YDJAY4PJVZ2KNY79Z518'), @@ -599,10 +604,4 @@ describe('/block tests', () => { expect(result2.operations[2].metadata).toEqual({ memo: 'memo-1' }); expect(result2.operations[3].metadata).toEqual({ memo: 'memo-1' }); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-rosetta/offline-api-tests.ts b/src/tests-rosetta/offline-api-tests.ts index 395b461a43..2887db0bb1 100644 --- a/src/tests-rosetta/offline-api-tests.ts +++ b/src/tests-rosetta/offline-api-tests.ts @@ -12,7 +12,6 @@ import { makeUnsignedContractCall, makeUnsignedSTXTokenTransfer, MessageSignature, - noneCV, pubKeyfromPrivKey, publicKeyToString, SignedTokenTransferOptions, @@ -24,7 +23,6 @@ import { UnsignedContractCallOptions, UnsignedTokenTransferOptions, } from '@stacks/transactions'; -import { bufferToHexPrefixString } from '../helpers'; import { RosettaConstructionCombineRequest, RosettaConstructionCombineResponse, @@ -52,9 +50,9 @@ import { OfflineDummyStore } from '../datastore/offline-dummy-store'; import { getStacksTestnetNetwork, testnetKeys } from '../api/routes/debug'; import { getSignature, getStacksNetwork, publicKeyToBitcoinAddress } from '../rosetta-helpers'; import * as nock from 'nock'; -import * as poxHelpers from '../pox-helpers'; import { PgStore } from '../datastore/pg-store'; import { decodeBtcAddress } from '@stacks/stacking'; +import { bufferToHex } from '@hirosystems/api-toolkit'; describe('Rosetta offline API', () => { let db: PgStore; @@ -67,6 +65,12 @@ describe('Rosetta offline API', () => { nock.enableNetConnect('127.0.0.1:3999'); }); + afterAll(async () => { + await api.terminate(); + nock.cleanAll(); + nock.enableNetConnect() + }); + test('Success: offline - network/list', async () => { const query1 = await supertest(api.server).post(`/rosetta/v1/network/list`); expect(query1.status).toBe(200); @@ -517,7 +521,7 @@ describe('Rosetta offline API', () => { network: 'testnet', }, signed: true, - transaction: bufferToHexPrefixString(Buffer.from(testTransaction.serialize())), + transaction: bufferToHex(Buffer.from(testTransaction.serialize())), }; const result = await supertest(api.server).post(`/rosetta/v1/construction/parse`).send(request); @@ -564,7 +568,7 @@ describe('Rosetta offline API', () => { network: 'testnet', }, signed: false, - transaction: bufferToHexPrefixString(Buffer.from(testTransaction.serialize())), + transaction: bufferToHex(Buffer.from(testTransaction.serialize())), }; const result = await supertest(api.server).post(`/rosetta/v1/construction/parse`).send(request); @@ -1210,12 +1214,4 @@ describe('Rosetta offline API', () => { expect(JSON.parse(result.text)).toEqual(expectedResponse); }); - - /* rosetta construction end */ - - afterAll(async () => { - await api.terminate(); - nock.cleanAll(); - nock.enableNetConnect() - }); }); diff --git a/src/tests-rosetta/setup.ts b/src/tests-rosetta/setup.ts index 808478e1b4..93c3db8c10 100644 --- a/src/tests-rosetta/setup.ts +++ b/src/tests-rosetta/setup.ts @@ -4,5 +4,6 @@ import { defaultSetupInit } from '../test-utils/shared-setup'; export default async () => { console.log('Jest - setup..'); await defaultSetupInit({dummyEventHandler: true}); + process.env.PG_DATABASE = 'postgres'; console.log('Jest - setup done'); }; diff --git a/src/tests-rpc/core-rpc-tests.ts b/src/tests-rpc/core-rpc-tests.ts index 729675447d..22c6009794 100644 --- a/src/tests-rpc/core-rpc-tests.ts +++ b/src/tests-rpc/core-rpc-tests.ts @@ -1,10 +1,4 @@ -import { PgWriteStore } from '../datastore/pg-write-store'; import { StacksCoreRpcClient } from '../core-rpc/client'; -import { ApiServer, startApiServer } from '../api/init'; -import { startEventServer } from '../event-stream/event-server'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { Server } from 'net'; -import { ChainID } from '@stacks/transactions'; describe('core RPC tests', () => { let client: StacksCoreRpcClient; @@ -38,8 +32,4 @@ describe('core RPC tests', () => { const fee = await client.getEstimatedTransferFee(); expect(fee).toBeTruthy(); }); - - afterAll(async () => { - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-subnets/global-setup.ts b/src/tests-subnets/global-setup.ts index bf7b40caf6..c659867d9d 100644 --- a/src/tests-subnets/global-setup.ts +++ b/src/tests-subnets/global-setup.ts @@ -1,11 +1,11 @@ -import { loadDotEnv, timeout } from '../helpers'; +import { loadDotEnv } from '../helpers'; import { StacksCoreRpcClient } from '../core-rpc/client'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations } from '../datastore/migrations'; import { EventStreamServer, startEventServer } from '../event-stream/event-server'; -import { ApiServer, startApiServer } from '../api/init'; import { ChainID } from '@stacks/transactions'; -import { StacksNetwork, StacksTestnet } from '@stacks/network'; +import { cycleMigrations, timeout } from '@hirosystems/api-toolkit'; +import { MIGRATIONS_DIR } from '../datastore/pg-store'; +import { getConnectionArgs } from '../datastore/connection'; export interface GlobalTestEnv { db: PgWriteStore; @@ -19,7 +19,6 @@ async function standByForInfoToBeReady(client: StacksCoreRpcClient): Promise => { process.env.STACKS_CHAIN_ID = '0x80000000'; const db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false }); - await cycleMigrations(); + await cycleMigrations(MIGRATIONS_DIR, getConnectionArgs()); const eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); const subnetClient = new StacksCoreRpcClient(); diff --git a/src/tests-subnets/subnet-tests.ts b/src/tests-subnets/subnet-tests.ts index 2e01761aeb..99e1814ee1 100644 --- a/src/tests-subnets/subnet-tests.ts +++ b/src/tests-subnets/subnet-tests.ts @@ -7,10 +7,6 @@ import { } from '@stacks/stacks-blockchain-api-types'; import * as supertest from 'supertest'; import { - Account, - accountFromKey, - fetchGet, - readOnlyFnCall, standByForTxSuccess, standByUntilBlock, standByUntilBurnBlock, @@ -23,7 +19,6 @@ import { contractPrincipalCV, makeContractCall, makeContractDeploy, - StacksTransaction, serializeCV, standardPrincipalCV, uintCV, @@ -34,11 +29,10 @@ import { cvToString, noneCV, } from '@stacks/transactions'; -import { testnetKeys } from '../api/routes/debug'; import { StacksCoreRpcClient } from '../core-rpc/client'; import { StacksTestnet } from '@stacks/network'; -import { timeout } from '../helpers'; import { ClarityTypeID, decodeClarityValue } from 'stacks-encoding-native-js'; +import { timeout } from '@hirosystems/api-toolkit'; describe('Subnets tests', () => { let l1Client: StacksCoreRpcClient; diff --git a/src/tests-tokens-metadata/tokens-metadata-tests.ts b/src/tests-tokens-metadata/tokens-metadata-tests.ts index b5335d8588..1bc4c23ff8 100644 --- a/src/tests-tokens-metadata/tokens-metadata-tests.ts +++ b/src/tests-tokens-metadata/tokens-metadata-tests.ts @@ -12,21 +12,18 @@ import * as fs from 'fs'; import { EventStreamServer, startEventServer } from '../event-stream/event-server'; import { getStacksTestnetNetwork } from '../rosetta-helpers'; import { StacksCoreRpcClient } from '../core-rpc/client'; -import { timeout, waiter, Waiter } from '../helpers'; import * as nock from 'nock'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { TokensProcessorQueue } from '../token-metadata/tokens-processor-queue'; import { performFetch } from '../token-metadata/helpers'; import { getPagingQueryLimit, ResourceType } from '../api/pagination'; -import { standByForTx as standByForTxShared } from '../test-utils/test-helpers'; +import { migrate, standByForTx as standByForTxShared } from '../test-utils/test-helpers'; import { logger } from '../logger'; +import { Waiter, waiter, timeout } from '@hirosystems/api-toolkit'; const deploymentAddr = 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6'; const pKey = 'cb3df38053d132895220b9ce471f6b676db5b9bf0b4adefb55f2118ece2478df01'; const stacksNetwork = getStacksTestnetNetwork(); -const HOST = 'localhost'; -const PORT = 20443; describe('tokens metadata tests', () => { let db: PgWriteStore; @@ -86,8 +83,7 @@ describe('tokens metadata tests', () => { } beforeAll(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', skipMigrations: true }); eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); @@ -102,6 +98,14 @@ describe('tokens metadata tests', () => { nock.cleanAll(); }); + afterAll(async () => { + await eventServer.closeAsync(); + tokensProcessorQueue.close(); + await api.forceKill(); + await db?.close(); + await migrate('down'); + }); + test('metadata disabled', async () => { process.env['STACKS_API_ENABLE_FT_METADATA'] = '0'; process.env['STACKS_API_ENABLE_NFT_METADATA'] = '0'; @@ -397,12 +401,4 @@ describe('tokens metadata tests', () => { }); }).rejects.toThrow(/network timeout/); }); - - afterAll(async () => { - await eventServer.closeAsync(); - tokensProcessorQueue.close(); - await api.forceKill(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests-tokens-strict/strict-mode-tests.ts b/src/tests-tokens-strict/strict-mode-tests.ts index d6f8467328..a57f94a875 100644 --- a/src/tests-tokens-strict/strict-mode-tests.ts +++ b/src/tests-tokens-strict/strict-mode-tests.ts @@ -11,8 +11,8 @@ import { DbTxTypeId } from '../datastore/common'; import { stringCV } from '@stacks/transactions/dist/clarity/types/stringCV'; import { getTokenMetadataFetchTimeoutMs } from '../token-metadata/helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { TokensProcessorQueue } from '../token-metadata/tokens-processor-queue'; +import { migrate } from '../test-utils/test-helpers'; const NFT_CONTRACT_ABI: ClarityAbi = { maps: [], @@ -112,8 +112,7 @@ describe('token metadata strict mode', () => { const contractTxId = '0x1f1f'; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false }); api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); @@ -139,6 +138,12 @@ describe('token metadata strict mode', () => { await db.update(block); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('retryable error increases retry_count', async () => { process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable const handler = new TokensContractHandler({ @@ -380,10 +385,4 @@ describe('token metadata strict mode', () => { expect(metadata.found).toBe(true); expect(metadata.result?.token_uri).toBe('http://indigo.com/nft.jpeg'); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/address-tests.ts b/src/tests/address-tests.ts index aec474394a..4e34f9d3fd 100644 --- a/src/tests/address-tests.ts +++ b/src/tests/address-tests.ts @@ -31,16 +31,16 @@ import { DbTx, } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { bufferToHexPrefixString, I32_MAX } from '../helpers'; +import { I32_MAX } from '../helpers'; import { TestBlockBuilder, testMempoolTx, TestMicroblockStreamBuilder, } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { createDbTxFromCoreMsg } from '../datastore/helpers'; -import { PgSqlClient } from '../datastore/connection'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('address tests', () => { let db: PgWriteStore; @@ -48,8 +48,7 @@ describe('address tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -59,6 +58,12 @@ describe('address tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('address transaction transfers', async () => { const testAddr1 = 'ST3J8EVYHVKH6XXPD61EE8XEHW4Y2K83861225AB1'; const testAddr2 = 'ST1HB64MAJ1MBV4CQ80GF01DZS4T1DSMX20ADCRA4'; @@ -100,7 +105,7 @@ describe('address tests', () => { tx_index: indexIdIndex, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), index_block_hash: block.index_block_hash, block_hash: block.block_hash, block_height: block.block_height, @@ -108,7 +113,7 @@ describe('address tests', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: BigInt(amount), - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: recipient, status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -175,7 +180,7 @@ describe('address tests', () => { tx_id: tx.tx_id, tx_index: tx.tx_index, block_height: tx.block_height, - value: bufferToHexPrefixString(Buffer.from(serializeCV(uintCV(amount)))), + value: bufferToHex(Buffer.from(serializeCV(uintCV(amount)))), recipient, sender, }; @@ -876,7 +881,7 @@ describe('address tests', () => { tx_index: indexIdIndex, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), index_block_hash: block.index_block_hash, block_hash: block.block_hash, block_height: block.block_height, @@ -884,7 +889,7 @@ describe('address tests', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: BigInt(amount), - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: recipient, status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -926,14 +931,14 @@ describe('address tests', () => { tx_index: 4, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), index_block_hash: block.index_block_hash, block_hash: block.block_hash, block_height: block.block_height, burn_block_time: block.burn_block_time, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -1145,7 +1150,7 @@ describe('address tests', () => { execution_cost_write_length: 0, contract_call_contract_id: testContractAddr, contract_call_function_name: 'test-contract-fn', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray(uintCV(123456), stringAsciiCV('hello')) ), abi: JSON.stringify(contractJsonAbi), @@ -2165,7 +2170,7 @@ describe('address tests', () => { tx_id: '0x521234', anchor_mode: 3, nonce: 1, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), type_id: DbTxTypeId.Coinbase, status: 1, post_conditions: '0x01f5', @@ -2175,7 +2180,7 @@ describe('address tests', () => { sender_address: senderAddress, sponsor_nonce: 3, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), pruned: false, receipt_time: 1616063078, }; @@ -2219,7 +2224,7 @@ describe('address tests', () => { tx_id: '0x52123456', anchor_mode: 3, nonce: 1, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), type_id: DbTxTypeId.Coinbase, status: 1, post_conditions: '0x01f5', @@ -2229,7 +2234,7 @@ describe('address tests', () => { sender_address: senderAddress, sponsor_nonce: 6, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), pruned: false, receipt_time: 1616063078, }; @@ -2316,7 +2321,7 @@ describe('address tests', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: 1n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: 'none', status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -2426,7 +2431,7 @@ describe('address tests', () => { parent_burn_block_time: 1626124935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: 1n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: 'none', status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -2578,7 +2583,7 @@ describe('address tests', () => { sponsor_address: undefined, origin_hash_mode: 1, token_transfer_amount: 50n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: contractId, event_count: 1, parent_index_block_hash: block2.block.index_block_hash, @@ -2835,10 +2840,4 @@ describe('address tests', () => { expect(json6.results.length).toEqual(4); expect(json6.results[0].tx_id).toEqual('0xffa1'); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index 5201937750..980093e012 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -9,11 +9,11 @@ import { DataStoreBlockUpdateData, } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { bufferToHexPrefixString, I32_MAX } from '../helpers'; +import { I32_MAX } from '../helpers'; import { TestBlockBuilder, TestMicroblockStreamBuilder } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('block tests', () => { let db: PgWriteStore; @@ -21,8 +21,7 @@ describe('block tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -32,6 +31,12 @@ describe('block tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('info block time', async () => { const query1 = await supertest(api.server).get(`/extended/v1/info/network_block_times`); expect(query1.status).toBe(200); @@ -92,7 +97,7 @@ describe('block tests', () => { burn_block_time: 1594647995, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -403,9 +408,9 @@ describe('block tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: true, @@ -433,9 +438,9 @@ describe('block tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000001', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: true, @@ -500,10 +505,4 @@ describe('block tests', () => { expect(blockQuery.body.execution_cost_write_count).toBe(3); expect(blockQuery.body.execution_cost_write_length).toBe(3); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/burnchain-tests.ts b/src/tests/burnchain-tests.ts index b0a3fc9ef3..b2b93bb5d5 100644 --- a/src/tests/burnchain-tests.ts +++ b/src/tests/burnchain-tests.ts @@ -3,8 +3,8 @@ import { ChainID } from '@stacks/transactions'; import { DbBurnchainReward, DbRewardSlotHolder } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; +import { PgSqlClient } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('burnchain tests', () => { let db: PgWriteStore; @@ -12,8 +12,7 @@ describe('burnchain tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -23,6 +22,12 @@ describe('burnchain tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('fetch reward slot holders', async () => { const slotHolder1: DbRewardSlotHolder = { canonical: true, @@ -466,10 +471,4 @@ describe('burnchain tests', () => { expect(JSON.parse(rewardResult.text)).toEqual(expectedResp1); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/cache-control-tests.ts b/src/tests/cache-control-tests.ts index 76c32ad48d..482884b1ed 100644 --- a/src/tests/cache-control-tests.ts +++ b/src/tests/cache-control-tests.ts @@ -3,13 +3,12 @@ import { ChainID } from '@stacks/transactions'; import { getBlockFromDataStore } from '../api/controllers/db-controller'; import { DbBlock, DbMicroblockPartial, DbTxRaw, DbTxStatus, DbTxTypeId } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { PoolClient } from 'pg'; -import { bufferToHexPrefixString, I32_MAX } from '../helpers'; +import { I32_MAX } from '../helpers'; import { parseIfNoneMatchHeader } from '../api/controllers/cache-controller'; import { TestBlockBuilder, testMempoolTx } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('cache-control tests', () => { let db: PgWriteStore; @@ -17,8 +16,7 @@ describe('cache-control tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -28,6 +26,12 @@ describe('cache-control tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('parse if-none-match header', () => { // Test various combinations of etags with and without weak-validation prefix, with and without // wrapping quotes, without and without spaces after commas. @@ -104,7 +108,7 @@ describe('cache-control tests', () => { burn_block_time: 1594647995, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -271,7 +275,7 @@ describe('cache-control tests', () => { sponsor_address: undefined, origin_hash_mode: 1, token_transfer_amount: 50n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: addr2, event_count: 1, parent_index_block_hash: block1.index_block_hash, @@ -634,10 +638,4 @@ describe('cache-control tests', () => { const etag5 = request11.headers['etag']; expect(etag2).not.toBe(etag5); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index aebdd03979..d08f864878 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -21,63 +21,22 @@ import { DbNonFungibleTokenMetadata, DbFungibleTokenMetadata, DbTx, - DataStoreTxEventData, } from '../datastore/common'; import { getBlocksWithMetadata, parseDbEvent } from '../api/controllers/db-controller'; import * as assert from 'assert'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { getPostgres, PgServer, PgSqlClient } from '../datastore/connection'; -import { bnsNameCV, bufferToHexPrefixString, I32_MAX } from '../helpers'; +import { bnsNameCV, I32_MAX } from '../helpers'; import { ChainID } from '@stacks/transactions'; import { TestBlockBuilder } from '../test-utils/test-builders'; -import { sqlTransactionContext } from '../datastore/pg-store'; - -function testEnvVars( - envVars: Record, - use: () => Promise -): Promise; -function testEnvVars(envVars: Record, use: () => void): void; -function testEnvVars( - envVars: Record, - use: () => void | Promise -): void | Promise { - const existing = Object.fromEntries( - Object.keys(envVars) - .filter(k => k in process.env) - .map(k => [k, process.env[k]]) - ); - const added = Object.keys(envVars).filter(k => !(k in process.env)); - Object.entries(envVars).forEach(([k, v]) => { - process.env[k] = v; - if (v === undefined) { - delete process.env[k]; - } - }); - const restoreEnvVars = () => { - added.forEach(k => delete process.env[k]); - Object.entries(existing).forEach(([k, v]) => (process.env[k] = v)); - }; - let runFn: void | Promise; - try { - runFn = use(); - if (runFn instanceof Promise) { - return runFn.finally(() => restoreEnvVars()); - } - } finally { - if (!(runFn instanceof Promise)) { - restoreEnvVars(); - } - } -} +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('postgres datastore', () => { let db: PgWriteStore; let client: PgSqlClient; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -86,245 +45,9 @@ describe('postgres datastore', () => { client = db.sql; }); - test('bytea column serialization', async () => { - const vectors = [ - { - from: '0x0001', - to: '0x0001', - }, - { - from: '0X0002', - to: '0x0002', - }, - { - from: '0xFfF3', - to: '0xfff3', - }, - { - from: Buffer.from('0004', 'hex'), - to: '0x0004', - }, - { - from: new Uint16Array(new Uint8Array([0x00, 0x05]).buffer), - to: '0x0005', - }, - { - from: '\\x0006', - to: '0x0006', - }, - { - from: '\\xfFf7', - to: '0xfff7', - }, - { - from: '\\x', - to: '0x', - }, - { - from: '', - to: '0x', - }, - { - from: Buffer.alloc(0), - to: '0x', - }, - ]; - await db.sql.begin(async sql => { - await sql` - CREATE TEMPORARY TABLE bytea_testing( - value bytea NOT NULL - ) ON COMMIT DROP - `; - for (const v of vectors) { - const query = await sql<{ value: string }[]>` - insert into bytea_testing (value) values (${v.from}) - returning value - `; - expect(query[0].value).toBe(v.to); - } - }); - const badInputs = ['0x123', '1234', '0xnoop', new Date(), 1234]; - for (const input of badInputs) { - const query = async () => - db.sql.begin(async sql => { - await sql` - CREATE TEMPORARY TABLE bytea_testing( - value bytea NOT NULL - ) ON COMMIT DROP - `; - return await sql`insert into bytea_testing (value) values (${input})`; - }); - await expect(query()).rejects.toThrow(); - } - }); - - test('postgres uri config', () => { - const uri = - 'postgresql://test_user:secret_password@database.server.com:3211/test_db?ssl=true¤tSchema=test_schema&application_name=test-conn-str'; - testEnvVars( - { - PG_CONNECTION_URI: uri, - PG_DATABASE: undefined, - PG_USER: undefined, - PG_PASSWORD: undefined, - PG_HOST: undefined, - PG_PORT: undefined, - PG_SSL: undefined, - PG_SCHEMA: undefined, - PG_APPLICATION_NAME: undefined, - }, - () => { - const sql = getPostgres({ usageName: 'tests' }); - expect(sql.options.database).toBe('test_db'); - expect(sql.options.user).toBe('test_user'); - expect(sql.options.pass).toBe('secret_password'); - expect(sql.options.host).toStrictEqual(['database.server.com']); - expect(sql.options.port).toStrictEqual([3211]); - expect(sql.options.ssl).toBe('true'); - expect(sql.options.connection.search_path).toBe('test_schema'); - expect(sql.options.connection.application_name).toBe('test-conn-str:tests'); - } - ); - }); - - test('postgres env var config', () => { - testEnvVars( - { - PG_CONNECTION_URI: undefined, - PG_DATABASE: 'pg_db_db1', - PG_USER: 'pg_user_user1', - PG_PASSWORD: 'pg_password_password1', - PG_HOST: 'pg_host_host1', - PG_PORT: '9876', - PG_SSL: 'true', - PG_SCHEMA: 'pg_schema_schema1', - PG_APPLICATION_NAME: 'test-env-vars', - PG_MAX_LIFETIME: '5', - PG_IDLE_TIMEOUT: '1', - }, - () => { - const sql = getPostgres({ usageName: 'tests' }); - expect(sql.options.database).toBe('pg_db_db1'); - expect(sql.options.user).toBe('pg_user_user1'); - expect(sql.options.pass).toBe('pg_password_password1'); - expect(sql.options.host).toStrictEqual(['pg_host_host1']); - expect(sql.options.port).toStrictEqual([9876]); - expect(sql.options.ssl).toBe(true); - expect(sql.options.max_lifetime).toBe(5); - expect(sql.options.idle_timeout).toBe(1); - expect(sql.options.connection.search_path).toBe('pg_schema_schema1'); - expect(sql.options.connection.application_name).toBe('test-env-vars:tests'); - } - ); - }); - - test('postgres primary env var config fallback', () => { - testEnvVars( - { - PG_CONNECTION_URI: undefined, - PG_DATABASE: 'pg_db_db1', - PG_USER: 'pg_user_user1', - PG_PASSWORD: 'pg_password_password1', - PG_HOST: 'pg_host_host1', - PG_PORT: '9876', - PG_SSL: 'true', - PG_SCHEMA: 'pg_schema_schema1', - PG_APPLICATION_NAME: 'test-env-vars', - PG_MAX_LIFETIME: '5', - PG_IDLE_TIMEOUT: '1', - // Primary values: - PG_PRIMARY_DATABASE: 'primary_db', - PG_PRIMARY_USER: 'primary_user', - PG_PRIMARY_PASSWORD: 'primary_password', - PG_PRIMARY_HOST: 'primary_host', - PG_PRIMARY_PORT: '9999', - }, - () => { - const sql = getPostgres({ usageName: 'tests', pgServer: PgServer.primary }); - // Primary values take precedence. - expect(sql.options.database).toBe('primary_db'); - expect(sql.options.user).toBe('primary_user'); - expect(sql.options.pass).toBe('primary_password'); - expect(sql.options.host).toStrictEqual(['primary_host']); - expect(sql.options.port).toStrictEqual([9999]); - // Other values come from defaults. - expect(sql.options.ssl).toBe(true); - expect(sql.options.max_lifetime).toBe(5); - expect(sql.options.idle_timeout).toBe(1); - expect(sql.options.connection.search_path).toBe('pg_schema_schema1'); - expect(sql.options.connection.application_name).toBe('test-env-vars:tests'); - } - ); - }); - - test('postgres connection application_name', async () => { - await testEnvVars( - { - PG_APPLICATION_NAME: 'test-app-name', - }, - async () => { - const testDb = await PgWriteStore.connect({ - usageName: 'test-usage-name', - skipMigrations: true, - }); - try { - const name = await testDb.getConnectionApplicationName(); - expect(name).toStrictEqual('test-app-name:test-usage-name;datastore-crud'); - } finally { - await testDb.close(); - } - } - ); - }); - - test('postgres conflicting config', () => { - const uri = - 'postgresql://test_user:secret_password@database.server.com:3211/test_db?ssl=true¤tSchema=test_schema'; - testEnvVars( - { - PG_CONNECTION_URI: uri, - PG_DATABASE: 'pg_db_db1', - PG_USER: 'pg_user_user1', - PG_PASSWORD: 'pg_password_password1', - PG_HOST: 'pg_host_host1', - PG_PORT: '9876', - PG_SSL: 'true', - PG_SCHEMA: 'pg_schema_schema1', - }, - () => { - expect(() => { - const config = getPostgres({ usageName: 'tests' }); - }).toThrowError(); - } - ); - }); - - test('postgres transaction connection integrity', async () => { - const usageName = 'stacks-blockchain-api:tests;datastore-crud'; - const obj = db.sql; - - expect(sqlTransactionContext.getStore()).toBeUndefined(); - await db.sqlTransaction(async sql => { - // Transaction flag is open. - expect(sqlTransactionContext.getStore()?.usageName).toBe(usageName); - // New connection object. - const newObj = sql; - expect(obj).not.toEqual(newObj); - expect(sqlTransactionContext.getStore()?.sql).toEqual(newObj); - - // Nested tx uses the same connection object. - await db.sqlTransaction(sql => { - expect(sqlTransactionContext.getStore()?.usageName).toBe(usageName); - expect(newObj).toEqual(sql); - }); - - // Getter returns the same connection object too. - expect(db.sql).toEqual(newObj); - }); - - // Back to normal. - expect(sqlTransactionContext.getStore()).toBeUndefined(); - expect(db.sql).toEqual(obj); + afterEach(async () => { + await db?.close(); + await migrate('down'); }); test('pg address STX balances', async () => { @@ -973,7 +696,7 @@ describe('postgres datastore', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: BigInt(amount), - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: recipient, status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -3439,7 +3162,7 @@ describe('postgres datastore', () => { type_id: DbTxTypeId.TokenTransfer, receipt_time: 123456, token_transfer_amount: 1n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: 'stx-recipient-addr', status: DbTxStatus.Pending, post_conditions: '0x', @@ -3711,7 +3434,7 @@ describe('postgres datastore', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 1, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -3746,7 +3469,7 @@ describe('postgres datastore', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -3943,7 +3666,7 @@ describe('postgres datastore', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 1, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -3978,7 +3701,7 @@ describe('postgres datastore', () => { sender_address: 'sender-addr', sponsor_address: undefined, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 1, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -4209,7 +3932,7 @@ describe('postgres datastore', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -4526,7 +4249,7 @@ describe('postgres datastore', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -4591,7 +4314,7 @@ describe('postgres datastore', () => { tx_index: 0, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('abc')), + raw_tx: bufferToHex(Buffer.from('abc')), index_block_hash: '0x1234', block_hash: '0x5678', block_height: block1.block_height, @@ -4607,7 +4330,7 @@ describe('postgres datastore', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -4687,7 +4410,7 @@ describe('postgres datastore', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 4, parent_index_block_hash: '0x00', parent_block_hash: '0x00', @@ -5261,9 +4984,4 @@ describe('postgres datastore', () => { db.getTxListDetails({ txIds: [], includeUnanchored: true }) ).resolves.not.toThrow(); }); - - afterEach(async () => { - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/git-info-script-tests.ts b/src/tests/git-info-script-tests.ts deleted file mode 100644 index 23ffa4e4ec..0000000000 --- a/src/tests/git-info-script-tests.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import * as os from 'os'; -import { spawnSync, execSync } from 'child_process'; - -describe('git info script', () => { - test('error when git repo data not available', () => { - const scriptFilePath = path.resolve('git-info-generator.mjs'); - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'stacks-api-test-')); - const result = spawnSync(`node "${scriptFilePath}"`, { - cwd: tempDir, - shell: true, - encoding: 'utf8', - }); - expect(result.status).toStrictEqual(1); - expect(result.stderr).toEqual(expect.stringContaining('not a git repository')); - }); - - test('error when no git tags found', () => { - const scriptFilePath = path.resolve('git-info-generator.mjs'); - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'stacks-api-test-')); - execSync( - 'git init && git config user.name test && git config user.email test && git commit --allow-empty -n -m test', - { cwd: tempDir } - ); - const result = spawnSync(`node "${scriptFilePath}"`, { - cwd: tempDir, - shell: true, - encoding: 'utf8', - }); - expect(result.status).toStrictEqual(1); - expect(result.stderr).toEqual(expect.stringContaining('no tag found')); - }); - - test('generates get info file correctly', () => { - const scriptFilePath = path.resolve('git-info-generator.mjs'); - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'stacks-api-test-')); - execSync( - 'git init && git config user.name test && git config user.email test && git commit --allow-empty -n -m test && git tag v1.2.3 && git branch -m my_branch', - { cwd: tempDir } - ); - const result = spawnSync(`node "${scriptFilePath}"`, { - cwd: tempDir, - shell: true, - encoding: 'utf8', - }); - expect(result.status).toStrictEqual(0); - const gitInfoFilePath = path.join(tempDir, '.git-info'); - expect(fs.existsSync(gitInfoFilePath)); - const gitInfoContent = fs.readFileSync(gitInfoFilePath, { encoding: 'utf8' }); - const gitInfoParts = gitInfoContent.split('\n'); - expect(gitInfoParts[0]).toStrictEqual('my_branch'); - expect(gitInfoParts[1]).toBeTruthy(); - expect(gitInfoParts[2]).toStrictEqual('v1.2.3'); - }); -}); diff --git a/src/tests/helpers-tests.ts b/src/tests/helpers-tests.ts index 43bd43e37b..6bd7ab9f0f 100644 --- a/src/tests/helpers-tests.ts +++ b/src/tests/helpers-tests.ts @@ -1,17 +1,12 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import * as c32check from 'c32check'; -import * as poxHelpers from '../pox-helpers'; import { bitcoinToStacksAddress, stacksToBitcoinAddress } from 'stacks-encoding-native-js'; import * as c32AddrCache from '../c32-addr-cache'; import { ADDR_CACHE_ENV_VAR } from '../c32-addr-cache'; -import { getCurrentGitTag, has0xPrefix, isValidBitcoinAddress } from '../helpers'; +import { isValidBitcoinAddress } from '../helpers'; import { ECPair, getBitcoinAddressFromKey } from '../ec-helpers'; import { decodeBtcAddress, poxAddressToBtcAddress } from '@stacks/stacking'; - -test('get git tag', () => { - const tag = getCurrentGitTag(); - expect(tag).toBeTruthy(); -}); +import { has0xPrefix } from '@hirosystems/api-toolkit'; describe('has0xPrefix()', () => { test('falsy case, where there be no 0x', () => { diff --git a/src/tests/import-genesis-tests.ts b/src/tests/import-genesis-tests.ts index 17a4aae0e5..fa26ae3b32 100644 --- a/src/tests/import-genesis-tests.ts +++ b/src/tests/import-genesis-tests.ts @@ -1,14 +1,13 @@ import { importV1TokenOfferingData } from '../import-v1'; import { bitcoinToStacksAddress } from 'stacks-encoding-native-js'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; describe('import genesis data tests', () => { let db: PgWriteStore; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -16,6 +15,11 @@ describe('import genesis data tests', () => { }); }); + afterEach(async () => { + await db?.close(); + await migrate('down'); + }); + test('import token offering data', async () => { const initialDbConfigState = await db.getConfigState(); expect(initialDbConfigState.token_offering_imported).toBe(false); @@ -39,11 +43,6 @@ describe('import genesis data tests', () => { const res4 = await db.getTokenOfferingLocked(addr4, 0); expect(res4?.result?.total_locked).toEqual('1666666664'); }); - - afterEach(async () => { - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); describe('fast b58 to c32 address conversion', () => { diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index c9df081521..d8d135d692 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1,9 +1,7 @@ import * as supertest from 'supertest'; import { ChainID } from '@stacks/transactions'; import { startApiServer, ApiServer } from '../api/init'; -import { PgSqlClient } from '../datastore/connection'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { DbBlock, DbTxRaw, @@ -12,13 +10,15 @@ import { DbTxStatus, DataStoreBlockUpdateData, } from '../datastore/common'; -import { bufferToHexPrefixString, I32_MAX } from '../helpers'; +import { I32_MAX } from '../helpers'; import { TestBlockBuilder, testMempoolTx, TestMicroblockStreamBuilder, } from '../test-utils/test-builders'; import { getPagingQueryLimit, ResourceType } from '../api/pagination'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('mempool tests', () => { let db: PgWriteStore; @@ -26,8 +26,7 @@ describe('mempool tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -40,7 +39,7 @@ describe('mempool tests', () => { afterEach(async () => { await api.terminate(); await db?.close(); - await runMigrations(undefined, 'down'); + await migrate('down'); }); test('garbage collection', async () => { @@ -152,11 +151,11 @@ describe('mempool tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, status: DbTxStatus.Pending, receipt_time: 1594307695, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: false, @@ -196,14 +195,14 @@ describe('mempool tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.VersionedSmartContract, status: DbTxStatus.Pending, receipt_time: 1594307695, smart_contract_clarity_version: 2, smart_contract_contract_id: 'some-versioned-smart-contract', smart_contract_source_code: '(some-versioned-contract-src)', - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: false, @@ -247,11 +246,11 @@ describe('mempool tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, status: DbTxStatus.Pending, receipt_time: 1594307695, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: true, @@ -292,11 +291,11 @@ describe('mempool tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, status: DbTxStatus.Pending, receipt_time: 1594307695, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: true, @@ -582,10 +581,10 @@ describe('mempool tests', () => { tx_id: `0x891200000000000000000000000000000000000000000000000000000000000${i}`, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, receipt_time: (new Date(`2020-07-09T15:14:0${i}Z`).getTime() / 1000) | 0, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, post_conditions: '0x01f5', fee_rate: 1234n, @@ -721,7 +720,7 @@ describe('mempool tests', () => { tx_id: `0x89120000000000000000000000000000000000000000000000000000000000${paddedIndex}`, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: xfer.type_id, receipt_time: (new Date(`2020-07-09T15:14:${paddedIndex}Z`).getTime() / 1000) | 0, status: 1, @@ -1197,7 +1196,7 @@ describe('mempool tests', () => { tx_id: '0x521234', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), type_id: DbTxTypeId.Coinbase, status: 1, post_conditions: '0x01f5', @@ -1206,7 +1205,7 @@ describe('mempool tests', () => { sponsor_address: undefined, sender_address: senderAddress, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), pruned: false, receipt_time: 1616063078, }; @@ -1224,7 +1223,7 @@ describe('mempool tests', () => { tx_id: '0x521234', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), type_id: DbTxTypeId.Coinbase, status: 1, post_conditions: '0x01f5', @@ -1233,7 +1232,7 @@ describe('mempool tests', () => { sponsor_address: undefined, sender_address: senderAddress, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), pruned: false, receipt_time: 1616063078, }; @@ -1269,7 +1268,7 @@ describe('mempool tests', () => { tx_id: '0x521234', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), type_id: DbTxTypeId.Coinbase, status: 1, post_conditions: '0x01f5', @@ -1278,7 +1277,7 @@ describe('mempool tests', () => { sponsor_address: undefined, sender_address: senderAddress, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), pruned: false, receipt_time: 1616063078, }; @@ -1504,7 +1503,7 @@ describe('mempool tests', () => { tx_id: txId, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), type_id: DbTxTypeId.Coinbase, status: 1, post_conditions: '0x01f5', @@ -1513,7 +1512,7 @@ describe('mempool tests', () => { sponsor_address: undefined, sender_address: senderAddress, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), pruned: false, receipt_time: 1616063078, }; diff --git a/src/tests/microblock-tests.ts b/src/tests/microblock-tests.ts index 2dde14047f..a6918d99ed 100644 --- a/src/tests/microblock-tests.ts +++ b/src/tests/microblock-tests.ts @@ -19,8 +19,7 @@ import { DbSmartContract, } from '../datastore/common'; import { startApiServer } from '../api/init'; -import { PgSqlClient } from '../datastore/connection'; -import { bufferToHexPrefixString, httpPostRequest, I32_MAX } from '../helpers'; +import { httpPostRequest, I32_MAX } from '../helpers'; import { AddressStxBalanceResponse, AddressStxInboundListResponse, @@ -39,17 +38,17 @@ import { startEventServer } from '../event-stream/event-server'; import * as fs from 'fs'; import { createClarityValueArray } from '../stacks-encoding-helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { getRawEventRequests } from '../datastore/event-requests'; +import { getRawEventRequests } from '../event-replay/event-requests'; import { logger } from '../logger'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('microblock tests', () => { let db: PgWriteStore; let client: PgSqlClient; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -58,6 +57,11 @@ describe('microblock tests', () => { client = db.sql; }); + afterEach(async () => { + await db?.close(); + await migrate('down'); + }); + test('microblock out of order events', async () => { // test that the event observer can ingest events with out of order microblocks await useWithCleanup( @@ -301,7 +305,7 @@ describe('microblock tests', () => { sponsor_address: undefined, sender_address: addr1, origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 1, parent_index_block_hash: block1.parent_index_block_hash, parent_block_hash: block1.parent_block_hash, @@ -347,7 +351,7 @@ describe('microblock tests', () => { event_type: DbEventTypeId.SmartContractLog, contract_identifier: contractAddr, topic: 'some-topic', - value: bufferToHexPrefixString(Buffer.from(serializeCV(bufferCVFromString('some val')))), + value: bufferToHex(Buffer.from(serializeCV(bufferCVFromString('some val')))), }; const smartContract1: DbSmartContract = { tx_id: tx1.tx_id, @@ -415,7 +419,7 @@ describe('microblock tests', () => { sponsor_address: undefined, origin_hash_mode: 1, token_transfer_amount: 50n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: addr2, event_count: 1, parent_index_block_hash: block1.index_block_hash, @@ -455,7 +459,7 @@ describe('microblock tests', () => { sponsor_address: undefined, origin_hash_mode: 1, token_transfer_amount: 50n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: addr2, event_count: 1, parent_index_block_hash: block1.index_block_hash, @@ -471,7 +475,7 @@ describe('microblock tests', () => { execution_cost_write_length: 0, contract_call_contract_id: contractAddr, contract_call_function_name: 'test-contract-fn', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray(uintCV(123456), stringAsciiCV('hello')) ), abi: JSON.stringify(contractJsonAbi), @@ -682,26 +686,19 @@ describe('microblock tests', () => { const addrStxInbound1 = await supertest(api.server).get( `/extended/v1/address/${addr2}/stx_inbound` ); - const { - body: addrStxInboundBody1, - }: { body: AddressStxInboundListResponse } = addrStxInbound1; + const { body: addrStxInboundBody1 }: { body: AddressStxInboundListResponse } = + addrStxInbound1; expect(addrStxInboundBody1.results).toHaveLength(0); const addrStxInbound2 = await supertest(api.server).get( `/extended/v1/address/${addr2}/stx_inbound?unanchored` ); - const { - body: addrStxInboundBody2, - }: { body: AddressStxInboundListResponse } = addrStxInbound2; + const { body: addrStxInboundBody2 }: { body: AddressStxInboundListResponse } = + addrStxInbound2; expect(addrStxInboundBody2.results).toHaveLength(1); expect(addrStxInboundBody2.results[0].tx_id).toBe(mbTx1.tx_id); expect(addrStxInboundBody2.results[0].amount).toBe(mbTxStxEvent1.amount.toString()); } ); }); - - afterEach(async () => { - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/other-tests.ts b/src/tests/other-tests.ts index 9b5f7dd8d2..bbd6ad784c 100644 --- a/src/tests/other-tests.ts +++ b/src/tests/other-tests.ts @@ -10,13 +10,13 @@ import { DbMinerReward, } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { bufferToHexPrefixString, I32_MAX, microStxToStx, STACKS_DECIMAL_PLACES } from '../helpers'; +import { I32_MAX, microStxToStx, STACKS_DECIMAL_PLACES } from '../helpers'; import { FEE_RATE } from '../api/routes/fee-rate'; import { FeeRateRequest } from 'docs/generated'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; import { getPagingQueryLimit, ResourceType } from '../api/pagination'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('other tests', () => { let db: PgWriteStore; @@ -24,8 +24,7 @@ describe('other tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -35,6 +34,12 @@ describe('other tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('stx-supply', async () => { const testAddr1 = 'testAddr1'; const dbBlock1: DbBlock = { @@ -68,7 +73,7 @@ describe('other tests', () => { burn_block_time: dbBlock1.burn_block_time, parent_burn_block_time: 0, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -305,10 +310,4 @@ describe('other tests', () => { const result = await supertest(api.server).get(`/extended/v1/block/`); expect(result.body.error).toBe('The database service is unavailable'); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/search-tests.ts b/src/tests/search-tests.ts index 32b0ee3b23..08961cbb5c 100644 --- a/src/tests/search-tests.ts +++ b/src/tests/search-tests.ts @@ -14,10 +14,10 @@ import { DataStoreBlockUpdateData, } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { bufferToHexPrefixString, I32_MAX } from '../helpers'; +import { I32_MAX } from '../helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('search tests', () => { let db: PgWriteStore; @@ -25,8 +25,7 @@ describe('search tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -36,6 +35,12 @@ describe('search tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('search term - hash', async () => { const block: DbBlock = { block_hash: '0x1234000000000000000000000000000000000000000000000000000000000000', @@ -69,7 +74,7 @@ describe('search tests', () => { burn_block_time: 2837565, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -98,10 +103,10 @@ describe('search tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, receipt_time: 123456, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, post_conditions: '0x01f5', fee_rate: 1234n, @@ -276,7 +281,7 @@ describe('search tests', () => { burn_block_time: 2837565, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -304,10 +309,10 @@ describe('search tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, receipt_time: 123456, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, post_conditions: '0x01f5', fee_rate: 1234n, @@ -607,7 +612,7 @@ describe('search tests', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: 1n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: 'none', status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -658,7 +663,7 @@ describe('search tests', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: 1n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + token_transfer_memo: bufferToHex(Buffer.from('test-raw-tx')), token_transfer_recipient_address: addr2, status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -927,7 +932,7 @@ describe('search tests', () => { tx_id: '0x1111882200000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), receipt_time: 123456, smart_contract_contract_id: contractAddr2, smart_contract_source_code: '(some-src)', @@ -1042,7 +1047,7 @@ describe('search tests', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: 1n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: 'none', status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -1079,7 +1084,7 @@ describe('search tests', () => { parent_burn_block_time: 1626122935, type_id: DbTxTypeId.TokenTransfer, token_transfer_amount: 1n, - token_transfer_memo: bufferToHexPrefixString(Buffer.from('hi')), + token_transfer_memo: bufferToHex(Buffer.from('hi')), token_transfer_recipient_address: addr2, status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 @@ -1533,7 +1538,7 @@ describe('search tests', () => { tx_id: '0x1111882200000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), receipt_time: 123456, smart_contract_contract_id: contractAddr2, smart_contract_source_code: '(some-src)', @@ -1627,10 +1632,4 @@ describe('search tests', () => { }; expect(JSON.parse(searchResult13.text)).toEqual(expectedResp13); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/smart-contract-tests.ts b/src/tests/smart-contract-tests.ts index f7096f22c3..195b5fe2b3 100644 --- a/src/tests/smart-contract-tests.ts +++ b/src/tests/smart-contract-tests.ts @@ -9,10 +9,10 @@ import { DbSmartContractEvent, } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { bufferToHexPrefixString, I32_MAX, waiter } from '../helpers'; +import { I32_MAX } from '../helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { PgSqlClient } from '../datastore/connection'; +import { bufferToHex, PgSqlClient, waiter } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('smart contract tests', () => { let db: PgWriteStore; @@ -20,8 +20,7 @@ describe('smart contract tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: true, @@ -31,6 +30,12 @@ describe('smart contract tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('list contract log events', async () => { const logEventWaiter = waiter<{ txId: string; eventIndex: number }>(); const handler = (txId: string, eventIndex: number) => @@ -82,7 +87,7 @@ describe('smart contract tests', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -104,7 +109,7 @@ describe('smart contract tests', () => { event_type: DbEventTypeId.SmartContractLog, contract_identifier: 'some-contract-id', topic: 'some-topic', - value: bufferToHexPrefixString(Buffer.from(serializeCV(bufferCVFromString('some val')))), + value: bufferToHex(Buffer.from(serializeCV(bufferCVFromString('some val')))), }; const smartContract1: DbSmartContract = { tx_id: '0x421234', @@ -438,7 +443,7 @@ describe('smart contract tests', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -460,7 +465,7 @@ describe('smart contract tests', () => { event_type: DbEventTypeId.SmartContractLog, contract_identifier: 'some-contract-id', topic: 'some-topic', - value: bufferToHexPrefixString(Buffer.from(serializeCV(bufferCVFromString('some val')))), + value: bufferToHex(Buffer.from(serializeCV(bufferCVFromString('some val')))), }; const contractJsonAbi = { maps: [], @@ -1700,10 +1705,4 @@ describe('smart contract tests', () => { ); expect(query.status).toBe(431); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/socket-io-tests.ts b/src/tests/socket-io-tests.ts index 2c381a6b65..c72cebdd21 100644 --- a/src/tests/socket-io-tests.ts +++ b/src/tests/socket-io-tests.ts @@ -2,7 +2,6 @@ import { io } from 'socket.io-client'; import { ChainID } from '@stacks/common'; import { ApiServer, startApiServer } from '../api/init'; import { DbAssetEventTypeId, DbTxStatus } from '../datastore/common'; -import { waiter, Waiter } from '../helpers'; import { Block, Microblock, @@ -18,15 +17,15 @@ import { TestMicroblockStreamBuilder, } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; +import { Waiter, waiter } from '@hirosystems/api-toolkit'; describe('socket-io', () => { let apiServer: ApiServer; let db: PgWriteStore; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', skipMigrations: true }); apiServer = await startApiServer({ datastore: db, @@ -34,6 +33,12 @@ describe('socket-io', () => { }); }); + afterEach(async () => { + await apiServer.terminate(); + await db?.close(); + await migrate('down'); + }); + test('socket-io > block updates', async () => { const address = apiServer.address; const socket = io(`http://${address}`, { @@ -543,10 +548,4 @@ describe('socket-io', () => { await disconnectWaiter; expect(disconnectReason).toBe('ping timeout'); }); - - afterEach(async () => { - await apiServer.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/synthetic-stx-txs-tests.ts b/src/tests/synthetic-stx-txs-tests.ts index c8e424a074..cd9b7dd278 100644 --- a/src/tests/synthetic-stx-txs-tests.ts +++ b/src/tests/synthetic-stx-txs-tests.ts @@ -164,8 +164,7 @@ describe('synthetic stx txs', () => { type_id: 1, }, { - hex: - '0x0c00000002096861736862797465730200000014e725a898f9fe204da28afb5cf7766602d1b30ad90776657273696f6e020000000101', + hex: '0x0c00000002096861736862797465730200000014e725a898f9fe204da28afb5cf7766602d1b30ad90776657273696f6e020000000101', repr: '(tuple (hashbytes 0xe725a898f9fe204da28afb5cf7766602d1b30ad9) (version 0x01))', type_id: 12, }, @@ -241,8 +240,7 @@ describe('synthetic stx txs', () => { type_id: 1, }, { - hex: - '0x0c00000002096861736862797465730200000014c23dc19a1ea61a205312b229c6bd4046bf15f3670776657273696f6e020000000101', + hex: '0x0c00000002096861736862797465730200000014c23dc19a1ea61a205312b229c6bd4046bf15f3670776657273696f6e020000000101', repr: '(tuple (hashbytes 0xc23dc19a1ea61a205312b229c6bd4046bf15f367) (version 0x01))', type_id: 12, }, diff --git a/src/tests/token-tests.ts b/src/tests/token-tests.ts index d93ee3026b..77572694c0 100644 --- a/src/tests/token-tests.ts +++ b/src/tests/token-tests.ts @@ -3,17 +3,15 @@ import { ChainID } from '@stacks/transactions'; import { ApiServer, startApiServer } from '../api/init'; import { TestBlockBuilder, TestMicroblockStreamBuilder } from '../test-utils/test-builders'; import { DbAssetEventTypeId } from '../datastore/common'; -import { hexToBuffer } from '../helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; describe('/extended/v1/tokens tests', () => { let db: PgWriteStore; let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -22,6 +20,12 @@ describe('/extended/v1/tokens tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('/nft/holdings', async () => { const addr1 = 'SP3BK1NNSWN719Z6KDW05RBGVS940YCN6X84STYPR'; const addr2 = 'SP466FNC0P7JWTNM2R9T199QRZN1MYEDTAR0KP27'; @@ -1007,10 +1011,4 @@ describe('/extended/v1/tokens tests', () => { expect(result11.results[0].value.hex).toEqual('0x01000000000000000000000000000009cb'); expect(result11.results[1].value.hex).toEqual('0x01000000000000000000000000000009ca'); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/tx-tests.ts b/src/tests/tx-tests.ts index 6dbbe30b0b..d56b7a35cf 100644 --- a/src/tests/tx-tests.ts +++ b/src/tests/tx-tests.ts @@ -37,13 +37,13 @@ import { DbStxEvent, } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { bufferToHexPrefixString, I32_MAX } from '../helpers'; +import { I32_MAX } from '../helpers'; import { TestBlockBuilder } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { createDbTxFromCoreMsg } from '../datastore/helpers'; -import { PgSqlClient } from '../datastore/connection'; import { getPagingQueryLimit, ResourceType } from '../api/pagination'; +import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; +import { migrate } from '../test-utils/test-helpers'; describe('tx tests', () => { let db: PgWriteStore; @@ -51,8 +51,7 @@ describe('tx tests', () => { let api: ApiServer; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -62,17 +61,23 @@ describe('tx tests', () => { api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); }); + afterEach(async () => { + await api.terminate(); + await db?.close(); + await migrate('down'); + }); + test('fetch tx list details', async () => { const mempoolTx: DbMempoolTxRaw = { pruned: false, tx_id: '0x8912000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, status: DbTxStatus.Pending, receipt_time: 1594307695, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: false, @@ -89,7 +94,7 @@ describe('tx tests', () => { tx_id: '0x8407751d1a8d11ee986aca32a6459d9cd798283a12e048ebafcd4cc7dadb29af', anchor_mode: DbTxAnchorMode.Any, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), canonical: true, microblock_canonical: true, microblock_sequence: 2147483647, @@ -151,9 +156,9 @@ describe('tx tests', () => { tx_id: '0x8915000000000000000000000000000000000000000000000000000000000000', anchor_mode: 3, nonce: 1000, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), post_conditions: '0x01f5', fee_rate: 1234n, sponsored: true, @@ -195,7 +200,7 @@ describe('tx tests', () => { tx_id: versionedSmartContract1.tx_id, anchor_mode: 3, nonce: 1000, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), type_id: DbTxTypeId.VersionedSmartContract, smart_contract_clarity_version: versionedSmartContract1.clarity_version ?? undefined, smart_contract_contract_id: versionedSmartContract1.contract_id, @@ -344,7 +349,7 @@ describe('tx tests', () => { const txPayload = tx.payload as TxPayloadVersionedSmartContract; const dbTx = createDbTxFromCoreMsg({ core_tx: { - raw_tx: bufferToHexPrefixString(versionedSmartContractTx), + raw_tx: bufferToHex(versionedSmartContractTx), status: 'success', raw_result: '0x0100000000000000000000000000000001', // u1 txid: tx.tx_id, @@ -362,7 +367,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(versionedSmartContractTx), + raw_tx: bufferToHex(versionedSmartContractTx), parsed_tx: tx, sender_address: tx.auth.origin_condition.signer.address, sponsor_address: undefined, @@ -491,7 +496,7 @@ describe('tx tests', () => { const tx = decodeTransaction(versionedSmartContractTx); const dbTx = createDbTxFromCoreMsg({ core_tx: { - raw_tx: bufferToHexPrefixString(versionedSmartContractTx), + raw_tx: bufferToHex(versionedSmartContractTx), status: 'success', raw_result: '0x0100000000000000000000000000000001', // u1 txid: tx.tx_id, @@ -509,7 +514,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(versionedSmartContractTx), + raw_tx: bufferToHex(versionedSmartContractTx), parsed_tx: tx, sender_address: tx.auth.origin_condition.signer.address, sponsor_address: undefined, @@ -628,7 +633,7 @@ describe('tx tests', () => { const tx = decodeTransaction(versionedSmartContractTx); const dbTx = createDbTxFromCoreMsg({ core_tx: { - raw_tx: bufferToHexPrefixString(versionedSmartContractTx), + raw_tx: bufferToHex(versionedSmartContractTx), status: 'success', raw_result: '0x0100000000000000000000000000000001', // u1 txid: tx.tx_id, @@ -646,7 +651,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(versionedSmartContractTx), + raw_tx: bufferToHex(versionedSmartContractTx), parsed_tx: tx, sender_address: tx.auth.origin_condition.signer.address, sponsor_address: undefined, @@ -794,7 +799,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), parsed_tx: tx, sender_address: 'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y', sponsor_address: 'SP2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7GB36ZAR0', @@ -1003,7 +1008,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), parsed_tx: tx, sender_address: address, sponsor_address: sponsoredAddress, @@ -1133,7 +1138,7 @@ describe('tx tests', () => { tx_index: 0, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), index_block_hash: dbBlock.index_block_hash, block_hash: dbBlock.block_hash, block_height: dbBlock.block_height, @@ -1154,7 +1159,7 @@ describe('tx tests', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -1379,7 +1384,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), parsed_tx: tx, sender_address: 'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y', sponsor_address: undefined, @@ -1600,7 +1605,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), parsed_tx: tx, sender_address: 'SP2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7GB36ZAR0', sponsor_address: undefined, @@ -1744,7 +1749,7 @@ describe('tx tests', () => { }, }, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), parsed_tx: tx, sender_address: 'SP2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7GB36ZAR0', sponsor_address: undefined, @@ -1862,7 +1867,7 @@ describe('tx tests', () => { tx_index: 0, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), index_block_hash: block.index_block_hash, block_hash: block.block_hash, block_height: block.block_height, @@ -1883,7 +1888,7 @@ describe('tx tests', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -1917,7 +1922,7 @@ describe('tx tests', () => { tx_id: '0x521234', anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), type_id: DbTxTypeId.Coinbase, status: 1, post_conditions: '0x01f5', @@ -1926,7 +1931,7 @@ describe('tx tests', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), pruned: false, receipt_time: 1616063078, }; @@ -1935,9 +1940,9 @@ describe('tx tests', () => { const searchResult1 = await supertest(api.server).get(`/extended/v1/tx/${tx.tx_id}/raw`); expect(searchResult1.status).toBe(200); expect(searchResult1.type).toBe('application/json'); - expect(searchResult1.body.raw_tx).toEqual(bufferToHexPrefixString(Buffer.from('test-raw-tx'))); + expect(searchResult1.body.raw_tx).toEqual(bufferToHex(Buffer.from('test-raw-tx'))); const expectedResponse1 = { - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), }; expect(JSON.parse(searchResult1.text)).toEqual(expectedResponse1); @@ -1977,7 +1982,7 @@ describe('tx tests', () => { tx_index: 0, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-tx')), + raw_tx: bufferToHex(Buffer.from('test-raw-tx')), index_block_hash: '0x1234', block_hash: block.block_hash, block_height: block.block_height, @@ -1998,7 +2003,7 @@ describe('tx tests', () => { sponsor_address: undefined, sender_address: 'sender-addr', origin_hash_mode: 1, - coinbase_payload: bufferToHexPrefixString(Buffer.from('hi')), + coinbase_payload: bufferToHex(Buffer.from('hi')), event_count: 0, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -2626,14 +2631,14 @@ describe('tx tests', () => { tx_index: 4, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), index_block_hash: block.index_block_hash, block_hash: block.block_hash, block_height: block.block_height, burn_block_time: 1594647995, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -2757,7 +2762,7 @@ describe('tx tests', () => { tx_id: '0x8407751d1a8d11ee986aca32a6459d9cd798283a12e048ebafcd4cc7dadb29af', anchor_mode: DbTxAnchorMode.Any, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), canonical: true, microblock_canonical: true, microblock_sequence: 2147483647, @@ -2786,7 +2791,7 @@ describe('tx tests', () => { execution_cost_write_length: 339, contract_call_contract_id: 'SP3YK7KWMYRCDMV5M4792T0T7DERQXHJJGGEPV1N8.pg-mdomains-v1', contract_call_function_name: 'bns-name-preorder', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray(bufferCV(Buffer.from('test')), uintCV(1234n)) ), }; @@ -2795,7 +2800,7 @@ describe('tx tests', () => { tx_id: '0x1513739d6a3f86d4597f5296cc536f6890e2affff9aece285e37399be697b43f', anchor_mode: DbTxAnchorMode.Any, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), canonical: true, microblock_canonical: true, microblock_sequence: 2147483647, @@ -2824,7 +2829,7 @@ describe('tx tests', () => { execution_cost_write_length: 339, contract_call_contract_id: 'SP000000000000000000002Q6VF78.bns', contract_call_function_name: 'name-register', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray(bufferCV(Buffer.from('test')), uintCV(1234n)) ), }; @@ -3055,7 +3060,7 @@ describe('tx tests', () => { tx_id: '0x4413739d6a3f86d4597f5296cc536f6890e2affff9aece285e37399be697b43f', anchor_mode: DbTxAnchorMode.Any, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), status: DbTxStatus.Success, post_conditions: '0x01f5', fee_rate: 139200n, @@ -3065,7 +3070,7 @@ describe('tx tests', () => { origin_hash_mode: 1, contract_call_contract_id: 'SP000000000000000000002Q6VF78.bns', contract_call_function_name: 'name-register', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray(bufferCV(Buffer.from('test')), uintCV(1234n)) ), pruned: false, @@ -3115,7 +3120,7 @@ describe('tx tests', () => { tx_id: '0x5513739d6a3f86d4597f5296cc536f6890e2affff9aece285e37399be697b43f', anchor_mode: DbTxAnchorMode.Any, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), status: DbTxStatus.Success, post_conditions: '0x01f5', fee_rate: 139200n, @@ -3125,7 +3130,7 @@ describe('tx tests', () => { origin_hash_mode: 1, contract_call_contract_id: 'SP3YK7KWMYRCDMV5M4792T0T7DERQXHJJGGEPV1N8.pg-mdomains-v1', contract_call_function_name: 'bns-name-preorder', - contract_call_function_args: bufferToHexPrefixString( + contract_call_function_args: bufferToHex( createClarityValueArray(bufferCV(Buffer.from('test')), uintCV(1234n)) ), pruned: false, @@ -3197,14 +3202,14 @@ describe('tx tests', () => { tx_index: 4, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), index_block_hash: block.index_block_hash, block_hash: block.block_hash, block_height: block.block_height, burn_block_time: block.burn_block_time, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -3289,14 +3294,14 @@ describe('tx tests', () => { tx_index: 4, anchor_mode: 3, nonce: 0, - raw_tx: bufferToHexPrefixString(Buffer.from('')), + raw_tx: bufferToHex(Buffer.from('')), index_block_hash: block.index_block_hash, block_hash: block.block_hash, block_height: block.block_height, burn_block_time: block.burn_block_time, parent_burn_block_time: 1626122935, type_id: DbTxTypeId.Coinbase, - coinbase_payload: bufferToHexPrefixString(Buffer.from('coinbase hi')), + coinbase_payload: bufferToHex(Buffer.from('coinbase hi')), status: 1, raw_result: '0x0100000000000000000000000000000001', // u1 canonical: true, @@ -3482,10 +3487,4 @@ describe('tx tests', () => { }) ); }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/v2-proxy-tests.ts b/src/tests/v2-proxy-tests.ts index 5e1624de31..da5aad053e 100644 --- a/src/tests/v2-proxy-tests.ts +++ b/src/tests/v2-proxy-tests.ts @@ -1,7 +1,6 @@ import * as supertest from 'supertest'; import { ChainID } from '@stacks/transactions'; import { startApiServer } from '../api/init'; -import { PoolClient } from 'pg'; import { useWithCleanup, withEnvVars } from './test-helpers'; import * as fs from 'fs'; import * as path from 'path'; @@ -9,14 +8,13 @@ import * as os from 'os'; import * as nock from 'nock'; import { DbBlock } from '../datastore/common'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; describe('v2-proxy tests', () => { let db: PgWriteStore; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false, @@ -24,6 +22,11 @@ describe('v2-proxy tests', () => { }); }); + afterEach(async () => { + await db?.close(); + await migrate('down'); + }); + test('tx post multicast', async () => { const primaryProxyEndpoint = 'proxy-stacks-node:12345'; const extraTxEndpoint = 'http://extra-tx-endpoint-a/test'; @@ -108,9 +111,4 @@ describe('v2-proxy tests', () => { } ); }); - - afterEach(async () => { - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/websocket-tests.ts b/src/tests/websocket-tests.ts index b1d6f31e2b..54b175019e 100644 --- a/src/tests/websocket-tests.ts +++ b/src/tests/websocket-tests.ts @@ -1,7 +1,6 @@ import * as WebSocket from 'ws'; import { startApiServer, ApiServer } from '../api/init'; import { DbTxTypeId, DbTxStatus, DbAssetEventTypeId } from '../datastore/common'; -import { waiter, Waiter } from '../helpers'; import { once } from 'events'; import { RpcWebSocketClient } from 'rpc-websocket-client'; import { @@ -31,15 +30,15 @@ import { TestMicroblockStreamBuilder, } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { migrate } from '../test-utils/test-helpers'; +import { Waiter, waiter } from '@hirosystems/api-toolkit'; describe('websocket notifications', () => { let apiServer: ApiServer; let db: PgWriteStore; beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', skipMigrations: true }); apiServer = await startApiServer({ datastore: db, @@ -47,6 +46,12 @@ describe('websocket notifications', () => { }); }); + afterEach(async () => { + await apiServer.terminate(); + await db?.close(); + await migrate('down'); + }); + test('websocket rpc - tx subscription updates', async () => { const addr = apiServer.address; const wsAddress = `ws://${addr}/extended/v1/ws`; @@ -727,10 +732,4 @@ describe('websocket notifications', () => { client.webSocket.close(); } }); - - afterEach(async () => { - await apiServer.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/tests/ws-transmitter-tests.ts b/src/tests/ws-transmitter-tests.ts index 4a371e84ca..d4284a09f8 100644 --- a/src/tests/ws-transmitter-tests.ts +++ b/src/tests/ws-transmitter-tests.ts @@ -1,5 +1,4 @@ import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { WebSocketTransmitter } from '../api/routes/ws/web-socket-transmitter'; import { Server } from 'http'; import { @@ -8,6 +7,7 @@ import { WebSocketPayload, WebSocketTopics, } from '../api/routes/ws/web-socket-channel'; +import { migrate } from '../test-utils/test-helpers'; class TestChannel extends WebSocketChannel { connect(): void { @@ -36,10 +36,15 @@ describe('ws transmitter', () => { beforeEach(async () => { process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); + await migrate('up'); db = await PgWriteStore.connect({ usageName: 'tests', skipMigrations: true }); }); + afterEach(async () => { + await db?.close(); + await migrate('down'); + }); + test('handles pg exceptions gracefully', async () => { const fakeServer = new Server(); transmitter = new WebSocketTransmitter(db, fakeServer); @@ -51,9 +56,4 @@ describe('ws transmitter', () => { await expect(transmitter['nftEventUpdate']('0xff', 0)).resolves.not.toThrow(); await expect(transmitter['addressUpdate']('0xff', 1)).resolves.not.toThrow(); }); - - afterEach(async () => { - await db?.close(); - await runMigrations(undefined, 'down'); - }); }); diff --git a/src/token-metadata/helpers.ts b/src/token-metadata/helpers.ts index c7e13751f4..17154bae17 100644 --- a/src/token-metadata/helpers.ts +++ b/src/token-metadata/helpers.ts @@ -5,7 +5,7 @@ import { TokenMetadataProcessingMode, } from './tokens-contract-handler'; import fetch from 'node-fetch'; -import { parseArgBoolean } from '../helpers'; +import { parseBoolean } from '@hirosystems/api-toolkit'; export function isFtMetadataEnabled() { const opt = process.env['STACKS_API_ENABLE_FT_METADATA']?.toLowerCase().trim(); @@ -22,7 +22,7 @@ export function isNftMetadataEnabled() { * @returns TokenMetadataProcessingMode */ export function getTokenMetadataProcessingMode(): TokenMetadataProcessingMode { - if (parseArgBoolean(process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'])) { + if (parseBoolean(process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'])) { return TokenMetadataProcessingMode.strict; } return TokenMetadataProcessingMode.default; diff --git a/src/token-metadata/tokens-contract-handler.ts b/src/token-metadata/tokens-contract-handler.ts index 341a0e1a10..5a75b47087 100644 --- a/src/token-metadata/tokens-contract-handler.ts +++ b/src/token-metadata/tokens-contract-handler.ts @@ -11,7 +11,7 @@ import { uintCV, UIntCV, } from '@stacks/transactions'; -import { ChainID, getChainIDNetwork, parseDataUrl, REPO_DIR, stopwatch } from '../helpers'; +import { ChainID, getChainIDNetwork, parseDataUrl, REPO_DIR } from '../helpers'; import * as querystring from 'querystring'; import { getTokenMetadataFetchTimeoutMs, @@ -25,6 +25,7 @@ import { ReadOnlyContractCallResponse, StacksCoreRpcClient } from '../core-rpc/c import { FetchError } from 'node-fetch'; import { PgWriteStore } from '../datastore/pg-write-store'; import { logger } from '../logger'; +import { stopwatch } from '@hirosystems/api-toolkit'; /** * The maximum number of bytes of metadata to fetch. From 872bcbdea14b28f1ecbeb8ee1a10de27bdf27f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 7 Nov 2023 13:38:05 -0600 Subject: [PATCH 14/91] merge master into nakamoto (#1746) * docs: Update how-to-install-stacks-cli.md (#1727) Cleaned up the voice and made this page more conversational. Of note, similar to my last PR, I'm removing some language around "Stacks 2.0" here alongside this cleanup * docs: Update rosetta-support.md (#1728) there is a missing period * docs: Update overview.md (#1729) Grammar fixes * docs: Update how-to-run-api-node.md (#1730) A number of grammar fixes and tweaks * docs: Update how-to-run-mainnet-node.md (#1731) Grammar fixes! * docs: Update how-to-run-testnet-node.md (#1732) Grammar fixes * fix: move nft custody view into a table (#1741) * fix: move to table * fix: old nft events query * fix: nft-custody-table migration * fix: no longer rename old views, just remove them --------- Co-authored-by: Matt --------- Co-authored-by: max-crawford <102705427+max-crawford@users.noreply.github.com> Co-authored-by: Matt --- content/feature-guides/rosetta-support.md | 2 +- .../how-to-install-stacks-cli.md | 24 +- content/how-to-guides/how-to-run-api-node.md | 18 +- .../how-to-guides/how-to-run-mainnet-node.md | 12 +- .../how-to-guides/how-to-run-testnet-node.md | 14 +- content/overview.md | 14 +- .../1696872367486_nft-custody-tables.js | 215 ++++++++++++++++++ src/datastore/common.ts | 14 ++ src/datastore/pg-store.ts | 7 +- src/datastore/pg-write-store.ts | 162 +++++++++---- src/tests/search-tests.ts | 4 +- 11 files changed, 392 insertions(+), 94 deletions(-) create mode 100644 migrations/1696872367486_nft-custody-tables.js diff --git a/content/feature-guides/rosetta-support.md b/content/feature-guides/rosetta-support.md index 1d24082fc5..7059b3df65 100644 --- a/content/feature-guides/rosetta-support.md +++ b/content/feature-guides/rosetta-support.md @@ -56,4 +56,4 @@ rosetta-cli \ `rosetta-cli` will then sync with the blockchain until it reaches the tip, and then exit, displaying the test results. Currently, account reconciliation is disabled; proper testing of that feature requires token transfer transactions while `rosetta-cli` is running. Documentation for the Rosetta APIs can be found [here](https://hirosystems.github.io/stacks-blockchain-api/). -You may also review Data and Construction Rosetta endpoints [here](https://docs.hiro.so/api#tag/Rosetta) +You may also review Data and Construction Rosetta endpoints [here](https://docs.hiro.so/api#tag/Rosetta). diff --git a/content/how-to-guides/how-to-install-stacks-cli.md b/content/how-to-guides/how-to-install-stacks-cli.md index 2822084f40..be78bafac4 100644 --- a/content/how-to-guides/how-to-install-stacks-cli.md +++ b/content/how-to-guides/how-to-install-stacks-cli.md @@ -2,7 +2,7 @@ title: How to install Stacks CLI --- -The Stacks CLI enables interactions with the Stacks 2.0 blockchain through a set of commands. +The Stacks CLI enables interactions with the Stacks blockchain through a set of commands. ## Installation @@ -18,7 +18,7 @@ The `-g` flag makes the CLI commands available globally ## Network selection -By default, the CLI will attempt to interact with the mainnet of the Stacks 2.0 blockchain. However, it is possible to override the network and set it to the testnet: +By default, the CLI will attempt to interact with Stacks mainnet. However, it is possible to override the network and set it to testnet: ```sh stx -t @@ -26,7 +26,7 @@ stx -t :::info -For account usage, that means addresses generated will _only_ be available for the specific network. An account generated for the testnet cannot be used on the mainnet. +For account usage, that means addresses generated will _only_ be available for the specific network. An account generated for testnet cannot be used on mainnet. ::: @@ -42,7 +42,7 @@ This section describes how to use the CLI to manage an account. :::caution -It is not recommended to use the CLI to handle accounts with real STX tokens on the mainnet. Using an appropriate wallet build to support secure token holding is recommended. +We don't recommended you use the CLI to handle accounts with real STX tokens on the mainnet. Instead, use an appropriate wallet to support secure token holding. ::: @@ -68,14 +68,14 @@ Your response should look like this: } ``` -The mnemonic is your 24 word seed phrase which you should back up securely if you want access to this account again in the future. Once lost, it cannot be recovered. +The mnemonic is your 24 word seed phrase, which you should back up securely if you want access to this account again in the future. Once lost, it cannot be recovered. The Stacks address associated with the newly generated account is: `ST1BG7MHW2R524WMF7X8PGG3V45ZN040EB9EW0GQJ` :::note -The preceding address is a testnet address that can only be used on the testnet. +The preceding address is a testnet address that can only be used on testnet. ::: @@ -115,10 +115,10 @@ This section describes how to use the CLI to generate and broadcast transactions In order to send tokens, the CLI command requires 5 parameters: - **Recipient Address**: The Stacks address of the recipient -- **Amount**: The number of Stacks to send denoted in microstacks (1 STX = 1000000 microstacks) -- **Fee Rate**: The transaction fee rate for this transaction. You can safely set a fee rate of 200 for Testnet +- **Amount**: The number of Stacks to send denoted in microstacks (1 STX = 1,000,000 microstacks) +- **Fee Rate**: The fee rate for this transaction. You can safely set a fee rate of 200 for testnet - **Nonce**: The nonce is a number that needs to be incremented monotonically for each transaction from the account. This ensures transactions are not duplicated -- **Private Key**: This is the private key corresponding to your account that was generated when +- **Private Key**: This is the private key corresponding to your account The CLI command to use with these parameters is `send_tokens`: @@ -135,7 +135,7 @@ stx send_tokens ST2KMMVJAB00W5Z6XWTFPH6B13JE9RJ2DCSHYX0S7 1000 200 0 381314da39a With this command we’re sending 1000 microstacks to the Stacks address `ST2KMMVJAB00W5Z6XWTFPH6B13JE9RJ2DCSHYX0S7`. -We set the fee rate to `200` microstacks. If you're not sure how much your transaction will cost. +We set the fee rate to `200` microstacks. :::tip @@ -147,9 +147,9 @@ The nonce is set to `0` for this transaction, since it will be the first transac Finally, the last parameter is the private key for the account. `381314da39a45f43f45ffd33b5d8767d1a38db0da71fea50ed9508e048765cf301` -Once again, we’re using the `-t` option to indicate that this is a Testnet transaction, so it should be broadcasted to Testnet. +Once again, we’re using the `-t` option to indicate that this is a testnet transaction, so it should be broadcast to testnet. -If valid, the transaction will be broadcasted to the network and the command will respond with a transaction ID. +If valid, the transaction will be broadcast to the network, and the command will respond with a transaction ID. :::tip diff --git a/content/how-to-guides/how-to-run-api-node.md b/content/how-to-guides/how-to-run-api-node.md index 7d63685509..4c54448747 100644 --- a/content/how-to-guides/how-to-run-api-node.md +++ b/content/how-to-guides/how-to-run-api-node.md @@ -1,23 +1,23 @@ --- -title: How to run API node +title: How to Run an API Node --- -This procedure demonstrates how to run a local API node using Docker images. There are several components that must be +This guide shows you how to run a local API node using Docker images. There are several components that must be configured and run in a specific order for the local API node to work. -For this procedure, the order in which the services are brought up is very important. In order to start the API node +Note: the order in which the services are brought up is very important. In order to start the API node successfully, you need to bring up the services in the following order: 1. `postgres` 2. `stacks-blockchain-api` 3. `stacks-blockchain` -When bringing down the API node, you should bring the services down in the exact reverse order in which they were -brought up, to avoid losing data. +When bringing down the API node, you should bring the services down in the reverse order in which they were +brought up in order to avoid losing data. :::note -This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on +This guide focuses on Unix-like operating systems (Linux and MacOS). This has not been tested on Windows. ::: @@ -25,7 +25,7 @@ Windows. ## Prerequisites Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi -boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software +boards and other system-on-chip architectures. However, in order to complete this guide, you do need the following software installed on the node host machine: - [Docker](https://docs.docker.com/get-docker/) @@ -234,13 +234,13 @@ To verify the database is ready: 2. List current databases with the command `\l` 3. Disconnect from the database with the command `\q` -To verify the `stacks-blockchain` tip height is progressing use the following command: +To verify that the `stacks-blockchain` tip height is progressing, use the following command: ```sh curl -sL localhost:20443/v2/info | jq ``` -If the instance is running you should receive terminal output similar to the following: +If the instance is running, you should receive terminal output similar to the following: ```json { diff --git a/content/how-to-guides/how-to-run-mainnet-node.md b/content/how-to-guides/how-to-run-mainnet-node.md index c3539a7fd6..6114213652 100644 --- a/content/how-to-guides/how-to-run-mainnet-node.md +++ b/content/how-to-guides/how-to-run-mainnet-node.md @@ -1,12 +1,12 @@ --- -title: How to run mainnet node +title: How to Run a Mainnet Node --- -This procedure demonstrates how to run a local mainnet node using Docker images. +This guide shows you how to run a local mainnet node using Docker images. :::note -This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on +This guide focuses on Unix-like operating systems (Linux and MacOS). This has not been tested on Windows. ::: @@ -14,7 +14,7 @@ Windows. ## Prerequisites Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi -boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software +boards and other system-on-chip architectures. However, in order to complete this guide, you do need the following software installed on the node host machine: - [Docker](https://docs.docker.com/get-docker/) @@ -129,13 +129,13 @@ INFO [1626290748.103291] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitc INFO [1626290776.956535] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.7% (12000 out of 691034) ``` -To verify the `stacks-blockchain` tip height is progressing use the following command: +To verify that the `stacks-blockchain` tip height is progressing, use the following command: ```sh curl -sL localhost:20443/v2/info | jq ``` -If the instance is running you should receive terminal output similar to the following: +If the instance is running, you should receive terminal output similar to the following: ```json { diff --git a/content/how-to-guides/how-to-run-testnet-node.md b/content/how-to-guides/how-to-run-testnet-node.md index b5e5cc2f98..d1db09ee7c 100644 --- a/content/how-to-guides/how-to-run-testnet-node.md +++ b/content/how-to-guides/how-to-run-testnet-node.md @@ -1,12 +1,12 @@ --- -title: How to run testnet node +title: How to Run a Testnet Node --- -This procedure demonstrates how to run a local testnet node using Docker images. +This guide shows you how to run a local testnet node using Docker images. :::note -This procedure focuses on Unix-like operating systems (Linux and MacOS). This procedure has not been tested on +This guide focuses on Unix-like operating systems (Linux and MacOS). This has not been tested on Windows. ::: @@ -14,7 +14,7 @@ Windows. ## Prerequisites Running a node has no specialized hardware requirements. Users have been successful in running nodes on Raspberry Pi -boards and other system-on-chip architectures. In order to complete this procedure, you must have the following software +boards and other system-on-chip architectures. However, in order to complete this procedure, you do need the following software installed on the node host machine: - [Docker](https://docs.docker.com/get-docker/) @@ -45,7 +45,7 @@ These egress ports are for syncing `stacks-blockchain` and Bitcoin headers. If t ## Step 1: Initial setup -In order to run the testnet node, you must download the Docker images and create a directory structure to hold the +In order to run a testnet node, you must download the Docker images and create a directory structure to hold the persistent data from the services. Download and configure the Docker images with the following commands: ```sh @@ -100,13 +100,13 @@ INFO [1626290748.103291] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitc INFO [1626290776.956535] [src/burnchains/bitcoin/spv.rs:926] [main] Syncing Bitcoin headers: 1.7% (12000 out of 2034380) ``` -To verify the `stacks-blockchain` tip height is progressing use the following command: +To verify that the `stacks-blockchain` tip height is progressing, use the following command: ```sh curl -sL localhost:20443/v2/info | jq ``` -If the instance is running you should receive terminal output similar to the following: +If the instance is running, you should receive terminal output similar to the following: ```json { diff --git a/content/overview.md b/content/overview.md index 9e408725bb..3f3904cc50 100644 --- a/content/overview.md +++ b/content/overview.md @@ -6,7 +6,7 @@ Title: Overview The Stacks blockchain API allows you to query the Stacks blockchain and interact with smart contracts. It was built to maintain paginated, materialized views of the Stacks Blockchain. -The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust the hosted server, but this API also provides a faster development experience. You may wish to consider running your own API instance to create a fully trustless architecture for your app. +The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust us as the hosted server, but in return we provide a faster development experience. If you want a fully trustless architecture for your app, you may wish to consider running your own API instance. > **_NOTE:_** > @@ -18,14 +18,14 @@ The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust the ![API architecture!](images/api-architecture.png) -* The `stacks-node` has it's own minimal set of http endpoints referred to as `RPC endpoints` +* The `stacks-node` has its own minimal set of http endpoints referred to as `RPC endpoints` * The `stacks-blockchain-api` allows clients to access these endpoints by proxying them through to a load-balanced pool of `stacks-nodes`. * See: https://github.com/blockstack/stacks-blockchain/blob/master/docs/rpc-endpoints.md -- some common ones: - * `POST /v2/transactions` - broadcast a tx. + * `POST /v2/transactions` - broadcast a transaction. * `GET /v2/pox` - get current PoX-relevant information. - * `POST /v2/contracts/call-read//` - evaluates and returns the result of calling a Clarity function. - * `POST /v2/fees/transaction` - evaluates a given transaction and returns tx fee estimation data. - * `GET /v2/accounts/
` - used to get the current `nonce` required for creating transactions. + * `POST /v2/contracts/call-read//` - evaluate and return the result of calling a Clarity function. + * `POST /v2/fees/transaction` - evaluate a given transaction and return transaction fee estimation data. + * `GET /v2/accounts/
` - get the current `nonce` required for creating transactions. * The endpoints implemented by `stacks-blockchain-api` provide data that the `stacks-node` can't due to various constraints. @@ -52,7 +52,7 @@ The Stacks Blockchain API is hosted by Hiro. Using it requires you to trust the * ALSO the OpenAPI + JSONSchemas are used to generate a standalone `@stacks/blockchain-api-client`. -* The easiest/quickest way to develop in this repo is using the vscode debugger. It uses docker-compose to setup a `stacks-node` and postgres instance. +* The easiest/quickest way to develop in this repo is using the VS Code debugger. It uses docker-compose to setup a `stacks-node` and Postgres instance. * Alternatively, you can run `npm run dev:integrated` which does the same thing but without a debugger. diff --git a/migrations/1696872367486_nft-custody-tables.js b/migrations/1696872367486_nft-custody-tables.js new file mode 100644 index 0000000000..f74a748f5e --- /dev/null +++ b/migrations/1696872367486_nft-custody-tables.js @@ -0,0 +1,215 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.dropMaterializedView('nft_custody'); + pgm.createTable('nft_custody', { + asset_identifier: { + type: 'string', + notNull: true, + }, + value: { + type: 'bytea', + notNull: true, + }, + recipient: { + type: 'text', + }, + block_height: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + parent_index_block_hash: { + type: 'bytea', + notNull: true, + }, + microblock_hash: { + type: 'bytea', + notNull: true, + }, + microblock_sequence: { + type: 'integer', + notNull: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + tx_index: { + type: 'smallint', + notNull: true, + }, + event_index: { + type: 'integer', + notNull: true, + }, + }); + pgm.createConstraint('nft_custody', 'nft_custody_unique', 'UNIQUE(asset_identifier, value)'); + pgm.createIndex('nft_custody', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody', 'value'); + pgm.createIndex('nft_custody', [ + { name: 'block_height', sort: 'DESC' }, + { name: 'microblock_sequence', sort: 'DESC' }, + { name: 'tx_index', sort: 'DESC' }, + { name: 'event_index', sort: 'DESC' } + ]); + pgm.sql(` + INSERT INTO nft_custody (asset_identifier, value, recipient, tx_id, block_height, index_block_hash, parent_index_block_hash, microblock_hash, microblock_sequence, tx_index, event_index) ( + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height, + nft.index_block_hash, nft.parent_index_block_hash, nft.microblock_hash, nft.microblock_sequence, nft.tx_index, nft.event_index + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + ) + `); + + pgm.dropMaterializedView('nft_custody_unanchored'); + pgm.createTable('nft_custody_unanchored', { + asset_identifier: { + type: 'string', + notNull: true, + }, + value: { + type: 'bytea', + notNull: true, + }, + recipient: { + type: 'text', + }, + block_height: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + parent_index_block_hash: { + type: 'bytea', + notNull: true, + }, + microblock_hash: { + type: 'bytea', + notNull: true, + }, + microblock_sequence: { + type: 'integer', + notNull: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + tx_index: { + type: 'smallint', + notNull: true, + }, + event_index: { + type: 'integer', + notNull: true, + }, + }); + pgm.createConstraint('nft_custody_unanchored', 'nft_custody_unanchored_unique', 'UNIQUE(asset_identifier, value)'); + pgm.createIndex('nft_custody_unanchored', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody_unanchored', 'value'); + pgm.createIndex('nft_custody_unanchored', [ + { name: 'block_height', sort: 'DESC' }, + { name: 'microblock_sequence', sort: 'DESC' }, + { name: 'tx_index', sort: 'DESC' }, + { name: 'event_index', sort: 'DESC' } + ]); + pgm.sql(` + INSERT INTO nft_custody_unanchored (asset_identifier, value, recipient, tx_id, block_height, index_block_hash, parent_index_block_hash, microblock_hash, microblock_sequence, tx_index, event_index) ( + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height, + nft.index_block_hash, nft.parent_index_block_hash, nft.microblock_hash, nft.microblock_sequence, nft.tx_index, nft.event_index + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + ) + `); +}; + +exports.down = pgm => { + pgm.dropTable('nft_custody'); + pgm.createMaterializedView('nft_custody', { data: true }, ` + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + `); + pgm.createIndex('nft_custody', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody', ['asset_identifier', 'value'], { unique: true }); + pgm.createIndex('nft_custody', 'value'); + + pgm.dropTable('nft_custody_unanchored'); + pgm.createMaterializedView('nft_custody_unanchored', { data: true }, ` + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient, tx_id, nft.block_height + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + `); + pgm.createIndex('nft_custody_unanchored', ['recipient', 'asset_identifier']); + pgm.createIndex('nft_custody_unanchored', ['asset_identifier', 'value'], { unique: true }); + pgm.createIndex('nft_custody_unanchored', 'value'); +}; diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 18b974d923..c9373f32e9 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -1363,6 +1363,20 @@ export interface NftEventInsertValues { value: PgBytea; } +export interface NftCustodyInsertValues { + event_index: number; + tx_id: PgBytea; + tx_index: number; + block_height: number; + index_block_hash: PgBytea; + parent_index_block_hash: PgBytea; + microblock_hash: PgBytea; + microblock_sequence: number; + recipient: string | null; + asset_identifier: string; + value: PgBytea; +} + export interface FtEventInsertValues { event_index: number; tx_id: PgBytea; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 2dade8833e..2f3e114b90 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -3264,6 +3264,7 @@ export class PgStore extends BasePgStore { FROM ${nftCustody} AS nft WHERE nft.recipient = ${args.principal} ${assetIdFilter} + ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC LIMIT ${args.limit} OFFSET ${args.offset} ) @@ -3465,11 +3466,11 @@ export class PgStore extends BasePgStore { AND block_height <= ${args.blockHeight} ORDER BY asset_identifier, value, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC ) - SELECT sender, recipient, asset_identifier, value, event_index, asset_event_type_id, address_transfers.block_height, address_transfers.tx_id, (COUNT(*) OVER())::INTEGER AS count - FROM address_transfers + SELECT sender, recipient, asset_identifier, value, at.event_index, asset_event_type_id, at.block_height, at.tx_id, (COUNT(*) OVER())::INTEGER AS count + FROM address_transfers AS at INNER JOIN ${args.includeUnanchored ? this.sql`last_nft_transfers` : this.sql`nft_custody`} USING (asset_identifier, value, recipient) - ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC + ORDER BY at.block_height DESC, at.microblock_sequence DESC, at.tx_index DESC, event_index DESC LIMIT ${args.limit} OFFSET ${args.offset} `; diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index ef8c3c7028..ff86ad0e84 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -64,6 +64,7 @@ import { DbPox3Event, RawEventRequestInsertValues, IndexesState, + NftCustodyInsertValues, } from './common'; import { ClarityAbi } from '@stacks/transactions'; import { @@ -399,7 +400,7 @@ export class PgWriteStore extends PgStore { await this.updateFtEvent(sql, entry.tx, ftEvent); } for (const nftEvent of entry.nftEvents) { - await this.updateNftEvent(sql, entry.tx, nftEvent); + await this.updateNftEvent(sql, entry.tx, nftEvent, false); } deployedSmartContracts.push(...entry.smartContracts); for (const smartContract of entry.smartContracts) { @@ -458,7 +459,6 @@ export class PgWriteStore extends PgStore { const ibdHeight = getIbdBlockHeight(); this.isIbdBlockHeightReached = ibdHeight ? data.block.block_height > ibdHeight : true; - await this.refreshNftCustody(batchedTxData); await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); @@ -764,7 +764,6 @@ export class PgWriteStore extends PgStore { } }); - await this.refreshNftCustody(txData, true); await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); @@ -1331,27 +1330,65 @@ export class PgWriteStore extends PgStore { `; } - async updateNftEvent(sql: PgSqlClient, tx: DbTx, event: DbNftEvent) { - const values: NftEventInsertValues = { + async updateNftEvent(sql: PgSqlClient, tx: DbTx, event: DbNftEvent, microblock: boolean) { + const custody: NftCustodyInsertValues = { + asset_identifier: event.asset_identifier, + value: event.value, tx_id: event.tx_id, index_block_hash: tx.index_block_hash, parent_index_block_hash: tx.parent_index_block_hash, microblock_hash: tx.microblock_hash, microblock_sequence: tx.microblock_sequence, - microblock_canonical: tx.microblock_canonical, - sender: event.sender ?? null, recipient: event.recipient ?? null, event_index: event.event_index, tx_index: event.tx_index, block_height: event.block_height, + }; + const values: NftEventInsertValues = { + ...custody, + microblock_canonical: tx.microblock_canonical, canonical: event.canonical, + sender: event.sender ?? null, asset_event_type_id: event.asset_event_type_id, - asset_identifier: event.asset_identifier, - value: event.value, }; await sql` INSERT INTO nft_events ${sql(values)} `; + if (tx.canonical && tx.microblock_canonical && event.canonical) { + const table = microblock ? sql`nft_custody_unanchored` : sql`nft_custody`; + await sql` + INSERT INTO ${table} ${sql(custody)} + ON CONFLICT ON CONSTRAINT ${table}_unique DO UPDATE SET + tx_id = EXCLUDED.tx_id, + index_block_hash = EXCLUDED.index_block_hash, + parent_index_block_hash = EXCLUDED.parent_index_block_hash, + microblock_hash = EXCLUDED.microblock_hash, + microblock_sequence = EXCLUDED.microblock_sequence, + recipient = EXCLUDED.recipient, + event_index = EXCLUDED.event_index, + tx_index = EXCLUDED.tx_index, + block_height = EXCLUDED.block_height + WHERE + ( + EXCLUDED.block_height > ${table}.block_height + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence > ${table}.microblock_sequence + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence + AND EXCLUDED.tx_index > ${table}.tx_index + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence + AND EXCLUDED.tx_index = ${table}.tx_index + AND EXCLUDED.event_index > ${table}.event_index + ) + `; + } } async updateBatchSmartContractEvent(sql: PgSqlClient, tx: DbTx, events: DbSmartContractEvent[]) { @@ -2263,7 +2300,7 @@ export class PgWriteStore extends PgStore { await this.updateFtEvent(sql, entry.tx, ftEvent); } for (const nftEvent of entry.nftEvents) { - await this.updateNftEvent(sql, entry.tx, nftEvent); + await this.updateNftEvent(sql, entry.tx, nftEvent, true); } for (const smartContract of entry.smartContracts) { await this.updateSmartContract(sql, entry.tx, smartContract); @@ -2345,11 +2382,74 @@ export class PgWriteStore extends PgStore { AND (index_block_hash = ${args.indexBlockHash} OR index_block_hash = '\\x'::bytea) AND tx_id IN ${sql(txIds)} `; + await this.updateNftCustodyFromReOrg(sql, { + index_block_hash: args.indexBlockHash, + microblocks: args.microblocks, + }); } return { updatedTxs: updatedMbTxs }; } + /** + * Refreshes NFT custody data for events within a block or series of microblocks. + * @param sql - SQL client + * @param args - Block and microblock hashes + */ + async updateNftCustodyFromReOrg( + sql: PgSqlClient, + args: { + index_block_hash: string; + microblocks: string[]; + } + ): Promise { + for (const table of [sql`nft_custody`, sql`nft_custody_unanchored`]) { + await sql` + INSERT INTO ${table} + (asset_identifier, value, tx_id, index_block_hash, parent_index_block_hash, microblock_hash, + microblock_sequence, recipient, event_index, tx_index, block_height) + ( + SELECT + DISTINCT ON(asset_identifier, value) asset_identifier, value, tx_id, txs.index_block_hash, + txs.parent_index_block_hash, txs.microblock_hash, txs.microblock_sequence, recipient, + nft.event_index, txs.tx_index, txs.block_height + FROM + nft_events AS nft + INNER JOIN + txs USING (tx_id) + WHERE + txs.canonical = true + AND txs.microblock_canonical = true + AND nft.canonical = true + AND nft.microblock_canonical = true + AND nft.index_block_hash = ${args.index_block_hash} + ${ + args.microblocks.length > 0 + ? sql`AND nft.microblock_hash IN ${sql(args.microblocks)}` + : sql`` + } + ORDER BY + asset_identifier, + value, + txs.block_height DESC, + txs.microblock_sequence DESC, + txs.tx_index DESC, + nft.event_index DESC + ) + ON CONFLICT ON CONSTRAINT ${table}_unique DO UPDATE SET + tx_id = EXCLUDED.tx_id, + index_block_hash = EXCLUDED.index_block_hash, + parent_index_block_hash = EXCLUDED.parent_index_block_hash, + microblock_hash = EXCLUDED.microblock_hash, + microblock_sequence = EXCLUDED.microblock_sequence, + recipient = EXCLUDED.recipient, + event_index = EXCLUDED.event_index, + tx_index = EXCLUDED.tx_index, + block_height = EXCLUDED.block_height + `; + } + } + /** * Fetches from the `microblocks` table with a given `parent_index_block_hash` and a known * latest unanchored microblock tip. Microblocks that are chained to the given tip are @@ -2611,6 +2711,10 @@ export class PgWriteStore extends PgStore { } else { updatedEntities.markedNonCanonical.nftEvents += nftResult.count; } + await this.updateNftCustodyFromReOrg(sql, { + index_block_hash: indexBlockHash, + microblocks: [], + }); // todo: do we still need pox2 marking here? const pox2Result = await sql` @@ -2980,49 +3084,13 @@ export class PgWriteStore extends PgStore { } /** - * Refreshes the `nft_custody` and `nft_custody_unanchored` materialized views if necessary. - * @param sql - DB client - * @param txs - Transaction event data - * @param unanchored - If this refresh is requested from a block or microblock - */ - async refreshNftCustody(txs: DataStoreTxEventData[], unanchored: boolean = false) { - await this.sqlWriteTransaction(async sql => { - const newNftEventCount = txs - .map(tx => tx.nftEvents.length) - .reduce((prev, cur) => prev + cur, 0); - if (newNftEventCount > 0) { - // Always refresh unanchored view since even if we're in a new anchored block we should update the - // unanchored state to the current one. - await this.refreshMaterializedView('nft_custody_unanchored', sql); - if (!unanchored) { - await this.refreshMaterializedView('nft_custody', sql); - } - } else if (!unanchored) { - // Even if we didn't receive new NFT events in a new anchor block, we should check if we need to - // update the anchored view to reflect any changes made by previous microblocks. - const result = await sql<{ outdated: boolean }[]>` - WITH anchored_height AS (SELECT MAX(block_height) AS anchored FROM nft_custody), - unanchored_height AS (SELECT MAX(block_height) AS unanchored FROM nft_custody_unanchored) - SELECT unanchored > anchored AS outdated - FROM anchored_height CROSS JOIN unanchored_height - `; - if (result.length > 0 && result[0].outdated) { - await this.refreshMaterializedView('nft_custody', sql); - } - } - }); - } - - /** - * (event-replay) Finishes DB setup after an event-replay. + * Called when a full event import is complete. */ async finishEventReplay() { if (!this.isEventReplay) { return; } await this.sqlWriteTransaction(async sql => { - await this.refreshMaterializedView('nft_custody', sql, false); - await this.refreshMaterializedView('nft_custody_unanchored', sql, false); await this.refreshMaterializedView('chain_tip', sql, false); await this.refreshMaterializedView('mempool_digest', sql, false); }); diff --git a/src/tests/search-tests.ts b/src/tests/search-tests.ts index 08961cbb5c..94c8621339 100644 --- a/src/tests/search-tests.ts +++ b/src/tests/search-tests.ts @@ -825,7 +825,7 @@ describe('search tests', () => { recipient: addr7, sender: 'none', }; - await db.updateNftEvent(client, stxTx1, nftEvent1); + await db.updateNftEvent(client, stxTx1, nftEvent1, false); // test address as a nft event recipient const searchResult7 = await supertest(api.server).get(`/extended/v1/search/${addr7}`); @@ -853,7 +853,7 @@ describe('search tests', () => { recipient: 'none', sender: addr8, }; - await db.updateNftEvent(client, stxTx1, nftEvent2); + await db.updateNftEvent(client, stxTx1, nftEvent2, false); // test address as a nft event sender const searchResult8 = await supertest(api.server).get(`/extended/v1/search/${addr8}`); From a490d673f81f536e1009c36893a1237e4cb18a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Thu, 9 Nov 2023 10:11:26 -0600 Subject: [PATCH 15/91] refactor: remove old token metadata processor (#1747) * refactor: remove old processor, start fetching data from contract * refactor: remove old tests * fix: tests and lint * fix: use lru cache * chore: delete old tables * chore: fix comments [skip ci] * fix: env comment block [skip ci] * chore: avoid duplicate RPC lookups * fix: make an incremental migration to drop tables * fix: re-add metadata processing ENV flag --------- Co-authored-by: Matthew Little --- .env | 35 +- .github/workflows/ci.yml | 91 --- .vscode/launch.json | 34 -- .../1699540187362_remove-token-metadata.js | 132 +++++ package.json | 2 - src/api/controllers/db-controller.ts | 26 +- src/api/init.ts | 2 +- src/api/routes/rosetta/account.ts | 34 +- src/api/routes/rosetta/construction.ts | 2 +- src/api/routes/rosetta/mempool.ts | 2 +- src/api/routes/{tokens => }/tokens.ts | 163 +----- src/datastore/common.ts | 106 ---- src/datastore/pg-store.ts | 191 ------- src/datastore/pg-write-store.ts | 143 ----- src/helpers.ts | 43 -- src/index.ts | 19 - src/rosetta/rosetta-ft-metadata-client.ts | 204 +++++++ src/{ => rosetta}/rosetta-helpers.ts | 57 +- .../construction.ts | 2 +- src/tests-rosetta/account-tests.ts | 35 +- src/tests-rosetta/block-tests.ts | 34 +- src/tests-rosetta/offline-api-tests.ts | 2 +- src/tests-tokens-metadata/setup.ts | 13 - src/tests-tokens-metadata/teardown.ts | 5 - .../test-contracts/beeple-data-url-a.clar | 58 -- .../test-contracts/beeple-data-url-b.clar | 58 -- .../test-contracts/beeple-data-url-c.clar | 58 -- .../test-contracts/beeple.clar | 58 -- .../test-contracts/ft-trait.clar | 24 - .../test-contracts/hey-token.clar | 58 -- .../test-contracts/nft-trait.clar | 15 - .../tokens-metadata-tests.ts | 404 ------------- src/tests-tokens-strict/setup.ts | 8 - src/tests-tokens-strict/strict-mode-tests.ts | 388 ------------- src/tests-tokens-strict/teardown.ts | 8 - src/tests/datastore-tests.ts | 44 -- src/token-metadata/helpers.ts | 263 --------- src/token-metadata/tokens-contract-handler.ts | 535 ------------------ src/token-metadata/tokens-processor-queue.ts | 175 ------ tests/jest.config.tokens-metadata.js | 13 - tests/jest.config.tokens-strict.js | 13 - tests/jest.config.tokens.js | 13 - 42 files changed, 427 insertions(+), 3143 deletions(-) create mode 100644 migrations/1699540187362_remove-token-metadata.js rename src/api/routes/{tokens => }/tokens.ts (65%) create mode 100644 src/rosetta/rosetta-ft-metadata-client.ts rename src/{ => rosetta}/rosetta-helpers.ts (95%) delete mode 100644 src/tests-tokens-metadata/setup.ts delete mode 100644 src/tests-tokens-metadata/teardown.ts delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/ft-trait.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/hey-token.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/nft-trait.clar delete mode 100644 src/tests-tokens-metadata/tokens-metadata-tests.ts delete mode 100644 src/tests-tokens-strict/setup.ts delete mode 100644 src/tests-tokens-strict/strict-mode-tests.ts delete mode 100644 src/tests-tokens-strict/teardown.ts delete mode 100644 src/token-metadata/helpers.ts delete mode 100644 src/token-metadata/tokens-contract-handler.ts delete mode 100644 src/token-metadata/tokens-processor-queue.ts delete mode 100644 tests/jest.config.tokens-metadata.js delete mode 100644 tests/jest.config.tokens-strict.js delete mode 100644 tests/jest.config.tokens.js diff --git a/.env b/.env index 095a69072e..ed6d6d26ba 100644 --- a/.env +++ b/.env @@ -122,34 +122,17 @@ STACKS_NODE_TYPE=L1 # Override the default file path for the proxy cache control file # STACKS_API_PROXY_CACHE_CONTROL_FILE=/path/to/.proxy-cache-control.json -# Enable token metadata processing. Disabled by default. +# Enable FT metadata processing for Rosetta operations display. Disabled by default. # STACKS_API_ENABLE_FT_METADATA=1 -# STACKS_API_ENABLE_NFT_METADATA=1 - -# If token metadata processing is enabled, this variable determines how the API reacts to metadata processing failures. -# When strict mode is enabled, any failures caused by recoverable errors will be retried indefinitely. Otherwise, -# the API will give up after `STACKS_API_TOKEN_METADATA_MAX_RETRIES` is reached for that smart contract. -# STACKS_API_TOKEN_METADATA_STRICT_MODE=1 - -# Maximum number of times we'll try processing FT/NFT metadata for a specific smart contract if we've failed -# because of a recoverable error. -# Only used if `STACKS_API_TOKEN_METADATA_STRICT_MODE` is disabled. -# STACKS_API_TOKEN_METADATA_MAX_RETRIES=5 - -# Controls the token metadata error handling mode. The possible values are: -# * `warning`: If required metadata is not found, the API will issue a warning and not display data for that token. -# * `error`: If required metadata is not found, the API will throw an error. -# If not specified or any other value is provided, the mode will be set to `warning`. -# STACKS_API_TOKEN_METADATA_ERROR_MODE=warning -# Configure a script to handle image URLs during token metadata processing. -# This example script uses the `imgix.net` service to create CDN URLs. -# Must be an executable script that accepts the URL as the first program argument -# and outputs a result URL to stdout. -# STACKS_API_IMAGE_CACHE_PROCESSOR=./config/token-metadata-image-cache-imgix.js -# Env vars needed for the above sample `imgix` script: -# IMGIX_DOMAIN=https://.imgix.net -# IMGIX_TOKEN= +# The Rosetta API endpoints require FT metadata to display operations with the proper `symbol` and +# `decimals` values. If FT metadata is enabled, this variable controls the token metadata error +# handling mode when metadata is not found. +# The possible values are: +# * `warning`: The API will issue a warning and not display data for that token. +# * `error`: The API will throw an error. If not specified or any other value is provided, the mode +# will be set to `warning`. +# STACKS_API_TOKEN_METADATA_ERROR_MODE=warning # Web Socket ping interval to determine client availability, in seconds. # STACKS_API_WS_PING_INTERVAL=5 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ac6bc5440..23bd5373ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -848,96 +848,6 @@ jobs: flag-name: run-${{ github.job }} parallel: true - test-tokens-metadata: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version-file: ".nvmrc" - - - name: Install deps - run: npm ci - - - name: Setup env vars - run: echo "STACKS_CORE_EVENT_HOST=http://0.0.0.0" >> $GITHUB_ENV - - - name: Setup integration environment - run: | - sudo ufw disable - npm run devenv:deploy-krypton -- -d - npm run devenv:logs-krypton -- --no-color &> docker-compose-logs.txt & - - - name: Run tokens tests - run: npm run test:tokens-metadata - - - name: Print integration environment logs - run: cat docker-compose-logs.txt - if: failure() - - - name: Teardown integration environment - run: npm run devenv:stop-krypton - if: always() - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - if: always() - - - name: Upload coverage to Coveralls - uses: coverallsapp/github-action@master - if: ${{ false }} - with: - github-token: ${{ secrets.github_token }} - flag-name: run-${{ github.job }} - parallel: true - - test-tokens-strict: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version-file: ".nvmrc" - - - name: Install deps - run: npm ci - - - name: Setup env vars - run: echo "STACKS_CORE_EVENT_HOST=http://0.0.0.0" >> $GITHUB_ENV - - - name: Setup integration environment - run: | - sudo ufw disable - npm run devenv:deploy-krypton -- -d - npm run devenv:logs-krypton -- --no-color &> docker-compose-logs.txt & - - - name: Run tokens tests - run: npm run test:tokens-strict - - - name: Print integration environment logs - run: cat docker-compose-logs.txt - if: failure() - - - name: Teardown integration environment - run: npm run devenv:stop-krypton - if: always() - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - if: always() - - - name: Upload coverage to Coveralls - uses: coverallsapp/github-action@master - if: ${{ false }} - with: - github-token: ${{ secrets.github_token }} - flag-name: run-${{ github.job }} - parallel: true - build-publish: runs-on: ubuntu-latest needs: @@ -948,7 +858,6 @@ jobs: - test-bns - test-rosetta - test-rosetta-cli-construction - - test-tokens-strict steps: - uses: actions/checkout@v3 with: diff --git a/.vscode/launch.json b/.vscode/launch.json index ced0a3a5f1..6ef212dc0b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -346,40 +346,6 @@ "preLaunchTask": "deploy:krypton", "postDebugTask": "stop:krypton", }, - { - "type": "node", - "request": "launch", - "name": "Jest: Tokens - strict mode", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": [ - "--testTimeout=3600000", - "--runInBand", - "--no-cache", - "--config", - "${workspaceRoot}/tests/jest.config.tokens-strict.js", - ], - "outputCapture": "std", - "console": "integratedTerminal", - "preLaunchTask": "deploy:krypton", - "postDebugTask": "stop:krypton", - }, - { - "type": "node", - "request": "launch", - "name": "Jest: Tokens - metadata", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": [ - "--testTimeout=3600000", - "--runInBand", - "--no-cache", - "--config", - "${workspaceRoot}/tests/jest.config.tokens-metadata.js", - ], - "outputCapture": "std", - "console": "integratedTerminal", - "preLaunchTask": "deploy:krypton", - "postDebugTask": "stop:krypton", - }, { "type": "node", "request": "launch", diff --git a/migrations/1699540187362_remove-token-metadata.js b/migrations/1699540187362_remove-token-metadata.js new file mode 100644 index 0000000000..bef655efd7 --- /dev/null +++ b/migrations/1699540187362_remove-token-metadata.js @@ -0,0 +1,132 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.dropTable('token_metadata_queue'); + pgm.dropTable('nft_metadata'); + pgm.dropTable('ft_metadata'); +}; + +exports.down = pgm => { + pgm.createTable('token_metadata_queue', { + queue_id: { + type: 'serial', + primaryKey: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + contract_id: { + type: 'string', + notNull: true, + }, + contract_abi: { + type: 'string', + notNull: true, + }, + block_height: { + type: 'integer', + notNull: true, + }, + processed: { + type: 'boolean', + notNull: true, + }, + retry_count: { + type: 'integer', + notNull: true, + default: 0, + } + }); + pgm.createIndex('token_metadata_queue', [{ name: 'block_height', sort: 'DESC' }]); + pgm.createTable('nft_metadata', { + id: { + type: 'serial', + primaryKey: true, + }, + name: { + type: 'string', + notNull: true, + }, + token_uri: { + type: 'string', + notNull: true, + }, + description: { + type: 'string', + notNull: true, + }, + image_uri: { + type: 'string', + notNull: true, + }, + image_canonical_uri: { + type: 'string', + notNull: true, + }, + contract_id: { + type: 'string', + notNull: true, + unique: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + sender_address: { + type: 'string', + notNull: true, + } + }); + pgm.createIndex('nft_metadata', 'contract_id', { method: 'hash' }); + pgm.createTable('ft_metadata', { + id: { + type: 'serial', + primaryKey: true, + }, + name: { + type: 'string', + notNull: true, + }, + token_uri: { + type: 'string', + notNull: true, + }, + description: { + type: 'string', + notNull: true, + }, + image_uri: { + type: 'string', + notNull: true, + }, + image_canonical_uri: { + type: 'string', + notNull: true, + }, + contract_id: { + type: 'string', + notNull: true, + unique: true, + }, + symbol: { + type: 'string', + notNull: true, + }, + decimals: { + type: 'integer', + notNull: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + sender_address: { + type: 'string', + notNull: true, + } + }); + pgm.createIndex('ft_metadata', 'contract_id', { method: 'hash' }); +} diff --git a/package.json b/package.json index defce13e92..f1d69a9631 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,6 @@ "test:integration:rosetta-cli:construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:bns": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.bns.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:bns-e2e": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.bns-e2e.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:tokens-strict": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-strict.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:tokens-metadata": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.tokens-metadata.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:rpc": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.rpc.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:event-replay": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.event-replay.js --no-cache --runInBand; npm run devenv:stop\"", "test:integration:btc-faucet": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.bitcoind.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.btc-faucet.js --no-cache --runInBand; npm run devenv:stop\"", diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 8eca6563a4..20ba98bd91 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -63,7 +63,7 @@ import { } from '../../datastore/common'; import { unwrapOptional, FoundOrNot, unixEpochToIso, EMPTY_HASH_256, ChainID } from '../../helpers'; import { serializePostCondition, serializePostConditionMode } from '../serializers/post-conditions'; -import { getOperations, parseTransactionMemo } from '../../rosetta-helpers'; +import { getOperations, parseTransactionMemo } from '../../rosetta/rosetta-helpers'; import { PgStore } from '../../datastore/pg-store'; import { Pox2EventName } from '../../pox-helpers'; import { logger } from '../../logger'; @@ -164,30 +164,6 @@ export function getTxStatus(txStatus: DbTxStatus | string): string { } } -type EventTypeString = - | 'smart_contract_log' - | 'stx_asset' - | 'fungible_token_asset' - | 'non_fungible_token_asset' - | 'stx_lock'; - -export function getEventTypeString(eventTypeId: DbEventTypeId): EventTypeString { - switch (eventTypeId) { - case DbEventTypeId.SmartContractLog: - return 'smart_contract_log'; - case DbEventTypeId.StxAsset: - return 'stx_asset'; - case DbEventTypeId.FungibleTokenAsset: - return 'fungible_token_asset'; - case DbEventTypeId.NonFungibleTokenAsset: - return 'non_fungible_token_asset'; - case DbEventTypeId.StxLock: - return 'stx_lock'; - default: - throw new Error(`Unexpected DbEventTypeId: ${eventTypeId}`); - } -} - export function getAssetEventTypeString( assetEventTypeId: DbAssetEventTypeId ): 'transfer' | 'mint' | 'burn' { diff --git a/src/api/init.ts b/src/api/init.ts index f549296ac0..d2494e1334 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -31,7 +31,7 @@ import * as expressListEndpoints from 'express-list-endpoints'; import { createMiddleware as createPrometheusMiddleware } from '@promster/express'; import { createMicroblockRouter } from './routes/microblock'; import { createStatusRouter } from './routes/status'; -import { createTokenRouter } from './routes/tokens/tokens'; +import { createTokenRouter } from './routes/tokens'; import { createFeeRateRouter } from './routes/fee-rate'; import { setResponseNonCacheable } from './controllers/cache-controller'; diff --git a/src/api/routes/rosetta/account.ts b/src/api/routes/rosetta/account.ts index c333e5f455..469a40fdae 100644 --- a/src/api/routes/rosetta/account.ts +++ b/src/api/routes/rosetta/account.ts @@ -13,9 +13,8 @@ import { } from '@stacks/stacks-blockchain-api-types'; import { RosettaErrors, RosettaConstants, RosettaErrorsTypes } from '../../rosetta-constants'; import { rosettaValidateRequest, ValidSchema, makeRosettaError } from '../../rosetta-validate'; -import { getValidatedFtMetadata } from '../../../rosetta-helpers'; -import { isFtMetadataEnabled } from '../../../token-metadata/helpers'; import { has0xPrefix } from '@hirosystems/api-toolkit'; +import { RosettaFtMetadataClient } from '../../../rosetta/rosetta-ft-metadata-client'; export function createRosettaAccountRouter(db: PgStore, chainId: ChainID): express.Router { const router = express.Router(); @@ -122,22 +121,21 @@ export function createRosettaAccountRouter(db: PgStore, chainId: ChainID): expre ]; // Add Fungible Token balances. - if (isFtMetadataEnabled()) { - const ftBalances = await db.getFungibleTokenBalances({ - stxAddress: accountIdentifier.address, - untilBlock: block.block_height, - }); - for (const [ftAssetIdentifier, ftBalance] of ftBalances) { - const ftMetadata = await getValidatedFtMetadata(db, ftAssetIdentifier); - if (ftMetadata) { - balances.push({ - value: ftBalance.balance.toString(), - currency: { - symbol: ftMetadata.symbol, - decimals: ftMetadata.decimals, - }, - }); - } + const ftBalances = await db.getFungibleTokenBalances({ + stxAddress: accountIdentifier.address, + untilBlock: block.block_height, + }); + const metadataClient = new RosettaFtMetadataClient(chainId); + for (const [ftAssetIdentifier, ftBalance] of ftBalances) { + const ftMetadata = await metadataClient.getFtMetadata(ftAssetIdentifier); + if (ftMetadata) { + balances.push({ + value: ftBalance.balance.toString(), + currency: { + symbol: ftMetadata.symbol, + decimals: ftMetadata.decimals, + }, + }); } } diff --git a/src/api/routes/rosetta/construction.ts b/src/api/routes/rosetta/construction.ts index 49a9e2f074..011f2ee13d 100644 --- a/src/api/routes/rosetta/construction.ts +++ b/src/api/routes/rosetta/construction.ts @@ -80,7 +80,7 @@ import { rawTxToBaseTx, rawTxToStacksTransaction, verifySignature, -} from './../../../rosetta-helpers'; +} from '../../../rosetta/rosetta-helpers'; import { makeRosettaError, rosettaValidateRequest, ValidSchema } from './../../rosetta-validate'; import { has0xPrefix, hexToBuffer } from '@hirosystems/api-toolkit'; diff --git a/src/api/routes/rosetta/mempool.ts b/src/api/routes/rosetta/mempool.ts index 657fcaef2f..bdaee0b446 100644 --- a/src/api/routes/rosetta/mempool.ts +++ b/src/api/routes/rosetta/mempool.ts @@ -8,7 +8,7 @@ import { RosettaMempoolTransactionResponse, RosettaTransaction, } from '@stacks/stacks-blockchain-api-types'; -import { getOperations, parseTransactionMemo } from '../../../rosetta-helpers'; +import { getOperations, parseTransactionMemo } from '../../../rosetta/rosetta-helpers'; import { RosettaErrors, RosettaErrorsTypes } from '../../rosetta-constants'; import { has0xPrefix } from '@hirosystems/api-toolkit'; diff --git a/src/api/routes/tokens/tokens.ts b/src/api/routes/tokens.ts similarity index 65% rename from src/api/routes/tokens/tokens.ts rename to src/api/routes/tokens.ts index ba365a4949..50bec6ff8d 100644 --- a/src/api/routes/tokens/tokens.ts +++ b/src/api/routes/tokens.ts @@ -1,25 +1,20 @@ -import { asyncHandler } from '../../async-handler'; +import { asyncHandler } from '../async-handler'; import * as express from 'express'; import { - FungibleTokenMetadata, - FungibleTokensMetadataList, NonFungibleTokenHistoryEvent, NonFungibleTokenHistoryEventList, NonFungibleTokenHolding, NonFungibleTokenHoldingsList, - NonFungibleTokenMetadata, NonFungibleTokenMint, NonFungibleTokenMintList, - NonFungibleTokensMetadataList, } from '@stacks/stacks-blockchain-api-types'; -import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from './../../pagination'; -import { isFtMetadataEnabled, isNftMetadataEnabled } from '../../../token-metadata/helpers'; -import { isValidPrincipal } from '../../../helpers'; -import { booleanValueForParam, isUnanchoredRequest } from '../../../api/query-helpers'; +import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; +import { isValidPrincipal } from '../../helpers'; +import { booleanValueForParam, isUnanchoredRequest } from '../query-helpers'; import { decodeClarityValueToRepr } from 'stacks-encoding-native-js'; -import { getAssetEventTypeString, parseDbTx } from '../../controllers/db-controller'; -import { getETagCacheHandler, setETagCacheHeaders } from '../../controllers/cache-controller'; -import { PgStore } from '../../../datastore/pg-store'; +import { getAssetEventTypeString, parseDbTx } from '../controllers/db-controller'; +import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; +import { PgStore } from '../../datastore/pg-store'; import { has0xPrefix } from '@hirosystems/api-toolkit'; export function createTokenRouter(db: PgStore): express.Router { @@ -229,149 +224,5 @@ export function createTokenRouter(db: PgStore): express.Router { }) ); - router.get( - '/ft/metadata', - asyncHandler(async (req, res) => { - if (!isFtMetadataEnabled()) { - res.status(500).json({ - error: 'FT metadata processing is not enabled on this server', - }); - return; - } - - const limit = getPagingQueryLimit(ResourceType.Token, req.query.limit); - const offset = parsePagingQueryInput(req.query.offset ?? 0); - - const { results, total } = await db.getFtMetadataList({ offset, limit }); - - const response: FungibleTokensMetadataList = { - limit: limit, - offset: offset, - total: total, - results: results, - }; - - res.status(200).json(response); - }) - ); - - router.get( - '/nft/metadata', - asyncHandler(async (req, res) => { - if (!isNftMetadataEnabled()) { - res.status(500).json({ - error: 'NFT metadata processing is not enabled on this server', - }); - return; - } - - let limit: number; - try { - limit = getPagingQueryLimit(ResourceType.Token, req.query.limit); - } catch (error: any) { - res.status(400).json({ error: error.message }); - return; - } - - const offset = parsePagingQueryInput(req.query.offset ?? 0); - - const { results, total } = await db.getNftMetadataList({ offset, limit }); - - const response: NonFungibleTokensMetadataList = { - limit: limit, - offset: offset, - total: total, - results: results, - }; - - res.status(200).json(response); - }) - ); - - router.get( - '/:contractId/ft/metadata', - asyncHandler(async (req, res) => { - if (!isFtMetadataEnabled()) { - res.status(500).json({ - error: 'FT metadata processing is not enabled on this server', - }); - return; - } - - const { contractId } = req.params; - - const metadata = await db.getFtMetadata(contractId); - if (!metadata.found) { - res.status(404).json({ error: 'tokens not found' }); - return; - } - - const { - token_uri, - name, - description, - image_uri, - image_canonical_uri, - symbol, - decimals, - tx_id, - sender_address, - } = metadata.result; - - const response: FungibleTokenMetadata = { - token_uri: token_uri, - name: name, - description: description, - image_uri: image_uri, - image_canonical_uri: image_canonical_uri, - symbol: symbol, - decimals: decimals, - tx_id: tx_id, - sender_address: sender_address, - }; - res.status(200).json(response); - }) - ); - - router.get( - '/:contractId/nft/metadata', - asyncHandler(async (req, res) => { - if (!isNftMetadataEnabled()) { - res.status(500).json({ - error: 'NFT metadata processing is not enabled on this server', - }); - return; - } - - const { contractId } = req.params; - const metadata = await db.getNftMetadata(contractId); - - if (!metadata.found) { - res.status(404).json({ error: 'tokens not found' }); - return; - } - const { - token_uri, - name, - description, - image_uri, - image_canonical_uri, - tx_id, - sender_address, - } = metadata.result; - - const response: NonFungibleTokenMetadata = { - token_uri: token_uri, - name: name, - description: description, - image_uri: image_uri, - image_canonical_uri: image_canonical_uri, - tx_id: tx_id, - sender_address: sender_address, - }; - res.status(200).json(response); - }) - ); - return router; } diff --git a/src/datastore/common.ts b/src/datastore/common.ts index c9373f32e9..be4fd1ee98 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -546,12 +546,6 @@ export interface AddressNftEventIdentifier { asset_event_type_id: number; } -export interface TokenMetadataUpdateInfo { - queueId: number; - txId: string; - contractId: string; -} - export interface DataStoreBlockUpdateData { block: DbBlock; microblocks: DbMicroblock[]; @@ -750,40 +744,6 @@ export type BlockIdentifier = | { burnBlockHash: string } | { burnBlockHeight: number }; -export interface DbNonFungibleTokenMetadata { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - tx_id: string; - sender_address: string; -} - -export interface DbFungibleTokenMetadata { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - symbol: string; - decimals: number; - tx_id: string; - sender_address: string; -} - -export interface DbTokenMetadataQueueEntry { - queueId: number; - txId: string; - contractId: string; - contractAbi: ClarityAbi; - blockHeight: number; - processed: boolean; - retry_count: number; -} - export interface DbChainTip { blockHeight: number; indexBlockHash: string; @@ -1016,40 +976,6 @@ export interface BlocksWithMetadata { total: number; } -export interface NonFungibleTokenMetadataQueryResult { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - tx_id: string; - sender_address: string; -} - -export interface FungibleTokenMetadataQueryResult { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - symbol: string; - decimals: number; - tx_id: string; - sender_address: string; -} - -export interface DbTokenMetadataQueueEntryQuery { - queue_id: number; - tx_id: string; - contract_id: string; - contract_abi: string; - block_height: number; - processed: boolean; - retry_count: number; -} - export interface RawTxQueryResult { raw_tx: string; } @@ -1519,38 +1445,6 @@ export interface RewardSlotHolderInsertValues { slot_index: number; } -export interface TokenMetadataQueueEntryInsertValues { - tx_id: PgBytea; - contract_id: string; - contract_abi: string; - block_height: number; - processed: boolean; -} - -export interface NftMetadataInsertValues { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - tx_id: PgBytea; - sender_address: string; -} - -export interface FtMetadataInsertValues { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - symbol: string; - decimals: number; - tx_id: PgBytea; - sender_address: string; -} - export interface SmartContractInsertValues { tx_id: PgBytea; canonical: boolean; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 2f3e114b90..1e2e6327ca 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -35,7 +35,6 @@ import { DbEventTypeId, DbFtBalance, DbFtEvent, - DbFungibleTokenMetadata, DbGetBlockWithMetadataOpts, DbGetBlockWithMetadataResponse, DbInboundStxTransfer, @@ -44,7 +43,6 @@ import { DbMicroblock, DbMinerReward, DbNftEvent, - DbNonFungibleTokenMetadata, DbPox2Event, DbPox3Event, DbPox3Stacker, @@ -55,8 +53,6 @@ import { DbStxBalance, DbStxEvent, DbStxLockEvent, - DbTokenMetadataQueueEntry, - DbTokenMetadataQueueEntryQuery, DbTokenOfferingLocked, DbTx, DbTxGlobalStatus, @@ -64,13 +60,11 @@ import { DbTxTypeId, DbTxWithAssetTransfers, FaucetRequestQueryResult, - FungibleTokenMetadataQueryResult, MempoolTxQueryResult, MicroblockQueryResult, NftEventWithTxMetadata, NftHoldingInfo, NftHoldingInfoWithTxMetadata, - NonFungibleTokenMetadataQueryResult, Pox2EventQueryResult, Pox3EventQueryResult, RawTxQueryResult, @@ -1849,63 +1843,6 @@ export class PgStore extends BasePgStore { }); } - /** - * Returns a single entry from the `token_metadata_queue` table. - * @param queueId - queue entry id - */ - async getTokenMetadataQueueEntry( - queueId: number - ): Promise> { - const result = await this.sql` - SELECT * FROM token_metadata_queue WHERE queue_id = ${queueId} - `; - if (result.length === 0) { - return { found: false }; - } - const row = result[0]; - const entry: DbTokenMetadataQueueEntry = { - queueId: row.queue_id, - txId: row.tx_id, - contractId: row.contract_id, - contractAbi: JSON.parse(row.contract_abi), - blockHeight: row.block_height, - processed: row.processed, - retry_count: row.retry_count, - }; - return { found: true, result: entry }; - } - - async getTokenMetadataQueue( - limit: number, - excludingEntries: number[] - ): Promise { - const result = await this.sql` - SELECT * - FROM token_metadata_queue - WHERE ${ - excludingEntries.length - ? this.sql`NOT (queue_id IN ${this.sql(excludingEntries)})` - : this.sql`TRUE` - } - AND processed = false - ORDER BY block_height ASC, queue_id ASC - LIMIT ${limit} - `; - const entries = result.map(row => { - const entry: DbTokenMetadataQueueEntry = { - queueId: row.queue_id, - txId: row.tx_id, - contractId: row.contract_id, - contractAbi: JSON.parse(row.contract_abi), - blockHeight: row.block_height, - processed: row.processed, - retry_count: row.retry_count, - }; - return entry; - }); - return entries; - } - async getSmartContract(contractId: string) { const result = await this.sql< { @@ -4293,132 +4230,4 @@ export class PgStore extends BasePgStore { } return result; } - - async getFtMetadata(contractId: string): Promise> { - const queryResult = await this.sql` - SELECT token_uri, name, description, image_uri, image_canonical_uri, symbol, decimals, contract_id, tx_id, sender_address - FROM ft_metadata - WHERE contract_id = ${contractId} - LIMIT 1 - `; - if (queryResult.length > 0) { - const metadata: DbFungibleTokenMetadata = { - token_uri: queryResult[0].token_uri, - name: queryResult[0].name, - description: queryResult[0].description, - image_uri: queryResult[0].image_uri, - image_canonical_uri: queryResult[0].image_canonical_uri, - symbol: queryResult[0].symbol, - decimals: queryResult[0].decimals, - contract_id: queryResult[0].contract_id, - tx_id: queryResult[0].tx_id, - sender_address: queryResult[0].sender_address, - }; - return { - found: true, - result: metadata, - }; - } else { - return { found: false } as const; - } - } - - async getNftMetadata(contractId: string): Promise> { - const queryResult = await this.sql` - SELECT token_uri, name, description, image_uri, image_canonical_uri, contract_id, tx_id, sender_address - FROM nft_metadata - WHERE contract_id = ${contractId} - LIMIT 1 - `; - if (queryResult.length > 0) { - const metadata: DbNonFungibleTokenMetadata = { - token_uri: queryResult[0].token_uri, - name: queryResult[0].name, - description: queryResult[0].description, - image_uri: queryResult[0].image_uri, - image_canonical_uri: queryResult[0].image_canonical_uri, - contract_id: queryResult[0].contract_id, - tx_id: queryResult[0].tx_id, - sender_address: queryResult[0].sender_address, - }; - return { - found: true, - result: metadata, - }; - } else { - return { found: false } as const; - } - } - - async getFtMetadataList({ - limit, - offset, - }: { - limit: number; - offset: number; - }): Promise<{ results: DbFungibleTokenMetadata[]; total: number }> { - return await this.sqlTransaction(async sql => { - const totalQuery = await sql<{ count: number }[]>` - SELECT COUNT(*)::integer - FROM ft_metadata - `; - const resultQuery = await sql` - SELECT * - FROM ft_metadata - LIMIT ${limit} - OFFSET ${offset} - `; - const parsed = resultQuery.map(r => { - const metadata: DbFungibleTokenMetadata = { - name: r.name, - description: r.description, - token_uri: r.token_uri, - image_uri: r.image_uri, - image_canonical_uri: r.image_canonical_uri, - decimals: r.decimals, - symbol: r.symbol, - contract_id: r.contract_id, - tx_id: r.tx_id, - sender_address: r.sender_address, - }; - return metadata; - }); - return { results: parsed, total: totalQuery[0].count }; - }); - } - - async getNftMetadataList({ - limit, - offset, - }: { - limit: number; - offset: number; - }): Promise<{ results: DbNonFungibleTokenMetadata[]; total: number }> { - return await this.sqlTransaction(async sql => { - const totalQuery = await sql<{ count: number }[]>` - SELECT COUNT(*)::integer - FROM nft_metadata - `; - const resultQuery = await sql` - SELECT * - FROM nft_metadata - LIMIT ${limit} - OFFSET ${offset} - `; - const parsed = resultQuery.map(r => { - const metadata: DbNonFungibleTokenMetadata = { - name: r.name, - description: r.description, - token_uri: r.token_uri, - image_uri: r.image_uri, - image_canonical_uri: r.image_canonical_uri, - contract_id: r.contract_id, - tx_id: r.tx_id, - sender_address: r.sender_address, - }; - return metadata; - }); - return { results: parsed, total: totalQuery[0].count }; - }); - } } diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index ff86ad0e84..6cd51a0ce3 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -22,9 +22,6 @@ import { DataStoreMicroblockUpdateData, DbMicroblock, DataStoreTxEventData, - DbNonFungibleTokenMetadata, - DbFungibleTokenMetadata, - DbTokenMetadataQueueEntry, DbFaucetRequest, MinerRewardInsertValues, BlockInsertValues, @@ -42,12 +39,9 @@ import { TxInsertValues, MempoolTxInsertValues, MempoolTxQueryResult, - TokenMetadataQueueEntryInsertValues, SmartContractInsertValues, BnsNameInsertValues, BnsNamespaceInsertValues, - FtMetadataInsertValues, - NftMetadataInsertValues, FaucetRequestInsertValues, MicroblockInsertValues, TxQueryResult, @@ -66,7 +60,6 @@ import { IndexesState, NftCustodyInsertValues, } from './common'; -import { ClarityAbi } from '@stacks/transactions'; import { BLOCK_COLUMNS, convertTxQueryResultToDbMempoolTx, @@ -82,7 +75,6 @@ import { } from './helpers'; import { PgNotifier } from './pg-notifier'; import { MIGRATIONS_DIR, PgStore } from './pg-store'; -import { isProcessableTokenMetadata } from '../token-metadata/helpers'; import * as zoneFileParser from 'zone-file'; import { parseResolver, parseZoneFileTxt } from '../event-stream/bns/bns-helpers'; import { Pox2EventName } from '../pox-helpers'; @@ -200,7 +192,6 @@ export class PgWriteStore extends PgStore { } async update(data: DataStoreBlockUpdateData): Promise { - const tokenMetadataQueueEntries: DbTokenMetadataQueueEntry[] = []; let garbageCollectedMempoolTxs: string[] = []; let batchedTxData: DataStoreTxEventData[] = []; const deployedSmartContracts: DbSmartContract[] = []; @@ -418,34 +409,6 @@ export class PgWriteStore extends PgStore { logger.debug(`Garbage collected ${mempoolGarbageResults.deletedTxs.length} mempool txs`); } garbageCollectedMempoolTxs = mempoolGarbageResults.deletedTxs; - - const tokenContractDeployments = data.txs - .filter( - entry => - entry.tx.type_id === DbTxTypeId.SmartContract || - entry.tx.type_id === DbTxTypeId.VersionedSmartContract - ) - .filter(entry => entry.tx.status === DbTxStatus.Success) - .filter(entry => entry.smartContracts[0].abi && entry.smartContracts[0].abi !== 'null') - .map(entry => { - const smartContract = entry.smartContracts[0]; - const contractAbi: ClarityAbi = JSON.parse(smartContract.abi as string); - const queueEntry: DbTokenMetadataQueueEntry = { - queueId: -1, - txId: entry.tx.tx_id, - contractId: smartContract.contract_id, - contractAbi: contractAbi, - blockHeight: entry.tx.block_height, - processed: false, - retry_count: 0, - }; - return queueEntry; - }) - .filter(entry => isProcessableTokenMetadata(entry.contractAbi)); - for (const pendingQueueEntry of tokenContractDeployments) { - const queueEntry = await this.updateTokenMetadataQueue(sql, pendingQueueEntry); - tokenMetadataQueueEntries.push(queueEntry); - } } if (!this.isEventReplay) { @@ -490,9 +453,6 @@ export class PgWriteStore extends PgStore { eventIndex: nftEvent.event_index, }); } - for (const tokenMetadataQueueEntry of tokenMetadataQueueEntries) { - await this.notifier.sendTokenMetadata({ queueId: tokenMetadataQueueEntry.queueId }); - } } } @@ -1841,28 +1801,6 @@ export class PgWriteStore extends PgStore { } } - async updateTokenMetadataQueue( - sql: PgSqlClient, - entry: DbTokenMetadataQueueEntry - ): Promise { - const values: TokenMetadataQueueEntryInsertValues = { - tx_id: entry.txId, - contract_id: entry.contractId, - contract_abi: JSON.stringify(entry.contractAbi), - block_height: entry.blockHeight, - processed: false, - }; - const queryResult = await sql<{ queue_id: number }[]>` - INSERT INTO token_metadata_queue ${sql(values)} - RETURNING queue_id - `; - const result: DbTokenMetadataQueueEntry = { - ...entry, - queueId: queryResult[0].queue_id, - }; - return result; - } - async updateSmartContract(sql: PgSqlClient, tx: DbTx, smartContract: DbSmartContract) { const values: SmartContractInsertValues = { tx_id: smartContract.tx_id, @@ -2061,87 +1999,6 @@ export class PgWriteStore extends PgStore { `; } - async updateFtMetadata(ftMetadata: DbFungibleTokenMetadata, dbQueueId: number): Promise { - const length = await this.sqlWriteTransaction(async sql => { - const values: FtMetadataInsertValues = { - token_uri: ftMetadata.token_uri, - name: ftMetadata.name, - description: ftMetadata.description, - image_uri: ftMetadata.image_uri, - image_canonical_uri: ftMetadata.image_canonical_uri, - contract_id: ftMetadata.contract_id, - symbol: ftMetadata.symbol, - decimals: ftMetadata.decimals, - tx_id: ftMetadata.tx_id, - sender_address: ftMetadata.sender_address, - }; - const result = await sql` - INSERT INTO ft_metadata ${sql(values)} - ON CONFLICT (contract_id) - DO - UPDATE SET ${sql(values)} - `; - await sql` - UPDATE token_metadata_queue - SET processed = true - WHERE queue_id = ${dbQueueId} - `; - return result.count; - }); - await this.notifier?.sendTokens({ contractID: ftMetadata.contract_id }); - return length; - } - - async updateNFtMetadata( - nftMetadata: DbNonFungibleTokenMetadata, - dbQueueId: number - ): Promise { - const length = await this.sqlWriteTransaction(async sql => { - const values: NftMetadataInsertValues = { - token_uri: nftMetadata.token_uri, - name: nftMetadata.name, - description: nftMetadata.description, - image_uri: nftMetadata.image_uri, - image_canonical_uri: nftMetadata.image_canonical_uri, - contract_id: nftMetadata.contract_id, - tx_id: nftMetadata.tx_id, - sender_address: nftMetadata.sender_address, - }; - const result = await sql` - INSERT INTO nft_metadata ${sql(values)} - ON CONFLICT (contract_id) - DO - UPDATE SET ${sql(values)} - `; - await sql` - UPDATE token_metadata_queue - SET processed = true - WHERE queue_id = ${dbQueueId} - `; - return result.count; - }); - await this.notifier?.sendTokens({ contractID: nftMetadata.contract_id }); - return length; - } - - async updateProcessedTokenMetadataQueueEntry(queueId: number): Promise { - await this.sql` - UPDATE token_metadata_queue - SET processed = true - WHERE queue_id = ${queueId} - `; - } - - async increaseTokenMetadataQueueEntryRetryCount(queueId: number): Promise { - const result = await this.sql<{ retry_count: number }[]>` - UPDATE token_metadata_queue - SET retry_count = retry_count + 1 - WHERE queue_id = ${queueId} - RETURNING retry_count - `; - return result[0].retry_count; - } - async updateBatchTokenOfferingLocked(sql: PgSqlClient, lockedInfos: DbTokenOfferingLocked[]) { try { const res = await sql` diff --git a/src/helpers.ts b/src/helpers.ts index 41e30ee0c1..ac8ab8216a 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -646,49 +646,6 @@ export function normalizeHashString(input: string): string | false { return `0x${hashBuffer.toString('hex')}`; } -export function parseDataUrl( - s: string -): - | { mediaType?: string; contentType?: string; charset?: string; base64: boolean; data: string } - | false { - try { - const url = new URL(s); - if (url.protocol !== 'data:') { - return false; - } - const validDataUrlRegex = - /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()|~`]+)*)?(;base64)?,(.*)$/i; - const parts = validDataUrlRegex.exec(s.trim()); - if (parts === null) { - return false; - } - const parsed: { - mediaType?: string; - contentType?: string; - charset?: string; - base64: boolean; - data: string; - } = { - base64: false, - data: '', - }; - if (parts[1]) { - parsed.mediaType = parts[1].toLowerCase(); - const mediaTypeParts = parts[1].split(';').map(x => x.toLowerCase()); - parsed.contentType = mediaTypeParts[0]; - mediaTypeParts.slice(1).forEach(attribute => { - const p = attribute.split('='); - Object.assign(parsed, { [p[0]]: p[1] }); - }); - } - parsed.base64 = !!parts[parts.length - 2]; - parsed.data = parts[parts.length - 1] || ''; - return parsed; - } catch (e) { - return false; - } -} - /** * Unsigned 32-bit integer. * - Mainnet: 0x00000001 diff --git a/src/index.ts b/src/index.ts index 0e94cc7c9f..cf220a553f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,8 +18,6 @@ import { injectC32addressEncodeCache } from './c32-addr-cache'; import { exportEventsAsTsv, importEventsFromTsv } from './event-replay/event-replay'; import { PgStore } from './datastore/pg-store'; import { PgWriteStore } from './datastore/pg-write-store'; -import { isFtMetadataEnabled, isNftMetadataEnabled } from './token-metadata/helpers'; -import { TokensProcessorQueue } from './token-metadata/tokens-processor-queue'; import { registerMempoolPromStats } from './datastore/helpers'; import { logger } from './logger'; import { ReplayController } from './event-replay/parquet-based/replay-controller'; @@ -162,23 +160,6 @@ async function init(): Promise { monitorCoreRpcConnection().catch(error => { logger.error(error, 'Error monitoring RPC connection'); }); - - if (!isFtMetadataEnabled()) { - logger.warn('Fungible Token metadata processing is not enabled.'); - } - if (!isNftMetadataEnabled()) { - logger.warn('Non-Fungible Token metadata processing is not enabled.'); - } - if (isFtMetadataEnabled() || isNftMetadataEnabled()) { - const tokenMetadataProcessor = new TokensProcessorQueue(dbWriteStore, configuredChainID); - registerShutdownConfig({ - name: 'Token Metadata Processor', - handler: () => tokenMetadataProcessor.close(), - forceKillable: true, - }); - // Enqueue a batch of pending token metadata processors, if any. - await tokenMetadataProcessor.checkDbQueue(); - } } if ( diff --git a/src/rosetta/rosetta-ft-metadata-client.ts b/src/rosetta/rosetta-ft-metadata-client.ts new file mode 100644 index 0000000000..8d11618d30 --- /dev/null +++ b/src/rosetta/rosetta-ft-metadata-client.ts @@ -0,0 +1,204 @@ +import { + ClarityType, + ClarityValue, + getAddressFromPrivateKey, + hexToCV, + makeRandomPrivKey, + TransactionVersion, + UIntCV, +} from '@stacks/transactions'; +import { ChainID, getChainIDNetwork } from '../helpers'; +import { ReadOnlyContractCallResponse, StacksCoreRpcClient } from '../core-rpc/client'; +import { logger } from '../logger'; +import * as LRUCache from 'lru-cache'; + +/** Fungible token metadata for Rosetta operations display */ +export interface RosettaFtMetadata { + symbol: string; + decimals: number; +} + +interface RosettaFtContractCallParams { + address: string; + contractAddress: string; + contractName: string; + functionName: string; +} + +enum RosettaTokenMetadataErrorMode { + /** Default mode. If a required token metadata is not found when it is needed for a response, the + * API will issue a warning. */ + warning, + /** If a required token metadata is not found, the API will throw an error. */ + error, +} + +/** + * Determines the token metadata error handling mode based on .env values. + * @returns TokenMetadataMode + */ +function tokenMetadataErrorMode(): RosettaTokenMetadataErrorMode { + switch (process.env['STACKS_API_TOKEN_METADATA_ERROR_MODE']) { + case 'error': + return RosettaTokenMetadataErrorMode.error; + default: + return RosettaTokenMetadataErrorMode.warning; + } +} + +function isFtMetadataEnabled() { + const opt = process.env['STACKS_API_ENABLE_FT_METADATA']?.toLowerCase().trim(); + return opt === '1' || opt === 'true'; +} + +/** + * LRU cache that keeps `RosettaFtMetadata` entries for FTs used in the Stacks chain and retrieved + * by the Rosetta endpoints. + */ +const ftMetadataCache = new LRUCache>({ + max: 5_000, +}); + +/** + * Retrieves FT metadata for tokens used by Rosetta. Keeps data in cache for faster future + * retrieval. + */ +export class RosettaFtMetadataClient { + private readonly chainId: ChainID; + private readonly nodeRpcClient: StacksCoreRpcClient; + + constructor(chainId: ChainID) { + this.chainId = chainId; + this.nodeRpcClient = new StacksCoreRpcClient(); + } + + getFtMetadata(assetIdentifier: string): Promise { + if (!isFtMetadataEnabled()) return Promise.resolve(undefined); + const cachedMetadata = ftMetadataCache.get(assetIdentifier); + if (cachedMetadata) return cachedMetadata; + + const resolvePromise = this.resolveFtMetadata(assetIdentifier); + ftMetadataCache.set(assetIdentifier, resolvePromise); + // If the promise is rejected, remove the entry from the cache so that it can be retried later. + resolvePromise.catch(_ => { + ftMetadataCache.del(assetIdentifier); + }); + return resolvePromise; + } + + private async resolveFtMetadata(assetIdentifier: string): Promise { + const tokenContractId = assetIdentifier.split('::')[0]; + const [contractAddress, contractName] = tokenContractId.split('.'); + try { + const address = getAddressFromPrivateKey( + makeRandomPrivKey().data, + getChainIDNetwork(this.chainId) === 'mainnet' + ? TransactionVersion.Mainnet + : TransactionVersion.Testnet + ); + const symbol = await this.readStringFromContract({ + functionName: 'get-symbol', + contractAddress, + contractName, + address, + }); + const decimals = await this.readUIntFromContract({ + functionName: 'get-decimals', + contractAddress, + contractName, + address, + }); + if (symbol !== undefined && decimals !== undefined) { + const metadata = { symbol, decimals: parseInt(decimals.toString()) }; + return metadata; + } + } catch (error) { + if (tokenMetadataErrorMode() === RosettaTokenMetadataErrorMode.warning) { + logger.warn(error, `FT metadata not found for token: ${assetIdentifier}`); + } else { + throw new Error(`FT metadata not found for token: ${assetIdentifier}`); + } + } + } + + private async readStringFromContract( + args: RosettaFtContractCallParams + ): Promise { + const clarityValue = await this.makeReadOnlyContractCall(args); + return this.checkAndParseString(clarityValue); + } + + private async readUIntFromContract( + args: RosettaFtContractCallParams + ): Promise { + const clarityValue = await this.makeReadOnlyContractCall(args); + const uintVal = this.checkAndParseUintCV(clarityValue); + try { + return BigInt(uintVal.value.toString()); + } catch (error) { + throw new Error(`Invalid uint value '${uintVal}'`); + } + } + + private unwrapClarityType(clarityValue: ClarityValue): ClarityValue { + let unwrappedClarityValue: ClarityValue = clarityValue; + while ( + unwrappedClarityValue.type === ClarityType.ResponseOk || + unwrappedClarityValue.type === ClarityType.OptionalSome + ) { + unwrappedClarityValue = unwrappedClarityValue.value; + } + return unwrappedClarityValue; + } + + private checkAndParseUintCV(responseCV: ClarityValue): UIntCV { + const unwrappedClarityValue = this.unwrapClarityType(responseCV); + if (unwrappedClarityValue.type === ClarityType.UInt) { + return unwrappedClarityValue; + } + throw new Error( + `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping uint` + ); + } + + private checkAndParseString(responseCV: ClarityValue): string | undefined { + const unwrappedClarityValue = this.unwrapClarityType(responseCV); + if ( + unwrappedClarityValue.type === ClarityType.StringASCII || + unwrappedClarityValue.type === ClarityType.StringUTF8 + ) { + return unwrappedClarityValue.data; + } else if (unwrappedClarityValue.type === ClarityType.OptionalNone) { + return undefined; + } + throw new Error( + `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping string` + ); + } + + private async makeReadOnlyContractCall(args: RosettaFtContractCallParams): Promise { + let result: ReadOnlyContractCallResponse; + try { + result = await this.nodeRpcClient.sendReadOnlyContractCall( + args.contractAddress, + args.contractName, + args.functionName, + args.address, + [] + ); + } catch (error) { + throw new Error(`Error making read-only contract call: ${error}`); + } + if (!result.okay) { + // Only runtime errors reported by the Stacks node should be retryable. + if ( + result.cause.startsWith('Runtime') || + result.cause.startsWith('Unchecked(NoSuchContract') + ) { + throw new Error(`Runtime error while calling read-only function ${args.functionName}`); + } + throw new Error(`Error calling read-only function ${args.functionName}`); + } + return hexToCV(result.result); + } +} diff --git a/src/rosetta-helpers.ts b/src/rosetta/rosetta-helpers.ts similarity index 95% rename from src/rosetta-helpers.ts rename to src/rosetta/rosetta-helpers.ts index 50cb6f9f6b..ebeb48f9b3 100644 --- a/src/rosetta-helpers.ts +++ b/src/rosetta/rosetta-helpers.ts @@ -25,26 +25,23 @@ import { StacksMainnet, StacksTestnet } from '@stacks/network'; import { ec as EC } from 'elliptic'; import * as btc from 'bitcoinjs-lib'; import { - getAssetEventTypeString, - getEventTypeString, getTxFromDataStore, getTxStatus, getTxTypeString, parseContractCallMetadata, -} from './api/controllers/db-controller'; +} from '../api/controllers/db-controller'; import { PoxContractIdentifier, RosettaConstants, RosettaNetworks, RosettaOperationType, -} from './api/rosetta-constants'; +} from '../api/rosetta-constants'; import { BaseTx, DbAssetEventTypeId, DbEvent, DbEventTypeId, DbFtEvent, - DbFungibleTokenMetadata, DbMempoolTx, DbMinerReward, DbStxEvent, @@ -53,12 +50,11 @@ import { DbTxStatus, DbTxTypeId, StxUnlockEvent, -} from './datastore/common'; -import { getTxSenderAddress, getTxSponsorAddress } from './event-stream/reader'; -import { unwrapOptional, getSendManyContract } from './helpers'; +} from '../datastore/common'; +import { getTxSenderAddress, getTxSponsorAddress } from '../event-stream/reader'; +import { unwrapOptional, getSendManyContract } from '../helpers'; -import { getCoreNodeEndpoint } from './core-rpc/client'; -import { TokenMetadataErrorMode } from './token-metadata/tokens-contract-handler'; +import { getCoreNodeEndpoint } from '../core-rpc/client'; import { ClarityTypeID, decodeClarityValue, @@ -76,12 +72,12 @@ import { ClarityValue, ClarityValueList, } from 'stacks-encoding-native-js'; -import { PgStore } from './datastore/pg-store'; -import { isFtMetadataEnabled, tokenMetadataErrorMode } from './token-metadata/helpers'; +import { PgStore } from '../datastore/pg-store'; import { poxAddressToBtcAddress } from '@stacks/stacking'; import { parseRecoverableSignatureVrs } from '@stacks/common'; -import { logger } from './logger'; +import { logger } from '../logger'; import { hexToBuffer } from '@hirosystems/api-toolkit'; +import { RosettaFtMetadata, RosettaFtMetadataClient } from './rosetta-ft-metadata-client'; enum CoinAction { CoinSpent = 'coin_spent', @@ -243,6 +239,7 @@ async function processEvents( // match them by index. const sendManyMemos = decodeSendManyContractCallMemos(baseTx, chainID); let sendManyStxTransferEventIndex = 0; + const metadataClient = new RosettaFtMetadataClient(chainID); for (const event of events) { const txEventType = event.event_type; @@ -298,7 +295,7 @@ async function processEvents( case DbEventTypeId.NonFungibleTokenAsset: break; case DbEventTypeId.FungibleTokenAsset: - const ftMetadata = await getValidatedFtMetadata(db, event.asset_identifier); + const ftMetadata = await metadataClient.getFtMetadata(event.asset_identifier); if (!ftMetadata) { break; } @@ -435,7 +432,7 @@ function makeBurnOperation(tx: DbStxEvent, baseTx: BaseTx, index: number): Roset function makeFtBurnOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, baseTx: BaseTx, index: number ): RosettaOperation { @@ -482,7 +479,7 @@ function makeMintOperation(tx: DbStxEvent, baseTx: BaseTx, index: number): Roset function makeFtMintOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, baseTx: BaseTx, index: number ): RosettaOperation { @@ -548,7 +545,7 @@ function makeSenderOperation( function makeFtSenderOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, tx: BaseTx, index: number ): RosettaOperation { @@ -621,7 +618,7 @@ function makeReceiverOperation( function makeFtReceiverOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, tx: BaseTx, index: number ): RosettaOperation { @@ -1148,28 +1145,6 @@ export function rawTxToBaseTx(raw_tx: string): BaseTx { return dbTx; } -export async function getValidatedFtMetadata( - db: PgStore, - assetIdentifier: string -): Promise { - if (!isFtMetadataEnabled()) { - return; - } - const tokenContractId = assetIdentifier.split('::')[0]; - const ftMetadata = await db.getFtMetadata(tokenContractId); - if (!ftMetadata.found) { - if (tokenMetadataErrorMode() === TokenMetadataErrorMode.warning) { - logger.warn(`FT metadata not found for token: ${assetIdentifier}`); - } else { - // TODO: Check if the metadata wasn't found because the contract ABI is not SIP-010 - // compliant or because there was a recoverable error that prevented the metadata - // from being processed. - throw new Error(`FT metadata not found for token: ${assetIdentifier}`); - } - } - return ftMetadata.result; -} - export function getSigners(transaction: StacksTransaction): RosettaAccountIdentifier[] | undefined { let address; if (transaction.payload.payloadType == PayloadType.TokenTransfer) { @@ -1218,7 +1193,7 @@ export function getSigners(transaction: StacksTransaction): RosettaAccountIdenti return account_identifier_signers; } -export function getStacksTestnetNetwork() { +function getStacksTestnetNetwork() { return new StacksTestnet({ url: `http://${getCoreNodeEndpoint()}`, }); diff --git a/src/tests-rosetta-construction/construction.ts b/src/tests-rosetta-construction/construction.ts index 4a6eacfa63..3c40d9d4bd 100644 --- a/src/tests-rosetta-construction/construction.ts +++ b/src/tests-rosetta-construction/construction.ts @@ -50,7 +50,7 @@ import { RosettaOperationTypes, } from '../api/rosetta-constants'; import { getStacksTestnetNetwork, testnetKeys } from '../api/routes/debug'; -import { getSignature, getStacksNetwork } from '../rosetta-helpers'; +import { getSignature, getStacksNetwork } from '../rosetta/rosetta-helpers'; import { makeSigHashPreSign, MessageSignature } from '@stacks/transactions'; import { PgWriteStore } from '../datastore/pg-write-store'; import { decodeBtcAddress } from '@stacks/stacking'; diff --git a/src/tests-rosetta/account-tests.ts b/src/tests-rosetta/account-tests.ts index 4dbb795b3f..53de71efc2 100644 --- a/src/tests-rosetta/account-tests.ts +++ b/src/tests-rosetta/account-tests.ts @@ -1,10 +1,11 @@ import * as supertest from 'supertest'; -import { ChainID } from '@stacks/transactions'; +import { ChainID, cvToHex, stringUtf8CV, uintCV } from '@stacks/transactions'; import { ApiServer, startApiServer } from '../api/init'; import { TestBlockBuilder } from '../test-utils/test-builders'; -import { DbAssetEventTypeId, DbFungibleTokenMetadata } from '../datastore/common'; +import { DbAssetEventTypeId } from '../datastore/common'; import { PgWriteStore } from '../datastore/pg-write-store'; import { migrate } from '../test-utils/test-helpers'; +import nock = require('nock'); describe('/account tests', () => { let db: PgWriteStore; @@ -27,20 +28,21 @@ describe('/account tests', () => { const addr1 = 'SP3WV3VC6GM1WF215SDHP0MESQ3BNXHB1N6TPB70S'; const addr2 = 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y'; - // Declare fungible token - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'https://cdn.citycoins.co/metadata/newyorkcitycoin.json', - name: 'newyorkcitycoin', - description: 'A CityCoin for New York City, ticker is NYC, Stack it to earn Stacks (STX)', - image_uri: 'https://stacks-api.imgix.net/https%3A%2F%2Fcdn.citycoins.co%2Flogos%2Fnewyorkcitycoin.png?s=38a8d89aa6b4ef3fcc9958da3eb34480', - image_canonical_uri: 'https://cdn.citycoins.co/logos/newyorkcitycoin.png', - symbol: 'NYC', - decimals: 0, - tx_id: '0x9c8ddc44fcfdfc67af5425c4174833fc5814627936d573fe38fc29a46ba746e6', - sender_address: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5', - contract_id: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5.newyorkcitycoin-token' - }; - await db.updateFtMetadata(ftMetadata, 1); + const nodeUrl = `http://${process.env['STACKS_CORE_RPC_HOST']}:${process.env['STACKS_CORE_RPC_PORT']}`; + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-decimals') + .reply(200, { + okay: true, + result: cvToHex(uintCV(0)), + }); + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-symbol') + .reply(200, { + okay: true, + result: cvToHex(stringUtf8CV('NYC')), + }); // FT transfer const block1 = new TestBlockBuilder({ @@ -98,5 +100,6 @@ describe('/account tests', () => { value: '7500' } ]); + nock.cleanAll(); }); }); diff --git a/src/tests-rosetta/block-tests.ts b/src/tests-rosetta/block-tests.ts index 8d662355a4..d8e2d67701 100644 --- a/src/tests-rosetta/block-tests.ts +++ b/src/tests-rosetta/block-tests.ts @@ -1,13 +1,14 @@ import * as supertest from 'supertest'; -import { bufferCV, ChainID, cvToHex, listCV, stringAsciiCV, tupleCV, uintCV } from '@stacks/transactions'; +import { bufferCV, ChainID, cvToHex, listCV, stringAsciiCV, stringUtf8CV, tupleCV, uintCV } from '@stacks/transactions'; import { ApiServer, startApiServer } from '../api/init'; import { TestBlockBuilder } from '../test-utils/test-builders'; -import { DbAssetEventTypeId, DbFungibleTokenMetadata, DbTxTypeId } from '../datastore/common'; +import { DbAssetEventTypeId, DbTxTypeId } from '../datastore/common'; import { createClarityValueArray } from '../stacks-encoding-helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; import { principalCV } from '@stacks/transactions/dist/clarity/types/principalCV'; import { migrate } from '../test-utils/test-helpers'; import { bufferToHex } from '@hirosystems/api-toolkit'; +import nock = require('nock'); describe('/block tests', () => { let db: PgWriteStore; @@ -116,20 +117,21 @@ describe('/block tests', () => { const addr1 = 'SP3WV3VC6GM1WF215SDHP0MESQ3BNXHB1N6TPB70S'; const addr2 = 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y'; - // Declare fungible token - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'https://cdn.citycoins.co/metadata/newyorkcitycoin.json', - name: 'newyorkcitycoin', - description: 'A CityCoin for New York City, ticker is NYC, Stack it to earn Stacks (STX)', - image_uri: 'https://stacks-api.imgix.net/https%3A%2F%2Fcdn.citycoins.co%2Flogos%2Fnewyorkcitycoin.png?s=38a8d89aa6b4ef3fcc9958da3eb34480', - image_canonical_uri: 'https://cdn.citycoins.co/logos/newyorkcitycoin.png', - symbol: 'NYC', - decimals: 0, - tx_id: '0x9c8ddc44fcfdfc67af5425c4174833fc5814627936d573fe38fc29a46ba746e6', - sender_address: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5', - contract_id: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5.newyorkcitycoin-token' - }; - await db.updateFtMetadata(ftMetadata, 1); + const nodeUrl = `http://${process.env['STACKS_CORE_RPC_HOST']}:${process.env['STACKS_CORE_RPC_PORT']}`; + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-decimals') + .reply(200, { + okay: true, + result: cvToHex(uintCV(0)), + }); + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-symbol') + .reply(200, { + okay: true, + result: cvToHex(stringUtf8CV('NYC')), + }); // FT transfer const block1 = new TestBlockBuilder({ diff --git a/src/tests-rosetta/offline-api-tests.ts b/src/tests-rosetta/offline-api-tests.ts index 2887db0bb1..73577fa3b4 100644 --- a/src/tests-rosetta/offline-api-tests.ts +++ b/src/tests-rosetta/offline-api-tests.ts @@ -48,7 +48,7 @@ import { } from '../api/rosetta-constants'; import { OfflineDummyStore } from '../datastore/offline-dummy-store'; import { getStacksTestnetNetwork, testnetKeys } from '../api/routes/debug'; -import { getSignature, getStacksNetwork, publicKeyToBitcoinAddress } from '../rosetta-helpers'; +import { getSignature, getStacksNetwork, publicKeyToBitcoinAddress } from '../rosetta/rosetta-helpers'; import * as nock from 'nock'; import { PgStore } from '../datastore/pg-store'; import { decodeBtcAddress } from '@stacks/stacking'; diff --git a/src/tests-tokens-metadata/setup.ts b/src/tests-tokens-metadata/setup.ts deleted file mode 100644 index f2d1cf887b..0000000000 --- a/src/tests-tokens-metadata/setup.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { loadDotEnv } from '../helpers'; - -// ts-unused-exports:disable-next-line -export default () => { - console.log('Jest - setup..'); - if (!process.env.NODE_ENV) { - process.env.NODE_ENV = 'test'; - } - loadDotEnv(); - process.env.PG_DATABASE = 'postgres'; - process.env.STACKS_CHAIN_ID = '0x80000000'; - console.log('Jest - setup done'); -}; diff --git a/src/tests-tokens-metadata/teardown.ts b/src/tests-tokens-metadata/teardown.ts deleted file mode 100644 index 8638723d18..0000000000 --- a/src/tests-tokens-metadata/teardown.ts +++ /dev/null @@ -1,5 +0,0 @@ -// ts-unused-exports:disable-next-line -export default () => { - console.log('Jest - teardown..'); - console.log('Jest - teardown done'); -}; diff --git a/src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar b/src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar deleted file mode 100644 index a773a93d5f..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; (impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "data:,%7B%22name%22%3A%22Heystack%22%2C%22description%22%3A%22Heystack%20is%20a%20SIP-010-compliant%20fungible%20token%22%2C%22imageUrl%22%3A%22https%3A%2F%2Fheystack.xyz%2Fassets%2FStacks128w.png%22%7D"))) - -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar b/src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar deleted file mode 100644 index a8dfbf21c5..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; (impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "data:;base64,eyJuYW1lIjoiSGV5c3RhY2siLCJkZXNjcmlwdGlvbiI6IkhleXN0YWNrIGlzIGEgU0lQLTAxMC1jb21wbGlhbnQgZnVuZ2libGUgdG9rZW4iLCJpbWFnZVVybCI6Imh0dHBzOi8vaGV5c3RhY2sueHl6L2Fzc2V0cy9TdGFja3MxMjh3LnBuZyJ9"))) - -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar b/src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar deleted file mode 100644 index fa335337ac..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; (impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "data:application/json,{\"name\":\"Heystack\",\"description\":\"Heystack is a SIP-010-compliant fungible token\",\"imageUrl\":\"https://heystack.xyz/assets/Stacks128w.png\"}"))) - ;; (ok (some "data:text/html,"))) -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/beeple.clar b/src/tests-tokens-metadata/test-contracts/beeple.clar deleted file mode 100644 index d7ea8b693b..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple.clar +++ /dev/null @@ -1,58 +0,0 @@ -(impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "ipfs://ipfs/QmPAg1mjxcEQPPtqsLoEcauVedaeMH81WXDPvPx3VC5zUz"))) - -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/ft-trait.clar b/src/tests-tokens-metadata/test-contracts/ft-trait.clar deleted file mode 100644 index 69255cf9e9..0000000000 --- a/src/tests-tokens-metadata/test-contracts/ft-trait.clar +++ /dev/null @@ -1,24 +0,0 @@ -(define-trait sip-010-trait - ( - ;; Transfer from the caller to a new principal - (transfer (uint principal principal (optional (buff 34))) (response bool uint)) - - ;; the human readable name of the token - (get-name () (response (string-ascii 32) uint)) - - ;; the ticker symbol, or empty if none - (get-symbol () (response (string-ascii 32) uint)) - - ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token - (get-decimals () (response uint uint)) - - ;; the balance of the passed principal - (get-balance (principal) (response uint uint)) - - ;; the current total supply (which does not need to be a constant) - (get-total-supply () (response uint uint)) - - ;; an optional URI that represents metadata of this token - (get-token-uri () (response (optional (string-utf8 256)) uint)) - ) -) diff --git a/src/tests-tokens-metadata/test-contracts/hey-token.clar b/src/tests-tokens-metadata/test-contracts/hey-token.clar deleted file mode 100644 index bd9a50c5c1..0000000000 --- a/src/tests-tokens-metadata/test-contracts/hey-token.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; Implement the `ft-trait` trait defined in the `ft-trait` contract -;; https://github.com/hstove/stacks-fungible-token -(impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.ft-trait.sip-010-trait) - -(define-constant contract-creator tx-sender) - -(define-fungible-token hey-token) - -;; Mint developer tokens -(ft-mint? hey-token u10000 contract-creator) -(ft-mint? hey-token u10000 'ST399W7Z9WS0GMSNQGJGME5JADNKN56R65VGM5KGA) ;; fara -(ft-mint? hey-token u10000 'ST1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHEG3NHN3) ;; thomas -(ft-mint? hey-token u10000 'ST1NY8TXACV7D74886MK05SYW2XA72XJMDVPF3F3D) ;; kyran -(ft-mint? hey-token u10000 'ST34XEPDJJFJKFPT87CCZQCPGXR4PJ8ERFRP0F3GX) ;; jasper -(ft-mint? hey-token u10000 'ST3AGWHGAZKQS4JQ67WQZW5X8HZYZ4ZBWPPNWNMKF) ;; andres -(ft-mint? hey-token u10000 'ST17YZQB1228EK9MPHQXA8GC4G3HVWZ66X779FEBY) ;; esh -(ft-mint? hey-token u10000 'ST3Q0M9WAVBW633CG72VHNFZM2H82D2BJMBX85WP4) ;; mark - -;; get the token balance of owner -(define-read-only (get-balance (owner principal)) - (begin - (ok (ft-get-balance hey-token owner)))) - -;; returns the total number of tokens -(define-read-only (get-total-supply) - (ok (ft-get-supply hey-token))) - -;; returns the token name -(define-read-only (get-name) - (ok "Heystack Token")) - -;; the symbol or "ticker" for this token -(define-read-only (get-symbol) - (ok "HEY")) - -;; the number of decimals used -(define-read-only (get-decimals) - (ok u0)) - -;; Transfers tokens to a recipient -(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) - (if (is-eq tx-sender sender) - (begin - (try! (ft-transfer? hey-token amount sender recipient)) - (print memo) - (ok true) - ) - (err u4))) - -(define-read-only (get-token-uri) - (ok (some u"https://heystack.xyz/token-metadata.json"))) - -(define-public (gift-tokens (recipient principal)) - (begin - (asserts! (is-eq tx-sender recipient) (err u0)) - (ft-mint? hey-token u1 recipient) - ) -) diff --git a/src/tests-tokens-metadata/test-contracts/nft-trait.clar b/src/tests-tokens-metadata/test-contracts/nft-trait.clar deleted file mode 100644 index cc558fdb5a..0000000000 --- a/src/tests-tokens-metadata/test-contracts/nft-trait.clar +++ /dev/null @@ -1,15 +0,0 @@ -(define-trait nft-trait - ( - ;; Last token ID, limited to uint range - (get-last-token-id () (response uint uint)) - - ;; URI for metadata associated with the token - (get-token-uri (uint) (response (optional (string-ascii 256)) uint)) - - ;; Owner of a given token identifier - (get-owner (uint) (response (optional principal) uint)) - - ;; Transfer from the sender to a new principal - (transfer (uint principal principal) (response bool uint)) - ) -) diff --git a/src/tests-tokens-metadata/tokens-metadata-tests.ts b/src/tests-tokens-metadata/tokens-metadata-tests.ts deleted file mode 100644 index 1bc4c23ff8..0000000000 --- a/src/tests-tokens-metadata/tokens-metadata-tests.ts +++ /dev/null @@ -1,404 +0,0 @@ -import * as supertest from 'supertest'; -import { - makeContractDeploy, - ChainID, - getAddressFromPrivateKey, - PostConditionMode, - AnchorMode, -} from '@stacks/transactions'; -import { DbFungibleTokenMetadata, DbNonFungibleTokenMetadata } from '../datastore/common'; -import { startApiServer, ApiServer } from '../api/init'; -import * as fs from 'fs'; -import { EventStreamServer, startEventServer } from '../event-stream/event-server'; -import { getStacksTestnetNetwork } from '../rosetta-helpers'; -import { StacksCoreRpcClient } from '../core-rpc/client'; -import * as nock from 'nock'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { TokensProcessorQueue } from '../token-metadata/tokens-processor-queue'; -import { performFetch } from '../token-metadata/helpers'; -import { getPagingQueryLimit, ResourceType } from '../api/pagination'; -import { migrate, standByForTx as standByForTxShared } from '../test-utils/test-helpers'; -import { logger } from '../logger'; -import { Waiter, waiter, timeout } from '@hirosystems/api-toolkit'; - -const deploymentAddr = 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6'; -const pKey = 'cb3df38053d132895220b9ce471f6b676db5b9bf0b4adefb55f2118ece2478df01'; -const stacksNetwork = getStacksTestnetNetwork(); - -describe('tokens metadata tests', () => { - let db: PgWriteStore; - let api: ApiServer; - let eventServer: EventStreamServer; - let tokensProcessorQueue: TokensProcessorQueue; - - const standByForTx = (expectedTxId: string) => standByForTxShared(expectedTxId, api); - - function standByForTokens(id: string): Promise { - const contractId = new Promise(resolve => { - tokensProcessorQueue.processEndEvent.attachOnce( - token => token.contractId === id, - () => resolve() - ); - }); - - return contractId; - } - - async function sendCoreTx(serializedTx: Buffer): Promise<{ txId: string }> { - try { - const submitResult = await new StacksCoreRpcClient().sendTransaction(serializedTx); - return submitResult; - } catch (error) { - logger.error(error); - } - return Promise.resolve({ txId: '' }); - } - - async function deployContract(contractName: string, senderPk: string, sourceFile: string) { - const senderAddress = getAddressFromPrivateKey(senderPk, stacksNetwork.version); - const source = fs.readFileSync(sourceFile).toString(); - const normalized_contract_source = source.replace(/\r/g, '').replace(/\t/g, ' '); - - const contractDeployTx = await makeContractDeploy({ - contractName: contractName, - codeBody: normalized_contract_source, - senderKey: senderPk, - network: stacksNetwork, - postConditionMode: PostConditionMode.Allow, - sponsored: false, - anchorMode: AnchorMode.Any, - fee: 100000, - }); - - const contractId = senderAddress + '.' + contractName; - - // const feeRateReq = await fetch(stacksNetwork.getTransferFeeEstimateApiUrl()); - // const feeRateResult = await feeRateReq.text(); - // const txBytes = BigInt(Buffer.from(contractDeployTx.serialize()).byteLength); - // const feeRate = BigInt(feeRateResult); - // const fee = feeRate * txBytes; - // contractDeployTx.setFee(fee); - const { txId } = await sendCoreTx(Buffer.from(contractDeployTx.serialize())); - return { txId, contractId }; - } - - beforeAll(async () => { - await migrate('up'); - db = await PgWriteStore.connect({ usageName: 'tests', skipMigrations: true }); - eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); - api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); - tokensProcessorQueue = new TokensProcessorQueue(db, ChainID.Testnet); - await new StacksCoreRpcClient().waitForConnection(60000); - }); - - beforeEach(() => { - process.env['STACKS_API_ENABLE_FT_METADATA'] = '1'; - process.env['STACKS_API_ENABLE_NFT_METADATA'] = '1'; - process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'] = '1'; - nock.cleanAll(); - }); - - afterAll(async () => { - await eventServer.closeAsync(); - tokensProcessorQueue.close(); - await api.forceKill(); - await db?.close(); - await migrate('down'); - }); - - test('metadata disabled', async () => { - process.env['STACKS_API_ENABLE_FT_METADATA'] = '0'; - process.env['STACKS_API_ENABLE_NFT_METADATA'] = '0'; - const query1 = await supertest(api.server).get(`/extended/v1/tokens/nft/metadata`); - expect(query1.status).toBe(500); - expect(query1.body.error).toMatch(/not enabled/); - const query2 = await supertest(api.server).get(`/extended/v1/tokens/ft/metadata`); - expect(query2.status).toBe(500); - expect(query2.body.error).toMatch(/not enabled/); - const query3 = await supertest(api.server).get(`/extended/v1/tokens/example/nft/metadata`); - expect(query3.status).toBe(500); - expect(query3.body.error).toMatch(/not enabled/); - const query4 = await supertest(api.server).get(`/extended/v1/tokens/example/ft/metadata`); - expect(query4.status).toBe(500); - expect(query4.body.error).toMatch(/not enabled/); - }); - - test('token nft-metadata data URL plain percent-encoded', async () => { - const standByPromise = standByForTokens(`${deploymentAddr}.beeple-a`); - const contract1 = await deployContract( - 'beeple-a', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar' - ); - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body).toHaveProperty('description'); - expect(query1.body).toHaveProperty('image_uri'); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('failed processing is retried in next block', async () => { - const entryProcessedWaiter: Waiter = waiter(); - const blockHandler = async (blockHash: string) => { - const entry = await db.getTokenMetadataQueueEntry(1); - if (entry.result?.processed) { - entryProcessedWaiter.finish(blockHash); - } - }; - db.eventEmitter.on('blockUpdate', blockHandler); - // Set as not processed. - await db.sql` - UPDATE token_metadata_queue - SET processed = false - WHERE queue_id = 1 - `; - // This will resolve when processed is true again. - await entryProcessedWaiter; - db.eventEmitter.off('blockUpdate', blockHandler); - }); - - test('token nft-metadata data URL base64 w/o media type', async () => { - const standByPromise = standByForTokens(`${deploymentAddr}.beeple-b`); - const contract1 = await deployContract( - 'beeple-b', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body).toHaveProperty('description'); - expect(query1.body).toHaveProperty('image_uri'); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token nft-metadata data URL plain non-encoded', async () => { - const standByPromise = standByForTokens(`${deploymentAddr}.beeple-c`); - const contract1 = await deployContract( - 'beeple-c', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body).toHaveProperty('description'); - expect(query1.body).toHaveProperty('image_uri'); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token nft-metadata', async () => { - //mock the response - const nftMetadata = { - name: 'EVERYDAYS: THE FIRST 5000 DAYS', - imageUrl: - 'https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq', - description: - 'I made a picture from start to finish every single day from May 1st, 2007 - January 7th, 2021. This is every motherfucking one of those pictures.', - }; - nock('https://ipfs.io') - .persist() - .get('/ipfs/QmPAg1mjxcEQPPtqsLoEcauVedaeMH81WXDPvPx3VC5zUz') - .reply(200, nftMetadata); - - const contract = await deployContract( - 'nft-trait', - pKey, - 'src/tests-tokens-metadata/test-contracts/nft-trait.clar' - ); - const tx = await standByForTx(contract.txId); - if (tx.status != 1) logger.error(tx, 'contract deploy error'); - - const standByPromise = standByForTokens(`${deploymentAddr}.beeple`); - const contract1 = await deployContract( - 'beeple', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const senderAddress = getAddressFromPrivateKey(pKey, stacksNetwork.version); - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${senderAddress}.beeple/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body.name).toBe(nftMetadata.name); - expect(query1.body.description).toBe(nftMetadata.description); - expect(query1.body.image_uri).toBe(nftMetadata.imageUrl); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token ft-metadata tests', async () => { - //mock the response - const ftMetadata = { - name: 'Heystack', - description: - 'Heystack is a SIP-010-compliant fungible token on the Stacks Blockchain, used on the Heystack app', - image: 'https://heystack.xyz/assets/Stacks128w.png', - }; - - // https://heystack.xyz/token-metadata.json - nock('https://heystack.xyz').persist().get('/token-metadata.json').reply(200, ftMetadata); - - const contract = await deployContract( - 'ft-trait', - pKey, - 'src/tests-tokens-metadata/test-contracts/ft-trait.clar' - ); - - const tx = await standByForTx(contract.txId); - if (tx.status != 1) logger.error(tx, 'contract deploy error'); - - const standByPromise = standByForTokens(`${deploymentAddr}.hey-token`); - const contract1 = await deployContract( - 'hey-token', - pKey, - 'src/tests-tokens-metadata/test-contracts/hey-token.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/ft/metadata` - ); - - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body.description).toBe(ftMetadata.description); - expect(query1.body.image_uri).toBe(ftMetadata.image); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token ft-metadata list', async () => { - for (let i = 0; i < 200; i++) { - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'ft-token', - name: 'ft-metadata' + i, - description: 'ft -metadata description', - symbol: 'stx', - decimals: 5, - image_uri: 'ft-metadata image uri example', - image_canonical_uri: 'ft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.ft-metadata' + i, - tx_id: '0x123456', - sender_address: 'ABCDEFGHIJ', - }; - await db.updateFtMetadata(ftMetadata, 1); - } - - const query = await supertest(api.server).get(`/extended/v1/tokens/ft/metadata`); - expect(query.status).toBe(200); - expect(query.body.total).toBeGreaterThan(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.limit).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.offset).toStrictEqual(0); - expect(query.body.results.length).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/ft/metadata?limit=20&offset=10` - ); - expect(query1.status).toBe(200); - expect(query1.body.total).toBeGreaterThanOrEqual(200); - expect(query1.body.limit).toStrictEqual(20); - expect(query1.body.offset).toStrictEqual(10); - expect(query1.body.results.length).toStrictEqual(20); - }); - - test('token nft-metadata list', async () => { - for (let i = 0; i < 200; i++) { - const nftMetadata: DbNonFungibleTokenMetadata = { - token_uri: 'nft-tokenuri', - name: 'nft-metadata' + i, - description: 'nft -metadata description' + i, - image_uri: 'nft-metadata image uri example', - image_canonical_uri: 'nft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.nft-metadata' + i, - tx_id: '0x12345678', - sender_address: 'ABCDEFGHIJ', - }; - - await db.updateNFtMetadata(nftMetadata, 1); - } - - const query = await supertest(api.server).get(`/extended/v1/tokens/nft/metadata`); - expect(query.status).toBe(200); - expect(query.body.total).toBeGreaterThan(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.limit).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.offset).toStrictEqual(0); - expect(query.body.results.length).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/nft/metadata?limit=20&offset=10` - ); - expect(query1.status).toBe(200); - expect(query1.body.total).toBeGreaterThanOrEqual(200); - expect(query1.body.limit).toStrictEqual(20); - expect(query1.body.offset).toStrictEqual(10); - expect(query1.body.results.length).toStrictEqual(20); - }); - - test('large metadata payload test', async () => { - //mock the response - const maxResponseBytes = 10_000; - const randomData = Buffer.alloc(maxResponseBytes + 100, 'x', 'utf8'); - nock('https://example.com').persist().get('/large_payload').reply(200, randomData.toString()); - - await expect(async () => { - await performFetch('https://example.com/large_payload', { - maxResponseBytes: maxResponseBytes, - }); - }).rejects.toThrow(/over limit/); - }); - - test('timeout metadata payload test', async () => { - //mock the response - const responseTimeout = 100; - nock('https://example.com') - .persist() - .get('/timeout_payload') - .reply(200, async (_uri, _requestBody, cb) => { - await timeout(responseTimeout + 200); - cb(null, '{"hello":"world"}'); - }); - - await expect(async () => { - await performFetch('https://example.com/timeout_payload', { - timeoutMs: responseTimeout, - }); - }).rejects.toThrow(/network timeout/); - }); -}); diff --git a/src/tests-tokens-strict/setup.ts b/src/tests-tokens-strict/setup.ts deleted file mode 100644 index 7cb3c98c09..0000000000 --- a/src/tests-tokens-strict/setup.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defaultSetupInit } from '../test-utils/shared-setup'; - -// ts-unused-exports:disable-next-line -export default async () => { - console.log('Jest - setup..'); - await defaultSetupInit(); - console.log('Jest - setup done'); -}; diff --git a/src/tests-tokens-strict/strict-mode-tests.ts b/src/tests-tokens-strict/strict-mode-tests.ts deleted file mode 100644 index a57f94a875..0000000000 --- a/src/tests-tokens-strict/strict-mode-tests.ts +++ /dev/null @@ -1,388 +0,0 @@ -import * as nock from 'nock'; -import { ChainID, ClarityAbi, cvToHex, noneCV, uintCV } from '@stacks/transactions'; -import { PoolClient } from 'pg'; -import { TestBlockBuilder } from '../test-utils/test-builders'; -import { ApiServer, startApiServer } from '../api/init'; -import { - METADATA_MAX_PAYLOAD_BYTE_SIZE, - TokensContractHandler, -} from '../token-metadata/tokens-contract-handler'; -import { DbTxTypeId } from '../datastore/common'; -import { stringCV } from '@stacks/transactions/dist/clarity/types/stringCV'; -import { getTokenMetadataFetchTimeoutMs } from '../token-metadata/helpers'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { TokensProcessorQueue } from '../token-metadata/tokens-processor-queue'; -import { migrate } from '../test-utils/test-helpers'; - -const NFT_CONTRACT_ABI: ClarityAbi = { - maps: [], - functions: [ - { - access: 'read_only', - args: [], - name: 'get-last-token-id', - outputs: { - type: { - response: { - ok: 'uint128', - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ name: 'any', type: 'uint128' }], - name: 'get-token-uri', - outputs: { - type: { - response: { - ok: { - optional: { 'string-ascii': { length: 256 } }, - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ type: 'uint128', name: 'any' }], - name: 'get-owner', - outputs: { - type: { - response: { - ok: { - optional: 'principal', - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'public', - args: [ - { type: 'uint128', name: 'id' }, - { type: 'principal', name: 'sender' }, - { type: 'principal', name: 'recipient' }, - ], - name: 'transfer', - outputs: { - type: { - response: { - ok: 'bool', - error: { - tuple: [ - { type: { 'string-ascii': { length: 32 } }, name: 'kind' }, - { type: 'uint128', name: 'code' }, - ], - }, - }, - }, - }, - }, - ], - variables: [ - { - name: 'nft-not-found-err', - type: { response: { ok: 'none', error: 'uint128' } }, - access: 'constant', - }, - { - name: 'nft-not-owned-err', - type: { response: { ok: 'none', error: 'uint128' } }, - access: 'constant', - }, - { - name: 'sender-equals-recipient-err', - type: { response: { ok: 'none', error: 'uint128' } }, - access: 'constant', - }, - ], - fungible_tokens: [], - non_fungible_tokens: [{ name: 'beeple', type: 'uint128' }], -}; - -describe('token metadata strict mode', () => { - let db: PgWriteStore; - let api: ApiServer; - - const contractId = 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1'; - const contractTxId = '0x1f1f'; - - beforeEach(async () => { - await migrate('up'); - db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false }); - api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); - - process.env['STACKS_API_ENABLE_FT_METADATA'] = '1'; - process.env['STACKS_API_ENABLE_NFT_METADATA'] = '1'; - process.env['STACKS_CORE_RPC_PORT'] = '20443'; - nock.cleanAll(); - - const block = new TestBlockBuilder({ block_height: 1, index_block_hash: '0x01' }) - .addTx() - .addTx({ - tx_id: contractTxId, - type_id: DbTxTypeId.SmartContract, - smart_contract_contract_id: contractId, - smart_contract_source_code: '(source)', - }) - .addTxSmartContract({ - contract_id: contractId, - contract_source: '(source)', - abi: JSON.stringify(NFT_CONTRACT_ABI), - }) - .build(); - await db.update(block); - }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await migrate('down'); - }); - - test('retryable error increases retry_count', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toBe(1); - expect(entry.result?.processed).toBe(false); - }); - - test('retry_count limit reached marks entry as processed', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] = '0'; - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(true); - }); - - test('strict mode ignores retry_count limit', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'] = '1'; - process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] = '0'; - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(false); - }); - - test('db errors are handled gracefully in contract handler', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'] = '1'; - process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] = '0'; - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await db.close(); // End connection to trigger postgres error - await expect(handler.start()).resolves.not.toThrow(); - }); - - test('db errors are handled gracefully in queue', async () => { - const queue = new TokensProcessorQueue(db, ChainID.Testnet); - await db.close(); // End connection to trigger postgres error - await expect(queue.checkDbQueue()).resolves.not.toThrow(); - await expect(queue.drainDbQueue()).resolves.not.toThrow(); - await expect(queue.queueNotificationHandler(1)).resolves.not.toThrow(); - await expect( - queue.queueHandler({ queueId: 1, txId: '0x11', contractId: 'test' }) - ).resolves.not.toThrow(); - }); - - test('node runtime errors get retried', async () => { - const mockResponse = { - okay: false, - cause: 'Runtime(Foo(Bar))', - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(false); - }); - - test('other node errors fail immediately', async () => { - const mockResponse = { - okay: false, - cause: 'Unchecked(Foo(Bar))', - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - }); - - test('clarity value parse errors get retried', async () => { - const mockResponse = { - okay: true, - result: cvToHex(uintCV(5)), // `get-token-uri` will fail because this is a `uint` - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(false); - }); - - test('incorrect none uri strings are parsed as undefined', async () => { - const mockResponse = { - okay: true, - result: cvToHex(noneCV()), - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - const metadata = await db.getNftMetadata( - 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1' - ); - expect(metadata.result?.token_uri).toEqual(''); - }); - - test('metadata timeout errors get retried immediately', async () => { - process.env['STACKS_API_TOKEN_METADATA_FETCH_TIMEOUT_MS'] = '500'; - const mockTokenUri = { - okay: true, - result: cvToHex(stringCV('http://indigo.com/nft.jpeg', 'ascii')), - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockTokenUri); - // Timeout first time. - nock('http://indigo.com') - .get('/nft.jpeg') - .times(1) - .delay(getTokenMetadataFetchTimeoutMs() + 100) - .reply(200); - // Correct second time. - nock('http://indigo.com').get('/nft.jpeg').reply(200, {}); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - }); - - test('metadata size exceeded errors fail immediately', async () => { - const mockTokenUri = { - okay: true, - result: cvToHex(stringCV('http://indigo.com/nft.jpeg', 'ascii')), - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockTokenUri); - const bigAssBuffer = Buffer.alloc(METADATA_MAX_PAYLOAD_BYTE_SIZE + 100); - nock('http://indigo.com').get('/nft.jpeg').reply(200, bigAssBuffer); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - - // Metadata still contains the rest of the data. - const metadata = await db.getNftMetadata(contractId); - expect(metadata.found).toBe(true); - expect(metadata.result?.token_uri).toBe('http://indigo.com/nft.jpeg'); - }); -}); diff --git a/src/tests-tokens-strict/teardown.ts b/src/tests-tokens-strict/teardown.ts deleted file mode 100644 index 53858b8433..0000000000 --- a/src/tests-tokens-strict/teardown.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defaultSetupTeardown } from '../test-utils/shared-setup'; - -// ts-unused-exports:disable-next-line -export default async () => { - console.log('Jest - teardown..'); - await defaultSetupTeardown(); - console.log('Jest - teardown done'); -}; diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index d08f864878..197ef2f1ce 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -18,8 +18,6 @@ import { DbBnsName, DbBnsSubdomain, DbTokenOfferingLocked, - DbNonFungibleTokenMetadata, - DbFungibleTokenMetadata, DbTx, } from '../datastore/common'; import { getBlocksWithMetadata, parseDbEvent } from '../api/controllers/db-controller'; @@ -4918,48 +4916,6 @@ describe('postgres datastore', () => { expect(results.found).toBe(false); }); - test('pg token nft-metadata', async () => { - const nftMetadata: DbNonFungibleTokenMetadata = { - token_uri: 'nft-tokenuri', - name: 'nft-metadata', - description: 'nft -metadata description', - image_uri: 'nft-metadata image uri example', - image_canonical_uri: 'nft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.nft-metadata', - tx_id: '0x1234', - sender_address: 'sender-addr-test', - }; - - const rowCount = await db.updateNFtMetadata(nftMetadata, 1); - expect(rowCount).toBe(1); - - const query = await db.getNftMetadata(nftMetadata.contract_id); - expect(query.found).toBe(true); - if (query.found) expect(query.result).toStrictEqual(nftMetadata); - }); - - test('pg token ft-metadata', async () => { - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'ft-token', - name: 'ft-metadata', - description: 'ft -metadata description', - symbol: 'stx', - decimals: 5, - image_uri: 'ft-metadata image uri example', - image_canonical_uri: 'ft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.ft-metadata', - tx_id: '0x1234', - sender_address: 'sender-addr-test', - }; - - const rowCount = await db.updateFtMetadata(ftMetadata, 1); - expect(rowCount).toBe(1); - - const query = await db.getFtMetadata(ftMetadata.contract_id); - expect(query.found).toBe(true); - if (query.found) expect(query.result).toStrictEqual(ftMetadata); - }); - test('empty parameter lists are handled correctly', async () => { const block = new TestBlockBuilder({ block_height: 1 }).addTx().build(); await db.update(block); diff --git a/src/token-metadata/helpers.ts b/src/token-metadata/helpers.ts deleted file mode 100644 index 17154bae17..0000000000 --- a/src/token-metadata/helpers.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { ClarityAbi, ClarityAbiFunction } from '@stacks/transactions'; -import { - METADATA_MAX_PAYLOAD_BYTE_SIZE, - TokenMetadataErrorMode, - TokenMetadataProcessingMode, -} from './tokens-contract-handler'; -import fetch from 'node-fetch'; -import { parseBoolean } from '@hirosystems/api-toolkit'; - -export function isFtMetadataEnabled() { - const opt = process.env['STACKS_API_ENABLE_FT_METADATA']?.toLowerCase().trim(); - return opt === '1' || opt === 'true'; -} - -export function isNftMetadataEnabled() { - const opt = process.env['STACKS_API_ENABLE_NFT_METADATA']?.toLowerCase().trim(); - return opt === '1' || opt === 'true'; -} - -/** - * Determines the token metadata processing mode based on .env values. - * @returns TokenMetadataProcessingMode - */ -export function getTokenMetadataProcessingMode(): TokenMetadataProcessingMode { - if (parseBoolean(process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'])) { - return TokenMetadataProcessingMode.strict; - } - return TokenMetadataProcessingMode.default; -} - -export function getTokenMetadataMaxRetries() { - const opt = process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] ?? '5'; - return parseInt(opt); -} - -export function getTokenMetadataFetchTimeoutMs() { - const opt = process.env['STACKS_API_TOKEN_METADATA_FETCH_TIMEOUT_MS'] ?? '10000'; - return parseInt(opt); -} - -/** - * Determines the token metadata error handling mode based on .env values. - * @returns TokenMetadataMode - */ -export function tokenMetadataErrorMode(): TokenMetadataErrorMode { - switch (process.env['STACKS_API_TOKEN_METADATA_ERROR_MODE']) { - case 'error': - return TokenMetadataErrorMode.error; - default: - return TokenMetadataErrorMode.warning; - } -} - -const FT_FUNCTIONS: ClarityAbiFunction[] = [ - { - access: 'public', - args: [ - { type: 'uint128', name: 'amount' }, - { type: 'principal', name: 'sender' }, - { type: 'principal', name: 'recipient' }, - { type: { optional: { buffer: { length: 34 } } }, name: 'memo' }, - ], - name: 'transfer', - outputs: { type: { response: { ok: 'bool', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-name', - outputs: { type: { response: { ok: { 'string-ascii': { length: 32 } }, error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-symbol', - outputs: { type: { response: { ok: { 'string-ascii': { length: 32 } }, error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-decimals', - outputs: { type: { response: { ok: 'uint128', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [{ type: 'principal', name: 'address' }], - name: 'get-balance', - outputs: { type: { response: { ok: 'uint128', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-total-supply', - outputs: { type: { response: { ok: 'uint128', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-token-uri', - outputs: { - type: { - response: { - ok: { - optional: { 'string-ascii': { length: 256 } }, - }, - error: 'uint128', - }, - }, - }, - }, -]; - -const NFT_FUNCTIONS: ClarityAbiFunction[] = [ - { - access: 'read_only', - args: [], - name: 'get-last-token-id', - outputs: { - type: { - response: { - ok: 'uint128', - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ name: 'any', type: 'uint128' }], - name: 'get-token-uri', - outputs: { - type: { - response: { - ok: { - optional: { 'string-ascii': { length: 256 } }, - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ type: 'uint128', name: 'any' }], - name: 'get-owner', - outputs: { - type: { - response: { - ok: { - optional: 'principal', - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'public', - args: [ - { type: 'uint128', name: 'id' }, - { type: 'principal', name: 'sender' }, - { type: 'principal', name: 'recipient' }, - ], - name: 'transfer', - outputs: { - type: { - response: { - ok: 'bool', - error: { - tuple: [ - { type: { 'string-ascii': { length: 32 } }, name: 'kind' }, - { type: 'uint128', name: 'code' }, - ], - }, - }, - }, - }, - }, -]; - -/** - * Checks if the given ABI contains functions from FT or NFT metadata standards (e.g. sip-09, sip-10) which can be resolved. - * The function also checks if the server has FT and/or NFT metadata processing enabled. - */ -export function isProcessableTokenMetadata(abi: ClarityAbi): boolean { - return ( - (isFtMetadataEnabled() && isCompliantFt(abi)) || (isNftMetadataEnabled() && isCompliantNft(abi)) - ); -} - -export function isCompliantNft(abi: ClarityAbi): boolean { - if (abi.non_fungible_tokens.length > 0) { - if (abiContains(abi, NFT_FUNCTIONS)) { - return true; - } - } - return false; -} - -export function isCompliantFt(abi: ClarityAbi): boolean { - if (abi.fungible_tokens.length > 0) { - if (abiContains(abi, FT_FUNCTIONS)) { - return true; - } - } - return false; -} - -/** - * This method check if the contract is compliance with sip-09 and sip-10 - * Ref: https://github.com/stacksgov/sips/tree/main/sips - */ -function abiContains(abi: ClarityAbi, standardFunction: ClarityAbiFunction[]): boolean { - return standardFunction.every(abiFun => findFunction(abiFun, abi.functions)); -} - -/** - * check if the fun exist in the function list - * @param fun - function to be found - * @param functionList - list of functions - * @returns - true if function is in the list false otherwise - */ -function findFunction(fun: ClarityAbiFunction, functionList: ClarityAbiFunction[]): boolean { - const found = functionList.find(standardFunction => { - if (standardFunction.name !== fun.name || standardFunction.args.length !== fun.args.length) - return false; - for (let i = 0; i < fun.args.length; i++) { - if (standardFunction.args[i].type.toString() !== fun.args[i].type.toString()) { - return false; - } - } - return true; - }); - return found !== undefined; -} - -export async function performFetch( - url: string, - opts?: { - timeoutMs?: number; - maxResponseBytes?: number; - } -): Promise { - const result = await fetch(url, { - size: opts?.maxResponseBytes ?? METADATA_MAX_PAYLOAD_BYTE_SIZE, - timeout: opts?.timeoutMs ?? getTokenMetadataFetchTimeoutMs(), - }); - if (!result.ok) { - let msg = ''; - try { - msg = await result.text(); - } catch (error) { - // ignore errors from fetching error text - } - throw new Error(`Response ${result.status}: ${result.statusText} fetching ${url} - ${msg}`); - } - const resultString = await result.text(); - try { - return JSON.parse(resultString) as Type; - } catch (error) { - throw new Error(`Error parsing response from ${url} as JSON: ${error}`); - } -} diff --git a/src/token-metadata/tokens-contract-handler.ts b/src/token-metadata/tokens-contract-handler.ts deleted file mode 100644 index 5a75b47087..0000000000 --- a/src/token-metadata/tokens-contract-handler.ts +++ /dev/null @@ -1,535 +0,0 @@ -import * as child_process from 'child_process'; -import { DbFungibleTokenMetadata, DbNonFungibleTokenMetadata } from '../datastore/common'; -import { - ClarityAbi, - ClarityType, - ClarityValue, - getAddressFromPrivateKey, - hexToCV, - makeRandomPrivKey, - TransactionVersion, - uintCV, - UIntCV, -} from '@stacks/transactions'; -import { ChainID, getChainIDNetwork, parseDataUrl, REPO_DIR } from '../helpers'; -import * as querystring from 'querystring'; -import { - getTokenMetadataFetchTimeoutMs, - getTokenMetadataMaxRetries, - getTokenMetadataProcessingMode, - isCompliantFt, - isCompliantNft, - performFetch, -} from './helpers'; -import { ReadOnlyContractCallResponse, StacksCoreRpcClient } from '../core-rpc/client'; -import { FetchError } from 'node-fetch'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { logger } from '../logger'; -import { stopwatch } from '@hirosystems/api-toolkit'; - -/** - * The maximum number of bytes of metadata to fetch. - * If the fetch encounters more bytes than this limit it throws and the metadata is not processed. - */ -export const METADATA_MAX_PAYLOAD_BYTE_SIZE = 1_000_000; // 1 megabyte - -/** - * The max number of immediate attempts that will be made to retrieve metadata from external URIs before declaring - * the failure as a non-retryable error. - */ -const METADATA_MAX_IMMEDIATE_RETRY_COUNT = 5; - -const PUBLIC_IPFS = 'https://ipfs.io'; - -export enum TokenMetadataProcessingMode { - /** If a recoverable processing error occurs, we'll try again until the max retry attempt is reached. See `.env` */ - default, - /** If a recoverable processing error occurs, we'll try again indefinitely. */ - strict, -} - -export enum TokenMetadataErrorMode { - /** Default mode. If a required token metadata is not found when it is needed for a response, the API will issue a warning. */ - warning, - /** If a required token metadata is not found, the API will throw an error. */ - error, -} - -/** - * A token metadata fetch/process error caused by something that we can try to do again later. - */ -class RetryableTokenMetadataError extends Error { - constructor(message: string) { - super(message); - this.message = message; - this.name = this.constructor.name; - } -} - -interface NftTokenMetadata { - name: string; - imageUri: string; - description: string; -} - -interface FtTokenMetadata { - name: string; - imageUri: string; - description: string; -} - -interface TokenHandlerArgs { - contractId: string; - smartContractAbi: ClarityAbi; - datastore: PgWriteStore; - chainId: ChainID; - txId: string; - dbQueueId: number; -} - -/** - * This class downloads, parses and indexes metadata info for a Fungible or Non-Fungible token in the Stacks blockchain - * by calling read-only functions in SIP-009 and SIP-010 compliant smart contracts. - */ -export class TokensContractHandler { - readonly contractAddress: string; - readonly contractName: string; - readonly contractId: string; - readonly txId: string; - readonly dbQueueId: number; - private readonly db: PgWriteStore; - private readonly randomPrivKey = makeRandomPrivKey(); - private readonly chainId: ChainID; - private readonly address: string; - private readonly tokenKind: 'ft' | 'nft'; - private readonly nodeRpcClient: StacksCoreRpcClient; - - constructor(args: TokenHandlerArgs) { - [this.contractAddress, this.contractName] = args.contractId.split('.'); - this.contractId = args.contractId; - this.db = args.datastore; - this.chainId = args.chainId; - this.txId = args.txId; - this.dbQueueId = args.dbQueueId; - this.nodeRpcClient = new StacksCoreRpcClient(); - - this.address = getAddressFromPrivateKey( - this.randomPrivKey.data, - getChainIDNetwork(this.chainId) === 'mainnet' - ? TransactionVersion.Mainnet - : TransactionVersion.Testnet - ); - if (isCompliantFt(args.smartContractAbi)) { - this.tokenKind = 'ft'; - } else if (isCompliantNft(args.smartContractAbi)) { - this.tokenKind = 'nft'; - } else { - throw new Error( - `TokenContractHandler passed an ABI that isn't compliant to FT or NFT standards` - ); - } - } - - async start() { - logger.info( - `[token-metadata] found ${ - this.tokenKind === 'ft' ? 'sip-010-ft-standard' : 'sip-009-nft-standard' - } compliant contract ${this.contractId} in tx ${this.txId}, begin retrieving metadata...` - ); - const sw = stopwatch(); - // This try/catch block will catch any and all errors that are generated while processing metadata - // (contract call errors, parse errors, timeouts, etc.). Fortunately, each of them were previously tagged - // as retryable or not retryable so we'll make a decision here about what to do in each case. - // If we choose to retry, this queue entry will simply not be marked as `processed = true` so it can be - // picked up by the `TokensProcessorQueue` at a later time. - let processingFinished = false; - try { - if (this.tokenKind === 'ft') { - await this.handleFtContract(); - } else if (this.tokenKind === 'nft') { - await this.handleNftContract(); - } - processingFinished = true; - } catch (error) { - if (error instanceof RetryableTokenMetadataError) { - try { - const retries = await this.db.increaseTokenMetadataQueueEntryRetryCount(this.dbQueueId); - if ( - getTokenMetadataProcessingMode() === TokenMetadataProcessingMode.strict || - retries <= getTokenMetadataMaxRetries() - ) { - logger.info( - `[token-metadata] a recoverable error happened while processing ${this.contractId}, trying again later: ${error}` - ); - } else { - logger.warn( - `[token-metadata] max retries reached while processing ${this.contractId}, giving up: ${error}` - ); - processingFinished = true; - } - } catch (error) { - logger.error(error); - processingFinished = true; - } - } else { - // Something more serious happened, mark this contract as done. - logger.error(error); - processingFinished = true; - } - } finally { - if (processingFinished) { - try { - await this.db.updateProcessedTokenMetadataQueueEntry(this.dbQueueId); - logger.info( - `[token-metadata] finished processing ${this.contractId} in ${sw.getElapsed()} ms` - ); - } catch (error) { - logger.error(error); - } - } - } - } - - /** - * fetch Fungible contract metadata - */ - private async handleFtContract() { - const contractCallName = await this.readStringFromContract('get-name'); - const contractCallUri = await this.readStringFromContract('get-token-uri'); - const contractCallSymbol = await this.readStringFromContract('get-symbol'); - - let contractCallDecimals: number | undefined; - const decimalsResult = await this.readUIntFromContract('get-decimals'); - if (decimalsResult) { - contractCallDecimals = Number(decimalsResult.toString()); - } - - let metadata: FtTokenMetadata | undefined; - if (contractCallUri) { - try { - metadata = await this.getMetadataFromUri(contractCallUri); - metadata = this.patchTokenMetadataImageUri(metadata); - } catch (error) { - // An unavailable external service failed to provide reasonable data (images, etc.). - // We will ignore these and fill out the remaining SIP-compliant metadata. - logger.warn( - `[token-metadata] ft metadata fetch error while processing ${this.contractId}: ${error}` - ); - } - } - let imgUrl: string | undefined; - if (metadata?.imageUri) { - const normalizedUrl = this.getImageUrl(metadata.imageUri); - imgUrl = await this.processImageUrl(normalizedUrl); - } - - const fungibleTokenMetadata: DbFungibleTokenMetadata = { - token_uri: contractCallUri ?? '', - name: contractCallName ?? metadata?.name ?? '', // prefer the on-chain name - description: metadata?.description ?? '', - image_uri: imgUrl ?? '', - image_canonical_uri: metadata?.imageUri ?? '', - symbol: contractCallSymbol ?? '', - decimals: contractCallDecimals ?? 0, - contract_id: this.contractId, - tx_id: this.txId, - sender_address: this.contractAddress, - }; - await this.db.updateFtMetadata(fungibleTokenMetadata, this.dbQueueId); - } - - /** - * fetch Non Fungible contract metadata - */ - private async handleNftContract() { - // TODO: This is incorrectly attempting to fetch the metadata for a specific - // NFT and applying it to the entire NFT type/contract. A new SIP needs created - // to define how generic metadata for an NFT type/contract should be retrieved. - // In the meantime, this will often fail or result in weird data, but at least - // the NFT type enumeration endpoints will have data like the contract ID and txid. - - // TODO: this should instead use the SIP-012 draft https://github.com/stacksgov/sips/pull/18 - // function `(get-nft-meta () (response (optional {name: (string-uft8 30), image: (string-ascii 255)}) uint))` - - let metadata: NftTokenMetadata | undefined; - const contractCallUri = await this.readStringFromContract('get-token-uri', [uintCV(0)]); - if (contractCallUri) { - try { - metadata = await this.getMetadataFromUri(contractCallUri); - metadata = this.patchTokenMetadataImageUri(metadata); - } catch (error) { - // An unavailable external service failed to provide reasonable data (images, etc.). - // We will ignore these and fill out the remaining SIP-compliant metadata. - logger.warn( - `[token-metadata] nft metadata fetch error while processing ${this.contractId}: ${error}` - ); - } - } - let imgUrl: string | undefined; - if (metadata?.imageUri) { - const normalizedUrl = this.getImageUrl(metadata.imageUri); - imgUrl = await this.processImageUrl(normalizedUrl); - } - - const nonFungibleTokenMetadata: DbNonFungibleTokenMetadata = { - token_uri: contractCallUri ?? '', - name: metadata?.name ?? '', - description: metadata?.description ?? '', - image_uri: imgUrl ?? '', - image_canonical_uri: metadata?.imageUri ?? '', - contract_id: `${this.contractId}`, - tx_id: this.txId, - sender_address: this.contractAddress, - }; - await this.db.updateNFtMetadata(nonFungibleTokenMetadata, this.dbQueueId); - } - - /** - * Token metadata schema for 'image uri' is not well defined or adhered to. - * This function looks for a handful of possible properties that could be used to - * specify the image, and returns a metadata object with a normalized image property. - */ - private patchTokenMetadataImageUri(metadata: T): T { - // compare using lowercase - const allowedImageProperties = ['image', 'imageurl', 'imageuri', 'image_url', 'image_uri']; - const objectKeys = new Map(Object.keys(metadata).map(prop => [prop.toLowerCase(), prop])); - for (const possibleProp of allowedImageProperties) { - const existingProp = objectKeys.get(possibleProp); - if (existingProp) { - const imageUriVal = (metadata as Record)[existingProp]; - if (typeof imageUriVal !== 'string') { - continue; - } - return { - ...metadata, - imageUri: imageUriVal, - }; - } - } - return { ...metadata }; - } - - /** - * If an external image processor script is configured, then it will process the given image URL for the purpose - * of caching on a CDN (or whatever else it may be created to do). The script is expected to return a new URL - * for the image. - * If the script is not configured, then the original URL is returned immediately. - * If a data-uri is passed, it is also immediately returned without being passed to the script. - */ - private async processImageUrl(imgUrl: string): Promise { - const imageCacheProcessor = process.env['STACKS_API_IMAGE_CACHE_PROCESSOR']; - if (!imageCacheProcessor) { - return imgUrl; - } - if (imgUrl.startsWith('data:')) { - return imgUrl; - } - const { code, stdout, stderr } = await new Promise<{ - code: number; - stdout: string; - stderr: string; - }>((resolve, reject) => { - const cp = child_process.spawn(imageCacheProcessor, [imgUrl], { cwd: REPO_DIR }); - let stdout = ''; - let stderr = ''; - cp.stdout.on('data', data => (stdout += data)); - cp.stderr.on('data', data => (stderr += data)); - cp.on('close', code => resolve({ code: code ?? 0, stdout, stderr })); - cp.on('error', error => reject(error)); - }); - if (code !== 0 && stderr) { - console.warn(`[token-metadata] stderr from STACKS_API_IMAGE_CACHE_PROCESSOR: ${stderr}`); - } - const result = stdout.trim(); - try { - const url = new URL(result); - return url.toString(); - } catch (error) { - throw new Error( - `Image processing script returned an invalid url for ${imgUrl}: ${result}, stderr: ${stderr}` - ); - } - } - - /** - * Helper method for creating http/s url for supported protocols. - * URLs with `http` or `https` protocols are returned as-is. - * URLs with `ipfs` or `ipns` protocols are returned with as an `https` url - * using a public IPFS gateway. - */ - private getFetchableUrl(uri: string): URL { - const parsedUri = new URL(uri); - if (parsedUri.protocol === 'http:' || parsedUri.protocol === 'https:') return parsedUri; - if (parsedUri.protocol === 'ipfs:') - return new URL(`${PUBLIC_IPFS}/${parsedUri.host}${parsedUri.pathname}`); - - if (parsedUri.protocol === 'ipns:') - return new URL(`${PUBLIC_IPFS}/${parsedUri.host}${parsedUri.pathname}`); - - throw new Error(`Unsupported uri protocol: ${uri}`); - } - - private getImageUrl(uri: string): string { - // Support images embedded in a Data URL - if (new URL(uri).protocol === 'data:') { - // const dataUrl = ParseDataUrl(uri); - const dataUrl = parseDataUrl(uri); - if (!dataUrl) { - throw new Error(`Data URL could not be parsed: ${uri}`); - } - if (!dataUrl.mediaType?.startsWith('image/')) { - throw new Error(`Token image is a Data URL with a non-image media type: ${uri}`); - } - return uri; - } - const fetchableUrl = this.getFetchableUrl(uri); - return fetchableUrl.toString(); - } - - /** - * Fetch metadata from uri - */ - private async getMetadataFromUri(token_uri: string): Promise { - // Support JSON embedded in a Data URL - if (new URL(token_uri).protocol === 'data:') { - const dataUrl = parseDataUrl(token_uri); - if (!dataUrl) { - throw new Error(`Data URL could not be parsed: ${token_uri}`); - } - let content: string; - // If media type is omitted it should default to percent-encoded `text/plain;charset=US-ASCII` - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs#syntax - // If media type is specified but without base64 then encoding is ambiguous, so check for - // percent-encoding or assume a literal string compatible with utf8. Because we're expecting - // a JSON object we can reliable check for a leading `%` char, otherwise assume unescaped JSON. - if (dataUrl.base64) { - content = Buffer.from(dataUrl.data, 'base64').toString('utf8'); - } else if (dataUrl.data.startsWith('%')) { - content = querystring.unescape(dataUrl.data); - } else { - content = dataUrl.data; - } - try { - return JSON.parse(content) as Type; - } catch (error) { - throw new Error(`Data URL could not be parsed as JSON: ${token_uri}`); - } - } - const httpUrl = this.getFetchableUrl(token_uri); - - let fetchImmediateRetryCount = 0; - let result: Type | undefined; - // We'll try to fetch metadata and give it `METADATA_MAX_IMMEDIATE_RETRY_COUNT` attempts - // for the external service to return a reasonable response, otherwise we'll consider the - // metadata as dead. - do { - try { - result = await performFetch(httpUrl.toString(), { - timeoutMs: getTokenMetadataFetchTimeoutMs(), - maxResponseBytes: METADATA_MAX_PAYLOAD_BYTE_SIZE, - }); - break; - } catch (error) { - fetchImmediateRetryCount++; - if ( - (error instanceof FetchError && error.type === 'max-size') || - fetchImmediateRetryCount >= METADATA_MAX_IMMEDIATE_RETRY_COUNT - ) { - throw error; - } - } - } while (fetchImmediateRetryCount < METADATA_MAX_IMMEDIATE_RETRY_COUNT); - if (result) { - return result; - } - throw new Error(`Unable to fetch metadata from ${token_uri}`); - } - - private async makeReadOnlyContractCall( - functionName: string, - functionArgs: ClarityValue[] - ): Promise { - let result: ReadOnlyContractCallResponse; - try { - result = await this.nodeRpcClient.sendReadOnlyContractCall( - this.contractAddress, - this.contractName, - functionName, - this.address, - functionArgs - ); - } catch (error) { - throw new RetryableTokenMetadataError(`Error making read-only contract call: ${error}`); - } - if (!result.okay) { - // Only runtime errors reported by the Stacks node should be retryable. - if ( - result.cause.startsWith('Runtime') || - result.cause.startsWith('Unchecked(NoSuchContract') - ) { - throw new RetryableTokenMetadataError( - `Runtime error while calling read-only function ${functionName}` - ); - } - throw new Error(`Error calling read-only function ${functionName}`); - } - return hexToCV(result.result); - } - - private async readStringFromContract( - functionName: string, - functionArgs: ClarityValue[] = [] - ): Promise { - const clarityValue = await this.makeReadOnlyContractCall(functionName, functionArgs); - return this.checkAndParseString(clarityValue); - } - - private async readUIntFromContract( - functionName: string, - functionArgs: ClarityValue[] = [] - ): Promise { - const clarityValue = await this.makeReadOnlyContractCall(functionName, functionArgs); - const uintVal = this.checkAndParseUintCV(clarityValue); - try { - return BigInt(uintVal.value.toString()); - } catch (error) { - throw new RetryableTokenMetadataError(`Invalid uint value '${uintVal}'`); - } - } - - private unwrapClarityType(clarityValue: ClarityValue): ClarityValue { - let unwrappedClarityValue: ClarityValue = clarityValue; - while ( - unwrappedClarityValue.type === ClarityType.ResponseOk || - unwrappedClarityValue.type === ClarityType.OptionalSome - ) { - unwrappedClarityValue = unwrappedClarityValue.value; - } - return unwrappedClarityValue; - } - - private checkAndParseUintCV(responseCV: ClarityValue): UIntCV { - const unwrappedClarityValue = this.unwrapClarityType(responseCV); - if (unwrappedClarityValue.type === ClarityType.UInt) { - return unwrappedClarityValue; - } - throw new RetryableTokenMetadataError( - `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping uint` - ); - } - - private checkAndParseString(responseCV: ClarityValue): string | undefined { - const unwrappedClarityValue = this.unwrapClarityType(responseCV); - if ( - unwrappedClarityValue.type === ClarityType.StringASCII || - unwrappedClarityValue.type === ClarityType.StringUTF8 - ) { - return unwrappedClarityValue.data; - } else if (unwrappedClarityValue.type === ClarityType.OptionalNone) { - return undefined; - } - throw new RetryableTokenMetadataError( - `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping string` - ); - } -} diff --git a/src/token-metadata/tokens-processor-queue.ts b/src/token-metadata/tokens-processor-queue.ts deleted file mode 100644 index 2596e41ab8..0000000000 --- a/src/token-metadata/tokens-processor-queue.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { ChainID, FoundOrNot } from '../helpers'; -import { Evt } from 'evt'; -import PQueue from 'p-queue'; -import { DbTokenMetadataQueueEntry, TokenMetadataUpdateInfo } from '../datastore/common'; -import { ClarityAbi } from '@stacks/transactions'; -import { TokensContractHandler } from './tokens-contract-handler'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { logger } from '../logger'; - -/** - * The maximum number of token metadata parsing operations that can be ran concurrently before - * being added to a FIFO queue. - */ -const TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT = 5; - -export class TokensProcessorQueue { - readonly queue: PQueue; - readonly db: PgWriteStore; - readonly chainId: ChainID; - - readonly processStartedEvent: Evt<{ - contractId: string; - txId: string; - }> = new Evt(); - - readonly processEndEvent: Evt<{ - contractId: string; - txId: string; - }> = new Evt(); - - /** The entries currently queued for processing in memory, keyed by the queue entry db id. */ - readonly queuedEntries: Map = new Map(); - - readonly onTokenMetadataUpdateQueued: (queueId: number) => void; - readonly onBlockUpdate: (blockHash: string) => void; - - constructor(db: PgWriteStore, chainId: ChainID) { - this.db = db; - this.chainId = chainId; - this.queue = new PQueue({ concurrency: TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT }); - this.onTokenMetadataUpdateQueued = entry => this.queueNotificationHandler(entry); - this.db.eventEmitter.on('tokenMetadataUpdateQueued', this.onTokenMetadataUpdateQueued); - this.onBlockUpdate = blockHash => this.blockNotificationHandler(blockHash); - this.db.eventEmitter.on('blockUpdate', this.onBlockUpdate); - } - - close() { - this.db.eventEmitter.off('tokenMetadataUpdateQueued', this.onTokenMetadataUpdateQueued); - this.db.eventEmitter.off('blockUpdate', this.onBlockUpdate); - this.queue.pause(); - this.queue.clear(); - } - - async drainDbQueue(): Promise { - let entries: DbTokenMetadataQueueEntry[] = []; - do { - if (this.queue.isPaused) { - return; - } - const queuedEntries = [...this.queuedEntries.keys()]; - try { - entries = await this.db.getTokenMetadataQueue( - TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT, - queuedEntries - ); - } catch (error) { - logger.error(error); - } - for (const entry of entries) { - await this.queueHandler(entry); - } - await this.queue.onEmpty(); - } while (entries.length > 0 || this.queuedEntries.size > 0); - } - - async checkDbQueue(): Promise { - if (this.queue.isPaused) { - return; - } - const queuedEntries = [...this.queuedEntries.keys()]; - const limit = TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT - this.queuedEntries.size; - if (limit > 0) { - let entries: DbTokenMetadataQueueEntry[]; - try { - entries = await this.db.getTokenMetadataQueue( - TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT, - queuedEntries - ); - } catch (error) { - logger.error(error); - return; - } - for (const entry of entries) { - await this.queueHandler(entry); - } - } - } - - async queueNotificationHandler(queueId: number) { - let queueEntry: FoundOrNot; - try { - queueEntry = await this.db.getTokenMetadataQueueEntry(queueId); - } catch (error) { - logger.error(error); - return; - } - if (queueEntry.found) { - await this.queueHandler(queueEntry.result); - } - } - - async blockNotificationHandler(_: string) { - await this.checkDbQueue(); - } - - async queueHandler(queueEntry: TokenMetadataUpdateInfo) { - if ( - this.queuedEntries.has(queueEntry.queueId) || - this.queuedEntries.size >= this.queue.concurrency - ) { - return; - } - let abi: string; - try { - const contractQuery = await this.db.getSmartContract(queueEntry.contractId); - if (!contractQuery.found || !contractQuery.result.abi) { - return; - } - abi = contractQuery.result.abi; - } catch (error) { - logger.error(error); - return; - } - logger.info( - `[token-metadata] queueing token contract for processing: ${queueEntry.contractId} from tx ${queueEntry.txId}` - ); - this.queuedEntries.set(queueEntry.queueId, queueEntry); - - const contractAbi: ClarityAbi = JSON.parse(abi); - - const tokenContractHandler = new TokensContractHandler({ - contractId: queueEntry.contractId, - smartContractAbi: contractAbi, - datastore: this.db, - chainId: this.chainId, - txId: queueEntry.txId, - dbQueueId: queueEntry.queueId, - }); - - void this.queue - .add(async () => { - this.processStartedEvent.post({ - contractId: queueEntry.contractId, - txId: queueEntry.txId, - }); - await tokenContractHandler.start(); - }) - .catch(error => { - logger.error( - error, - `[token-metadata] error processing token contract: ${tokenContractHandler.contractAddress} ${tokenContractHandler.contractName} from tx ${tokenContractHandler.txId}` - ); - }) - .finally(() => { - this.queuedEntries.delete(queueEntry.queueId); - this.processEndEvent.post({ - contractId: queueEntry.contractId, - txId: queueEntry.txId, - }); - if (this.queuedEntries.size < this.queue.concurrency) { - void this.checkDbQueue(); - } - }); - } -} diff --git a/tests/jest.config.tokens-metadata.js b/tests/jest.config.tokens-metadata.js deleted file mode 100644 index b6fa987623..0000000000 --- a/tests/jest.config.tokens-metadata.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - preset: 'ts-jest', - rootDir: `${require('path').dirname(__dirname)}/src`, - testMatch: ['/tests-tokens-metadata/*.ts'], - testPathIgnorePatterns: ['/tests-tokens-metadata/setup.ts', '/tests-tokens-metadata/teardown.ts'], - collectCoverageFrom: ['/**/*.ts'], - coveragePathIgnorePatterns: ['/tests*'], - coverageDirectory: '/../coverage', - globalSetup: '/tests-tokens-metadata/setup.ts', - globalTeardown: '/tests-tokens-metadata/teardown.ts', - testTimeout: 60000, - verbose: true, - } diff --git a/tests/jest.config.tokens-strict.js b/tests/jest.config.tokens-strict.js deleted file mode 100644 index 419d8e0455..0000000000 --- a/tests/jest.config.tokens-strict.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - preset: 'ts-jest', - rootDir: `${require('path').dirname(__dirname)}/src`, - testMatch: ['/tests-tokens-strict/*.ts'], - testPathIgnorePatterns: ['/tests-tokens-strict/setup.ts', '/tests-tokens-strict/teardown.ts'], - collectCoverageFrom: ['/**/*.ts'], - coveragePathIgnorePatterns: ['/tests*'], - coverageDirectory: '/../coverage', - globalSetup: '/tests-tokens-strict/setup.ts', - globalTeardown: '/tests-tokens-strict/teardown.ts', - testTimeout: 60000, - verbose: true, - } diff --git a/tests/jest.config.tokens.js b/tests/jest.config.tokens.js deleted file mode 100644 index c84cd3d649..0000000000 --- a/tests/jest.config.tokens.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - preset: 'ts-jest', - rootDir: `${require('path').dirname(__dirname)}/src`, - testMatch: ['/tests-tokens/*.ts'], - testPathIgnorePatterns: ['/tests-tokens/setup.ts', '/tests-tokens/teardown.ts'], - collectCoverageFrom: ['/**/*.ts'], - coveragePathIgnorePatterns: ['/tests*'], - coverageDirectory: '/../coverage', - globalSetup: '/tests-tokens/setup.ts', - globalTeardown: '/tests-tokens/teardown.ts', - testTimeout: 60000, - verbose: true, - } From 3a2e1ea17446ef4ba09a8241839e74ce8dd6f75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Thu, 9 Nov 2023 16:21:08 -0600 Subject: [PATCH 16/91] build: switch to bullseye image, pull duckdb binary (#1748) --- Dockerfile | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index c26f06b65f..c9ec7724ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,14 @@ -FROM node:18-alpine +FROM node:18-bullseye WORKDIR /app COPY . . +COPY --from=qldrsc/duckdb /usr/local/bin/duckdb /bin/duckdb -RUN apk add --no-cache --virtual .build-deps alpine-sdk python3 git openjdk8-jre cmake +RUN apt-get update && \ + apt-get install -y git openjdk-11-jre && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* RUN echo "GIT_TAG=$(git tag --points-at HEAD)" >> .env RUN npm ci && npm run build && npm run build:docs && npm prune --production -RUN apk del .build-deps - -# As no pre-built binaries of duckdb can be found for Alpine (musl based), -# a rebuild of duckdb package is need. -# -# Library used by the event-replay based on parquet files. -ARG DUCKDB_VERSION=0.8.1 -WORKDIR /duckdb -RUN apk add --no-cache --virtual .duckdb-build-deps python3 git g++ make -RUN git clone https://github.com/duckdb/duckdb.git -b v${DUCKDB_VERSION} --depth 1 \ - && cd duckdb/tools/nodejs \ - && ./configure && make all -WORKDIR /app -RUN npm uninstall duckdb && npm install /duckdb/duckdb/tools/nodejs -RUN apk del .duckdb-build-deps CMD ["node", "./lib/index.js"] From 536dbd1e462a93b2b930871e3b3a017fdc903f3d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 13 Nov 2023 16:58:00 +0000 Subject: [PATCH 17/91] chore(release): 7.3.3 [skip ci] ## [7.3.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.2...v7.3.3) (2023-11-13) ### Bug Fixes * move nft custody view into a table ([#1741](https://github.com/hirosystems/stacks-blockchain-api/issues/1741)) ([fb0d0ea](https://github.com/hirosystems/stacks-blockchain-api/commit/fb0d0eaa93a0614c54cfa28464fe5df25ac9c7dd)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80398743e6..497926d879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.3.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.2...v7.3.3) (2023-11-13) + + +### Bug Fixes + +* move nft custody view into a table ([#1741](https://github.com/hirosystems/stacks-blockchain-api/issues/1741)) ([fb0d0ea](https://github.com/hirosystems/stacks-blockchain-api/commit/fb0d0eaa93a0614c54cfa28464fe5df25ac9c7dd)) + ## [7.3.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.1...v7.3.2) (2023-09-14) From e192a6c0e2e0dbb8b0296efbc6ba05f682359d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 14 Nov 2023 09:45:05 -0600 Subject: [PATCH 18/91] refactor: remove old token metadata processor (#1750) --- .env | 35 +- .github/workflows/ci.yml | 91 --- .vscode/launch.json | 34 -- .../1699540187362_remove-token-metadata.js | 132 +++++ package.json | 2 - src/api/controllers/db-controller.ts | 26 +- src/api/init.ts | 2 +- src/api/routes/rosetta/account.ts | 34 +- src/api/routes/rosetta/construction.ts | 2 +- src/api/routes/rosetta/mempool.ts | 2 +- src/api/routes/{tokens => }/tokens.ts | 163 +----- src/datastore/common.ts | 106 ---- src/datastore/pg-store.ts | 191 ------- src/datastore/pg-write-store.ts | 143 ----- src/helpers.ts | 42 -- src/index.ts | 19 - src/rosetta/rosetta-ft-metadata-client.ts | 204 +++++++ src/{ => rosetta}/rosetta-helpers.ts | 87 +-- .../construction.ts | 2 +- src/tests-rosetta/account-tests.ts | 36 +- src/tests-rosetta/block-tests.ts | 34 +- src/tests-rosetta/offline-api-tests.ts | 2 +- src/tests-tokens-metadata/setup.ts | 13 - src/tests-tokens-metadata/teardown.ts | 5 - .../test-contracts/beeple-data-url-a.clar | 58 -- .../test-contracts/beeple-data-url-b.clar | 58 -- .../test-contracts/beeple-data-url-c.clar | 58 -- .../test-contracts/beeple.clar | 58 -- .../test-contracts/ft-trait.clar | 24 - .../test-contracts/hey-token.clar | 58 -- .../test-contracts/nft-trait.clar | 15 - .../tokens-metadata-tests.ts | 408 ------------- src/tests-tokens-strict/setup.ts | 8 - src/tests-tokens-strict/strict-mode-tests.ts | 389 ------------- src/tests-tokens-strict/teardown.ts | 8 - src/tests/datastore-tests.ts | 44 -- src/token-metadata/helpers.ts | 263 --------- src/token-metadata/tokens-contract-handler.ts | 534 ------------------ src/token-metadata/tokens-processor-queue.ts | 175 ------ tests/jest.config.tokens-metadata.js | 13 - tests/jest.config.tokens-strict.js | 13 - tests/jest.config.tokens.js | 13 - 42 files changed, 441 insertions(+), 3163 deletions(-) create mode 100644 migrations/1699540187362_remove-token-metadata.js rename src/api/routes/{tokens => }/tokens.ts (64%) create mode 100644 src/rosetta/rosetta-ft-metadata-client.ts rename src/{ => rosetta}/rosetta-helpers.ts (95%) delete mode 100644 src/tests-tokens-metadata/setup.ts delete mode 100644 src/tests-tokens-metadata/teardown.ts delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/beeple.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/ft-trait.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/hey-token.clar delete mode 100644 src/tests-tokens-metadata/test-contracts/nft-trait.clar delete mode 100644 src/tests-tokens-metadata/tokens-metadata-tests.ts delete mode 100644 src/tests-tokens-strict/setup.ts delete mode 100644 src/tests-tokens-strict/strict-mode-tests.ts delete mode 100644 src/tests-tokens-strict/teardown.ts delete mode 100644 src/token-metadata/helpers.ts delete mode 100644 src/token-metadata/tokens-contract-handler.ts delete mode 100644 src/token-metadata/tokens-processor-queue.ts delete mode 100644 tests/jest.config.tokens-metadata.js delete mode 100644 tests/jest.config.tokens-strict.js delete mode 100644 tests/jest.config.tokens.js diff --git a/.env b/.env index 1348d8552b..95d985ecbd 100644 --- a/.env +++ b/.env @@ -122,34 +122,17 @@ STACKS_NODE_TYPE=L1 # Override the default file path for the proxy cache control file # STACKS_API_PROXY_CACHE_CONTROL_FILE=/path/to/.proxy-cache-control.json -# Enable token metadata processing. Disabled by default. +# Enable FT metadata processing for Rosetta operations display. Disabled by default. # STACKS_API_ENABLE_FT_METADATA=1 -# STACKS_API_ENABLE_NFT_METADATA=1 - -# If token metadata processing is enabled, this variable determines how the API reacts to metadata processing failures. -# When strict mode is enabled, any failures caused by recoverable errors will be retried indefinitely. Otherwise, -# the API will give up after `STACKS_API_TOKEN_METADATA_MAX_RETRIES` is reached for that smart contract. -# STACKS_API_TOKEN_METADATA_STRICT_MODE=1 - -# Maximum number of times we'll try processing FT/NFT metadata for a specific smart contract if we've failed -# because of a recoverable error. -# Only used if `STACKS_API_TOKEN_METADATA_STRICT_MODE` is disabled. -# STACKS_API_TOKEN_METADATA_MAX_RETRIES=5 - -# Controls the token metadata error handling mode. The possible values are: -# * `warning`: If required metadata is not found, the API will issue a warning and not display data for that token. -# * `error`: If required metadata is not found, the API will throw an error. -# If not specified or any other value is provided, the mode will be set to `warning`. -# STACKS_API_TOKEN_METADATA_ERROR_MODE=warning -# Configure a script to handle image URLs during token metadata processing. -# This example script uses the `imgix.net` service to create CDN URLs. -# Must be an executable script that accepts the URL as the first program argument -# and outputs a result URL to stdout. -# STACKS_API_IMAGE_CACHE_PROCESSOR=./config/token-metadata-image-cache-imgix.js -# Env vars needed for the above sample `imgix` script: -# IMGIX_DOMAIN=https://.imgix.net -# IMGIX_TOKEN= +# The Rosetta API endpoints require FT metadata to display operations with the proper `symbol` and +# `decimals` values. If FT metadata is enabled, this variable controls the token metadata error +# handling mode when metadata is not found. +# The possible values are: +# * `warning`: The API will issue a warning and not display data for that token. +# * `error`: The API will throw an error. If not specified or any other value is provided, the mode +# will be set to `warning`. +# STACKS_API_TOKEN_METADATA_ERROR_MODE=warning # Web Socket ping interval to determine client availability, in seconds. # STACKS_API_WS_PING_INTERVAL=5 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20115adf60..474ce39bad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -848,96 +848,6 @@ jobs: flag-name: run-${{ github.job }} parallel: true - test-tokens-metadata: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Use Node.js - uses: actions/setup-node@v2 - with: - node-version-file: ".nvmrc" - - - name: Install deps - run: npm ci - - - name: Setup env vars - run: echo "STACKS_CORE_EVENT_HOST=http://0.0.0.0" >> $GITHUB_ENV - - - name: Setup integration environment - run: | - sudo ufw disable - npm run devenv:deploy-krypton -- -d - npm run devenv:logs-krypton -- --no-color &> docker-compose-logs.txt & - - - name: Run tokens tests - run: npm run test:tokens-metadata - - - name: Print integration environment logs - run: cat docker-compose-logs.txt - if: failure() - - - name: Teardown integration environment - run: npm run devenv:stop-krypton - if: always() - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 - if: always() - - - name: Upload coverage to Coveralls - uses: coverallsapp/github-action@master - if: ${{ false }} - with: - github-token: ${{ secrets.github_token }} - flag-name: run-${{ github.job }} - parallel: true - - test-tokens-strict: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Use Node.js - uses: actions/setup-node@v2 - with: - node-version-file: ".nvmrc" - - - name: Install deps - run: npm ci - - - name: Setup env vars - run: echo "STACKS_CORE_EVENT_HOST=http://0.0.0.0" >> $GITHUB_ENV - - - name: Setup integration environment - run: | - sudo ufw disable - npm run devenv:deploy-krypton -- -d - npm run devenv:logs-krypton -- --no-color &> docker-compose-logs.txt & - - - name: Run tokens tests - run: npm run test:tokens-strict - - - name: Print integration environment logs - run: cat docker-compose-logs.txt - if: failure() - - - name: Teardown integration environment - run: npm run devenv:stop-krypton - if: always() - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 - if: always() - - - name: Upload coverage to Coveralls - uses: coverallsapp/github-action@master - if: ${{ false }} - with: - github-token: ${{ secrets.github_token }} - flag-name: run-${{ github.job }} - parallel: true - build-publish: runs-on: ubuntu-latest needs: @@ -948,7 +858,6 @@ jobs: - test-bns - test-rosetta - test-rosetta-cli-construction - - test-tokens-strict steps: - uses: actions/checkout@v2 with: diff --git a/.vscode/launch.json b/.vscode/launch.json index ced0a3a5f1..6ef212dc0b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -346,40 +346,6 @@ "preLaunchTask": "deploy:krypton", "postDebugTask": "stop:krypton", }, - { - "type": "node", - "request": "launch", - "name": "Jest: Tokens - strict mode", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": [ - "--testTimeout=3600000", - "--runInBand", - "--no-cache", - "--config", - "${workspaceRoot}/tests/jest.config.tokens-strict.js", - ], - "outputCapture": "std", - "console": "integratedTerminal", - "preLaunchTask": "deploy:krypton", - "postDebugTask": "stop:krypton", - }, - { - "type": "node", - "request": "launch", - "name": "Jest: Tokens - metadata", - "program": "${workspaceFolder}/node_modules/.bin/jest", - "args": [ - "--testTimeout=3600000", - "--runInBand", - "--no-cache", - "--config", - "${workspaceRoot}/tests/jest.config.tokens-metadata.js", - ], - "outputCapture": "std", - "console": "integratedTerminal", - "preLaunchTask": "deploy:krypton", - "postDebugTask": "stop:krypton", - }, { "type": "node", "request": "launch", diff --git a/migrations/1699540187362_remove-token-metadata.js b/migrations/1699540187362_remove-token-metadata.js new file mode 100644 index 0000000000..bef655efd7 --- /dev/null +++ b/migrations/1699540187362_remove-token-metadata.js @@ -0,0 +1,132 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.dropTable('token_metadata_queue'); + pgm.dropTable('nft_metadata'); + pgm.dropTable('ft_metadata'); +}; + +exports.down = pgm => { + pgm.createTable('token_metadata_queue', { + queue_id: { + type: 'serial', + primaryKey: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + contract_id: { + type: 'string', + notNull: true, + }, + contract_abi: { + type: 'string', + notNull: true, + }, + block_height: { + type: 'integer', + notNull: true, + }, + processed: { + type: 'boolean', + notNull: true, + }, + retry_count: { + type: 'integer', + notNull: true, + default: 0, + } + }); + pgm.createIndex('token_metadata_queue', [{ name: 'block_height', sort: 'DESC' }]); + pgm.createTable('nft_metadata', { + id: { + type: 'serial', + primaryKey: true, + }, + name: { + type: 'string', + notNull: true, + }, + token_uri: { + type: 'string', + notNull: true, + }, + description: { + type: 'string', + notNull: true, + }, + image_uri: { + type: 'string', + notNull: true, + }, + image_canonical_uri: { + type: 'string', + notNull: true, + }, + contract_id: { + type: 'string', + notNull: true, + unique: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + sender_address: { + type: 'string', + notNull: true, + } + }); + pgm.createIndex('nft_metadata', 'contract_id', { method: 'hash' }); + pgm.createTable('ft_metadata', { + id: { + type: 'serial', + primaryKey: true, + }, + name: { + type: 'string', + notNull: true, + }, + token_uri: { + type: 'string', + notNull: true, + }, + description: { + type: 'string', + notNull: true, + }, + image_uri: { + type: 'string', + notNull: true, + }, + image_canonical_uri: { + type: 'string', + notNull: true, + }, + contract_id: { + type: 'string', + notNull: true, + unique: true, + }, + symbol: { + type: 'string', + notNull: true, + }, + decimals: { + type: 'integer', + notNull: true, + }, + tx_id: { + type: 'bytea', + notNull: true, + }, + sender_address: { + type: 'string', + notNull: true, + } + }); + pgm.createIndex('ft_metadata', 'contract_id', { method: 'hash' }); +} diff --git a/package.json b/package.json index 578f7a297b..4e73cd6dac 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,6 @@ "test:integration:rosetta-cli:construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:bns": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.bns.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:bns-e2e": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.bns-e2e.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:tokens-strict": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.tokens-strict.js --no-cache --runInBand; npm run devenv:stop-krypton\"", - "test:integration:tokens-metadata": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.tokens-metadata.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:rpc": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.rpc.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:event-replay": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.event-replay.js --no-cache --runInBand; npm run devenv:stop\"", "test:integration:btc-faucet": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml -f docker/docker-compose.dev.bitcoind.yml up --force-recreate -V\" \"cross-env NODE_ENV=development jest --config ./tests/jest.config.btc-faucet.js --no-cache --runInBand; npm run devenv:stop\"", diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 8eca6563a4..20ba98bd91 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -63,7 +63,7 @@ import { } from '../../datastore/common'; import { unwrapOptional, FoundOrNot, unixEpochToIso, EMPTY_HASH_256, ChainID } from '../../helpers'; import { serializePostCondition, serializePostConditionMode } from '../serializers/post-conditions'; -import { getOperations, parseTransactionMemo } from '../../rosetta-helpers'; +import { getOperations, parseTransactionMemo } from '../../rosetta/rosetta-helpers'; import { PgStore } from '../../datastore/pg-store'; import { Pox2EventName } from '../../pox-helpers'; import { logger } from '../../logger'; @@ -164,30 +164,6 @@ export function getTxStatus(txStatus: DbTxStatus | string): string { } } -type EventTypeString = - | 'smart_contract_log' - | 'stx_asset' - | 'fungible_token_asset' - | 'non_fungible_token_asset' - | 'stx_lock'; - -export function getEventTypeString(eventTypeId: DbEventTypeId): EventTypeString { - switch (eventTypeId) { - case DbEventTypeId.SmartContractLog: - return 'smart_contract_log'; - case DbEventTypeId.StxAsset: - return 'stx_asset'; - case DbEventTypeId.FungibleTokenAsset: - return 'fungible_token_asset'; - case DbEventTypeId.NonFungibleTokenAsset: - return 'non_fungible_token_asset'; - case DbEventTypeId.StxLock: - return 'stx_lock'; - default: - throw new Error(`Unexpected DbEventTypeId: ${eventTypeId}`); - } -} - export function getAssetEventTypeString( assetEventTypeId: DbAssetEventTypeId ): 'transfer' | 'mint' | 'burn' { diff --git a/src/api/init.ts b/src/api/init.ts index d8bdac6b18..546c2d4086 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -31,7 +31,7 @@ import * as expressListEndpoints from 'express-list-endpoints'; import { createMiddleware as createPrometheusMiddleware } from '@promster/express'; import { createMicroblockRouter } from './routes/microblock'; import { createStatusRouter } from './routes/status'; -import { createTokenRouter } from './routes/tokens/tokens'; +import { createTokenRouter } from './routes/tokens'; import { createFeeRateRouter } from './routes/fee-rate'; import { setResponseNonCacheable } from './controllers/cache-controller'; diff --git a/src/api/routes/rosetta/account.ts b/src/api/routes/rosetta/account.ts index be01d0e7cb..3a16449e85 100644 --- a/src/api/routes/rosetta/account.ts +++ b/src/api/routes/rosetta/account.ts @@ -13,8 +13,7 @@ import { } from '@stacks/stacks-blockchain-api-types'; import { RosettaErrors, RosettaConstants, RosettaErrorsTypes } from '../../rosetta-constants'; import { rosettaValidateRequest, ValidSchema, makeRosettaError } from '../../rosetta-validate'; -import { getValidatedFtMetadata } from '../../../rosetta-helpers'; -import { isFtMetadataEnabled } from '../../../token-metadata/helpers'; +import { RosettaFtMetadataClient } from '../../../rosetta/rosetta-ft-metadata-client'; export function createRosettaAccountRouter(db: PgStore, chainId: ChainID): express.Router { const router = express.Router(); @@ -121,22 +120,21 @@ export function createRosettaAccountRouter(db: PgStore, chainId: ChainID): expre ]; // Add Fungible Token balances. - if (isFtMetadataEnabled()) { - const ftBalances = await db.getFungibleTokenBalances({ - stxAddress: accountIdentifier.address, - untilBlock: block.block_height, - }); - for (const [ftAssetIdentifier, ftBalance] of ftBalances) { - const ftMetadata = await getValidatedFtMetadata(db, ftAssetIdentifier); - if (ftMetadata) { - balances.push({ - value: ftBalance.balance.toString(), - currency: { - symbol: ftMetadata.symbol, - decimals: ftMetadata.decimals, - }, - }); - } + const ftBalances = await db.getFungibleTokenBalances({ + stxAddress: accountIdentifier.address, + untilBlock: block.block_height, + }); + const metadataClient = new RosettaFtMetadataClient(chainId); + for (const [ftAssetIdentifier, ftBalance] of ftBalances) { + const ftMetadata = await metadataClient.getFtMetadata(ftAssetIdentifier); + if (ftMetadata) { + balances.push({ + value: ftBalance.balance.toString(), + currency: { + symbol: ftMetadata.symbol, + decimals: ftMetadata.decimals, + }, + }); } } diff --git a/src/api/routes/rosetta/construction.ts b/src/api/routes/rosetta/construction.ts index c570bccb91..0e3b975bb5 100644 --- a/src/api/routes/rosetta/construction.ts +++ b/src/api/routes/rosetta/construction.ts @@ -82,7 +82,7 @@ import { rawTxToBaseTx, rawTxToStacksTransaction, verifySignature, -} from './../../../rosetta-helpers'; +} from '../../../rosetta/rosetta-helpers'; import { makeRosettaError, rosettaValidateRequest, ValidSchema } from './../../rosetta-validate'; export function createRosettaConstructionRouter(db: PgStore, chainId: ChainID): express.Router { diff --git a/src/api/routes/rosetta/mempool.ts b/src/api/routes/rosetta/mempool.ts index ef3cef772e..f879eebab1 100644 --- a/src/api/routes/rosetta/mempool.ts +++ b/src/api/routes/rosetta/mempool.ts @@ -8,7 +8,7 @@ import { RosettaMempoolTransactionResponse, RosettaTransaction, } from '@stacks/stacks-blockchain-api-types'; -import { getOperations, parseTransactionMemo } from '../../../rosetta-helpers'; +import { getOperations, parseTransactionMemo } from '../../../rosetta/rosetta-helpers'; import { RosettaErrors, RosettaErrorsTypes } from '../../rosetta-constants'; export function createRosettaMempoolRouter(db: PgStore, chainId: ChainID): express.Router { diff --git a/src/api/routes/tokens/tokens.ts b/src/api/routes/tokens.ts similarity index 64% rename from src/api/routes/tokens/tokens.ts rename to src/api/routes/tokens.ts index 500e949171..f801f54e11 100644 --- a/src/api/routes/tokens/tokens.ts +++ b/src/api/routes/tokens.ts @@ -1,25 +1,20 @@ -import { asyncHandler } from '../../async-handler'; +import { asyncHandler } from '../async-handler'; import * as express from 'express'; import { - FungibleTokenMetadata, - FungibleTokensMetadataList, NonFungibleTokenHistoryEvent, NonFungibleTokenHistoryEventList, NonFungibleTokenHolding, NonFungibleTokenHoldingsList, - NonFungibleTokenMetadata, NonFungibleTokenMint, NonFungibleTokenMintList, - NonFungibleTokensMetadataList, } from '@stacks/stacks-blockchain-api-types'; -import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from './../../pagination'; -import { isFtMetadataEnabled, isNftMetadataEnabled } from '../../../token-metadata/helpers'; -import { has0xPrefix, isValidPrincipal } from '../../../helpers'; -import { booleanValueForParam, isUnanchoredRequest } from '../../../api/query-helpers'; +import { PgStore } from '../../datastore/pg-store'; +import { isValidPrincipal, has0xPrefix } from '../../helpers'; import { decodeClarityValueToRepr } from 'stacks-encoding-native-js'; -import { getAssetEventTypeString, parseDbTx } from '../../controllers/db-controller'; -import { getETagCacheHandler, setETagCacheHeaders } from '../../controllers/cache-controller'; -import { PgStore } from '../../../datastore/pg-store'; +import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; +import { parseDbTx, getAssetEventTypeString } from '../controllers/db-controller'; +import { getPagingQueryLimit, ResourceType, parsePagingQueryInput } from '../pagination'; +import { isUnanchoredRequest, booleanValueForParam } from '../query-helpers'; export function createTokenRouter(db: PgStore): express.Router { const router = express.Router(); @@ -228,149 +223,5 @@ export function createTokenRouter(db: PgStore): express.Router { }) ); - router.get( - '/ft/metadata', - asyncHandler(async (req, res) => { - if (!isFtMetadataEnabled()) { - res.status(500).json({ - error: 'FT metadata processing is not enabled on this server', - }); - return; - } - - const limit = getPagingQueryLimit(ResourceType.Token, req.query.limit); - const offset = parsePagingQueryInput(req.query.offset ?? 0); - - const { results, total } = await db.getFtMetadataList({ offset, limit }); - - const response: FungibleTokensMetadataList = { - limit: limit, - offset: offset, - total: total, - results: results, - }; - - res.status(200).json(response); - }) - ); - - router.get( - '/nft/metadata', - asyncHandler(async (req, res) => { - if (!isNftMetadataEnabled()) { - res.status(500).json({ - error: 'NFT metadata processing is not enabled on this server', - }); - return; - } - - let limit: number; - try { - limit = getPagingQueryLimit(ResourceType.Token, req.query.limit); - } catch (error: any) { - res.status(400).json({ error: error.message }); - return; - } - - const offset = parsePagingQueryInput(req.query.offset ?? 0); - - const { results, total } = await db.getNftMetadataList({ offset, limit }); - - const response: NonFungibleTokensMetadataList = { - limit: limit, - offset: offset, - total: total, - results: results, - }; - - res.status(200).json(response); - }) - ); - - router.get( - '/:contractId/ft/metadata', - asyncHandler(async (req, res) => { - if (!isFtMetadataEnabled()) { - res.status(500).json({ - error: 'FT metadata processing is not enabled on this server', - }); - return; - } - - const { contractId } = req.params; - - const metadata = await db.getFtMetadata(contractId); - if (!metadata.found) { - res.status(404).json({ error: 'tokens not found' }); - return; - } - - const { - token_uri, - name, - description, - image_uri, - image_canonical_uri, - symbol, - decimals, - tx_id, - sender_address, - } = metadata.result; - - const response: FungibleTokenMetadata = { - token_uri: token_uri, - name: name, - description: description, - image_uri: image_uri, - image_canonical_uri: image_canonical_uri, - symbol: symbol, - decimals: decimals, - tx_id: tx_id, - sender_address: sender_address, - }; - res.status(200).json(response); - }) - ); - - router.get( - '/:contractId/nft/metadata', - asyncHandler(async (req, res) => { - if (!isNftMetadataEnabled()) { - res.status(500).json({ - error: 'NFT metadata processing is not enabled on this server', - }); - return; - } - - const { contractId } = req.params; - const metadata = await db.getNftMetadata(contractId); - - if (!metadata.found) { - res.status(404).json({ error: 'tokens not found' }); - return; - } - const { - token_uri, - name, - description, - image_uri, - image_canonical_uri, - tx_id, - sender_address, - } = metadata.result; - - const response: NonFungibleTokenMetadata = { - token_uri: token_uri, - name: name, - description: description, - image_uri: image_uri, - image_canonical_uri: image_canonical_uri, - tx_id: tx_id, - sender_address: sender_address, - }; - res.status(200).json(response); - }) - ); - return router; } diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 57e6caffb7..7cef586547 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -546,12 +546,6 @@ export interface AddressNftEventIdentifier { asset_event_type_id: number; } -export interface TokenMetadataUpdateInfo { - queueId: number; - txId: string; - contractId: string; -} - export interface DataStoreBlockUpdateData { block: DbBlock; microblocks: DbMicroblock[]; @@ -749,40 +743,6 @@ export type BlockIdentifier = | { burnBlockHash: string } | { burnBlockHeight: number }; -export interface DbNonFungibleTokenMetadata { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - tx_id: string; - sender_address: string; -} - -export interface DbFungibleTokenMetadata { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - symbol: string; - decimals: number; - tx_id: string; - sender_address: string; -} - -export interface DbTokenMetadataQueueEntry { - queueId: number; - txId: string; - contractId: string; - contractAbi: ClarityAbi; - blockHeight: number; - processed: boolean; - retry_count: number; -} - export interface DbChainTip { blockHeight: number; indexBlockHash: string; @@ -1015,40 +975,6 @@ export interface BlocksWithMetadata { total: number; } -export interface NonFungibleTokenMetadataQueryResult { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - tx_id: string; - sender_address: string; -} - -export interface FungibleTokenMetadataQueryResult { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - symbol: string; - decimals: number; - tx_id: string; - sender_address: string; -} - -export interface DbTokenMetadataQueueEntryQuery { - queue_id: number; - tx_id: string; - contract_id: string; - contract_abi: string; - block_height: number; - processed: boolean; - retry_count: number; -} - export interface RawTxQueryResult { raw_tx: string; } @@ -1513,38 +1439,6 @@ export interface RewardSlotHolderInsertValues { slot_index: number; } -export interface TokenMetadataQueueEntryInsertValues { - tx_id: PgBytea; - contract_id: string; - contract_abi: string; - block_height: number; - processed: boolean; -} - -export interface NftMetadataInsertValues { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - tx_id: PgBytea; - sender_address: string; -} - -export interface FtMetadataInsertValues { - token_uri: string; - name: string; - description: string; - image_uri: string; - image_canonical_uri: string; - contract_id: string; - symbol: string; - decimals: number; - tx_id: PgBytea; - sender_address: string; -} - export interface SmartContractInsertValues { tx_id: PgBytea; canonical: boolean; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index b351323871..7bf9b9564a 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -35,7 +35,6 @@ import { DbEventTypeId, DbFtBalance, DbFtEvent, - DbFungibleTokenMetadata, DbGetBlockWithMetadataOpts, DbGetBlockWithMetadataResponse, DbInboundStxTransfer, @@ -44,7 +43,6 @@ import { DbMicroblock, DbMinerReward, DbNftEvent, - DbNonFungibleTokenMetadata, DbPox2Event, DbPox3Event, DbPox3Stacker, @@ -55,8 +53,6 @@ import { DbStxBalance, DbStxEvent, DbStxLockEvent, - DbTokenMetadataQueueEntry, - DbTokenMetadataQueueEntryQuery, DbTokenOfferingLocked, DbTx, DbTxGlobalStatus, @@ -64,13 +60,11 @@ import { DbTxTypeId, DbTxWithAssetTransfers, FaucetRequestQueryResult, - FungibleTokenMetadataQueryResult, MempoolTxQueryResult, MicroblockQueryResult, NftEventWithTxMetadata, NftHoldingInfo, NftHoldingInfoWithTxMetadata, - NonFungibleTokenMetadataQueryResult, Pox2EventQueryResult, Pox3EventQueryResult, RawTxQueryResult, @@ -1903,63 +1897,6 @@ export class PgStore { }); } - /** - * Returns a single entry from the `token_metadata_queue` table. - * @param queueId - queue entry id - */ - async getTokenMetadataQueueEntry( - queueId: number - ): Promise> { - const result = await this.sql` - SELECT * FROM token_metadata_queue WHERE queue_id = ${queueId} - `; - if (result.length === 0) { - return { found: false }; - } - const row = result[0]; - const entry: DbTokenMetadataQueueEntry = { - queueId: row.queue_id, - txId: row.tx_id, - contractId: row.contract_id, - contractAbi: JSON.parse(row.contract_abi), - blockHeight: row.block_height, - processed: row.processed, - retry_count: row.retry_count, - }; - return { found: true, result: entry }; - } - - async getTokenMetadataQueue( - limit: number, - excludingEntries: number[] - ): Promise { - const result = await this.sql` - SELECT * - FROM token_metadata_queue - WHERE ${ - excludingEntries.length - ? this.sql`NOT (queue_id IN ${this.sql(excludingEntries)})` - : this.sql`TRUE` - } - AND processed = false - ORDER BY block_height ASC, queue_id ASC - LIMIT ${limit} - `; - const entries = result.map(row => { - const entry: DbTokenMetadataQueueEntry = { - queueId: row.queue_id, - txId: row.tx_id, - contractId: row.contract_id, - contractAbi: JSON.parse(row.contract_abi), - blockHeight: row.block_height, - processed: row.processed, - retry_count: row.retry_count, - }; - return entry; - }); - return entries; - } - async getSmartContract(contractId: string) { const result = await this.sql< { @@ -4347,132 +4284,4 @@ export class PgStore { } return result; } - - async getFtMetadata(contractId: string): Promise> { - const queryResult = await this.sql` - SELECT token_uri, name, description, image_uri, image_canonical_uri, symbol, decimals, contract_id, tx_id, sender_address - FROM ft_metadata - WHERE contract_id = ${contractId} - LIMIT 1 - `; - if (queryResult.length > 0) { - const metadata: DbFungibleTokenMetadata = { - token_uri: queryResult[0].token_uri, - name: queryResult[0].name, - description: queryResult[0].description, - image_uri: queryResult[0].image_uri, - image_canonical_uri: queryResult[0].image_canonical_uri, - symbol: queryResult[0].symbol, - decimals: queryResult[0].decimals, - contract_id: queryResult[0].contract_id, - tx_id: queryResult[0].tx_id, - sender_address: queryResult[0].sender_address, - }; - return { - found: true, - result: metadata, - }; - } else { - return { found: false } as const; - } - } - - async getNftMetadata(contractId: string): Promise> { - const queryResult = await this.sql` - SELECT token_uri, name, description, image_uri, image_canonical_uri, contract_id, tx_id, sender_address - FROM nft_metadata - WHERE contract_id = ${contractId} - LIMIT 1 - `; - if (queryResult.length > 0) { - const metadata: DbNonFungibleTokenMetadata = { - token_uri: queryResult[0].token_uri, - name: queryResult[0].name, - description: queryResult[0].description, - image_uri: queryResult[0].image_uri, - image_canonical_uri: queryResult[0].image_canonical_uri, - contract_id: queryResult[0].contract_id, - tx_id: queryResult[0].tx_id, - sender_address: queryResult[0].sender_address, - }; - return { - found: true, - result: metadata, - }; - } else { - return { found: false } as const; - } - } - - async getFtMetadataList({ - limit, - offset, - }: { - limit: number; - offset: number; - }): Promise<{ results: DbFungibleTokenMetadata[]; total: number }> { - return await this.sqlTransaction(async sql => { - const totalQuery = await sql<{ count: number }[]>` - SELECT COUNT(*)::integer - FROM ft_metadata - `; - const resultQuery = await sql` - SELECT * - FROM ft_metadata - LIMIT ${limit} - OFFSET ${offset} - `; - const parsed = resultQuery.map(r => { - const metadata: DbFungibleTokenMetadata = { - name: r.name, - description: r.description, - token_uri: r.token_uri, - image_uri: r.image_uri, - image_canonical_uri: r.image_canonical_uri, - decimals: r.decimals, - symbol: r.symbol, - contract_id: r.contract_id, - tx_id: r.tx_id, - sender_address: r.sender_address, - }; - return metadata; - }); - return { results: parsed, total: totalQuery[0].count }; - }); - } - - async getNftMetadataList({ - limit, - offset, - }: { - limit: number; - offset: number; - }): Promise<{ results: DbNonFungibleTokenMetadata[]; total: number }> { - return await this.sqlTransaction(async sql => { - const totalQuery = await sql<{ count: number }[]>` - SELECT COUNT(*)::integer - FROM nft_metadata - `; - const resultQuery = await sql` - SELECT * - FROM nft_metadata - LIMIT ${limit} - OFFSET ${offset} - `; - const parsed = resultQuery.map(r => { - const metadata: DbNonFungibleTokenMetadata = { - name: r.name, - description: r.description, - token_uri: r.token_uri, - image_uri: r.image_uri, - image_canonical_uri: r.image_canonical_uri, - contract_id: r.contract_id, - tx_id: r.tx_id, - sender_address: r.sender_address, - }; - return metadata; - }); - return { results: parsed, total: totalQuery[0].count }; - }); - } } diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 29bb435d63..870d92f4c3 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -22,9 +22,6 @@ import { DataStoreMicroblockUpdateData, DbMicroblock, DataStoreTxEventData, - DbNonFungibleTokenMetadata, - DbFungibleTokenMetadata, - DbTokenMetadataQueueEntry, DbFaucetRequest, MinerRewardInsertValues, BlockInsertValues, @@ -42,12 +39,9 @@ import { TxInsertValues, MempoolTxInsertValues, MempoolTxQueryResult, - TokenMetadataQueueEntryInsertValues, SmartContractInsertValues, BnsNameInsertValues, BnsNamespaceInsertValues, - FtMetadataInsertValues, - NftMetadataInsertValues, FaucetRequestInsertValues, MicroblockInsertValues, TxQueryResult, @@ -64,7 +58,6 @@ import { DbPox3Event, NftCustodyInsertValues, } from './common'; -import { ClarityAbi } from '@stacks/transactions'; import { BLOCK_COLUMNS, convertTxQueryResultToDbMempoolTx, @@ -89,7 +82,6 @@ import { } from './connection'; import { runMigrations } from './migrations'; import { getPgClientConfig } from './connection-legacy'; -import { isProcessableTokenMetadata } from '../token-metadata/helpers'; import * as zoneFileParser from 'zone-file'; import { parseResolver, parseZoneFileTxt } from '../event-stream/bns/bns-helpers'; import { Pox2EventName } from '../pox-helpers'; @@ -207,7 +199,6 @@ export class PgWriteStore extends PgStore { } async update(data: DataStoreBlockUpdateData): Promise { - const tokenMetadataQueueEntries: DbTokenMetadataQueueEntry[] = []; let garbageCollectedMempoolTxs: string[] = []; let batchedTxData: DataStoreTxEventData[] = []; const deployedSmartContracts: DbSmartContract[] = []; @@ -425,34 +416,6 @@ export class PgWriteStore extends PgStore { logger.debug(`Garbage collected ${mempoolGarbageResults.deletedTxs.length} mempool txs`); } garbageCollectedMempoolTxs = mempoolGarbageResults.deletedTxs; - - const tokenContractDeployments = data.txs - .filter( - entry => - entry.tx.type_id === DbTxTypeId.SmartContract || - entry.tx.type_id === DbTxTypeId.VersionedSmartContract - ) - .filter(entry => entry.tx.status === DbTxStatus.Success) - .filter(entry => entry.smartContracts[0].abi && entry.smartContracts[0].abi !== 'null') - .map(entry => { - const smartContract = entry.smartContracts[0]; - const contractAbi: ClarityAbi = JSON.parse(smartContract.abi as string); - const queueEntry: DbTokenMetadataQueueEntry = { - queueId: -1, - txId: entry.tx.tx_id, - contractId: smartContract.contract_id, - contractAbi: contractAbi, - blockHeight: entry.tx.block_height, - processed: false, - retry_count: 0, - }; - return queueEntry; - }) - .filter(entry => isProcessableTokenMetadata(entry.contractAbi)); - for (const pendingQueueEntry of tokenContractDeployments) { - const queueEntry = await this.updateTokenMetadataQueue(sql, pendingQueueEntry); - tokenMetadataQueueEntries.push(queueEntry); - } } if (!this.isEventReplay) { @@ -497,9 +460,6 @@ export class PgWriteStore extends PgStore { eventIndex: nftEvent.event_index, }); } - for (const tokenMetadataQueueEntry of tokenMetadataQueueEntries) { - await this.notifier.sendTokenMetadata({ queueId: tokenMetadataQueueEntry.queueId }); - } } } @@ -1783,28 +1743,6 @@ export class PgWriteStore extends PgStore { } } - async updateTokenMetadataQueue( - sql: PgSqlClient, - entry: DbTokenMetadataQueueEntry - ): Promise { - const values: TokenMetadataQueueEntryInsertValues = { - tx_id: entry.txId, - contract_id: entry.contractId, - contract_abi: JSON.stringify(entry.contractAbi), - block_height: entry.blockHeight, - processed: false, - }; - const queryResult = await sql<{ queue_id: number }[]>` - INSERT INTO token_metadata_queue ${sql(values)} - RETURNING queue_id - `; - const result: DbTokenMetadataQueueEntry = { - ...entry, - queueId: queryResult[0].queue_id, - }; - return result; - } - async updateSmartContract(sql: PgSqlClient, tx: DbTx, smartContract: DbSmartContract) { const values: SmartContractInsertValues = { tx_id: smartContract.tx_id, @@ -2003,87 +1941,6 @@ export class PgWriteStore extends PgStore { `; } - async updateFtMetadata(ftMetadata: DbFungibleTokenMetadata, dbQueueId: number): Promise { - const length = await this.sqlWriteTransaction(async sql => { - const values: FtMetadataInsertValues = { - token_uri: ftMetadata.token_uri, - name: ftMetadata.name, - description: ftMetadata.description, - image_uri: ftMetadata.image_uri, - image_canonical_uri: ftMetadata.image_canonical_uri, - contract_id: ftMetadata.contract_id, - symbol: ftMetadata.symbol, - decimals: ftMetadata.decimals, - tx_id: ftMetadata.tx_id, - sender_address: ftMetadata.sender_address, - }; - const result = await sql` - INSERT INTO ft_metadata ${sql(values)} - ON CONFLICT (contract_id) - DO - UPDATE SET ${sql(values)} - `; - await sql` - UPDATE token_metadata_queue - SET processed = true - WHERE queue_id = ${dbQueueId} - `; - return result.count; - }); - await this.notifier?.sendTokens({ contractID: ftMetadata.contract_id }); - return length; - } - - async updateNFtMetadata( - nftMetadata: DbNonFungibleTokenMetadata, - dbQueueId: number - ): Promise { - const length = await this.sqlWriteTransaction(async sql => { - const values: NftMetadataInsertValues = { - token_uri: nftMetadata.token_uri, - name: nftMetadata.name, - description: nftMetadata.description, - image_uri: nftMetadata.image_uri, - image_canonical_uri: nftMetadata.image_canonical_uri, - contract_id: nftMetadata.contract_id, - tx_id: nftMetadata.tx_id, - sender_address: nftMetadata.sender_address, - }; - const result = await sql` - INSERT INTO nft_metadata ${sql(values)} - ON CONFLICT (contract_id) - DO - UPDATE SET ${sql(values)} - `; - await sql` - UPDATE token_metadata_queue - SET processed = true - WHERE queue_id = ${dbQueueId} - `; - return result.count; - }); - await this.notifier?.sendTokens({ contractID: nftMetadata.contract_id }); - return length; - } - - async updateProcessedTokenMetadataQueueEntry(queueId: number): Promise { - await this.sql` - UPDATE token_metadata_queue - SET processed = true - WHERE queue_id = ${queueId} - `; - } - - async increaseTokenMetadataQueueEntryRetryCount(queueId: number): Promise { - const result = await this.sql<{ retry_count: number }[]>` - UPDATE token_metadata_queue - SET retry_count = retry_count + 1 - WHERE queue_id = ${queueId} - RETURNING retry_count - `; - return result[0].retry_count; - } - async updateBatchTokenOfferingLocked(sql: PgSqlClient, lockedInfos: DbTokenOfferingLocked[]) { try { const res = await sql` diff --git a/src/helpers.ts b/src/helpers.ts index 358c34ff90..77886fc525 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -909,48 +909,6 @@ export function normalizeHashString(input: string): string | false { return `0x${hashBuffer.toString('hex')}`; } -export function parseDataUrl( - s: string -): - | { mediaType?: string; contentType?: string; charset?: string; base64: boolean; data: string } - | false { - try { - const url = new URL(s); - if (url.protocol !== 'data:') { - return false; - } - const validDataUrlRegex = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}()|~`]+)*)?(;base64)?,(.*)$/i; - const parts = validDataUrlRegex.exec(s.trim()); - if (parts === null) { - return false; - } - const parsed: { - mediaType?: string; - contentType?: string; - charset?: string; - base64: boolean; - data: string; - } = { - base64: false, - data: '', - }; - if (parts[1]) { - parsed.mediaType = parts[1].toLowerCase(); - const mediaTypeParts = parts[1].split(';').map(x => x.toLowerCase()); - parsed.contentType = mediaTypeParts[0]; - mediaTypeParts.slice(1).forEach(attribute => { - const p = attribute.split('='); - Object.assign(parsed, { [p[0]]: p[1] }); - }); - } - parsed.base64 = !!parts[parts.length - 2]; - parsed.data = parts[parts.length - 1] || ''; - return parsed; - } catch (e) { - return false; - } -} - /** * Unsigned 32-bit integer. * - Mainnet: 0x00000001 diff --git a/src/index.ts b/src/index.ts index 26fd473062..f737075a79 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,8 +23,6 @@ import { injectC32addressEncodeCache } from './c32-addr-cache'; import { exportEventsAsTsv, importEventsFromTsv } from './event-replay/event-replay'; import { PgStore } from './datastore/pg-store'; import { PgWriteStore } from './datastore/pg-write-store'; -import { isFtMetadataEnabled, isNftMetadataEnabled } from './token-metadata/helpers'; -import { TokensProcessorQueue } from './token-metadata/tokens-processor-queue'; import { registerMempoolPromStats } from './datastore/helpers'; import { logger } from './logger'; @@ -159,23 +157,6 @@ async function init(): Promise { monitorCoreRpcConnection().catch(error => { logger.error(error, 'Error monitoring RPC connection'); }); - - if (!isFtMetadataEnabled()) { - logger.warn('Fungible Token metadata processing is not enabled.'); - } - if (!isNftMetadataEnabled()) { - logger.warn('Non-Fungible Token metadata processing is not enabled.'); - } - if (isFtMetadataEnabled() || isNftMetadataEnabled()) { - const tokenMetadataProcessor = new TokensProcessorQueue(dbWriteStore, configuredChainID); - registerShutdownConfig({ - name: 'Token Metadata Processor', - handler: () => tokenMetadataProcessor.close(), - forceKillable: true, - }); - // Enqueue a batch of pending token metadata processors, if any. - await tokenMetadataProcessor.checkDbQueue(); - } } if ( diff --git a/src/rosetta/rosetta-ft-metadata-client.ts b/src/rosetta/rosetta-ft-metadata-client.ts new file mode 100644 index 0000000000..8d11618d30 --- /dev/null +++ b/src/rosetta/rosetta-ft-metadata-client.ts @@ -0,0 +1,204 @@ +import { + ClarityType, + ClarityValue, + getAddressFromPrivateKey, + hexToCV, + makeRandomPrivKey, + TransactionVersion, + UIntCV, +} from '@stacks/transactions'; +import { ChainID, getChainIDNetwork } from '../helpers'; +import { ReadOnlyContractCallResponse, StacksCoreRpcClient } from '../core-rpc/client'; +import { logger } from '../logger'; +import * as LRUCache from 'lru-cache'; + +/** Fungible token metadata for Rosetta operations display */ +export interface RosettaFtMetadata { + symbol: string; + decimals: number; +} + +interface RosettaFtContractCallParams { + address: string; + contractAddress: string; + contractName: string; + functionName: string; +} + +enum RosettaTokenMetadataErrorMode { + /** Default mode. If a required token metadata is not found when it is needed for a response, the + * API will issue a warning. */ + warning, + /** If a required token metadata is not found, the API will throw an error. */ + error, +} + +/** + * Determines the token metadata error handling mode based on .env values. + * @returns TokenMetadataMode + */ +function tokenMetadataErrorMode(): RosettaTokenMetadataErrorMode { + switch (process.env['STACKS_API_TOKEN_METADATA_ERROR_MODE']) { + case 'error': + return RosettaTokenMetadataErrorMode.error; + default: + return RosettaTokenMetadataErrorMode.warning; + } +} + +function isFtMetadataEnabled() { + const opt = process.env['STACKS_API_ENABLE_FT_METADATA']?.toLowerCase().trim(); + return opt === '1' || opt === 'true'; +} + +/** + * LRU cache that keeps `RosettaFtMetadata` entries for FTs used in the Stacks chain and retrieved + * by the Rosetta endpoints. + */ +const ftMetadataCache = new LRUCache>({ + max: 5_000, +}); + +/** + * Retrieves FT metadata for tokens used by Rosetta. Keeps data in cache for faster future + * retrieval. + */ +export class RosettaFtMetadataClient { + private readonly chainId: ChainID; + private readonly nodeRpcClient: StacksCoreRpcClient; + + constructor(chainId: ChainID) { + this.chainId = chainId; + this.nodeRpcClient = new StacksCoreRpcClient(); + } + + getFtMetadata(assetIdentifier: string): Promise { + if (!isFtMetadataEnabled()) return Promise.resolve(undefined); + const cachedMetadata = ftMetadataCache.get(assetIdentifier); + if (cachedMetadata) return cachedMetadata; + + const resolvePromise = this.resolveFtMetadata(assetIdentifier); + ftMetadataCache.set(assetIdentifier, resolvePromise); + // If the promise is rejected, remove the entry from the cache so that it can be retried later. + resolvePromise.catch(_ => { + ftMetadataCache.del(assetIdentifier); + }); + return resolvePromise; + } + + private async resolveFtMetadata(assetIdentifier: string): Promise { + const tokenContractId = assetIdentifier.split('::')[0]; + const [contractAddress, contractName] = tokenContractId.split('.'); + try { + const address = getAddressFromPrivateKey( + makeRandomPrivKey().data, + getChainIDNetwork(this.chainId) === 'mainnet' + ? TransactionVersion.Mainnet + : TransactionVersion.Testnet + ); + const symbol = await this.readStringFromContract({ + functionName: 'get-symbol', + contractAddress, + contractName, + address, + }); + const decimals = await this.readUIntFromContract({ + functionName: 'get-decimals', + contractAddress, + contractName, + address, + }); + if (symbol !== undefined && decimals !== undefined) { + const metadata = { symbol, decimals: parseInt(decimals.toString()) }; + return metadata; + } + } catch (error) { + if (tokenMetadataErrorMode() === RosettaTokenMetadataErrorMode.warning) { + logger.warn(error, `FT metadata not found for token: ${assetIdentifier}`); + } else { + throw new Error(`FT metadata not found for token: ${assetIdentifier}`); + } + } + } + + private async readStringFromContract( + args: RosettaFtContractCallParams + ): Promise { + const clarityValue = await this.makeReadOnlyContractCall(args); + return this.checkAndParseString(clarityValue); + } + + private async readUIntFromContract( + args: RosettaFtContractCallParams + ): Promise { + const clarityValue = await this.makeReadOnlyContractCall(args); + const uintVal = this.checkAndParseUintCV(clarityValue); + try { + return BigInt(uintVal.value.toString()); + } catch (error) { + throw new Error(`Invalid uint value '${uintVal}'`); + } + } + + private unwrapClarityType(clarityValue: ClarityValue): ClarityValue { + let unwrappedClarityValue: ClarityValue = clarityValue; + while ( + unwrappedClarityValue.type === ClarityType.ResponseOk || + unwrappedClarityValue.type === ClarityType.OptionalSome + ) { + unwrappedClarityValue = unwrappedClarityValue.value; + } + return unwrappedClarityValue; + } + + private checkAndParseUintCV(responseCV: ClarityValue): UIntCV { + const unwrappedClarityValue = this.unwrapClarityType(responseCV); + if (unwrappedClarityValue.type === ClarityType.UInt) { + return unwrappedClarityValue; + } + throw new Error( + `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping uint` + ); + } + + private checkAndParseString(responseCV: ClarityValue): string | undefined { + const unwrappedClarityValue = this.unwrapClarityType(responseCV); + if ( + unwrappedClarityValue.type === ClarityType.StringASCII || + unwrappedClarityValue.type === ClarityType.StringUTF8 + ) { + return unwrappedClarityValue.data; + } else if (unwrappedClarityValue.type === ClarityType.OptionalNone) { + return undefined; + } + throw new Error( + `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping string` + ); + } + + private async makeReadOnlyContractCall(args: RosettaFtContractCallParams): Promise { + let result: ReadOnlyContractCallResponse; + try { + result = await this.nodeRpcClient.sendReadOnlyContractCall( + args.contractAddress, + args.contractName, + args.functionName, + args.address, + [] + ); + } catch (error) { + throw new Error(`Error making read-only contract call: ${error}`); + } + if (!result.okay) { + // Only runtime errors reported by the Stacks node should be retryable. + if ( + result.cause.startsWith('Runtime') || + result.cause.startsWith('Unchecked(NoSuchContract') + ) { + throw new Error(`Runtime error while calling read-only function ${args.functionName}`); + } + throw new Error(`Error calling read-only function ${args.functionName}`); + } + return hexToCV(result.result); + } +} diff --git a/src/rosetta-helpers.ts b/src/rosetta/rosetta-helpers.ts similarity index 95% rename from src/rosetta-helpers.ts rename to src/rosetta/rosetta-helpers.ts index 945903d4f6..5d06c803ca 100644 --- a/src/rosetta-helpers.ts +++ b/src/rosetta/rosetta-helpers.ts @@ -1,6 +1,5 @@ import { ContractCallTransaction, - FungibleTokenMetadata, RosettaAccountIdentifier, RosettaCurrency, RosettaOperation, @@ -25,40 +24,18 @@ import { StacksMainnet, StacksTestnet } from '@stacks/network'; import { ec as EC } from 'elliptic'; import * as btc from 'bitcoinjs-lib'; import { - getAssetEventTypeString, - getEventTypeString, getTxFromDataStore, getTxStatus, getTxTypeString, parseContractCallMetadata, -} from './api/controllers/db-controller'; +} from '../api/controllers/db-controller'; import { PoxContractIdentifier, RosettaConstants, RosettaNetworks, RosettaOperationType, -} from './api/rosetta-constants'; -import { - BaseTx, - DbAssetEventTypeId, - DbEvent, - DbEventTypeId, - DbFtEvent, - DbFungibleTokenMetadata, - DbMempoolTx, - DbMinerReward, - DbStxEvent, - DbStxLockEvent, - DbTx, - DbTxStatus, - DbTxTypeId, - StxUnlockEvent, -} from './datastore/common'; -import { getTxSenderAddress, getTxSponsorAddress } from './event-stream/reader'; -import { unwrapOptional, hexToBuffer, getSendManyContract } from './helpers'; - -import { getCoreNodeEndpoint } from './core-rpc/client'; -import { TokenMetadataErrorMode } from './token-metadata/tokens-contract-handler'; +} from '../api/rosetta-constants'; +import { getCoreNodeEndpoint } from '../core-rpc/client'; import { ClarityTypeID, decodeClarityValue, @@ -76,11 +53,28 @@ import { ClarityValue, ClarityValueList, } from 'stacks-encoding-native-js'; -import { PgStore } from './datastore/pg-store'; -import { isFtMetadataEnabled, tokenMetadataErrorMode } from './token-metadata/helpers'; +import { PgStore } from '../datastore/pg-store'; import { poxAddressToBtcAddress } from '@stacks/stacking'; import { parseRecoverableSignatureVrs } from '@stacks/common'; -import { logger } from './logger'; +import { RosettaFtMetadata, RosettaFtMetadataClient } from './rosetta-ft-metadata-client'; +import { + DbTx, + DbMempoolTx, + BaseTx, + DbMinerReward, + DbEvent, + StxUnlockEvent, + DbEventTypeId, + DbAssetEventTypeId, + DbTxTypeId, + DbStxLockEvent, + DbTxStatus, + DbStxEvent, + DbFtEvent, +} from '../datastore/common'; +import { getTxSenderAddress, getTxSponsorAddress } from '../event-stream/reader'; +import { hexToBuffer, getSendManyContract, unwrapOptional } from '../helpers'; +import { logger } from '../logger'; enum CoinAction { CoinSpent = 'coin_spent', @@ -242,6 +236,7 @@ async function processEvents( // match them by index. const sendManyMemos = decodeSendManyContractCallMemos(baseTx, chainID); let sendManyStxTransferEventIndex = 0; + const metadataClient = new RosettaFtMetadataClient(chainID); for (const event of events) { const txEventType = event.event_type; @@ -297,7 +292,7 @@ async function processEvents( case DbEventTypeId.NonFungibleTokenAsset: break; case DbEventTypeId.FungibleTokenAsset: - const ftMetadata = await getValidatedFtMetadata(db, event.asset_identifier); + const ftMetadata = await metadataClient.getFtMetadata(event.asset_identifier); if (!ftMetadata) { break; } @@ -434,7 +429,7 @@ function makeBurnOperation(tx: DbStxEvent, baseTx: BaseTx, index: number): Roset function makeFtBurnOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, baseTx: BaseTx, index: number ): RosettaOperation { @@ -481,7 +476,7 @@ function makeMintOperation(tx: DbStxEvent, baseTx: BaseTx, index: number): Roset function makeFtMintOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, baseTx: BaseTx, index: number ): RosettaOperation { @@ -547,7 +542,7 @@ function makeSenderOperation( function makeFtSenderOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, tx: BaseTx, index: number ): RosettaOperation { @@ -620,7 +615,7 @@ function makeReceiverOperation( function makeFtReceiverOperation( ftEvent: DbFtEvent, - ftMetadata: FungibleTokenMetadata, + ftMetadata: RosettaFtMetadata, tx: BaseTx, index: number ): RosettaOperation { @@ -1147,28 +1142,6 @@ export function rawTxToBaseTx(raw_tx: string): BaseTx { return dbTx; } -export async function getValidatedFtMetadata( - db: PgStore, - assetIdentifier: string -): Promise { - if (!isFtMetadataEnabled()) { - return; - } - const tokenContractId = assetIdentifier.split('::')[0]; - const ftMetadata = await db.getFtMetadata(tokenContractId); - if (!ftMetadata.found) { - if (tokenMetadataErrorMode() === TokenMetadataErrorMode.warning) { - logger.warn(`FT metadata not found for token: ${assetIdentifier}`); - } else { - // TODO: Check if the metadata wasn't found because the contract ABI is not SIP-010 - // compliant or because there was a recoverable error that prevented the metadata - // from being processed. - throw new Error(`FT metadata not found for token: ${assetIdentifier}`); - } - } - return ftMetadata.result; -} - export function getSigners(transaction: StacksTransaction): RosettaAccountIdentifier[] | undefined { let address; if (transaction.payload.payloadType == PayloadType.TokenTransfer) { @@ -1217,7 +1190,7 @@ export function getSigners(transaction: StacksTransaction): RosettaAccountIdenti return account_identifier_signers; } -export function getStacksTestnetNetwork() { +function getStacksTestnetNetwork() { return new StacksTestnet({ url: `http://${getCoreNodeEndpoint()}`, }); diff --git a/src/tests-rosetta-construction/construction.ts b/src/tests-rosetta-construction/construction.ts index 12109483f8..b3df30aa26 100644 --- a/src/tests-rosetta-construction/construction.ts +++ b/src/tests-rosetta-construction/construction.ts @@ -53,7 +53,7 @@ import { RosettaOperationTypes, } from '../api/rosetta-constants'; import { getStacksTestnetNetwork, testnetKeys } from '../api/routes/debug'; -import { getSignature, getStacksNetwork } from '../rosetta-helpers'; +import { getSignature, getStacksNetwork } from '../rosetta/rosetta-helpers'; import { makeSigHashPreSign, MessageSignature } from '@stacks/transactions'; import { PgWriteStore } from '../datastore/pg-write-store'; import { runMigrations } from '../datastore/migrations'; diff --git a/src/tests-rosetta/account-tests.ts b/src/tests-rosetta/account-tests.ts index f6196b1f83..79a3ca67e4 100644 --- a/src/tests-rosetta/account-tests.ts +++ b/src/tests-rosetta/account-tests.ts @@ -1,11 +1,11 @@ import * as supertest from 'supertest'; -import { ChainID } from '@stacks/transactions'; -import { PoolClient } from 'pg'; +import { ChainID, cvToHex, stringUtf8CV, uintCV } from '@stacks/transactions'; import { ApiServer, startApiServer } from '../api/init'; import { TestBlockBuilder } from '../test-utils/test-builders'; -import { DbAssetEventTypeId, DbFungibleTokenMetadata } from '../datastore/common'; +import { DbAssetEventTypeId } from '../datastore/common'; import { PgWriteStore } from '../datastore/pg-write-store'; import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import * as nock from 'nock'; describe('/account tests', () => { let db: PgWriteStore; @@ -23,20 +23,21 @@ describe('/account tests', () => { const addr1 = 'SP3WV3VC6GM1WF215SDHP0MESQ3BNXHB1N6TPB70S'; const addr2 = 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y'; - // Declare fungible token - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'https://cdn.citycoins.co/metadata/newyorkcitycoin.json', - name: 'newyorkcitycoin', - description: 'A CityCoin for New York City, ticker is NYC, Stack it to earn Stacks (STX)', - image_uri: 'https://stacks-api.imgix.net/https%3A%2F%2Fcdn.citycoins.co%2Flogos%2Fnewyorkcitycoin.png?s=38a8d89aa6b4ef3fcc9958da3eb34480', - image_canonical_uri: 'https://cdn.citycoins.co/logos/newyorkcitycoin.png', - symbol: 'NYC', - decimals: 0, - tx_id: '0x9c8ddc44fcfdfc67af5425c4174833fc5814627936d573fe38fc29a46ba746e6', - sender_address: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5', - contract_id: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5.newyorkcitycoin-token' - }; - await db.updateFtMetadata(ftMetadata, 1); + const nodeUrl = `http://${process.env['STACKS_CORE_RPC_HOST']}:${process.env['STACKS_CORE_RPC_PORT']}`; + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-decimals') + .reply(200, { + okay: true, + result: cvToHex(uintCV(0)), + }); + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-symbol') + .reply(200, { + okay: true, + result: cvToHex(stringUtf8CV('NYC')), + }); // FT transfer const block1 = new TestBlockBuilder({ @@ -94,6 +95,7 @@ describe('/account tests', () => { value: '7500' } ]); + nock.cleanAll(); }); afterEach(async () => { diff --git a/src/tests-rosetta/block-tests.ts b/src/tests-rosetta/block-tests.ts index 98e8b1504b..d91c94821c 100644 --- a/src/tests-rosetta/block-tests.ts +++ b/src/tests-rosetta/block-tests.ts @@ -1,13 +1,14 @@ import * as supertest from 'supertest'; -import { bufferCV, ChainID, cvToHex, listCV, stringAsciiCV, tupleCV, uintCV } from '@stacks/transactions'; +import { bufferCV, ChainID, cvToHex, listCV, stringAsciiCV, stringUtf8CV, tupleCV, uintCV } from '@stacks/transactions'; import { ApiServer, startApiServer } from '../api/init'; import { TestBlockBuilder } from '../test-utils/test-builders'; -import { DbAssetEventTypeId, DbFungibleTokenMetadata, DbTxTypeId } from '../datastore/common'; +import { DbAssetEventTypeId, DbTxTypeId } from '../datastore/common'; import { createClarityValueArray } from '../stacks-encoding-helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; import { cycleMigrations, runMigrations } from '../datastore/migrations'; import { bufferToHexPrefixString } from '../helpers'; import { principalCV } from '@stacks/transactions/dist/clarity/types/principalCV'; +import * as nock from 'nock'; describe('/block tests', () => { let db: PgWriteStore; @@ -111,20 +112,21 @@ describe('/block tests', () => { const addr1 = 'SP3WV3VC6GM1WF215SDHP0MESQ3BNXHB1N6TPB70S'; const addr2 = 'ST27W5M8BRKA7C5MZE2R1S1F4XTPHFWFRNHA9M04Y'; - // Declare fungible token - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'https://cdn.citycoins.co/metadata/newyorkcitycoin.json', - name: 'newyorkcitycoin', - description: 'A CityCoin for New York City, ticker is NYC, Stack it to earn Stacks (STX)', - image_uri: 'https://stacks-api.imgix.net/https%3A%2F%2Fcdn.citycoins.co%2Flogos%2Fnewyorkcitycoin.png?s=38a8d89aa6b4ef3fcc9958da3eb34480', - image_canonical_uri: 'https://cdn.citycoins.co/logos/newyorkcitycoin.png', - symbol: 'NYC', - decimals: 0, - tx_id: '0x9c8ddc44fcfdfc67af5425c4174833fc5814627936d573fe38fc29a46ba746e6', - sender_address: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5', - contract_id: 'SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5.newyorkcitycoin-token' - }; - await db.updateFtMetadata(ftMetadata, 1); + const nodeUrl = `http://${process.env['STACKS_CORE_RPC_HOST']}:${process.env['STACKS_CORE_RPC_PORT']}`; + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-decimals') + .reply(200, { + okay: true, + result: cvToHex(uintCV(0)), + }); + nock(nodeUrl) + .persist() + .post('/v2/contracts/call-read/SP2H8PY27SEZ03MWRKS5XABZYQN17ETGQS3527SA5/newyorkcitycoin-token/get-symbol') + .reply(200, { + okay: true, + result: cvToHex(stringUtf8CV('NYC')), + }); // FT transfer const block1 = new TestBlockBuilder({ diff --git a/src/tests-rosetta/offline-api-tests.ts b/src/tests-rosetta/offline-api-tests.ts index 395b461a43..8cd7b143f3 100644 --- a/src/tests-rosetta/offline-api-tests.ts +++ b/src/tests-rosetta/offline-api-tests.ts @@ -50,7 +50,7 @@ import { } from '../api/rosetta-constants'; import { OfflineDummyStore } from '../datastore/offline-dummy-store'; import { getStacksTestnetNetwork, testnetKeys } from '../api/routes/debug'; -import { getSignature, getStacksNetwork, publicKeyToBitcoinAddress } from '../rosetta-helpers'; +import { getSignature, getStacksNetwork, publicKeyToBitcoinAddress } from '../rosetta/rosetta-helpers'; import * as nock from 'nock'; import * as poxHelpers from '../pox-helpers'; import { PgStore } from '../datastore/pg-store'; diff --git a/src/tests-tokens-metadata/setup.ts b/src/tests-tokens-metadata/setup.ts deleted file mode 100644 index f2d1cf887b..0000000000 --- a/src/tests-tokens-metadata/setup.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { loadDotEnv } from '../helpers'; - -// ts-unused-exports:disable-next-line -export default () => { - console.log('Jest - setup..'); - if (!process.env.NODE_ENV) { - process.env.NODE_ENV = 'test'; - } - loadDotEnv(); - process.env.PG_DATABASE = 'postgres'; - process.env.STACKS_CHAIN_ID = '0x80000000'; - console.log('Jest - setup done'); -}; diff --git a/src/tests-tokens-metadata/teardown.ts b/src/tests-tokens-metadata/teardown.ts deleted file mode 100644 index 8638723d18..0000000000 --- a/src/tests-tokens-metadata/teardown.ts +++ /dev/null @@ -1,5 +0,0 @@ -// ts-unused-exports:disable-next-line -export default () => { - console.log('Jest - teardown..'); - console.log('Jest - teardown done'); -}; diff --git a/src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar b/src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar deleted file mode 100644 index a773a93d5f..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; (impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "data:,%7B%22name%22%3A%22Heystack%22%2C%22description%22%3A%22Heystack%20is%20a%20SIP-010-compliant%20fungible%20token%22%2C%22imageUrl%22%3A%22https%3A%2F%2Fheystack.xyz%2Fassets%2FStacks128w.png%22%7D"))) - -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar b/src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar deleted file mode 100644 index a8dfbf21c5..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; (impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "data:;base64,eyJuYW1lIjoiSGV5c3RhY2siLCJkZXNjcmlwdGlvbiI6IkhleXN0YWNrIGlzIGEgU0lQLTAxMC1jb21wbGlhbnQgZnVuZ2libGUgdG9rZW4iLCJpbWFnZVVybCI6Imh0dHBzOi8vaGV5c3RhY2sueHl6L2Fzc2V0cy9TdGFja3MxMjh3LnBuZyJ9"))) - -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar b/src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar deleted file mode 100644 index fa335337ac..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; (impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "data:application/json,{\"name\":\"Heystack\",\"description\":\"Heystack is a SIP-010-compliant fungible token\",\"imageUrl\":\"https://heystack.xyz/assets/Stacks128w.png\"}"))) - ;; (ok (some "data:text/html,"))) -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/beeple.clar b/src/tests-tokens-metadata/test-contracts/beeple.clar deleted file mode 100644 index d7ea8b693b..0000000000 --- a/src/tests-tokens-metadata/test-contracts/beeple.clar +++ /dev/null @@ -1,58 +0,0 @@ -(impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.nft-trait.nft-trait) -(define-non-fungible-token beeple uint) - -;; Public functions -(define-constant nft-not-owned-err (err u401)) ;; unauthorized -(define-constant nft-not-found-err (err u404)) ;; not found -(define-constant sender-equals-recipient-err (err u405)) ;; method not allowed - -(define-private (nft-transfer-err (code uint)) - (if (is-eq u1 code) - nft-not-owned-err - (if (is-eq u2 code) - sender-equals-recipient-err - (if (is-eq u3 code) - nft-not-found-err - (err code))))) - -;; Transfers tokens to a specified principal. -(define-public (transfer (token-id uint) (sender principal) (recipient principal)) - (if (and - (is-eq tx-sender (unwrap! (nft-get-owner? beeple token-id) nft-not-found-err)) - (is-eq tx-sender sender) - (not (is-eq recipient sender))) - (match (nft-transfer? beeple token-id sender recipient) - success (ok success) - error (nft-transfer-err error)) - nft-not-owned-err)) - -;; Gets the owner of the specified token ID. -(define-read-only (get-owner (token-id uint)) - (ok (nft-get-owner? beeple token-id))) - -;; Gets the owner of the specified token ID. -(define-read-only (get-last-token-id) - (ok u1)) - -(define-read-only (get-token-uri (token-id uint)) - (ok (some "ipfs://ipfs/QmPAg1mjxcEQPPtqsLoEcauVedaeMH81WXDPvPx3VC5zUz"))) - -(define-read-only (get-meta (token-id uint)) - (if (is-eq token-id u1) - (ok (some {name: "EVERYDAYS: THE FIRST 5000 DAYS", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"})) - (ok none))) - -(define-read-only (get-nft-meta) - (ok (some {name: "beeple", uri: "https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq", mime-type: "image/jpeg"}))) - -(define-read-only (get-errstr (code uint)) - (ok (if (is-eq u401 code) - "nft-not-owned" - (if (is-eq u404 code) - "nft-not-found" - (if (is-eq u405 code) - "sender-equals-recipient" - "unknown-error"))))) - -;; Initialize the contract -(try! (nft-mint? beeple u1 tx-sender)) diff --git a/src/tests-tokens-metadata/test-contracts/ft-trait.clar b/src/tests-tokens-metadata/test-contracts/ft-trait.clar deleted file mode 100644 index 69255cf9e9..0000000000 --- a/src/tests-tokens-metadata/test-contracts/ft-trait.clar +++ /dev/null @@ -1,24 +0,0 @@ -(define-trait sip-010-trait - ( - ;; Transfer from the caller to a new principal - (transfer (uint principal principal (optional (buff 34))) (response bool uint)) - - ;; the human readable name of the token - (get-name () (response (string-ascii 32) uint)) - - ;; the ticker symbol, or empty if none - (get-symbol () (response (string-ascii 32) uint)) - - ;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token - (get-decimals () (response uint uint)) - - ;; the balance of the passed principal - (get-balance (principal) (response uint uint)) - - ;; the current total supply (which does not need to be a constant) - (get-total-supply () (response uint uint)) - - ;; an optional URI that represents metadata of this token - (get-token-uri () (response (optional (string-utf8 256)) uint)) - ) -) diff --git a/src/tests-tokens-metadata/test-contracts/hey-token.clar b/src/tests-tokens-metadata/test-contracts/hey-token.clar deleted file mode 100644 index bd9a50c5c1..0000000000 --- a/src/tests-tokens-metadata/test-contracts/hey-token.clar +++ /dev/null @@ -1,58 +0,0 @@ -;; Implement the `ft-trait` trait defined in the `ft-trait` contract -;; https://github.com/hstove/stacks-fungible-token -(impl-trait 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6.ft-trait.sip-010-trait) - -(define-constant contract-creator tx-sender) - -(define-fungible-token hey-token) - -;; Mint developer tokens -(ft-mint? hey-token u10000 contract-creator) -(ft-mint? hey-token u10000 'ST399W7Z9WS0GMSNQGJGME5JADNKN56R65VGM5KGA) ;; fara -(ft-mint? hey-token u10000 'ST1X6M947Z7E58CNE0H8YJVJTVKS9VW0PHEG3NHN3) ;; thomas -(ft-mint? hey-token u10000 'ST1NY8TXACV7D74886MK05SYW2XA72XJMDVPF3F3D) ;; kyran -(ft-mint? hey-token u10000 'ST34XEPDJJFJKFPT87CCZQCPGXR4PJ8ERFRP0F3GX) ;; jasper -(ft-mint? hey-token u10000 'ST3AGWHGAZKQS4JQ67WQZW5X8HZYZ4ZBWPPNWNMKF) ;; andres -(ft-mint? hey-token u10000 'ST17YZQB1228EK9MPHQXA8GC4G3HVWZ66X779FEBY) ;; esh -(ft-mint? hey-token u10000 'ST3Q0M9WAVBW633CG72VHNFZM2H82D2BJMBX85WP4) ;; mark - -;; get the token balance of owner -(define-read-only (get-balance (owner principal)) - (begin - (ok (ft-get-balance hey-token owner)))) - -;; returns the total number of tokens -(define-read-only (get-total-supply) - (ok (ft-get-supply hey-token))) - -;; returns the token name -(define-read-only (get-name) - (ok "Heystack Token")) - -;; the symbol or "ticker" for this token -(define-read-only (get-symbol) - (ok "HEY")) - -;; the number of decimals used -(define-read-only (get-decimals) - (ok u0)) - -;; Transfers tokens to a recipient -(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34)))) - (if (is-eq tx-sender sender) - (begin - (try! (ft-transfer? hey-token amount sender recipient)) - (print memo) - (ok true) - ) - (err u4))) - -(define-read-only (get-token-uri) - (ok (some u"https://heystack.xyz/token-metadata.json"))) - -(define-public (gift-tokens (recipient principal)) - (begin - (asserts! (is-eq tx-sender recipient) (err u0)) - (ft-mint? hey-token u1 recipient) - ) -) diff --git a/src/tests-tokens-metadata/test-contracts/nft-trait.clar b/src/tests-tokens-metadata/test-contracts/nft-trait.clar deleted file mode 100644 index cc558fdb5a..0000000000 --- a/src/tests-tokens-metadata/test-contracts/nft-trait.clar +++ /dev/null @@ -1,15 +0,0 @@ -(define-trait nft-trait - ( - ;; Last token ID, limited to uint range - (get-last-token-id () (response uint uint)) - - ;; URI for metadata associated with the token - (get-token-uri (uint) (response (optional (string-ascii 256)) uint)) - - ;; Owner of a given token identifier - (get-owner (uint) (response (optional principal) uint)) - - ;; Transfer from the sender to a new principal - (transfer (uint principal principal) (response bool uint)) - ) -) diff --git a/src/tests-tokens-metadata/tokens-metadata-tests.ts b/src/tests-tokens-metadata/tokens-metadata-tests.ts deleted file mode 100644 index b5335d8588..0000000000 --- a/src/tests-tokens-metadata/tokens-metadata-tests.ts +++ /dev/null @@ -1,408 +0,0 @@ -import * as supertest from 'supertest'; -import { - makeContractDeploy, - ChainID, - getAddressFromPrivateKey, - PostConditionMode, - AnchorMode, -} from '@stacks/transactions'; -import { DbFungibleTokenMetadata, DbNonFungibleTokenMetadata } from '../datastore/common'; -import { startApiServer, ApiServer } from '../api/init'; -import * as fs from 'fs'; -import { EventStreamServer, startEventServer } from '../event-stream/event-server'; -import { getStacksTestnetNetwork } from '../rosetta-helpers'; -import { StacksCoreRpcClient } from '../core-rpc/client'; -import { timeout, waiter, Waiter } from '../helpers'; -import * as nock from 'nock'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { TokensProcessorQueue } from '../token-metadata/tokens-processor-queue'; -import { performFetch } from '../token-metadata/helpers'; -import { getPagingQueryLimit, ResourceType } from '../api/pagination'; -import { standByForTx as standByForTxShared } from '../test-utils/test-helpers'; -import { logger } from '../logger'; - -const deploymentAddr = 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6'; -const pKey = 'cb3df38053d132895220b9ce471f6b676db5b9bf0b4adefb55f2118ece2478df01'; -const stacksNetwork = getStacksTestnetNetwork(); -const HOST = 'localhost'; -const PORT = 20443; - -describe('tokens metadata tests', () => { - let db: PgWriteStore; - let api: ApiServer; - let eventServer: EventStreamServer; - let tokensProcessorQueue: TokensProcessorQueue; - - const standByForTx = (expectedTxId: string) => standByForTxShared(expectedTxId, api); - - function standByForTokens(id: string): Promise { - const contractId = new Promise(resolve => { - tokensProcessorQueue.processEndEvent.attachOnce( - token => token.contractId === id, - () => resolve() - ); - }); - - return contractId; - } - - async function sendCoreTx(serializedTx: Buffer): Promise<{ txId: string }> { - try { - const submitResult = await new StacksCoreRpcClient().sendTransaction(serializedTx); - return submitResult; - } catch (error) { - logger.error(error); - } - return Promise.resolve({ txId: '' }); - } - - async function deployContract(contractName: string, senderPk: string, sourceFile: string) { - const senderAddress = getAddressFromPrivateKey(senderPk, stacksNetwork.version); - const source = fs.readFileSync(sourceFile).toString(); - const normalized_contract_source = source.replace(/\r/g, '').replace(/\t/g, ' '); - - const contractDeployTx = await makeContractDeploy({ - contractName: contractName, - codeBody: normalized_contract_source, - senderKey: senderPk, - network: stacksNetwork, - postConditionMode: PostConditionMode.Allow, - sponsored: false, - anchorMode: AnchorMode.Any, - fee: 100000, - }); - - const contractId = senderAddress + '.' + contractName; - - // const feeRateReq = await fetch(stacksNetwork.getTransferFeeEstimateApiUrl()); - // const feeRateResult = await feeRateReq.text(); - // const txBytes = BigInt(Buffer.from(contractDeployTx.serialize()).byteLength); - // const feeRate = BigInt(feeRateResult); - // const fee = feeRate * txBytes; - // contractDeployTx.setFee(fee); - const { txId } = await sendCoreTx(Buffer.from(contractDeployTx.serialize())); - return { txId, contractId }; - } - - beforeAll(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); - db = await PgWriteStore.connect({ usageName: 'tests', skipMigrations: true }); - eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); - api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); - tokensProcessorQueue = new TokensProcessorQueue(db, ChainID.Testnet); - await new StacksCoreRpcClient().waitForConnection(60000); - }); - - beforeEach(() => { - process.env['STACKS_API_ENABLE_FT_METADATA'] = '1'; - process.env['STACKS_API_ENABLE_NFT_METADATA'] = '1'; - process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'] = '1'; - nock.cleanAll(); - }); - - test('metadata disabled', async () => { - process.env['STACKS_API_ENABLE_FT_METADATA'] = '0'; - process.env['STACKS_API_ENABLE_NFT_METADATA'] = '0'; - const query1 = await supertest(api.server).get(`/extended/v1/tokens/nft/metadata`); - expect(query1.status).toBe(500); - expect(query1.body.error).toMatch(/not enabled/); - const query2 = await supertest(api.server).get(`/extended/v1/tokens/ft/metadata`); - expect(query2.status).toBe(500); - expect(query2.body.error).toMatch(/not enabled/); - const query3 = await supertest(api.server).get(`/extended/v1/tokens/example/nft/metadata`); - expect(query3.status).toBe(500); - expect(query3.body.error).toMatch(/not enabled/); - const query4 = await supertest(api.server).get(`/extended/v1/tokens/example/ft/metadata`); - expect(query4.status).toBe(500); - expect(query4.body.error).toMatch(/not enabled/); - }); - - test('token nft-metadata data URL plain percent-encoded', async () => { - const standByPromise = standByForTokens(`${deploymentAddr}.beeple-a`); - const contract1 = await deployContract( - 'beeple-a', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple-data-url-a.clar' - ); - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body).toHaveProperty('description'); - expect(query1.body).toHaveProperty('image_uri'); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('failed processing is retried in next block', async () => { - const entryProcessedWaiter: Waiter = waiter(); - const blockHandler = async (blockHash: string) => { - const entry = await db.getTokenMetadataQueueEntry(1); - if (entry.result?.processed) { - entryProcessedWaiter.finish(blockHash); - } - }; - db.eventEmitter.on('blockUpdate', blockHandler); - // Set as not processed. - await db.sql` - UPDATE token_metadata_queue - SET processed = false - WHERE queue_id = 1 - `; - // This will resolve when processed is true again. - await entryProcessedWaiter; - db.eventEmitter.off('blockUpdate', blockHandler); - }); - - test('token nft-metadata data URL base64 w/o media type', async () => { - const standByPromise = standByForTokens(`${deploymentAddr}.beeple-b`); - const contract1 = await deployContract( - 'beeple-b', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple-data-url-b.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body).toHaveProperty('description'); - expect(query1.body).toHaveProperty('image_uri'); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token nft-metadata data URL plain non-encoded', async () => { - const standByPromise = standByForTokens(`${deploymentAddr}.beeple-c`); - const contract1 = await deployContract( - 'beeple-c', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple-data-url-c.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body).toHaveProperty('description'); - expect(query1.body).toHaveProperty('image_uri'); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token nft-metadata', async () => { - //mock the response - const nftMetadata = { - name: 'EVERYDAYS: THE FIRST 5000 DAYS', - imageUrl: - 'https://ipfsgateway.makersplace.com/ipfs/QmZ15eQX8FPjfrtdX3QYbrhZxJpbLpvDpsgb2p3VEH8Bqq', - description: - 'I made a picture from start to finish every single day from May 1st, 2007 - January 7th, 2021. This is every motherfucking one of those pictures.', - }; - nock('https://ipfs.io') - .persist() - .get('/ipfs/QmPAg1mjxcEQPPtqsLoEcauVedaeMH81WXDPvPx3VC5zUz') - .reply(200, nftMetadata); - - const contract = await deployContract( - 'nft-trait', - pKey, - 'src/tests-tokens-metadata/test-contracts/nft-trait.clar' - ); - const tx = await standByForTx(contract.txId); - if (tx.status != 1) logger.error(tx, 'contract deploy error'); - - const standByPromise = standByForTokens(`${deploymentAddr}.beeple`); - const contract1 = await deployContract( - 'beeple', - pKey, - 'src/tests-tokens-metadata/test-contracts/beeple.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const senderAddress = getAddressFromPrivateKey(pKey, stacksNetwork.version); - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${senderAddress}.beeple/nft/metadata` - ); - expect(query1.status).toBe(200); - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body.name).toBe(nftMetadata.name); - expect(query1.body.description).toBe(nftMetadata.description); - expect(query1.body.image_uri).toBe(nftMetadata.imageUrl); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token ft-metadata tests', async () => { - //mock the response - const ftMetadata = { - name: 'Heystack', - description: - 'Heystack is a SIP-010-compliant fungible token on the Stacks Blockchain, used on the Heystack app', - image: 'https://heystack.xyz/assets/Stacks128w.png', - }; - - // https://heystack.xyz/token-metadata.json - nock('https://heystack.xyz').persist().get('/token-metadata.json').reply(200, ftMetadata); - - const contract = await deployContract( - 'ft-trait', - pKey, - 'src/tests-tokens-metadata/test-contracts/ft-trait.clar' - ); - - const tx = await standByForTx(contract.txId); - if (tx.status != 1) logger.error(tx, 'contract deploy error'); - - const standByPromise = standByForTokens(`${deploymentAddr}.hey-token`); - const contract1 = await deployContract( - 'hey-token', - pKey, - 'src/tests-tokens-metadata/test-contracts/hey-token.clar' - ); - - await standByPromise; - await tokensProcessorQueue.drainDbQueue(); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/${contract1.contractId}/ft/metadata` - ); - - expect(query1.body).toHaveProperty('token_uri'); - expect(query1.body).toHaveProperty('name'); - expect(query1.body.description).toBe(ftMetadata.description); - expect(query1.body.image_uri).toBe(ftMetadata.image); - expect(query1.body).toHaveProperty('image_canonical_uri'); - expect(query1.body).toHaveProperty('tx_id'); - expect(query1.body).toHaveProperty('sender_address'); - }); - - test('token ft-metadata list', async () => { - for (let i = 0; i < 200; i++) { - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'ft-token', - name: 'ft-metadata' + i, - description: 'ft -metadata description', - symbol: 'stx', - decimals: 5, - image_uri: 'ft-metadata image uri example', - image_canonical_uri: 'ft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.ft-metadata' + i, - tx_id: '0x123456', - sender_address: 'ABCDEFGHIJ', - }; - await db.updateFtMetadata(ftMetadata, 1); - } - - const query = await supertest(api.server).get(`/extended/v1/tokens/ft/metadata`); - expect(query.status).toBe(200); - expect(query.body.total).toBeGreaterThan(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.limit).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.offset).toStrictEqual(0); - expect(query.body.results.length).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/ft/metadata?limit=20&offset=10` - ); - expect(query1.status).toBe(200); - expect(query1.body.total).toBeGreaterThanOrEqual(200); - expect(query1.body.limit).toStrictEqual(20); - expect(query1.body.offset).toStrictEqual(10); - expect(query1.body.results.length).toStrictEqual(20); - }); - - test('token nft-metadata list', async () => { - for (let i = 0; i < 200; i++) { - const nftMetadata: DbNonFungibleTokenMetadata = { - token_uri: 'nft-tokenuri', - name: 'nft-metadata' + i, - description: 'nft -metadata description' + i, - image_uri: 'nft-metadata image uri example', - image_canonical_uri: 'nft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.nft-metadata' + i, - tx_id: '0x12345678', - sender_address: 'ABCDEFGHIJ', - }; - - await db.updateNFtMetadata(nftMetadata, 1); - } - - const query = await supertest(api.server).get(`/extended/v1/tokens/nft/metadata`); - expect(query.status).toBe(200); - expect(query.body.total).toBeGreaterThan(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.limit).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - expect(query.body.offset).toStrictEqual(0); - expect(query.body.results.length).toStrictEqual(getPagingQueryLimit(ResourceType.Token)); - - const query1 = await supertest(api.server).get( - `/extended/v1/tokens/nft/metadata?limit=20&offset=10` - ); - expect(query1.status).toBe(200); - expect(query1.body.total).toBeGreaterThanOrEqual(200); - expect(query1.body.limit).toStrictEqual(20); - expect(query1.body.offset).toStrictEqual(10); - expect(query1.body.results.length).toStrictEqual(20); - }); - - test('large metadata payload test', async () => { - //mock the response - const maxResponseBytes = 10_000; - const randomData = Buffer.alloc(maxResponseBytes + 100, 'x', 'utf8'); - nock('https://example.com').persist().get('/large_payload').reply(200, randomData.toString()); - - await expect(async () => { - await performFetch('https://example.com/large_payload', { - maxResponseBytes: maxResponseBytes, - }); - }).rejects.toThrow(/over limit/); - }); - - test('timeout metadata payload test', async () => { - //mock the response - const responseTimeout = 100; - nock('https://example.com') - .persist() - .get('/timeout_payload') - .reply(200, async (_uri, _requestBody, cb) => { - await timeout(responseTimeout + 200); - cb(null, '{"hello":"world"}'); - }); - - await expect(async () => { - await performFetch('https://example.com/timeout_payload', { - timeoutMs: responseTimeout, - }); - }).rejects.toThrow(/network timeout/); - }); - - afterAll(async () => { - await eventServer.closeAsync(); - tokensProcessorQueue.close(); - await api.forceKill(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); -}); diff --git a/src/tests-tokens-strict/setup.ts b/src/tests-tokens-strict/setup.ts deleted file mode 100644 index 7cb3c98c09..0000000000 --- a/src/tests-tokens-strict/setup.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defaultSetupInit } from '../test-utils/shared-setup'; - -// ts-unused-exports:disable-next-line -export default async () => { - console.log('Jest - setup..'); - await defaultSetupInit(); - console.log('Jest - setup done'); -}; diff --git a/src/tests-tokens-strict/strict-mode-tests.ts b/src/tests-tokens-strict/strict-mode-tests.ts deleted file mode 100644 index d6f8467328..0000000000 --- a/src/tests-tokens-strict/strict-mode-tests.ts +++ /dev/null @@ -1,389 +0,0 @@ -import * as nock from 'nock'; -import { ChainID, ClarityAbi, cvToHex, noneCV, uintCV } from '@stacks/transactions'; -import { PoolClient } from 'pg'; -import { TestBlockBuilder } from '../test-utils/test-builders'; -import { ApiServer, startApiServer } from '../api/init'; -import { - METADATA_MAX_PAYLOAD_BYTE_SIZE, - TokensContractHandler, -} from '../token-metadata/tokens-contract-handler'; -import { DbTxTypeId } from '../datastore/common'; -import { stringCV } from '@stacks/transactions/dist/clarity/types/stringCV'; -import { getTokenMetadataFetchTimeoutMs } from '../token-metadata/helpers'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { cycleMigrations, runMigrations } from '../datastore/migrations'; -import { TokensProcessorQueue } from '../token-metadata/tokens-processor-queue'; - -const NFT_CONTRACT_ABI: ClarityAbi = { - maps: [], - functions: [ - { - access: 'read_only', - args: [], - name: 'get-last-token-id', - outputs: { - type: { - response: { - ok: 'uint128', - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ name: 'any', type: 'uint128' }], - name: 'get-token-uri', - outputs: { - type: { - response: { - ok: { - optional: { 'string-ascii': { length: 256 } }, - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ type: 'uint128', name: 'any' }], - name: 'get-owner', - outputs: { - type: { - response: { - ok: { - optional: 'principal', - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'public', - args: [ - { type: 'uint128', name: 'id' }, - { type: 'principal', name: 'sender' }, - { type: 'principal', name: 'recipient' }, - ], - name: 'transfer', - outputs: { - type: { - response: { - ok: 'bool', - error: { - tuple: [ - { type: { 'string-ascii': { length: 32 } }, name: 'kind' }, - { type: 'uint128', name: 'code' }, - ], - }, - }, - }, - }, - }, - ], - variables: [ - { - name: 'nft-not-found-err', - type: { response: { ok: 'none', error: 'uint128' } }, - access: 'constant', - }, - { - name: 'nft-not-owned-err', - type: { response: { ok: 'none', error: 'uint128' } }, - access: 'constant', - }, - { - name: 'sender-equals-recipient-err', - type: { response: { ok: 'none', error: 'uint128' } }, - access: 'constant', - }, - ], - fungible_tokens: [], - non_fungible_tokens: [{ name: 'beeple', type: 'uint128' }], -}; - -describe('token metadata strict mode', () => { - let db: PgWriteStore; - let api: ApiServer; - - const contractId = 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1'; - const contractTxId = '0x1f1f'; - - beforeEach(async () => { - process.env.PG_DATABASE = 'postgres'; - await cycleMigrations(); - db = await PgWriteStore.connect({ usageName: 'tests', withNotifier: false }); - api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); - - process.env['STACKS_API_ENABLE_FT_METADATA'] = '1'; - process.env['STACKS_API_ENABLE_NFT_METADATA'] = '1'; - process.env['STACKS_CORE_RPC_PORT'] = '20443'; - nock.cleanAll(); - - const block = new TestBlockBuilder({ block_height: 1, index_block_hash: '0x01' }) - .addTx() - .addTx({ - tx_id: contractTxId, - type_id: DbTxTypeId.SmartContract, - smart_contract_contract_id: contractId, - smart_contract_source_code: '(source)', - }) - .addTxSmartContract({ - contract_id: contractId, - contract_source: '(source)', - abi: JSON.stringify(NFT_CONTRACT_ABI), - }) - .build(); - await db.update(block); - }); - - test('retryable error increases retry_count', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toBe(1); - expect(entry.result?.processed).toBe(false); - }); - - test('retry_count limit reached marks entry as processed', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] = '0'; - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(true); - }); - - test('strict mode ignores retry_count limit', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'] = '1'; - process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] = '0'; - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(false); - }); - - test('db errors are handled gracefully in contract handler', async () => { - process.env['STACKS_CORE_RPC_PORT'] = '11111'; // Make node unreachable - process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'] = '1'; - process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] = '0'; - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await db.close(); // End connection to trigger postgres error - await expect(handler.start()).resolves.not.toThrow(); - }); - - test('db errors are handled gracefully in queue', async () => { - const queue = new TokensProcessorQueue(db, ChainID.Testnet); - await db.close(); // End connection to trigger postgres error - await expect(queue.checkDbQueue()).resolves.not.toThrow(); - await expect(queue.drainDbQueue()).resolves.not.toThrow(); - await expect(queue.queueNotificationHandler(1)).resolves.not.toThrow(); - await expect( - queue.queueHandler({ queueId: 1, txId: '0x11', contractId: 'test' }) - ).resolves.not.toThrow(); - }); - - test('node runtime errors get retried', async () => { - const mockResponse = { - okay: false, - cause: 'Runtime(Foo(Bar))', - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(false); - }); - - test('other node errors fail immediately', async () => { - const mockResponse = { - okay: false, - cause: 'Unchecked(Foo(Bar))', - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - }); - - test('clarity value parse errors get retried', async () => { - const mockResponse = { - okay: true, - result: cvToHex(uintCV(5)), // `get-token-uri` will fail because this is a `uint` - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(1); - expect(entry.result?.processed).toBe(false); - }); - - test('incorrect none uri strings are parsed as undefined', async () => { - const mockResponse = { - okay: true, - result: cvToHex(noneCV()), - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockResponse); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - const metadata = await db.getNftMetadata( - 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1' - ); - expect(metadata.result?.token_uri).toEqual(''); - }); - - test('metadata timeout errors get retried immediately', async () => { - process.env['STACKS_API_TOKEN_METADATA_FETCH_TIMEOUT_MS'] = '500'; - const mockTokenUri = { - okay: true, - result: cvToHex(stringCV('http://indigo.com/nft.jpeg', 'ascii')), - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockTokenUri); - // Timeout first time. - nock('http://indigo.com') - .get('/nft.jpeg') - .times(1) - .delay(getTokenMetadataFetchTimeoutMs() + 100) - .reply(200); - // Correct second time. - nock('http://indigo.com').get('/nft.jpeg').reply(200, {}); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - }); - - test('metadata size exceeded errors fail immediately', async () => { - const mockTokenUri = { - okay: true, - result: cvToHex(stringCV('http://indigo.com/nft.jpeg', 'ascii')), - }; - nock('http://127.0.0.1:20443') - .post( - '/v2/contracts/call-read/SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD/project-indigo-act1/get-token-uri' - ) - .reply(200, mockTokenUri); - const bigAssBuffer = Buffer.alloc(METADATA_MAX_PAYLOAD_BYTE_SIZE + 100); - nock('http://indigo.com').get('/nft.jpeg').reply(200, bigAssBuffer); - const handler = new TokensContractHandler({ - contractId: contractId, - smartContractAbi: NFT_CONTRACT_ABI, - datastore: db, - chainId: ChainID.Testnet, - txId: contractTxId, - dbQueueId: 1, - }); - await handler.start(); - const entry = await db.getTokenMetadataQueueEntry(1); - expect(entry.result?.retry_count).toEqual(0); - expect(entry.result?.processed).toBe(true); - - // Metadata still contains the rest of the data. - const metadata = await db.getNftMetadata(contractId); - expect(metadata.found).toBe(true); - expect(metadata.result?.token_uri).toBe('http://indigo.com/nft.jpeg'); - }); - - afterEach(async () => { - await api.terminate(); - await db?.close(); - await runMigrations(undefined, 'down'); - }); -}); diff --git a/src/tests-tokens-strict/teardown.ts b/src/tests-tokens-strict/teardown.ts deleted file mode 100644 index 53858b8433..0000000000 --- a/src/tests-tokens-strict/teardown.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defaultSetupTeardown } from '../test-utils/shared-setup'; - -// ts-unused-exports:disable-next-line -export default async () => { - console.log('Jest - teardown..'); - await defaultSetupTeardown(); - console.log('Jest - teardown done'); -}; diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index aebdd03979..116570da49 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -18,8 +18,6 @@ import { DbBnsName, DbBnsSubdomain, DbTokenOfferingLocked, - DbNonFungibleTokenMetadata, - DbFungibleTokenMetadata, DbTx, DataStoreTxEventData, } from '../datastore/common'; @@ -5195,48 +5193,6 @@ describe('postgres datastore', () => { expect(results.found).toBe(false); }); - test('pg token nft-metadata', async () => { - const nftMetadata: DbNonFungibleTokenMetadata = { - token_uri: 'nft-tokenuri', - name: 'nft-metadata', - description: 'nft -metadata description', - image_uri: 'nft-metadata image uri example', - image_canonical_uri: 'nft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.nft-metadata', - tx_id: '0x1234', - sender_address: 'sender-addr-test', - }; - - const rowCount = await db.updateNFtMetadata(nftMetadata, 1); - expect(rowCount).toBe(1); - - const query = await db.getNftMetadata(nftMetadata.contract_id); - expect(query.found).toBe(true); - if (query.found) expect(query.result).toStrictEqual(nftMetadata); - }); - - test('pg token ft-metadata', async () => { - const ftMetadata: DbFungibleTokenMetadata = { - token_uri: 'ft-token', - name: 'ft-metadata', - description: 'ft -metadata description', - symbol: 'stx', - decimals: 5, - image_uri: 'ft-metadata image uri example', - image_canonical_uri: 'ft-metadata image canonical uri example', - contract_id: 'ABCDEFGHIJ.ft-metadata', - tx_id: '0x1234', - sender_address: 'sender-addr-test', - }; - - const rowCount = await db.updateFtMetadata(ftMetadata, 1); - expect(rowCount).toBe(1); - - const query = await db.getFtMetadata(ftMetadata.contract_id); - expect(query.found).toBe(true); - if (query.found) expect(query.result).toStrictEqual(ftMetadata); - }); - test('empty parameter lists are handled correctly', async () => { const block = new TestBlockBuilder({ block_height: 1 }).addTx().build(); await db.update(block); diff --git a/src/token-metadata/helpers.ts b/src/token-metadata/helpers.ts deleted file mode 100644 index c7e13751f4..0000000000 --- a/src/token-metadata/helpers.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { ClarityAbi, ClarityAbiFunction } from '@stacks/transactions'; -import { - METADATA_MAX_PAYLOAD_BYTE_SIZE, - TokenMetadataErrorMode, - TokenMetadataProcessingMode, -} from './tokens-contract-handler'; -import fetch from 'node-fetch'; -import { parseArgBoolean } from '../helpers'; - -export function isFtMetadataEnabled() { - const opt = process.env['STACKS_API_ENABLE_FT_METADATA']?.toLowerCase().trim(); - return opt === '1' || opt === 'true'; -} - -export function isNftMetadataEnabled() { - const opt = process.env['STACKS_API_ENABLE_NFT_METADATA']?.toLowerCase().trim(); - return opt === '1' || opt === 'true'; -} - -/** - * Determines the token metadata processing mode based on .env values. - * @returns TokenMetadataProcessingMode - */ -export function getTokenMetadataProcessingMode(): TokenMetadataProcessingMode { - if (parseArgBoolean(process.env['STACKS_API_TOKEN_METADATA_STRICT_MODE'])) { - return TokenMetadataProcessingMode.strict; - } - return TokenMetadataProcessingMode.default; -} - -export function getTokenMetadataMaxRetries() { - const opt = process.env['STACKS_API_TOKEN_METADATA_MAX_RETRIES'] ?? '5'; - return parseInt(opt); -} - -export function getTokenMetadataFetchTimeoutMs() { - const opt = process.env['STACKS_API_TOKEN_METADATA_FETCH_TIMEOUT_MS'] ?? '10000'; - return parseInt(opt); -} - -/** - * Determines the token metadata error handling mode based on .env values. - * @returns TokenMetadataMode - */ -export function tokenMetadataErrorMode(): TokenMetadataErrorMode { - switch (process.env['STACKS_API_TOKEN_METADATA_ERROR_MODE']) { - case 'error': - return TokenMetadataErrorMode.error; - default: - return TokenMetadataErrorMode.warning; - } -} - -const FT_FUNCTIONS: ClarityAbiFunction[] = [ - { - access: 'public', - args: [ - { type: 'uint128', name: 'amount' }, - { type: 'principal', name: 'sender' }, - { type: 'principal', name: 'recipient' }, - { type: { optional: { buffer: { length: 34 } } }, name: 'memo' }, - ], - name: 'transfer', - outputs: { type: { response: { ok: 'bool', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-name', - outputs: { type: { response: { ok: { 'string-ascii': { length: 32 } }, error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-symbol', - outputs: { type: { response: { ok: { 'string-ascii': { length: 32 } }, error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-decimals', - outputs: { type: { response: { ok: 'uint128', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [{ type: 'principal', name: 'address' }], - name: 'get-balance', - outputs: { type: { response: { ok: 'uint128', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-total-supply', - outputs: { type: { response: { ok: 'uint128', error: 'uint128' } } }, - }, - { - access: 'read_only', - args: [], - name: 'get-token-uri', - outputs: { - type: { - response: { - ok: { - optional: { 'string-ascii': { length: 256 } }, - }, - error: 'uint128', - }, - }, - }, - }, -]; - -const NFT_FUNCTIONS: ClarityAbiFunction[] = [ - { - access: 'read_only', - args: [], - name: 'get-last-token-id', - outputs: { - type: { - response: { - ok: 'uint128', - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ name: 'any', type: 'uint128' }], - name: 'get-token-uri', - outputs: { - type: { - response: { - ok: { - optional: { 'string-ascii': { length: 256 } }, - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'read_only', - args: [{ type: 'uint128', name: 'any' }], - name: 'get-owner', - outputs: { - type: { - response: { - ok: { - optional: 'principal', - }, - error: 'uint128', - }, - }, - }, - }, - { - access: 'public', - args: [ - { type: 'uint128', name: 'id' }, - { type: 'principal', name: 'sender' }, - { type: 'principal', name: 'recipient' }, - ], - name: 'transfer', - outputs: { - type: { - response: { - ok: 'bool', - error: { - tuple: [ - { type: { 'string-ascii': { length: 32 } }, name: 'kind' }, - { type: 'uint128', name: 'code' }, - ], - }, - }, - }, - }, - }, -]; - -/** - * Checks if the given ABI contains functions from FT or NFT metadata standards (e.g. sip-09, sip-10) which can be resolved. - * The function also checks if the server has FT and/or NFT metadata processing enabled. - */ -export function isProcessableTokenMetadata(abi: ClarityAbi): boolean { - return ( - (isFtMetadataEnabled() && isCompliantFt(abi)) || (isNftMetadataEnabled() && isCompliantNft(abi)) - ); -} - -export function isCompliantNft(abi: ClarityAbi): boolean { - if (abi.non_fungible_tokens.length > 0) { - if (abiContains(abi, NFT_FUNCTIONS)) { - return true; - } - } - return false; -} - -export function isCompliantFt(abi: ClarityAbi): boolean { - if (abi.fungible_tokens.length > 0) { - if (abiContains(abi, FT_FUNCTIONS)) { - return true; - } - } - return false; -} - -/** - * This method check if the contract is compliance with sip-09 and sip-10 - * Ref: https://github.com/stacksgov/sips/tree/main/sips - */ -function abiContains(abi: ClarityAbi, standardFunction: ClarityAbiFunction[]): boolean { - return standardFunction.every(abiFun => findFunction(abiFun, abi.functions)); -} - -/** - * check if the fun exist in the function list - * @param fun - function to be found - * @param functionList - list of functions - * @returns - true if function is in the list false otherwise - */ -function findFunction(fun: ClarityAbiFunction, functionList: ClarityAbiFunction[]): boolean { - const found = functionList.find(standardFunction => { - if (standardFunction.name !== fun.name || standardFunction.args.length !== fun.args.length) - return false; - for (let i = 0; i < fun.args.length; i++) { - if (standardFunction.args[i].type.toString() !== fun.args[i].type.toString()) { - return false; - } - } - return true; - }); - return found !== undefined; -} - -export async function performFetch( - url: string, - opts?: { - timeoutMs?: number; - maxResponseBytes?: number; - } -): Promise { - const result = await fetch(url, { - size: opts?.maxResponseBytes ?? METADATA_MAX_PAYLOAD_BYTE_SIZE, - timeout: opts?.timeoutMs ?? getTokenMetadataFetchTimeoutMs(), - }); - if (!result.ok) { - let msg = ''; - try { - msg = await result.text(); - } catch (error) { - // ignore errors from fetching error text - } - throw new Error(`Response ${result.status}: ${result.statusText} fetching ${url} - ${msg}`); - } - const resultString = await result.text(); - try { - return JSON.parse(resultString) as Type; - } catch (error) { - throw new Error(`Error parsing response from ${url} as JSON: ${error}`); - } -} diff --git a/src/token-metadata/tokens-contract-handler.ts b/src/token-metadata/tokens-contract-handler.ts deleted file mode 100644 index 341a0e1a10..0000000000 --- a/src/token-metadata/tokens-contract-handler.ts +++ /dev/null @@ -1,534 +0,0 @@ -import * as child_process from 'child_process'; -import { DbFungibleTokenMetadata, DbNonFungibleTokenMetadata } from '../datastore/common'; -import { - ClarityAbi, - ClarityType, - ClarityValue, - getAddressFromPrivateKey, - hexToCV, - makeRandomPrivKey, - TransactionVersion, - uintCV, - UIntCV, -} from '@stacks/transactions'; -import { ChainID, getChainIDNetwork, parseDataUrl, REPO_DIR, stopwatch } from '../helpers'; -import * as querystring from 'querystring'; -import { - getTokenMetadataFetchTimeoutMs, - getTokenMetadataMaxRetries, - getTokenMetadataProcessingMode, - isCompliantFt, - isCompliantNft, - performFetch, -} from './helpers'; -import { ReadOnlyContractCallResponse, StacksCoreRpcClient } from '../core-rpc/client'; -import { FetchError } from 'node-fetch'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { logger } from '../logger'; - -/** - * The maximum number of bytes of metadata to fetch. - * If the fetch encounters more bytes than this limit it throws and the metadata is not processed. - */ -export const METADATA_MAX_PAYLOAD_BYTE_SIZE = 1_000_000; // 1 megabyte - -/** - * The max number of immediate attempts that will be made to retrieve metadata from external URIs before declaring - * the failure as a non-retryable error. - */ -const METADATA_MAX_IMMEDIATE_RETRY_COUNT = 5; - -const PUBLIC_IPFS = 'https://ipfs.io'; - -export enum TokenMetadataProcessingMode { - /** If a recoverable processing error occurs, we'll try again until the max retry attempt is reached. See `.env` */ - default, - /** If a recoverable processing error occurs, we'll try again indefinitely. */ - strict, -} - -export enum TokenMetadataErrorMode { - /** Default mode. If a required token metadata is not found when it is needed for a response, the API will issue a warning. */ - warning, - /** If a required token metadata is not found, the API will throw an error. */ - error, -} - -/** - * A token metadata fetch/process error caused by something that we can try to do again later. - */ -class RetryableTokenMetadataError extends Error { - constructor(message: string) { - super(message); - this.message = message; - this.name = this.constructor.name; - } -} - -interface NftTokenMetadata { - name: string; - imageUri: string; - description: string; -} - -interface FtTokenMetadata { - name: string; - imageUri: string; - description: string; -} - -interface TokenHandlerArgs { - contractId: string; - smartContractAbi: ClarityAbi; - datastore: PgWriteStore; - chainId: ChainID; - txId: string; - dbQueueId: number; -} - -/** - * This class downloads, parses and indexes metadata info for a Fungible or Non-Fungible token in the Stacks blockchain - * by calling read-only functions in SIP-009 and SIP-010 compliant smart contracts. - */ -export class TokensContractHandler { - readonly contractAddress: string; - readonly contractName: string; - readonly contractId: string; - readonly txId: string; - readonly dbQueueId: number; - private readonly db: PgWriteStore; - private readonly randomPrivKey = makeRandomPrivKey(); - private readonly chainId: ChainID; - private readonly address: string; - private readonly tokenKind: 'ft' | 'nft'; - private readonly nodeRpcClient: StacksCoreRpcClient; - - constructor(args: TokenHandlerArgs) { - [this.contractAddress, this.contractName] = args.contractId.split('.'); - this.contractId = args.contractId; - this.db = args.datastore; - this.chainId = args.chainId; - this.txId = args.txId; - this.dbQueueId = args.dbQueueId; - this.nodeRpcClient = new StacksCoreRpcClient(); - - this.address = getAddressFromPrivateKey( - this.randomPrivKey.data, - getChainIDNetwork(this.chainId) === 'mainnet' - ? TransactionVersion.Mainnet - : TransactionVersion.Testnet - ); - if (isCompliantFt(args.smartContractAbi)) { - this.tokenKind = 'ft'; - } else if (isCompliantNft(args.smartContractAbi)) { - this.tokenKind = 'nft'; - } else { - throw new Error( - `TokenContractHandler passed an ABI that isn't compliant to FT or NFT standards` - ); - } - } - - async start() { - logger.info( - `[token-metadata] found ${ - this.tokenKind === 'ft' ? 'sip-010-ft-standard' : 'sip-009-nft-standard' - } compliant contract ${this.contractId} in tx ${this.txId}, begin retrieving metadata...` - ); - const sw = stopwatch(); - // This try/catch block will catch any and all errors that are generated while processing metadata - // (contract call errors, parse errors, timeouts, etc.). Fortunately, each of them were previously tagged - // as retryable or not retryable so we'll make a decision here about what to do in each case. - // If we choose to retry, this queue entry will simply not be marked as `processed = true` so it can be - // picked up by the `TokensProcessorQueue` at a later time. - let processingFinished = false; - try { - if (this.tokenKind === 'ft') { - await this.handleFtContract(); - } else if (this.tokenKind === 'nft') { - await this.handleNftContract(); - } - processingFinished = true; - } catch (error) { - if (error instanceof RetryableTokenMetadataError) { - try { - const retries = await this.db.increaseTokenMetadataQueueEntryRetryCount(this.dbQueueId); - if ( - getTokenMetadataProcessingMode() === TokenMetadataProcessingMode.strict || - retries <= getTokenMetadataMaxRetries() - ) { - logger.info( - `[token-metadata] a recoverable error happened while processing ${this.contractId}, trying again later: ${error}` - ); - } else { - logger.warn( - `[token-metadata] max retries reached while processing ${this.contractId}, giving up: ${error}` - ); - processingFinished = true; - } - } catch (error) { - logger.error(error); - processingFinished = true; - } - } else { - // Something more serious happened, mark this contract as done. - logger.error(error); - processingFinished = true; - } - } finally { - if (processingFinished) { - try { - await this.db.updateProcessedTokenMetadataQueueEntry(this.dbQueueId); - logger.info( - `[token-metadata] finished processing ${this.contractId} in ${sw.getElapsed()} ms` - ); - } catch (error) { - logger.error(error); - } - } - } - } - - /** - * fetch Fungible contract metadata - */ - private async handleFtContract() { - const contractCallName = await this.readStringFromContract('get-name'); - const contractCallUri = await this.readStringFromContract('get-token-uri'); - const contractCallSymbol = await this.readStringFromContract('get-symbol'); - - let contractCallDecimals: number | undefined; - const decimalsResult = await this.readUIntFromContract('get-decimals'); - if (decimalsResult) { - contractCallDecimals = Number(decimalsResult.toString()); - } - - let metadata: FtTokenMetadata | undefined; - if (contractCallUri) { - try { - metadata = await this.getMetadataFromUri(contractCallUri); - metadata = this.patchTokenMetadataImageUri(metadata); - } catch (error) { - // An unavailable external service failed to provide reasonable data (images, etc.). - // We will ignore these and fill out the remaining SIP-compliant metadata. - logger.warn( - `[token-metadata] ft metadata fetch error while processing ${this.contractId}: ${error}` - ); - } - } - let imgUrl: string | undefined; - if (metadata?.imageUri) { - const normalizedUrl = this.getImageUrl(metadata.imageUri); - imgUrl = await this.processImageUrl(normalizedUrl); - } - - const fungibleTokenMetadata: DbFungibleTokenMetadata = { - token_uri: contractCallUri ?? '', - name: contractCallName ?? metadata?.name ?? '', // prefer the on-chain name - description: metadata?.description ?? '', - image_uri: imgUrl ?? '', - image_canonical_uri: metadata?.imageUri ?? '', - symbol: contractCallSymbol ?? '', - decimals: contractCallDecimals ?? 0, - contract_id: this.contractId, - tx_id: this.txId, - sender_address: this.contractAddress, - }; - await this.db.updateFtMetadata(fungibleTokenMetadata, this.dbQueueId); - } - - /** - * fetch Non Fungible contract metadata - */ - private async handleNftContract() { - // TODO: This is incorrectly attempting to fetch the metadata for a specific - // NFT and applying it to the entire NFT type/contract. A new SIP needs created - // to define how generic metadata for an NFT type/contract should be retrieved. - // In the meantime, this will often fail or result in weird data, but at least - // the NFT type enumeration endpoints will have data like the contract ID and txid. - - // TODO: this should instead use the SIP-012 draft https://github.com/stacksgov/sips/pull/18 - // function `(get-nft-meta () (response (optional {name: (string-uft8 30), image: (string-ascii 255)}) uint))` - - let metadata: NftTokenMetadata | undefined; - const contractCallUri = await this.readStringFromContract('get-token-uri', [uintCV(0)]); - if (contractCallUri) { - try { - metadata = await this.getMetadataFromUri(contractCallUri); - metadata = this.patchTokenMetadataImageUri(metadata); - } catch (error) { - // An unavailable external service failed to provide reasonable data (images, etc.). - // We will ignore these and fill out the remaining SIP-compliant metadata. - logger.warn( - `[token-metadata] nft metadata fetch error while processing ${this.contractId}: ${error}` - ); - } - } - let imgUrl: string | undefined; - if (metadata?.imageUri) { - const normalizedUrl = this.getImageUrl(metadata.imageUri); - imgUrl = await this.processImageUrl(normalizedUrl); - } - - const nonFungibleTokenMetadata: DbNonFungibleTokenMetadata = { - token_uri: contractCallUri ?? '', - name: metadata?.name ?? '', - description: metadata?.description ?? '', - image_uri: imgUrl ?? '', - image_canonical_uri: metadata?.imageUri ?? '', - contract_id: `${this.contractId}`, - tx_id: this.txId, - sender_address: this.contractAddress, - }; - await this.db.updateNFtMetadata(nonFungibleTokenMetadata, this.dbQueueId); - } - - /** - * Token metadata schema for 'image uri' is not well defined or adhered to. - * This function looks for a handful of possible properties that could be used to - * specify the image, and returns a metadata object with a normalized image property. - */ - private patchTokenMetadataImageUri(metadata: T): T { - // compare using lowercase - const allowedImageProperties = ['image', 'imageurl', 'imageuri', 'image_url', 'image_uri']; - const objectKeys = new Map(Object.keys(metadata).map(prop => [prop.toLowerCase(), prop])); - for (const possibleProp of allowedImageProperties) { - const existingProp = objectKeys.get(possibleProp); - if (existingProp) { - const imageUriVal = (metadata as Record)[existingProp]; - if (typeof imageUriVal !== 'string') { - continue; - } - return { - ...metadata, - imageUri: imageUriVal, - }; - } - } - return { ...metadata }; - } - - /** - * If an external image processor script is configured, then it will process the given image URL for the purpose - * of caching on a CDN (or whatever else it may be created to do). The script is expected to return a new URL - * for the image. - * If the script is not configured, then the original URL is returned immediately. - * If a data-uri is passed, it is also immediately returned without being passed to the script. - */ - private async processImageUrl(imgUrl: string): Promise { - const imageCacheProcessor = process.env['STACKS_API_IMAGE_CACHE_PROCESSOR']; - if (!imageCacheProcessor) { - return imgUrl; - } - if (imgUrl.startsWith('data:')) { - return imgUrl; - } - const { code, stdout, stderr } = await new Promise<{ - code: number; - stdout: string; - stderr: string; - }>((resolve, reject) => { - const cp = child_process.spawn(imageCacheProcessor, [imgUrl], { cwd: REPO_DIR }); - let stdout = ''; - let stderr = ''; - cp.stdout.on('data', data => (stdout += data)); - cp.stderr.on('data', data => (stderr += data)); - cp.on('close', code => resolve({ code: code ?? 0, stdout, stderr })); - cp.on('error', error => reject(error)); - }); - if (code !== 0 && stderr) { - console.warn(`[token-metadata] stderr from STACKS_API_IMAGE_CACHE_PROCESSOR: ${stderr}`); - } - const result = stdout.trim(); - try { - const url = new URL(result); - return url.toString(); - } catch (error) { - throw new Error( - `Image processing script returned an invalid url for ${imgUrl}: ${result}, stderr: ${stderr}` - ); - } - } - - /** - * Helper method for creating http/s url for supported protocols. - * URLs with `http` or `https` protocols are returned as-is. - * URLs with `ipfs` or `ipns` protocols are returned with as an `https` url - * using a public IPFS gateway. - */ - private getFetchableUrl(uri: string): URL { - const parsedUri = new URL(uri); - if (parsedUri.protocol === 'http:' || parsedUri.protocol === 'https:') return parsedUri; - if (parsedUri.protocol === 'ipfs:') - return new URL(`${PUBLIC_IPFS}/${parsedUri.host}${parsedUri.pathname}`); - - if (parsedUri.protocol === 'ipns:') - return new URL(`${PUBLIC_IPFS}/${parsedUri.host}${parsedUri.pathname}`); - - throw new Error(`Unsupported uri protocol: ${uri}`); - } - - private getImageUrl(uri: string): string { - // Support images embedded in a Data URL - if (new URL(uri).protocol === 'data:') { - // const dataUrl = ParseDataUrl(uri); - const dataUrl = parseDataUrl(uri); - if (!dataUrl) { - throw new Error(`Data URL could not be parsed: ${uri}`); - } - if (!dataUrl.mediaType?.startsWith('image/')) { - throw new Error(`Token image is a Data URL with a non-image media type: ${uri}`); - } - return uri; - } - const fetchableUrl = this.getFetchableUrl(uri); - return fetchableUrl.toString(); - } - - /** - * Fetch metadata from uri - */ - private async getMetadataFromUri(token_uri: string): Promise { - // Support JSON embedded in a Data URL - if (new URL(token_uri).protocol === 'data:') { - const dataUrl = parseDataUrl(token_uri); - if (!dataUrl) { - throw new Error(`Data URL could not be parsed: ${token_uri}`); - } - let content: string; - // If media type is omitted it should default to percent-encoded `text/plain;charset=US-ASCII` - // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs#syntax - // If media type is specified but without base64 then encoding is ambiguous, so check for - // percent-encoding or assume a literal string compatible with utf8. Because we're expecting - // a JSON object we can reliable check for a leading `%` char, otherwise assume unescaped JSON. - if (dataUrl.base64) { - content = Buffer.from(dataUrl.data, 'base64').toString('utf8'); - } else if (dataUrl.data.startsWith('%')) { - content = querystring.unescape(dataUrl.data); - } else { - content = dataUrl.data; - } - try { - return JSON.parse(content) as Type; - } catch (error) { - throw new Error(`Data URL could not be parsed as JSON: ${token_uri}`); - } - } - const httpUrl = this.getFetchableUrl(token_uri); - - let fetchImmediateRetryCount = 0; - let result: Type | undefined; - // We'll try to fetch metadata and give it `METADATA_MAX_IMMEDIATE_RETRY_COUNT` attempts - // for the external service to return a reasonable response, otherwise we'll consider the - // metadata as dead. - do { - try { - result = await performFetch(httpUrl.toString(), { - timeoutMs: getTokenMetadataFetchTimeoutMs(), - maxResponseBytes: METADATA_MAX_PAYLOAD_BYTE_SIZE, - }); - break; - } catch (error) { - fetchImmediateRetryCount++; - if ( - (error instanceof FetchError && error.type === 'max-size') || - fetchImmediateRetryCount >= METADATA_MAX_IMMEDIATE_RETRY_COUNT - ) { - throw error; - } - } - } while (fetchImmediateRetryCount < METADATA_MAX_IMMEDIATE_RETRY_COUNT); - if (result) { - return result; - } - throw new Error(`Unable to fetch metadata from ${token_uri}`); - } - - private async makeReadOnlyContractCall( - functionName: string, - functionArgs: ClarityValue[] - ): Promise { - let result: ReadOnlyContractCallResponse; - try { - result = await this.nodeRpcClient.sendReadOnlyContractCall( - this.contractAddress, - this.contractName, - functionName, - this.address, - functionArgs - ); - } catch (error) { - throw new RetryableTokenMetadataError(`Error making read-only contract call: ${error}`); - } - if (!result.okay) { - // Only runtime errors reported by the Stacks node should be retryable. - if ( - result.cause.startsWith('Runtime') || - result.cause.startsWith('Unchecked(NoSuchContract') - ) { - throw new RetryableTokenMetadataError( - `Runtime error while calling read-only function ${functionName}` - ); - } - throw new Error(`Error calling read-only function ${functionName}`); - } - return hexToCV(result.result); - } - - private async readStringFromContract( - functionName: string, - functionArgs: ClarityValue[] = [] - ): Promise { - const clarityValue = await this.makeReadOnlyContractCall(functionName, functionArgs); - return this.checkAndParseString(clarityValue); - } - - private async readUIntFromContract( - functionName: string, - functionArgs: ClarityValue[] = [] - ): Promise { - const clarityValue = await this.makeReadOnlyContractCall(functionName, functionArgs); - const uintVal = this.checkAndParseUintCV(clarityValue); - try { - return BigInt(uintVal.value.toString()); - } catch (error) { - throw new RetryableTokenMetadataError(`Invalid uint value '${uintVal}'`); - } - } - - private unwrapClarityType(clarityValue: ClarityValue): ClarityValue { - let unwrappedClarityValue: ClarityValue = clarityValue; - while ( - unwrappedClarityValue.type === ClarityType.ResponseOk || - unwrappedClarityValue.type === ClarityType.OptionalSome - ) { - unwrappedClarityValue = unwrappedClarityValue.value; - } - return unwrappedClarityValue; - } - - private checkAndParseUintCV(responseCV: ClarityValue): UIntCV { - const unwrappedClarityValue = this.unwrapClarityType(responseCV); - if (unwrappedClarityValue.type === ClarityType.UInt) { - return unwrappedClarityValue; - } - throw new RetryableTokenMetadataError( - `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping uint` - ); - } - - private checkAndParseString(responseCV: ClarityValue): string | undefined { - const unwrappedClarityValue = this.unwrapClarityType(responseCV); - if ( - unwrappedClarityValue.type === ClarityType.StringASCII || - unwrappedClarityValue.type === ClarityType.StringUTF8 - ) { - return unwrappedClarityValue.data; - } else if (unwrappedClarityValue.type === ClarityType.OptionalNone) { - return undefined; - } - throw new RetryableTokenMetadataError( - `Unexpected Clarity type '${unwrappedClarityValue.type}' while unwrapping string` - ); - } -} diff --git a/src/token-metadata/tokens-processor-queue.ts b/src/token-metadata/tokens-processor-queue.ts deleted file mode 100644 index 2596e41ab8..0000000000 --- a/src/token-metadata/tokens-processor-queue.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { ChainID, FoundOrNot } from '../helpers'; -import { Evt } from 'evt'; -import PQueue from 'p-queue'; -import { DbTokenMetadataQueueEntry, TokenMetadataUpdateInfo } from '../datastore/common'; -import { ClarityAbi } from '@stacks/transactions'; -import { TokensContractHandler } from './tokens-contract-handler'; -import { PgWriteStore } from '../datastore/pg-write-store'; -import { logger } from '../logger'; - -/** - * The maximum number of token metadata parsing operations that can be ran concurrently before - * being added to a FIFO queue. - */ -const TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT = 5; - -export class TokensProcessorQueue { - readonly queue: PQueue; - readonly db: PgWriteStore; - readonly chainId: ChainID; - - readonly processStartedEvent: Evt<{ - contractId: string; - txId: string; - }> = new Evt(); - - readonly processEndEvent: Evt<{ - contractId: string; - txId: string; - }> = new Evt(); - - /** The entries currently queued for processing in memory, keyed by the queue entry db id. */ - readonly queuedEntries: Map = new Map(); - - readonly onTokenMetadataUpdateQueued: (queueId: number) => void; - readonly onBlockUpdate: (blockHash: string) => void; - - constructor(db: PgWriteStore, chainId: ChainID) { - this.db = db; - this.chainId = chainId; - this.queue = new PQueue({ concurrency: TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT }); - this.onTokenMetadataUpdateQueued = entry => this.queueNotificationHandler(entry); - this.db.eventEmitter.on('tokenMetadataUpdateQueued', this.onTokenMetadataUpdateQueued); - this.onBlockUpdate = blockHash => this.blockNotificationHandler(blockHash); - this.db.eventEmitter.on('blockUpdate', this.onBlockUpdate); - } - - close() { - this.db.eventEmitter.off('tokenMetadataUpdateQueued', this.onTokenMetadataUpdateQueued); - this.db.eventEmitter.off('blockUpdate', this.onBlockUpdate); - this.queue.pause(); - this.queue.clear(); - } - - async drainDbQueue(): Promise { - let entries: DbTokenMetadataQueueEntry[] = []; - do { - if (this.queue.isPaused) { - return; - } - const queuedEntries = [...this.queuedEntries.keys()]; - try { - entries = await this.db.getTokenMetadataQueue( - TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT, - queuedEntries - ); - } catch (error) { - logger.error(error); - } - for (const entry of entries) { - await this.queueHandler(entry); - } - await this.queue.onEmpty(); - } while (entries.length > 0 || this.queuedEntries.size > 0); - } - - async checkDbQueue(): Promise { - if (this.queue.isPaused) { - return; - } - const queuedEntries = [...this.queuedEntries.keys()]; - const limit = TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT - this.queuedEntries.size; - if (limit > 0) { - let entries: DbTokenMetadataQueueEntry[]; - try { - entries = await this.db.getTokenMetadataQueue( - TOKEN_METADATA_PARSING_CONCURRENCY_LIMIT, - queuedEntries - ); - } catch (error) { - logger.error(error); - return; - } - for (const entry of entries) { - await this.queueHandler(entry); - } - } - } - - async queueNotificationHandler(queueId: number) { - let queueEntry: FoundOrNot; - try { - queueEntry = await this.db.getTokenMetadataQueueEntry(queueId); - } catch (error) { - logger.error(error); - return; - } - if (queueEntry.found) { - await this.queueHandler(queueEntry.result); - } - } - - async blockNotificationHandler(_: string) { - await this.checkDbQueue(); - } - - async queueHandler(queueEntry: TokenMetadataUpdateInfo) { - if ( - this.queuedEntries.has(queueEntry.queueId) || - this.queuedEntries.size >= this.queue.concurrency - ) { - return; - } - let abi: string; - try { - const contractQuery = await this.db.getSmartContract(queueEntry.contractId); - if (!contractQuery.found || !contractQuery.result.abi) { - return; - } - abi = contractQuery.result.abi; - } catch (error) { - logger.error(error); - return; - } - logger.info( - `[token-metadata] queueing token contract for processing: ${queueEntry.contractId} from tx ${queueEntry.txId}` - ); - this.queuedEntries.set(queueEntry.queueId, queueEntry); - - const contractAbi: ClarityAbi = JSON.parse(abi); - - const tokenContractHandler = new TokensContractHandler({ - contractId: queueEntry.contractId, - smartContractAbi: contractAbi, - datastore: this.db, - chainId: this.chainId, - txId: queueEntry.txId, - dbQueueId: queueEntry.queueId, - }); - - void this.queue - .add(async () => { - this.processStartedEvent.post({ - contractId: queueEntry.contractId, - txId: queueEntry.txId, - }); - await tokenContractHandler.start(); - }) - .catch(error => { - logger.error( - error, - `[token-metadata] error processing token contract: ${tokenContractHandler.contractAddress} ${tokenContractHandler.contractName} from tx ${tokenContractHandler.txId}` - ); - }) - .finally(() => { - this.queuedEntries.delete(queueEntry.queueId); - this.processEndEvent.post({ - contractId: queueEntry.contractId, - txId: queueEntry.txId, - }); - if (this.queuedEntries.size < this.queue.concurrency) { - void this.checkDbQueue(); - } - }); - } -} diff --git a/tests/jest.config.tokens-metadata.js b/tests/jest.config.tokens-metadata.js deleted file mode 100644 index b6fa987623..0000000000 --- a/tests/jest.config.tokens-metadata.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - preset: 'ts-jest', - rootDir: `${require('path').dirname(__dirname)}/src`, - testMatch: ['/tests-tokens-metadata/*.ts'], - testPathIgnorePatterns: ['/tests-tokens-metadata/setup.ts', '/tests-tokens-metadata/teardown.ts'], - collectCoverageFrom: ['/**/*.ts'], - coveragePathIgnorePatterns: ['/tests*'], - coverageDirectory: '/../coverage', - globalSetup: '/tests-tokens-metadata/setup.ts', - globalTeardown: '/tests-tokens-metadata/teardown.ts', - testTimeout: 60000, - verbose: true, - } diff --git a/tests/jest.config.tokens-strict.js b/tests/jest.config.tokens-strict.js deleted file mode 100644 index 419d8e0455..0000000000 --- a/tests/jest.config.tokens-strict.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - preset: 'ts-jest', - rootDir: `${require('path').dirname(__dirname)}/src`, - testMatch: ['/tests-tokens-strict/*.ts'], - testPathIgnorePatterns: ['/tests-tokens-strict/setup.ts', '/tests-tokens-strict/teardown.ts'], - collectCoverageFrom: ['/**/*.ts'], - coveragePathIgnorePatterns: ['/tests*'], - coverageDirectory: '/../coverage', - globalSetup: '/tests-tokens-strict/setup.ts', - globalTeardown: '/tests-tokens-strict/teardown.ts', - testTimeout: 60000, - verbose: true, - } diff --git a/tests/jest.config.tokens.js b/tests/jest.config.tokens.js deleted file mode 100644 index c84cd3d649..0000000000 --- a/tests/jest.config.tokens.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - preset: 'ts-jest', - rootDir: `${require('path').dirname(__dirname)}/src`, - testMatch: ['/tests-tokens/*.ts'], - testPathIgnorePatterns: ['/tests-tokens/setup.ts', '/tests-tokens/teardown.ts'], - collectCoverageFrom: ['/**/*.ts'], - coveragePathIgnorePatterns: ['/tests*'], - coverageDirectory: '/../coverage', - globalSetup: '/tests-tokens/setup.ts', - globalTeardown: '/tests-tokens/teardown.ts', - testTimeout: 60000, - verbose: true, - } From b35be4f2dc6e98923063700839427afa5568389f Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Tue, 14 Nov 2023 13:01:12 -0600 Subject: [PATCH 19/91] fix: release without token metadata processor From ab2184c8d183752a6e055bc3657071d72bfb42ed Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 14 Nov 2023 20:19:52 +0000 Subject: [PATCH 20/91] chore(release): 7.3.4 [skip ci] ## [7.3.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.3...v7.3.4) (2023-11-14) ### Bug Fixes * release without token metadata processor ([b35be4f](https://github.com/hirosystems/stacks-blockchain-api/commit/b35be4f2dc6e98923063700839427afa5568389f)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 497926d879..fb70a4485a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.3.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.3...v7.3.4) (2023-11-14) + + +### Bug Fixes + +* release without token metadata processor ([b35be4f](https://github.com/hirosystems/stacks-blockchain-api/commit/b35be4f2dc6e98923063700839427afa5568389f)) + ## [7.3.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.2...v7.3.3) (2023-11-13) From 04b71cc392b4e9b6518fd59b79886cc437656de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Thu, 16 Nov 2023 13:34:18 -0600 Subject: [PATCH 21/91] fix: convert `chain_tip` materialized view into a table (#1751) * feat: chain tip table * fix: handle reorgs --- migrations/1700071472495_chain-tip-table.js | 142 ++++++++++++++++++ src/api/controllers/cache-controller.ts | 6 +- src/api/routes/status.ts | 16 +- src/datastore/common.ts | 23 ++- src/datastore/pg-store.ts | 73 +++------ src/datastore/pg-write-store.ts | 110 +++++++------- src/event-stream/event-server.ts | 4 +- src/tests-event-replay/import-export-tests.ts | 38 ++--- .../poison-microblock-tests.ts | 9 +- src/tests/cache-control-tests.ts | 13 +- src/tests/datastore-tests.ts | 51 +++++-- src/tests/mempool-tests.ts | 2 +- src/tests/microblock-tests.ts | 26 ++-- 13 files changed, 313 insertions(+), 200 deletions(-) create mode 100644 migrations/1700071472495_chain-tip-table.js diff --git a/migrations/1700071472495_chain-tip-table.js b/migrations/1700071472495_chain-tip-table.js new file mode 100644 index 0000000000..dce518a530 --- /dev/null +++ b/migrations/1700071472495_chain-tip-table.js @@ -0,0 +1,142 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.dropMaterializedView('chain_tip'); + pgm.createTable('chain_tip', { + id: { + type: 'bool', + primaryKey: true, + default: true, + }, + block_height: { + type: 'integer', + notNull: true, + }, + block_count: { + type: 'integer', + notNull: true, + }, + block_hash: { + type: 'bytea', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + burn_block_height: { + type: 'integer', + notNull: true, + }, + microblock_hash: { + type: 'bytea', + }, + microblock_sequence: { + type: 'integer', + }, + microblock_count: { + type: 'integer', + notNull: true, + }, + tx_count: { + type: 'integer', + notNull: true, + }, + tx_count_unanchored: { + type: 'integer', + notNull: true, + }, + }); + pgm.addConstraint('chain_tip', 'chain_tip_one_row', 'CHECK(id)'); + pgm.sql(` + WITH block_tip AS ( + SELECT block_height, block_hash, index_block_hash, burn_block_height + FROM blocks + WHERE block_height = (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + microblock_tip AS ( + SELECT microblock_hash, microblock_sequence + FROM microblocks, block_tip + WHERE microblocks.parent_index_block_hash = block_tip.index_block_hash + AND microblock_canonical = true AND canonical = true + ORDER BY microblock_sequence DESC + LIMIT 1 + ), + microblock_count AS ( + SELECT COUNT(*)::INTEGER AS microblock_count + FROM microblocks + WHERE canonical = TRUE AND microblock_canonical = TRUE + ), + tx_count AS ( + SELECT COUNT(*)::INTEGER AS tx_count + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + AND block_height <= (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + tx_count_unanchored AS ( + SELECT COUNT(*)::INTEGER AS tx_count_unanchored + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + ) + INSERT INTO chain_tip (block_height, block_hash, index_block_hash, burn_block_height, + block_count, microblock_hash, microblock_sequence, microblock_count, tx_count, + tx_count_unanchored) + VALUES ( + COALESCE((SELECT block_height FROM block_tip), 0), + COALESCE((SELECT block_hash FROM block_tip), ''), + COALESCE((SELECT index_block_hash FROM block_tip), ''), + COALESCE((SELECT burn_block_height FROM block_tip), 0), + COALESCE((SELECT block_height FROM block_tip), 0), + (SELECT microblock_hash FROM microblock_tip), + (SELECT microblock_sequence FROM microblock_tip), + COALESCE((SELECT microblock_count FROM microblock_count), 0), + COALESCE((SELECT tx_count FROM tx_count), 0), + COALESCE((SELECT tx_count_unanchored FROM tx_count_unanchored), 0) + ) + `); +}; + +exports.down = pgm => { + pgm.dropTable('chain_tip'); + pgm.createMaterializedView('chain_tip', {}, ` + WITH block_tip AS ( + SELECT block_height, block_hash, index_block_hash, burn_block_height + FROM blocks + WHERE block_height = (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + microblock_tip AS ( + SELECT microblock_hash, microblock_sequence + FROM microblocks, block_tip + WHERE microblocks.parent_index_block_hash = block_tip.index_block_hash + AND microblock_canonical = true AND canonical = true + ORDER BY microblock_sequence DESC + LIMIT 1 + ), + microblock_count AS ( + SELECT COUNT(*)::INTEGER AS microblock_count + FROM microblocks + WHERE canonical = TRUE AND microblock_canonical = TRUE + ), + tx_count AS ( + SELECT COUNT(*)::INTEGER AS tx_count + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + AND block_height <= (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + tx_count_unanchored AS ( + SELECT COUNT(*)::INTEGER AS tx_count_unanchored + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + ) + SELECT *, block_tip.block_height AS block_count + FROM block_tip + LEFT JOIN microblock_tip ON TRUE + LEFT JOIN microblock_count ON TRUE + LEFT JOIN tx_count ON TRUE + LEFT JOIN tx_count_unanchored ON TRUE + LIMIT 1 + `); + pgm.createIndex('chain_tip', 'block_height', { unique: true }); +}; diff --git a/src/api/controllers/cache-controller.ts b/src/api/controllers/cache-controller.ts index 6d2f84fc77..470aeceba7 100644 --- a/src/api/controllers/cache-controller.ts +++ b/src/api/controllers/cache-controller.ts @@ -252,13 +252,13 @@ async function calculateETag( switch (etagType) { case ETagType.chainTip: try { - const chainTip = await db.getUnanchoredChainTip(); - if (!chainTip.found) { + const chainTip = await db.getChainTip(); + if (chainTip.block_height === 0) { // This should never happen unless the API is serving requests before it has synced any // blocks. return; } - return chainTip.result.microblockHash ?? chainTip.result.indexBlockHash; + return chainTip.microblock_hash ?? chainTip.index_block_hash; } catch (error) { logger.error(error, 'Unable to calculate chain_tip ETag'); return; diff --git a/src/api/routes/status.ts b/src/api/routes/status.ts index eb2cadfccc..328cb327ed 100644 --- a/src/api/routes/status.ts +++ b/src/api/routes/status.ts @@ -18,15 +18,15 @@ export function createStatusRouter(db: PgStore): express.Router { response.pox_v1_unlock_height = poxForceUnlockHeights.result.pox1UnlockHeight as number; response.pox_v2_unlock_height = poxForceUnlockHeights.result.pox2UnlockHeight as number; } - const chainTip = await db.getUnanchoredChainTip(); - if (chainTip.found) { + const chainTip = await db.getChainTip(); + if (chainTip.block_height > 0) { response.chain_tip = { - block_height: chainTip.result.blockHeight, - block_hash: chainTip.result.blockHash, - index_block_hash: chainTip.result.indexBlockHash, - microblock_hash: chainTip.result.microblockHash, - microblock_sequence: chainTip.result.microblockSequence, - burn_block_height: chainTip.result.burnBlockHeight, + block_height: chainTip.block_height, + block_hash: chainTip.block_hash, + index_block_hash: chainTip.index_block_hash, + microblock_hash: chainTip.microblock_hash, + microblock_sequence: chainTip.microblock_sequence, + burn_block_height: chainTip.burn_block_height, }; } setETagCacheHeaders(res); diff --git a/src/datastore/common.ts b/src/datastore/common.ts index be4fd1ee98..5ff49a4ba3 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -744,15 +744,6 @@ export type BlockIdentifier = | { burnBlockHash: string } | { burnBlockHeight: number }; -export interface DbChainTip { - blockHeight: number; - indexBlockHash: string; - blockHash: string; - microblockHash?: string; - microblockSequence?: number; - burnBlockHeight: number; -} - export interface BlockQueryResult { block_hash: string; index_block_hash: string; @@ -1461,10 +1452,16 @@ export interface SmartContractInsertValues { } export interface DbChainTip { - blockHeight: number; - blockHash: string; - indexBlockHash: string; - burnBlockHeight: number; + block_height: number; + block_count: number; + block_hash: string; + index_block_hash: string; + burn_block_height: number; + microblock_hash?: string; + microblock_sequence?: number; + microblock_count: number; + tx_count: number; + tx_count_unanchored: number; } export enum IndexesState { diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 1e2e6327ca..f5f888c640 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -202,26 +202,20 @@ export class PgStore extends BasePgStore { }); } - async getChainTip(sql: PgSqlClient): Promise<{ - blockHeight: number; - blockHash: string; - indexBlockHash: string; - burnBlockHeight: number; - }> { - const currentTipBlock = await sql< - { - block_height: number; - block_hash: string; - index_block_hash: string; - burn_block_height: number; - }[] - >`SELECT block_height, block_hash, index_block_hash, burn_block_height FROM chain_tip`; - const height = currentTipBlock[0]?.block_height ?? 0; + async getChainTip(): Promise { + const tipResult = await this.sql`SELECT * FROM chain_tip`; + const tip = tipResult[0]; return { - blockHeight: height, - blockHash: currentTipBlock[0]?.block_hash ?? '', - indexBlockHash: currentTipBlock[0]?.index_block_hash ?? '', - burnBlockHeight: currentTipBlock[0]?.burn_block_height ?? 0, + block_height: tip?.block_height ?? 0, + block_count: tip?.block_count ?? 0, + block_hash: tip?.block_hash ?? '', + index_block_hash: tip?.index_block_hash ?? '', + burn_block_height: tip?.burn_block_height ?? 0, + microblock_hash: tip?.microblock_hash ?? undefined, + microblock_sequence: tip?.microblock_sequence ?? undefined, + microblock_count: tip?.microblock_count ?? 0, + tx_count: tip?.tx_count ?? 0, + tx_count_unanchored: tip?.tx_count_unanchored ?? 0, }; } @@ -316,33 +310,6 @@ export class PgStore extends BasePgStore { return this.getPoxForcedUnlockHeightsInternal(this.sql); } - async getUnanchoredChainTip(): Promise> { - const result = await this.sql< - { - block_height: number; - index_block_hash: string; - block_hash: string; - microblock_hash: string | null; - microblock_sequence: number | null; - burn_block_height: number; - }[] - >`SELECT block_height, index_block_hash, block_hash, microblock_hash, microblock_sequence, burn_block_height - FROM chain_tip`; - if (result.length === 0) { - return { found: false } as const; - } - const row = result[0]; - const chainTipResult: DbChainTip = { - blockHeight: row.block_height, - indexBlockHash: row.index_block_hash, - blockHash: row.block_hash, - microblockHash: row.microblock_hash === null ? undefined : row.microblock_hash, - microblockSequence: row.microblock_sequence === null ? undefined : row.microblock_sequence, - burnBlockHeight: row.burn_block_height, - }; - return { found: true, result: chainTipResult }; - } - async getBlock(blockIdentifer: BlockIdentifier): Promise> { return this.getBlockInternal(this.sql, blockIdentifer); } @@ -626,8 +593,8 @@ export class PgStore extends BasePgStore { async getUnanchoredTxsInternal(sql: PgSqlClient): Promise<{ txs: DbTx[] }> { // Get transactions that have been streamed in microblocks but not yet accepted or rejected in an anchor block. - const { blockHeight } = await this.getChainTip(sql); - const unanchoredBlockHeight = blockHeight + 1; + const { block_height } = await this.getChainTip(); + const unanchoredBlockHeight = block_height + 1; const query = await sql` SELECT ${unsafeCols(sql, [...TX_COLUMNS, abiColumn()])} FROM txs @@ -1372,11 +1339,11 @@ export class PgStore extends BasePgStore { sql: PgSqlClient, { includeUnanchored }: { includeUnanchored: boolean } ): Promise { - const chainTip = await this.getChainTip(sql); + const chainTip = await this.getChainTip(); if (includeUnanchored) { - return chainTip.blockHeight + 1; + return chainTip.block_height + 1; } else { - return chainTip.blockHeight; + return chainTip.block_height; } } @@ -2159,9 +2126,9 @@ export class PgStore extends BasePgStore { async getStxBalanceAtBlock(stxAddress: string, blockHeight: number): Promise { return await this.sqlTransaction(async sql => { - const chainTip = await this.getChainTip(sql); + const chainTip = await this.getChainTip(); const blockHeightToQuery = - blockHeight > chainTip.blockHeight ? chainTip.blockHeight : blockHeight; + blockHeight > chainTip.block_height ? chainTip.block_height : blockHeight; const blockQuery = await this.getBlockByHeightInternal(sql, blockHeightToQuery); if (!blockQuery.found) { throw new Error(`Could not find block at height: ${blockHeight}`); diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 6cd51a0ce3..891e41d9aa 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -141,33 +141,6 @@ export class PgWriteStore extends PgStore { return store; } - async getChainTip(sql: PgSqlClient, useMaterializedView = true): Promise { - if (!this.isEventReplay && useMaterializedView) { - return super.getChainTip(sql); - } - // The `chain_tip` materialized view is not available during event replay. - // Since `getChainTip()` is used heavily during event ingestion, we'll fall back to - // a classic query. - const currentTipBlock = await sql< - { - block_height: number; - block_hash: string; - index_block_hash: string; - burn_block_height: number; - }[] - >` - SELECT block_height, block_hash, index_block_hash, burn_block_height - FROM blocks - WHERE canonical = true AND block_height = (SELECT MAX(block_height) FROM blocks) - `; - return { - blockHeight: currentTipBlock[0]?.block_height ?? 0, - blockHash: currentTipBlock[0]?.block_hash ?? '', - indexBlockHash: currentTipBlock[0]?.index_block_hash ?? '', - burnBlockHeight: currentTipBlock[0]?.burn_block_height ?? 0, - }; - } - async storeRawEventRequest(eventPath: string, payload: PgJsonb): Promise { // To avoid depending on the DB more than once and to allow the query transaction to settle, // we'll take the complete insert result and move that to the output TSV file instead of taking @@ -198,10 +171,10 @@ export class PgWriteStore extends PgStore { const contractLogEvents: DbSmartContractEvent[] = []; await this.sqlWriteTransaction(async sql => { - const chainTip = await this.getChainTip(sql, false); - await this.handleReorg(sql, data.block, chainTip.blockHeight); + const chainTip = await this.getChainTip(); + await this.handleReorg(sql, data.block, chainTip.block_height); // If the incoming block is not of greater height than current chain tip, then store data as non-canonical. - const isCanonical = data.block.block_height > chainTip.blockHeight; + const isCanonical = data.block.block_height > chainTip.block_height; if (!isCanonical) { data.block = { ...data.block, canonical: false }; data.microblocks = data.microblocks.map(mb => ({ ...mb, canonical: false })); @@ -417,12 +390,27 @@ export class PgWriteStore extends PgStore { const mempoolStats = await this.getMempoolStatsInternal({ sql }); this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); } + if (isCanonical) + await sql` + WITH new_tx_count AS ( + SELECT tx_count + ${data.txs.length} AS tx_count FROM chain_tip + ) + UPDATE chain_tip SET + block_height = ${data.block.block_height}, + block_hash = ${data.block.block_hash}, + index_block_hash = ${data.block.index_block_hash}, + burn_block_height = ${data.block.burn_block_height}, + microblock_hash = NULL, + microblock_sequence = NULL, + block_count = ${data.block.block_height}, + tx_count = (SELECT tx_count FROM new_tx_count), + tx_count_unanchored = (SELECT tx_count FROM new_tx_count) + `; }); // Do we have an IBD height defined in ENV? If so, check if this block update reached it. const ibdHeight = getIbdBlockHeight(); this.isIbdBlockHeightReached = ibdHeight ? data.block.block_height > ibdHeight : true; - await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); // Skip sending `PgNotifier` updates altogether if we're in the genesis block since this block is the @@ -597,12 +585,12 @@ export class PgWriteStore extends PgStore { const contractLogEvents: DbSmartContractEvent[] = []; await this.sqlWriteTransaction(async sql => { - // Sanity check: ensure incoming microblocks have a `parent_index_block_hash` that matches the API's - // current known canonical chain tip. We assume this holds true so incoming microblock data is always - // treated as being built off the current canonical anchor block. - const chainTip = await this.getChainTip(sql, false); + // Sanity check: ensure incoming microblocks have a `parent_index_block_hash` that matches the + // API's current known canonical chain tip. We assume this holds true so incoming microblock + // data is always treated as being built off the current canonical anchor block. + const chainTip = await this.getChainTip(); const nonCanonicalMicroblock = data.microblocks.find( - mb => mb.parent_index_block_hash !== chainTip.indexBlockHash + mb => mb.parent_index_block_hash !== chainTip.index_block_hash ); // Note: the stacks-node event emitter can send old microblocks that have already been processed by a previous anchor block. // Log warning and return, nothing to do. @@ -610,13 +598,13 @@ export class PgWriteStore extends PgStore { logger.info( `Failure in microblock ingestion, microblock ${nonCanonicalMicroblock.microblock_hash} ` + `points to parent index block hash ${nonCanonicalMicroblock.parent_index_block_hash} rather ` + - `than the current canonical tip's index block hash ${chainTip.indexBlockHash}.` + `than the current canonical tip's index block hash ${chainTip.index_block_hash}.` ); return; } // The block height is just one after the current chain tip height - const blockHeight = chainTip.blockHeight + 1; + const blockHeight = chainTip.block_height + 1; dbMicroblocks = data.microblocks.map(mb => { const dbMicroBlock: DbMicroblock = { canonical: true, @@ -629,8 +617,8 @@ export class PgWriteStore extends PgStore { parent_burn_block_hash: mb.parent_burn_block_hash, parent_burn_block_time: mb.parent_burn_block_time, block_height: blockHeight, - parent_block_height: chainTip.blockHeight, - parent_block_hash: chainTip.blockHash, + parent_block_height: chainTip.block_height, + parent_block_hash: chainTip.block_hash, index_block_hash: '', // Empty until microblock is confirmed in an anchor block block_hash: '', // Empty until microblock is confirmed in an anchor block }; @@ -642,7 +630,7 @@ export class PgWriteStore extends PgStore { // block with that data doesn't yet exist. const dbTx: DbTxRaw = { ...entry.tx, - parent_block_hash: chainTip.blockHash, + parent_block_hash: chainTip.block_hash, block_height: blockHeight, }; @@ -722,9 +710,20 @@ export class PgWriteStore extends PgStore { const mempoolStats = await this.getMempoolStatsInternal({ sql }); this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); } + if (currentMicroblockTip.microblock_canonical) + await sql` + UPDATE chain_tip SET + microblock_hash = ${currentMicroblockTip.microblock_hash}, + microblock_sequence = ${currentMicroblockTip.microblock_sequence}, + microblock_count = microblock_count + ${data.microblocks.length}, + tx_count_unanchored = ${ + currentMicroblockTip.microblock_sequence === 0 + ? sql`tx_count + ${data.txs.length}` + : sql`tx_count_unanchored + ${data.txs.length}` + } + `; }); - await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); if (this.notifier) { @@ -1728,7 +1727,7 @@ export class PgWriteStore extends PgStore { anchor_mode: tx.anchor_mode, status: tx.status, receipt_time: tx.receipt_time, - receipt_block_height: chainTip.blockHeight, + receipt_block_height: chainTip.block_height, post_conditions: tx.post_conditions, nonce: tx.nonce, fee_rate: tx.fee_rate, @@ -1767,7 +1766,7 @@ export class PgWriteStore extends PgStore { async updateMempoolTxs({ mempoolTxs: txs }: { mempoolTxs: DbMempoolTxRaw[] }): Promise { const updatedTxIds: string[] = []; await this.sqlWriteTransaction(async sql => { - const chainTip = await this.getChainTip(sql, false); + const chainTip = await this.getChainTip(); for (const tx of txs) { const inserted = await this.insertDbMempoolTx(tx, chainTip, sql); if (inserted) { @@ -2245,6 +2244,12 @@ export class PgWriteStore extends PgStore { }); } + // Update unanchored tx count in `chain_tip` table + const txCountDelta = updatedMbTxs.length * (args.isMicroCanonical ? 1 : -1); + await sql` + UPDATE chain_tip SET tx_count_unanchored = tx_count_unanchored + ${txCountDelta} + `; + return { updatedTxs: updatedMbTxs }; } @@ -2860,6 +2865,14 @@ export class PgWriteStore extends PgStore { await this.restoreOrphanedChain(sql, parentResult[0].index_block_hash, updatedEntities); this.logReorgResultInfo(updatedEntities); } + // Reflect updated transaction totals in `chain_tip` table. + const txCountDelta = + updatedEntities.markedCanonical.txs - updatedEntities.markedNonCanonical.txs; + await sql` + UPDATE chain_tip SET + tx_count = tx_count + ${txCountDelta}, + tx_count_unanchored = tx_count_unanchored + ${txCountDelta} + `; } return updatedEntities; } @@ -2944,13 +2957,8 @@ export class PgWriteStore extends PgStore { * Called when a full event import is complete. */ async finishEventReplay() { - if (!this.isEventReplay) { - return; - } - await this.sqlWriteTransaction(async sql => { - await this.refreshMaterializedView('chain_tip', sql, false); - await this.refreshMaterializedView('mempool_digest', sql, false); - }); + if (!this.isEventReplay) return; + await this.refreshMaterializedView('mempool_digest', this.sql, false); } /** diff --git a/src/event-stream/event-server.ts b/src/event-stream/event-server.ts index c767a44163..c0ec3c86c0 100644 --- a/src/event-stream/event-server.ts +++ b/src/event-stream/event-server.ts @@ -845,8 +845,8 @@ export async function startEventServer(opts: { if (ibdHeight) { app.use(IBD_PRUNABLE_ROUTES, async (req, res, next) => { try { - const chainTip = await db.getChainTip(db.sql, false); - if (chainTip.blockHeight > ibdHeight) { + const chainTip = await db.getChainTip(); + if (chainTip.block_height > ibdHeight) { next(); } else { handleRawEventRequest(req, res, next); diff --git a/src/tests-event-replay/import-export-tests.ts b/src/tests-event-replay/import-export-tests.ts index a5d52b7167..ed2fe9d03f 100644 --- a/src/tests-event-replay/import-export-tests.ts +++ b/src/tests-event-replay/import-export-tests.ts @@ -28,13 +28,12 @@ describe('import/export tests', () => { test('event import and export cycle', async () => { // Import from mocknet TSV await importEventsFromTsv('src/tests-event-replay/tsv/mocknet.tsv', 'archival', true, true); - const chainTip = await db.getUnanchoredChainTip(); - expect(chainTip.found).toBe(true); - expect(chainTip.result?.blockHeight).toBe(28); - expect(chainTip.result?.indexBlockHash).toBe( + const chainTip = await db.getChainTip(); + expect(chainTip.block_height).toBe(28); + expect(chainTip.index_block_hash).toBe( '0x76cd67a65c0dfd5ea450bb9efe30da89fa125bfc077c953802f718353283a533' ); - expect(chainTip.result?.blockHash).toBe( + expect(chainTip.block_hash).toBe( '0x7682af212d3c1ef62613412f9b5a727269b4548f14eca2e3f941f7ad8b3c11b2' ); @@ -51,13 +50,12 @@ describe('import/export tests', () => { // Re-import with exported TSV and check that chain tip matches. try { await importEventsFromTsv(`${tmpDir}/export.tsv`, 'archival', true, true); - const newChainTip = await db.getUnanchoredChainTip(); - expect(newChainTip.found).toBe(true); - expect(newChainTip.result?.blockHeight).toBe(28); - expect(newChainTip.result?.indexBlockHash).toBe( + const newChainTip = await db.getChainTip(); + expect(newChainTip.block_height).toBe(28); + expect(newChainTip.index_block_hash).toBe( '0x76cd67a65c0dfd5ea450bb9efe30da89fa125bfc077c953802f718353283a533' ); - expect(newChainTip.result?.blockHash).toBe( + expect(newChainTip.block_hash).toBe( '0x7682af212d3c1ef62613412f9b5a727269b4548f14eca2e3f941f7ad8b3c11b2' ); } finally { @@ -198,30 +196,14 @@ describe('IBD', () => { process.env.IBD_MODE_UNTIL_BLOCK = '1000'; // TSV has 1 microblock message. await expect(getIbdInterceptCountFromTsvEvents()).resolves.toBe(1); - await expect(db.getChainTip(client, false)).resolves.toHaveProperty('blockHeight', 28); + await expect(db.getChainTip()).resolves.toHaveProperty('block_height', 28); }); test('IBD mode does NOT block certain API routes once the threshold number of blocks are ingested', async () => { process.env.IBD_MODE_UNTIL_BLOCK = '1'; // Microblock processed normally. await expect(getIbdInterceptCountFromTsvEvents()).resolves.toBe(0); - await expect(db.getChainTip(client, false)).resolves.toHaveProperty('blockHeight', 28); - }); - - test('IBD mode prevents refreshing materialized views', async () => { - process.env.IBD_MODE_UNTIL_BLOCK = '1000'; - await getIbdInterceptCountFromTsvEvents(); - await db.refreshMaterializedView('chain_tip', client); - const res = await db.sql<{ block_height: number }[]>`SELECT * FROM chain_tip`; - expect(res.count).toBe(0); - }); - - test('IBD mode allows refreshing materialized views after height has passed', async () => { - process.env.IBD_MODE_UNTIL_BLOCK = '10'; - await getIbdInterceptCountFromTsvEvents(); - await db.refreshMaterializedView('chain_tip', client); - const res = await db.sql<{ block_height: number }[]>`SELECT * FROM chain_tip`; - expect(res[0].block_height).toBe(28); + await expect(db.getChainTip()).resolves.toHaveProperty('block_height', 28); }); test('IBD mode covers prune mode', async () => { diff --git a/src/tests-event-replay/poison-microblock-tests.ts b/src/tests-event-replay/poison-microblock-tests.ts index dd6d0ef741..5bd511ae56 100644 --- a/src/tests-event-replay/poison-microblock-tests.ts +++ b/src/tests-event-replay/poison-microblock-tests.ts @@ -25,22 +25,21 @@ describe('poison microblock for height 80743', () => { true ); const poisonTxId = '0x58ffe62029f94f7101b959536ea4953b9bce0ec3f6e2a06254c511bdd5cfa9e7'; - const chainTip = await db.getUnanchoredChainTip(); + const chainTip = await db.getChainTip(); // query the txs table and check the transaction type const searchResult = await db.searchHash({ hash: poisonTxId }); let entityData: any; if (searchResult.result?.entity_data) { entityData = searchResult.result?.entity_data; } - expect(chainTip.found).toBe(true); // check the transaction type to be contract call for this poison block expect(entityData.type_id).toBe(DbTxTypeId.ContractCall); expect(searchResult.found).toBe(true); - expect(chainTip.result?.blockHeight).toBe(1); - expect(chainTip.result?.indexBlockHash).toBe( + expect(chainTip.block_height).toBe(1); + expect(chainTip.index_block_hash).toBe( '0x05ca75b9949195da435e6e36d731dbaa10bb75fda576a52263e25164990bfdaa' ); - expect(chainTip.result?.blockHash).toBe( + expect(chainTip.block_hash).toBe( '0x6b83b44571365e6e530d679536578c71d6c376b07666f3671786b6fd8fac049c' ); }); diff --git a/src/tests/cache-control-tests.ts b/src/tests/cache-control-tests.ts index 482884b1ed..da9e0e826b 100644 --- a/src/tests/cache-control-tests.ts +++ b/src/tests/cache-control-tests.ts @@ -318,13 +318,12 @@ describe('cache-control tests', () => { ], }); - const chainTip2 = await db.getUnanchoredChainTip(); - expect(chainTip2.found).toBeTruthy(); - expect(chainTip2.result?.blockHash).toBe(block1.block_hash); - expect(chainTip2.result?.blockHeight).toBe(block1.block_height); - expect(chainTip2.result?.indexBlockHash).toBe(block1.index_block_hash); - expect(chainTip2.result?.microblockHash).toBe(mb1.microblock_hash); - expect(chainTip2.result?.microblockSequence).toBe(mb1.microblock_sequence); + const chainTip2 = await db.getChainTip(); + expect(chainTip2.block_hash).toBe(block1.block_hash); + expect(chainTip2.block_height).toBe(block1.block_height); + expect(chainTip2.index_block_hash).toBe(block1.index_block_hash); + expect(chainTip2.microblock_hash).toBe(mb1.microblock_hash); + expect(chainTip2.microblock_sequence).toBe(mb1.microblock_sequence); const expectedResp2 = { burn_block_time: 1594647996, diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index 197ef2f1ce..6889b0a25c 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -3733,6 +3733,7 @@ describe('postgres datastore', () => { contract_name: 'pox', }; + // Start canonical chain await db.update({ block: block1, microblocks: [], @@ -3953,6 +3954,7 @@ describe('postgres datastore', () => { abi: '{"thing":1}', }; + // Insert non-canonical block await db.update({ block: block2b, microblocks: [], @@ -4050,12 +4052,18 @@ describe('postgres datastore', () => { const blockQuery1 = await db.getBlock({ hash: block2b.block_hash }); expect(blockQuery1.result?.canonical).toBe(false); - const chainTip1 = await db.getChainTip(client); + const chainTip1 = await db.getChainTip(); expect(chainTip1).toEqual({ - blockHash: '0x33', - blockHeight: 3, - indexBlockHash: '0xcc', - burnBlockHeight: 123, + block_hash: '0x33', + block_height: 3, + index_block_hash: '0xcc', + burn_block_height: 123, + block_count: 3, + microblock_count: 0, + microblock_hash: undefined, + microblock_sequence: undefined, + tx_count: 2, // Tx from block 2b does not count + tx_count_unanchored: 2, }); const namespaces = await db.getNamespaceList({ includeUnanchored: false }); expect(namespaces.results.length).toBe(1); @@ -4109,12 +4117,19 @@ describe('postgres datastore', () => { await db.update({ block: block3b, microblocks: [], minerRewards: [], txs: [] }); const blockQuery2 = await db.getBlock({ hash: block3b.block_hash }); expect(blockQuery2.result?.canonical).toBe(false); - const chainTip2 = await db.getChainTip(client); + // Chain tip doesn't change yet. + const chainTip2 = await db.getChainTip(); expect(chainTip2).toEqual({ - blockHash: '0x33', - blockHeight: 3, - indexBlockHash: '0xcc', - burnBlockHeight: 123, + block_hash: '0x33', + block_height: 3, + index_block_hash: '0xcc', + burn_block_height: 123, + block_count: 3, + microblock_count: 0, + microblock_hash: undefined, + microblock_sequence: undefined, + tx_count: 2, + tx_count_unanchored: 2, }); const block4b: DbBlock = { @@ -4152,12 +4167,18 @@ describe('postgres datastore', () => { const blockQuery3 = await db.getBlock({ hash: block3b.block_hash }); expect(blockQuery3.result?.canonical).toBe(true); - const chainTip3 = await db.getChainTip(client); + const chainTip3 = await db.getChainTip(); expect(chainTip3).toEqual({ - blockHash: '0x44bb', - blockHeight: 4, - indexBlockHash: '0xddbb', - burnBlockHeight: 123, + block_count: 4, + block_hash: '0x44bb', + block_height: 4, + burn_block_height: 123, + index_block_hash: '0xddbb', + microblock_count: 0, + microblock_hash: undefined, + microblock_sequence: undefined, + tx_count: 2, // Tx from block 2b now counts, but compensates with tx from block 2 + tx_count_unanchored: 2, }); const b1 = await db.getBlock({ hash: block1.block_hash }); diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index d8d135d692..961d4d0756 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1539,7 +1539,7 @@ describe('mempool tests', () => { // Simulate the bug with a txs being in the mempool at confirmed at the same time by // directly inserting the mempool-tx and mined-tx, bypassing the normal update functions. await db.updateBlock(db.sql, dbBlock1); - const chainTip = await db.getChainTip(db.sql); + const chainTip = await db.getChainTip(); await db.insertDbMempoolTx(mempoolTx, chainTip, db.sql); await db.updateTx(db.sql, dbTx1); diff --git a/src/tests/microblock-tests.ts b/src/tests/microblock-tests.ts index a6918d99ed..06b27304aa 100644 --- a/src/tests/microblock-tests.ts +++ b/src/tests/microblock-tests.ts @@ -384,13 +384,12 @@ describe('microblock tests', () => { ], }); - const chainTip1 = await db.getUnanchoredChainTip(); - expect(chainTip1.found).toBeTruthy(); - expect(chainTip1.result?.blockHash).toBe(block1.block_hash); - expect(chainTip1.result?.blockHeight).toBe(block1.block_height); - expect(chainTip1.result?.indexBlockHash).toBe(block1.index_block_hash); - expect(chainTip1.result?.microblockHash).toBeUndefined(); - expect(chainTip1.result?.microblockSequence).toBeUndefined(); + const chainTip1 = await db.getChainTip(); + expect(chainTip1.block_hash).toBe(block1.block_hash); + expect(chainTip1.block_height).toBe(block1.block_height); + expect(chainTip1.index_block_hash).toBe(block1.index_block_hash); + expect(chainTip1.microblock_hash).toBeUndefined(); + expect(chainTip1.microblock_sequence).toBeUndefined(); const mb1: DbMicroblockPartial = { microblock_hash: '0xff01', @@ -546,13 +545,12 @@ describe('microblock tests', () => { ], }); - const chainTip2 = await db.getUnanchoredChainTip(); - expect(chainTip2.found).toBeTruthy(); - expect(chainTip2.result?.blockHash).toBe(block1.block_hash); - expect(chainTip2.result?.blockHeight).toBe(block1.block_height); - expect(chainTip2.result?.indexBlockHash).toBe(block1.index_block_hash); - expect(chainTip2.result?.microblockHash).toBe(mb1.microblock_hash); - expect(chainTip2.result?.microblockSequence).toBe(mb1.microblock_sequence); + const chainTip2 = await db.getChainTip(); + expect(chainTip2.block_hash).toBe(block1.block_hash); + expect(chainTip2.block_height).toBe(block1.block_height); + expect(chainTip2.index_block_hash).toBe(block1.index_block_hash); + expect(chainTip2.microblock_hash).toBe(mb1.microblock_hash); + expect(chainTip2.microblock_sequence).toBe(mb1.microblock_sequence); const txListResult1 = await supertest(api.server).get(`/extended/v1/tx`); const { body: txListBody1 }: { body: TransactionResults } = txListResult1; From 8a49ade307176837541dc73707e0ce998141000b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Thu, 16 Nov 2023 14:36:28 -0600 Subject: [PATCH 22/91] build: releases for nakamoto branch (#1752) --- .github/workflows/ci.yml | 1 + .releaserc | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23bd5373ae..789774a203 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ on: - master - develop - beta + - nakamoto tags-ignore: - "**" paths-ignore: diff --git a/.releaserc b/.releaserc index 82ddf7a705..e9d185e7d8 100644 --- a/.releaserc +++ b/.releaserc @@ -7,8 +7,8 @@ "prerelease": true }, { - "name": "stacks-2.4", - "channel": "stacks-2.4", + "name": "nakamoto", + "channel": "nakamoto", "prerelease": true } ], From ec950a2c425211dc9817f05aee2b3b6222382bf1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 16 Nov 2023 21:01:25 +0000 Subject: [PATCH 23/91] chore(release): 7.4.0-nakamoto.1 [skip ci] ## [7.4.0-nakamoto.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.2...v7.4.0-nakamoto.1) (2023-11-16) ### Features * add dataset store ([4211328](https://github.com/hirosystems/stacks-blockchain-api/commit/42113284381bc7d0913feb05cfecc65b37fdf814)) * add step to compile duckdb for Alpine image ([0f40e14](https://github.com/hirosystems/stacks-blockchain-api/commit/0f40e14aecd8390b90ea6c5c34a47601f3866e23)) * better handling of raw events insertion ([bb70ca9](https://github.com/hirosystems/stacks-blockchain-api/commit/bb70ca99c07bf777557bca5e4b9924d104d8f7fd)) * event-replay new_block events handling ([1708b42](https://github.com/hirosystems/stacks-blockchain-api/commit/1708b42c02b75882ec8ce8d05df5eddc7ef835b9)) * event-replay new_burn_block events handling ([6c0f448](https://github.com/hirosystems/stacks-blockchain-api/commit/6c0f4481c0f903d707c09e4e46a2330e67f32fff)) * event-replay raw events handling ([81f43cf](https://github.com/hirosystems/stacks-blockchain-api/commit/81f43cf7c314853f0d849ed8c8f6c0d0d6130a79)) * event-replay remainder events handling ([3ede07f](https://github.com/hirosystems/stacks-blockchain-api/commit/3ede07f134ac121505ca00b5bab7dba93a3def17)) * event-replay supporting parallel insertions ([f33ecee](https://github.com/hirosystems/stacks-blockchain-api/commit/f33ecee858a8d300e5926cb8238617e6e8b935a5)) * events folder as environment var ([701bd1a](https://github.com/hirosystems/stacks-blockchain-api/commit/701bd1a984c4ab064ddb1273a74cdb25975d7c1c)) * parallel processing using node cluster ([d02a7e8](https://github.com/hirosystems/stacks-blockchain-api/commit/d02a7e8ad87c9374bdf5f3e14740757984d0be75)) * processing raw events in parallel ([7a6f241](https://github.com/hirosystems/stacks-blockchain-api/commit/7a6f241923d0511b3d80308990dcf045b22562b6)) ### Bug Fixes * add token offering ([8ef039e](https://github.com/hirosystems/stacks-blockchain-api/commit/8ef039e89a083b555b88ce509f4e80d6270d096a)) * allow contract-principals in `/extended/v1/address/:principal/mempool` endpoint [#1685](https://github.com/hirosystems/stacks-blockchain-api/issues/1685) ([#1704](https://github.com/hirosystems/stacks-blockchain-api/issues/1704)) ([163b76a](https://github.com/hirosystems/stacks-blockchain-api/commit/163b76a31a548c84b9d8be8e07ef94e5631b311b)) * better args handlling ([c77ac57](https://github.com/hirosystems/stacks-blockchain-api/commit/c77ac57a9613a85418174355f6922f74676158e5)) * better path handling for workers ([1bd8f17](https://github.com/hirosystems/stacks-blockchain-api/commit/1bd8f17f07fc8bfff30684aa67deed1de56f7b11)) * changed processing order ([62a12bd](https://github.com/hirosystems/stacks-blockchain-api/commit/62a12bdef93c77a5ac6eb5b7e15c20b4c672e041)) * convert `chain_tip` materialized view into a table ([#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751)) ([04b71cc](https://github.com/hirosystems/stacks-blockchain-api/commit/04b71cc392b4e9b6518fd59b79886cc437656de7)) * flaky test ([484d2ea](https://github.com/hirosystems/stacks-blockchain-api/commit/484d2ea0cd765431e8017e42c53669e5bc6e8728)) * flaky test ([65175f5](https://github.com/hirosystems/stacks-blockchain-api/commit/65175f5cca0853c6bb07a9f377b8e39a134c8a8c)) * lint ([01589ea](https://github.com/hirosystems/stacks-blockchain-api/commit/01589eabbb88d2bc6453368a7b753813bd247a34)) * lint ([82eadcb](https://github.com/hirosystems/stacks-blockchain-api/commit/82eadcbe2fefd6ec5fc74b098445a6dedc63528b)) * lint ([8c67ae5](https://github.com/hirosystems/stacks-blockchain-api/commit/8c67ae532b9a992e93e0d00561e331197a5ca8ea)) * on attachments_new events processing ([0707313](https://github.com/hirosystems/stacks-blockchain-api/commit/07073139ccb4b6d71d429864e4612944ef84c646)) * re-enable indexes when finishing the replay ([fc379eb](https://github.com/hirosystems/stacks-blockchain-api/commit/fc379ebab97e41dc20645bfff34fb484251508b9)) * remove dangling promise ([62a48ae](https://github.com/hirosystems/stacks-blockchain-api/commit/62a48ae37d86591dcaa8a928c1b63ddf2b1a6056)) * revert configurable DB index type ([86154b2](https://github.com/hirosystems/stacks-blockchain-api/commit/86154b29e4e4af530da162133c99ebd609fab0e1)) * upgrade semver package to fix ReDoS vulnerability ([6b1605b](https://github.com/hirosystems/stacks-blockchain-api/commit/6b1605b74d7c1bad39fcb491caf4ed51426b7618)) --- CHANGELOG.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80398743e6..086c9be236 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,40 @@ +## [7.4.0-nakamoto.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.2...v7.4.0-nakamoto.1) (2023-11-16) + + +### Features + +* add dataset store ([4211328](https://github.com/hirosystems/stacks-blockchain-api/commit/42113284381bc7d0913feb05cfecc65b37fdf814)) +* add step to compile duckdb for Alpine image ([0f40e14](https://github.com/hirosystems/stacks-blockchain-api/commit/0f40e14aecd8390b90ea6c5c34a47601f3866e23)) +* better handling of raw events insertion ([bb70ca9](https://github.com/hirosystems/stacks-blockchain-api/commit/bb70ca99c07bf777557bca5e4b9924d104d8f7fd)) +* event-replay new_block events handling ([1708b42](https://github.com/hirosystems/stacks-blockchain-api/commit/1708b42c02b75882ec8ce8d05df5eddc7ef835b9)) +* event-replay new_burn_block events handling ([6c0f448](https://github.com/hirosystems/stacks-blockchain-api/commit/6c0f4481c0f903d707c09e4e46a2330e67f32fff)) +* event-replay raw events handling ([81f43cf](https://github.com/hirosystems/stacks-blockchain-api/commit/81f43cf7c314853f0d849ed8c8f6c0d0d6130a79)) +* event-replay remainder events handling ([3ede07f](https://github.com/hirosystems/stacks-blockchain-api/commit/3ede07f134ac121505ca00b5bab7dba93a3def17)) +* event-replay supporting parallel insertions ([f33ecee](https://github.com/hirosystems/stacks-blockchain-api/commit/f33ecee858a8d300e5926cb8238617e6e8b935a5)) +* events folder as environment var ([701bd1a](https://github.com/hirosystems/stacks-blockchain-api/commit/701bd1a984c4ab064ddb1273a74cdb25975d7c1c)) +* parallel processing using node cluster ([d02a7e8](https://github.com/hirosystems/stacks-blockchain-api/commit/d02a7e8ad87c9374bdf5f3e14740757984d0be75)) +* processing raw events in parallel ([7a6f241](https://github.com/hirosystems/stacks-blockchain-api/commit/7a6f241923d0511b3d80308990dcf045b22562b6)) + + +### Bug Fixes + +* add token offering ([8ef039e](https://github.com/hirosystems/stacks-blockchain-api/commit/8ef039e89a083b555b88ce509f4e80d6270d096a)) +* allow contract-principals in `/extended/v1/address/:principal/mempool` endpoint [#1685](https://github.com/hirosystems/stacks-blockchain-api/issues/1685) ([#1704](https://github.com/hirosystems/stacks-blockchain-api/issues/1704)) ([163b76a](https://github.com/hirosystems/stacks-blockchain-api/commit/163b76a31a548c84b9d8be8e07ef94e5631b311b)) +* better args handlling ([c77ac57](https://github.com/hirosystems/stacks-blockchain-api/commit/c77ac57a9613a85418174355f6922f74676158e5)) +* better path handling for workers ([1bd8f17](https://github.com/hirosystems/stacks-blockchain-api/commit/1bd8f17f07fc8bfff30684aa67deed1de56f7b11)) +* changed processing order ([62a12bd](https://github.com/hirosystems/stacks-blockchain-api/commit/62a12bdef93c77a5ac6eb5b7e15c20b4c672e041)) +* convert `chain_tip` materialized view into a table ([#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751)) ([04b71cc](https://github.com/hirosystems/stacks-blockchain-api/commit/04b71cc392b4e9b6518fd59b79886cc437656de7)) +* flaky test ([484d2ea](https://github.com/hirosystems/stacks-blockchain-api/commit/484d2ea0cd765431e8017e42c53669e5bc6e8728)) +* flaky test ([65175f5](https://github.com/hirosystems/stacks-blockchain-api/commit/65175f5cca0853c6bb07a9f377b8e39a134c8a8c)) +* lint ([01589ea](https://github.com/hirosystems/stacks-blockchain-api/commit/01589eabbb88d2bc6453368a7b753813bd247a34)) +* lint ([82eadcb](https://github.com/hirosystems/stacks-blockchain-api/commit/82eadcbe2fefd6ec5fc74b098445a6dedc63528b)) +* lint ([8c67ae5](https://github.com/hirosystems/stacks-blockchain-api/commit/8c67ae532b9a992e93e0d00561e331197a5ca8ea)) +* on attachments_new events processing ([0707313](https://github.com/hirosystems/stacks-blockchain-api/commit/07073139ccb4b6d71d429864e4612944ef84c646)) +* re-enable indexes when finishing the replay ([fc379eb](https://github.com/hirosystems/stacks-blockchain-api/commit/fc379ebab97e41dc20645bfff34fb484251508b9)) +* remove dangling promise ([62a48ae](https://github.com/hirosystems/stacks-blockchain-api/commit/62a48ae37d86591dcaa8a928c1b63ddf2b1a6056)) +* revert configurable DB index type ([86154b2](https://github.com/hirosystems/stacks-blockchain-api/commit/86154b29e4e4af530da162133c99ebd609fab0e1)) +* upgrade semver package to fix ReDoS vulnerability ([6b1605b](https://github.com/hirosystems/stacks-blockchain-api/commit/6b1605b74d7c1bad39fcb491caf4ed51426b7618)) + ## [7.3.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.1...v7.3.2) (2023-09-14) From 7a10cd8c4bb585c75a2437508802c7e5d908a564 Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Fri, 17 Nov 2023 10:28:12 -0600 Subject: [PATCH 24/91] fix: import statement in replay controller --- src/event-replay/parquet-based/replay-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event-replay/parquet-based/replay-controller.ts b/src/event-replay/parquet-based/replay-controller.ts index b011bd97f5..7943cba2f5 100644 --- a/src/event-replay/parquet-based/replay-controller.ts +++ b/src/event-replay/parquet-based/replay-controller.ts @@ -17,7 +17,7 @@ const cluster = _cluster as unknown as _cluster.Cluster; // typings fix import { FILE_PATH as raw_worker_path } from './workers/raw-worker'; import { FILE_PATH as new_block_worker_path } from './workers/new-block-worker'; import { cycleMigrations, dangerousDropAllTables } from '@hirosystems/api-toolkit'; -import { PgServer, getConnectionArgs } from 'src/datastore/connection'; +import { PgServer, getConnectionArgs } from '../../datastore/connection'; import { MIGRATIONS_DIR } from '../../datastore/pg-store'; /** From f33d4da43ef91b3828bfa6a29a0245e18626b017 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 17 Nov 2023 16:34:44 +0000 Subject: [PATCH 25/91] chore(release): 7.4.0-nakamoto.2 [skip ci] ## [7.4.0-nakamoto.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.1...v7.4.0-nakamoto.2) (2023-11-17) ### Bug Fixes * import statement in replay controller ([7a10cd8](https://github.com/hirosystems/stacks-blockchain-api/commit/7a10cd8c4bb585c75a2437508802c7e5d908a564)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 086c9be236..188c1f592e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-nakamoto.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.1...v7.4.0-nakamoto.2) (2023-11-17) + + +### Bug Fixes + +* import statement in replay controller ([7a10cd8](https://github.com/hirosystems/stacks-blockchain-api/commit/7a10cd8c4bb585c75a2437508802c7e5d908a564)) + ## [7.4.0-nakamoto.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.2...v7.4.0-nakamoto.1) (2023-11-16) From 7c45f53622338170477948d38f549c2136d830c1 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 8 Dec 2023 12:39:52 +0100 Subject: [PATCH 26/91] feat: ingestion for `TenureChange` and `NakamotoCoinbase` tx types (#1753) * feat: ingestion for TenureChange and NakamotoCoinbase tx types * fix: add new tx fields to batch tx insert query * chore: bump stacks-encoding-native-js * test: fix flaky socket-io timeout test --- .vscode/launch.json | 20 ++++++ .vscode/tasks.json | 23 +++++++ .../transaction-7-tenure-change.schema.json | 13 ++++ .../transaction.schema.json | 3 + ...ransaction-4-coinbase-metadata.schema.json | 5 ++ ...ction-7-tenure-change-metadata.schema.json | 45 +++++++++++++ .../transaction-7-tenure-change.example.json | 25 ++++++++ .../transaction-7-tenure-change.schema.json | 13 ++++ .../transaction-metadata.schema.json | 3 + .../transactions/transaction-type.schema.json | 2 +- .../transactions/transaction.schema.json | 3 + docs/generated.d.ts | 64 +++++++++++++++++-- docs/openapi.yaml | 2 +- migrations/1701368149776_nakamoto-txs.js | 44 +++++++++++++ package-lock.json | 8 +-- package.json | 2 +- src/api/controllers/db-controller.ts | 56 ++++++++++++++++ src/datastore/common.ts | 52 +++++++++++++++ src/datastore/helpers.ts | 46 +++++++++++++ src/datastore/pg-write-store.ts | 21 ++++++ src/event-stream/reader.ts | 20 ++++++ src/rosetta/rosetta-helpers.ts | 6 ++ src/test-utils/test-builders.ts | 2 + src/tests/socket-io-tests.ts | 2 +- 24 files changed, 468 insertions(+), 12 deletions(-) create mode 100644 docs/entities/mempool-transactions/transaction-7-tenure-change.schema.json create mode 100644 docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json create mode 100644 docs/entities/transactions/transaction-7-tenure-change.example.json create mode 100644 docs/entities/transactions/transaction-7-tenure-change.schema.json create mode 100644 migrations/1701368149776_nakamoto-txs.js diff --git a/.vscode/launch.json b/.vscode/launch.json index 6ef212dc0b..845f9a4802 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -48,6 +48,26 @@ }, "killBehavior": "polite", }, + { + "type": "node", + "request": "launch", + "name": "Launch: w/ postgres", + "skipFiles": [ + "/**" + ], + "runtimeArgs": ["-r", "ts-node/register/transpile-only", "-r", "tsconfig-paths/register"], + "args": ["${workspaceFolder}/src/index.ts"], + "outputCapture": "std", + "internalConsoleOptions": "openOnSessionStart", + "preLaunchTask": "deploy:pg", + "postDebugTask": "stop:pg", + "env": { + "STACKS_CHAIN_ID": "0x80000000", + "NODE_ENV": "development", + "TS_NODE_SKIP_IGNORE": "true" + }, + "killBehavior": "polite", + }, { "type": "node", "request": "launch", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4742f26ab2..62a73ce93e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -44,6 +44,29 @@ }, "presentation": { "echo": true, "reveal": "always", "focus": false, "panel": "dedicated", "clear": false } }, + { + "label": "deploy:pg", + "type": "shell", + "command": "docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V", + "isBackground": true, + "problemMatcher": [{ + "pattern": [{ "regexp": ".", "file": 1, "location": 2, "message": 3 }], + "background": { "activeOnStart": true, "beginsPattern": ".", "endsPattern": "." } + }], + "presentation": { "echo": true, "reveal": "always", "focus": false, "panel": "dedicated", "clear": false } + }, + { + "label": "stop:pg", + "type": "shell", + "command": "docker compose -f docker/docker-compose.dev.postgres.yml down -v -t 0", + "presentation": { + "echo": true, + "reveal": "silent", + "focus": false, + "panel": "shared", + "clear": false + } + }, { "label": "deploy:subnets", "type": "shell", diff --git a/docs/entities/mempool-transactions/transaction-7-tenure-change.schema.json b/docs/entities/mempool-transactions/transaction-7-tenure-change.schema.json new file mode 100644 index 0000000000..2ed384aaf5 --- /dev/null +++ b/docs/entities/mempool-transactions/transaction-7-tenure-change.schema.json @@ -0,0 +1,13 @@ +{ + "type": "object", + "title": "MempoolTenureChangeTransaction", + "description": "Describes representation of a Type 7 Stacks transaction: Tenure Change", + "allOf": [ + { + "$ref": "./abstract-transaction.schema.json" + }, + { + "$ref": "../transactions/transaction-7-tenure-change-metadata.schema.json" + } + ] +} diff --git a/docs/entities/mempool-transactions/transaction.schema.json b/docs/entities/mempool-transactions/transaction.schema.json index 2043c0d650..ec86068828 100644 --- a/docs/entities/mempool-transactions/transaction.schema.json +++ b/docs/entities/mempool-transactions/transaction.schema.json @@ -17,6 +17,9 @@ }, { "$ref": "./transaction-4-coinbase.schema.json" + }, + { + "$ref": "./transaction-7-tenure-change.schema.json" } ] } diff --git a/docs/entities/transactions/transaction-4-coinbase-metadata.schema.json b/docs/entities/transactions/transaction-4-coinbase-metadata.schema.json index 7ac8e41946..d79a045b12 100644 --- a/docs/entities/transactions/transaction-4-coinbase-metadata.schema.json +++ b/docs/entities/transactions/transaction-4-coinbase-metadata.schema.json @@ -22,6 +22,11 @@ "type": "string", "nullable": true, "description": "A principal that will receive the miner rewards for this coinbase transaction. Can be either a standard principal or contract principal. Only specified for `coinbase-to-alt-recipient` transaction types, otherwise null." + }, + "vrf_proof": { + "type": "string", + "nullable": true, + "description": "Hex encoded 80-byte VRF proof" } } } diff --git a/docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json b/docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json new file mode 100644 index 0000000000..68f6728abb --- /dev/null +++ b/docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json @@ -0,0 +1,45 @@ +{ + "type": "object", + "title": "TenureChangeTransactionMetadata", + "description": "Describes representation of a Type 7 Stacks transaction: Tenure Change", + "required": ["tx_type"], + "additionalProperties": false, + "properties": { + "tx_type": { + "type": "string", + "enum": ["tenure_change"] + }, + "tenure_change_payload": { + "type": "object", + "additionalProperties": false, + "required": ["previous_tenure_end", "previous_tenure_blocks", "cause", "pubkey_hash", "signature", "signers"], + "properties": { + "previous_tenure_end": { + "type": "string", + "description": "(Hex string) Stacks Block hash" + }, + "previous_tenure_blocks": { + "type": "number", + "description": "The number of blocks produced in the previous tenure." + }, + "cause": { + "type": "string", + "enum": ["block_found", "no_block_found", "null_miner"], + "description": "Cause of change in mining tenure. Depending on cause, tenure can be ended or extended." + }, + "pubkey_hash": { + "type": "string", + "description": "(Hex string) The ECDSA public key hash of the current tenure." + }, + "signature": { + "type": "string", + "description": "(Hex string) A Schnorr signature from the Stackers." + }, + "signers": { + "type": "string", + "description": "(Hex string) A bitmap of which Stackers signed." + } + } + } + } +} diff --git a/docs/entities/transactions/transaction-7-tenure-change.example.json b/docs/entities/transactions/transaction-7-tenure-change.example.json new file mode 100644 index 0000000000..797263ba80 --- /dev/null +++ b/docs/entities/transactions/transaction-7-tenure-change.example.json @@ -0,0 +1,25 @@ +{ + "tx_id": "0x5e9f3933e358df6a73fec0d47ce3e1062c20812c129f5294e6f37a8d27c051d9", + "tx_status": "success", + "tx_type": "coinbase", + "fee_rate": "0", + "sender_address": "ST3WCQ6S0DFT7YHF53M8JPKGDS1N1GSSR91677XF1", + "sponsored": false, + "post_condition_mode": "deny", + "is_unanchored": false, + "microblock_hash": "", + "microblock_sequence": 2147483647, + "microblock_canonical": true, + "block_hash": "0x58412b50266debd0c35b1a20348ad9c0f17e5525fb155a97033256c83c9e2491", + "block_height": 3231, + "burn_block_time": 1594230455, + "canonical": true, + "tx_index": 0, + "tx_result": { + "hex": "0x03", + "repr": "true" + }, + "coinbase_payload": { + "data": "0x0000000000000000000000000000000000000000000000000000000000000000" + } +} diff --git a/docs/entities/transactions/transaction-7-tenure-change.schema.json b/docs/entities/transactions/transaction-7-tenure-change.schema.json new file mode 100644 index 0000000000..42d2e52e1f --- /dev/null +++ b/docs/entities/transactions/transaction-7-tenure-change.schema.json @@ -0,0 +1,13 @@ +{ + "type": "object", + "title": "TenureChangeTransaction", + "description": "Describes representation of a Type 7 Stacks transaction: Tenure Change", + "allOf": [ + { + "$ref": "./abstract-transaction.schema.json" + }, + { + "$ref": "./transaction-7-tenure-change-metadata.schema.json" + } + ] +} diff --git a/docs/entities/transactions/transaction-metadata.schema.json b/docs/entities/transactions/transaction-metadata.schema.json index 37ee53ebea..502f413b54 100644 --- a/docs/entities/transactions/transaction-metadata.schema.json +++ b/docs/entities/transactions/transaction-metadata.schema.json @@ -16,6 +16,9 @@ }, { "$ref": "./transaction-4-coinbase-metadata.schema.json" + }, + { + "$ref": "./transaction-7-tenure-change-metadata.schema.json" } ] } diff --git a/docs/entities/transactions/transaction-type.schema.json b/docs/entities/transactions/transaction-type.schema.json index da73d93392..78026c6a8a 100644 --- a/docs/entities/transactions/transaction-type.schema.json +++ b/docs/entities/transactions/transaction-type.schema.json @@ -2,5 +2,5 @@ "title": "TransactionType", "description": "String literal of all Stacks 2.0 transaction types", "type": "string", - "enum": ["token_transfer", "smart_contract", "contract_call", "poison_microblock", "coinbase"] + "enum": ["token_transfer", "smart_contract", "contract_call", "poison_microblock", "coinbase", "tenure_change"] } diff --git a/docs/entities/transactions/transaction.schema.json b/docs/entities/transactions/transaction.schema.json index 1a57db4bde..6b07eeefbb 100644 --- a/docs/entities/transactions/transaction.schema.json +++ b/docs/entities/transactions/transaction.schema.json @@ -17,6 +17,9 @@ }, { "$ref": "./transaction-4-coinbase.schema.json" + }, + { + "$ref": "./transaction-7-tenure-change.schema.json" } ] } diff --git a/docs/generated.d.ts b/docs/generated.d.ts index 450d834b3e..d1c42c1e17 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -127,6 +127,7 @@ export type SchemaMergeRootStub = | MempoolContractCallTransaction | MempoolPoisonMicroblockTransaction | MempoolCoinbaseTransaction + | MempoolTenureChangeTransaction | MempoolTransactionStatus | MempoolTransaction | Microblock @@ -209,6 +210,8 @@ export type SchemaMergeRootStub = | PoisonMicroblockTransaction | CoinbaseTransactionMetadata | CoinbaseTransaction + | TenureChangeTransactionMetadata + | TenureChangeTransaction | TransactionFound | TransactionList | TransactionMetadata @@ -324,7 +327,8 @@ export type Transaction = | SmartContractTransaction | ContractCallTransaction | PoisonMicroblockTransaction - | CoinbaseTransaction; + | CoinbaseTransaction + | TenureChangeTransaction; /** * Describes representation of a Type-0 Stacks 2.0 transaction. https://github.com/blockstack/stacks-blockchain/blob/master/sip/sip-005-blocks-and-transactions.md#type-0-transferring-an-asset */ @@ -526,6 +530,10 @@ export type PoisonMicroblockTransaction = AbstractTransaction & PoisonMicroblock * Describes representation of a Type 3 Stacks 2.0 transaction: Poison Microblock */ export type CoinbaseTransaction = AbstractTransaction & CoinbaseTransactionMetadata; +/** + * Describes representation of a Type 7 Stacks transaction: Tenure Change + */ +export type TenureChangeTransaction = AbstractTransaction & TenureChangeTransactionMetadata; /** * Describes all transaction types on Stacks 2.0 blockchain */ @@ -534,7 +542,8 @@ export type MempoolTransaction = | MempoolSmartContractTransaction | MempoolContractCallTransaction | MempoolPoisonMicroblockTransaction - | MempoolCoinbaseTransaction; + | MempoolCoinbaseTransaction + | MempoolTenureChangeTransaction; /** * Describes representation of a Type-0 Stacks 2.0 transaction. https://github.com/blockstack/stacks-blockchain/blob/master/sip/sip-005-blocks-and-transactions.md#type-0-transferring-an-asset */ @@ -578,6 +587,10 @@ export type MempoolPoisonMicroblockTransaction = AbstractMempoolTransaction & Po * Describes representation of a Type 3 Stacks 2.0 transaction: Poison Microblock */ export type MempoolCoinbaseTransaction = AbstractMempoolTransaction & CoinbaseTransactionMetadata; +/** + * Describes representation of a Type 7 Stacks transaction: Tenure Change + */ +export type MempoolTenureChangeTransaction = AbstractMempoolTransaction & TenureChangeTransactionMetadata; /** * Fetch a user's raw zone file. This only works for RFC-compliant zone files. This method returns an error for names that have non-standard zone files. */ @@ -705,11 +718,18 @@ export type TransactionMetadata = | SmartContractTransactionMetadata | ContractCallTransactionMetadata | PoisonMicroblockTransactionMetadata - | CoinbaseTransactionMetadata; + | CoinbaseTransactionMetadata + | TenureChangeTransactionMetadata; /** * String literal of all Stacks 2.0 transaction types */ -export type TransactionType = "token_transfer" | "smart_contract" | "contract_call" | "poison_microblock" | "coinbase"; +export type TransactionType = + | "token_transfer" + | "smart_contract" + | "contract_call" + | "poison_microblock" + | "coinbase" + | "tenure_change"; export type RpcAddressBalanceNotificationParams = { address: string; } & AddressStxBalanceResponse; @@ -1098,6 +1118,42 @@ export interface CoinbaseTransactionMetadata { * A principal that will receive the miner rewards for this coinbase transaction. Can be either a standard principal or contract principal. Only specified for `coinbase-to-alt-recipient` transaction types, otherwise null. */ alt_recipient?: string; + /** + * Hex encoded 80-byte VRF proof + */ + vrf_proof?: string; + }; +} +/** + * Describes representation of a Type 7 Stacks transaction: Tenure Change + */ +export interface TenureChangeTransactionMetadata { + tx_type: "tenure_change"; + tenure_change_payload?: { + /** + * (Hex string) Stacks Block hash + */ + previous_tenure_end: string; + /** + * The number of blocks produced in the previous tenure. + */ + previous_tenure_blocks: number; + /** + * Cause of change in mining tenure. Depending on cause, tenure can be ended or extended. + */ + cause: "block_found" | "no_block_found" | "null_miner"; + /** + * (Hex string) The ECDSA public key hash of the current tenure. + */ + pubkey_hash: string; + /** + * (Hex string) A Schnorr signature from the Stackers. + */ + signature: string; + /** + * (Hex string) A bitmap of which Stackers signed. + */ + signers: string; }; } /** diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 60933f83ac..16db1e359b 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -228,7 +228,7 @@ paths: example: coinbase items: type: string - enum: [coinbase, token_transfer, smart_contract, contract_call, poison_microblock] + enum: [coinbase, token_transfer, smart_contract, contract_call, poison_microblock, tenure_change] - name: unanchored in: query description: Include transaction data from unanchored (i.e. unconfirmed) microblocks diff --git a/migrations/1701368149776_nakamoto-txs.js b/migrations/1701368149776_nakamoto-txs.js new file mode 100644 index 0000000000..626757c032 --- /dev/null +++ b/migrations/1701368149776_nakamoto-txs.js @@ -0,0 +1,44 @@ +/** @param { import("node-pg-migrate").MigrationBuilder } pgm */ +exports.up = pgm => { + pgm.addColumns('txs', { + // `nakamoto-coinbase` tx types + coinbase_vrf_proof: 'bytea', + + // `tenure-change` tx types + tenure_change_previous_tenure_end: 'bytea', + tenure_change_previous_tenure_blocks: 'integer', + tenure_change_cause: 'smallint', + tenure_change_pubkey_hash: 'bytea', + tenure_change_signature: 'bytea', + tenure_change_signers: 'bytea', + }); + + pgm.addColumns('mempool_txs', { + // `nakamoto-coinbase` tx types + coinbase_vrf_proof: 'bytea', + + // `tenure-change` tx types + tenure_change_previous_tenure_end: 'bytea', + tenure_change_previous_tenure_blocks: 'integer', + tenure_change_cause: 'smallint', + tenure_change_pubkey_hash: 'bytea', + tenure_change_signature: 'bytea', + tenure_change_signers: 'bytea', + }); + + pgm.addConstraint('txs', 'valid_tenure-change', `CHECK (type_id != 7 OR ( + NOT (tenure_change_previous_tenure_end, tenure_change_previous_tenure_blocks, tenure_change_cause, tenure_change_pubkey_hash, tenure_change_signature, tenure_change_signers) IS NULL + ))`); + + pgm.addConstraint('txs', 'valid_nakamoto-coinbase', `CHECK (type_id != 8 OR ( + NOT (coinbase_payload, coinbase_vrf_proof) IS NULL + ))`); + + pgm.addConstraint('mempool_txs', 'valid_tenure-change', `CHECK (type_id != 7 OR ( + NOT (tenure_change_previous_tenure_end, tenure_change_previous_tenure_blocks, tenure_change_cause, tenure_change_pubkey_hash, tenure_change_signature, tenure_change_signers) IS NULL + ))`); + + pgm.addConstraint('mempool_txs', 'valid_nakamoto-coinbase', `CHECK (type_id != 8 OR ( + NOT (coinbase_payload, coinbase_vrf_proof) IS NULL + ))`); +}; diff --git a/package-lock.json b/package-lock.json index 015e651d2b..6daeefe001 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,7 @@ "socket.io": "4.6.1", "source-map-support": "0.5.21", "split2": "3.2.2", - "stacks-encoding-native-js": "1.0.0", + "stacks-encoding-native-js": "1.1.0-beta.3", "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", @@ -12825,9 +12825,9 @@ "dev": true }, "node_modules/stacks-encoding-native-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stacks-encoding-native-js/-/stacks-encoding-native-js-1.0.0.tgz", - "integrity": "sha512-7lbcU98ozN+/XvMViXc1cZe72PB3Lz/Fcw5Lv4xcRbDfZDqdT4LqNzDfApb0TrrPWDf1moT2jtR5Lq0pSm1byQ==", + "version": "1.1.0-beta.3", + "resolved": "https://registry.npmjs.org/stacks-encoding-native-js/-/stacks-encoding-native-js-1.1.0-beta.3.tgz", + "integrity": "sha512-A9Fh/hAs0CK8XTv/F5fyLAcoH2ONTPuHoQO19qfwgvpgJcbsdVKrrdaf/N5604YWilA1SK80bXFV7va5+aBiFw==", "dependencies": { "@types/node": "^16.11.26", "detect-libc": "^2.0.1" diff --git a/package.json b/package.json index f1d69a9631..5541d46493 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "socket.io": "4.6.1", "source-map-support": "0.5.21", "split2": "3.2.2", - "stacks-encoding-native-js": "1.0.0", + "stacks-encoding-native-js": "1.1.0-beta.3", "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 20ba98bd91..ac4ac4711f 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -26,6 +26,7 @@ import { RosettaParentBlockIdentifier, RosettaTransaction, SmartContractTransactionMetadata, + TenureChangeTransactionMetadata, TokenTransferTransactionMetadata, Transaction, TransactionAnchorModeType, @@ -115,6 +116,19 @@ function getTxAnchorModeString(anchorMode: number): TransactionAnchorModeType { } } +function getTxTenureChangeCauseString(cause: number) { + switch (cause) { + case 0: + return 'block_found'; + case 1: + return 'no_block_found'; + case 2: + return 'null_miner'; + default: + throw new Error(`Unexpected tenure change cause value ${cause}`); + } +} + export function getTxTypeId(typeString: Transaction['tx_type']): DbTxTypeId[] { switch (typeString) { case 'token_transfer': @@ -901,6 +915,48 @@ function parseDbTxTypeMetadata(dbTx: DbTx | DbMempoolTx): TransactionMetadata { }; return metadata; } + case DbTxTypeId.NakamotoCoinbase: { + const metadata: CoinbaseTransactionMetadata = { + tx_type: 'coinbase', + coinbase_payload: { + data: unwrapOptional(dbTx.coinbase_payload, () => 'Unexpected nullish coinbase_payload'), + alt_recipient: dbTx.coinbase_alt_recipient ?? (null as any), + vrf_proof: unwrapOptional(dbTx.coinbase_vrf_proof, () => 'Unexpected nullish vrf_proof'), + }, + }; + return metadata; + } + case DbTxTypeId.TenureChange: { + const metadata: TenureChangeTransactionMetadata = { + tx_type: 'tenure_change', + tenure_change_payload: { + previous_tenure_end: unwrapOptional( + dbTx.tenure_change_previous_tenure_end, + () => 'Unexpected nullish tenure_change_previous_tenure_end' + ), + previous_tenure_blocks: unwrapOptional( + dbTx.tenure_change_previous_tenure_blocks, + () => 'Unexpected nullish tenure_change_previous_tenure_blocks' + ), + cause: getTxTenureChangeCauseString( + unwrapOptional(dbTx.tenure_change_cause, () => 'Unexpected nullish tenure_change_cause') + ), + pubkey_hash: unwrapOptional( + dbTx.tenure_change_pubkey_hash, + () => 'Unexpected nullish tenure_change_pubkey_hash' + ), + signature: unwrapOptional( + dbTx.tenure_change_signature, + () => 'Unexpected nullish tenure_change_signature' + ), + signers: unwrapOptional( + dbTx.tenure_change_signers, + () => 'Unexpected nullish tenure_change_signers' + ), + }, + }; + return metadata; + } default: { throw new Error(`Unexpected DbTxTypeId: ${dbTx.type_id}`); } diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 5ff49a4ba3..f21a6219cd 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -89,6 +89,8 @@ export enum DbTxTypeId { Coinbase = 0x04, CoinbaseToAltRecipient = 0x05, VersionedSmartContract = 0x06, + TenureChange = 0x07, + NakamotoCoinbase = 0x08, } export enum DbTxStatus { @@ -138,6 +140,14 @@ export interface BaseTx { /** Hex encoded Clarity values. Undefined if function defines no args. */ contract_call_function_args?: string; abi?: string; + + /** Only valid for `tenure-change` tx types. */ + tenure_change_previous_tenure_end?: string; + tenure_change_previous_tenure_blocks?: number; + tenure_change_cause?: number; + tenure_change_pubkey_hash?: string; + tenure_change_signature?: string; + tenure_change_signers?: string; } export interface DbTx extends BaseTx { @@ -185,6 +195,9 @@ export interface DbTx extends BaseTx { /** Only valid for `coinbase-to-alt-recipient` tx types. Either a standard principal or contract principal. */ coinbase_alt_recipient?: string; + /** Only valid for `nakamoto-coinbase` tx types. Hex encoded 80-bytes. */ + coinbase_vrf_proof?: string; + event_count: number; execution_cost_read_count: number; @@ -260,6 +273,9 @@ export interface DbMempoolTx extends BaseTx { /** Only valid for `coinbase-to-alt-recipient` tx types. Either a standard principal or contract principal. */ coinbase_alt_recipient?: string; + + /** Only valid for `nakamoto-coinbase` tx types. Hex encoded 80-bytes. */ + coinbase_vrf_proof?: string; } export interface DbMempoolTxRaw extends DbMempoolTx { @@ -828,6 +844,17 @@ export interface MempoolTxQueryResult { /** Only valid for `coinbase-to-alt-recipient` tx types. Either a standard principal or contract principal. */ coinbase_alt_recipient?: string; + /** Only valid for `nakamoto-coinbase` tx types. Hex encoded 80-bytes. */ + coinbase_vrf_proof?: string; + + // `tenure-change` tx types + tenure_change_previous_tenure_end?: string; + tenure_change_previous_tenure_blocks?: number; + tenure_change_cause?: number; + tenure_change_pubkey_hash: string; + tenure_change_signature?: string; + tenure_change_signers?: string; + // sending abi in case tx is contract call abi: unknown | null; } @@ -888,6 +915,17 @@ export interface TxQueryResult { // `coinbase-to-alt-recipient` tx types coinbase_alt_recipient?: string; + // `nakamoto-coinbase` tx types. Hex encoded 80-bytes. + coinbase_vrf_proof?: string; + + // `tenure-change` tx types + tenure_change_previous_tenure_end?: string; + tenure_change_previous_tenure_blocks?: number; + tenure_change_cause?: number; + tenure_change_pubkey_hash: string; + tenure_change_signature?: string; + tenure_change_signers?: string; + // events count event_count: number; @@ -1010,6 +1048,13 @@ export interface TxInsertValues { poison_microblock_header_2: PgBytea | null; coinbase_payload: PgBytea | null; coinbase_alt_recipient: string | null; + coinbase_vrf_proof: string | null; + tenure_change_previous_tenure_end: string | null; + tenure_change_previous_tenure_blocks: number | null; + tenure_change_cause: number | null; + tenure_change_pubkey_hash: string | null; + tenure_change_signature: string | null; + tenure_change_signers: string | null; raw_result: PgBytea; event_count: number; execution_cost_read_count: number; @@ -1049,6 +1094,13 @@ export interface MempoolTxInsertValues { poison_microblock_header_2: PgBytea | null; coinbase_payload: PgBytea | null; coinbase_alt_recipient: string | null; + coinbase_vrf_proof: string | null; + tenure_change_previous_tenure_end: string | null; + tenure_change_previous_tenure_blocks: number | null; + tenure_change_cause: number | null; + tenure_change_pubkey_hash: string | null; + tenure_change_signature: string | null; + tenure_change_signers: string | null; } export interface BlockInsertValues { diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index 7eafa68fc7..ccf0889964 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -102,6 +102,13 @@ export const TX_COLUMNS = [ 'poison_microblock_header_2', 'coinbase_payload', 'coinbase_alt_recipient', + 'coinbase_vrf_proof', + 'tenure_change_previous_tenure_end', + 'tenure_change_previous_tenure_blocks', + 'tenure_change_cause', + 'tenure_change_pubkey_hash', + 'tenure_change_signature', + 'tenure_change_signers', 'raw_result', 'event_count', 'execution_cost_read_count', @@ -140,6 +147,13 @@ export const MEMPOOL_TX_COLUMNS = [ 'poison_microblock_header_2', 'coinbase_payload', 'coinbase_alt_recipient', + 'coinbase_vrf_proof', + 'tenure_change_previous_tenure_end', + 'tenure_change_previous_tenure_blocks', + 'tenure_change_cause', + 'tenure_change_pubkey_hash', + 'tenure_change_signature', + 'tenure_change_signers', ]; export const BLOCK_COLUMNS = [ @@ -370,6 +384,19 @@ function parseTxTypeSpecificQueryResult( } else if (target.type_id === DbTxTypeId.CoinbaseToAltRecipient) { target.coinbase_payload = result.coinbase_payload; target.coinbase_alt_recipient = result.coinbase_alt_recipient; + } else if (target.type_id === DbTxTypeId.NakamotoCoinbase) { + target.coinbase_payload = result.coinbase_payload; + if (result.coinbase_alt_recipient) { + target.coinbase_alt_recipient = result.coinbase_alt_recipient; + } + target.coinbase_vrf_proof = result.coinbase_vrf_proof; + } else if (target.type_id === DbTxTypeId.TenureChange) { + target.tenure_change_previous_tenure_end = result.tenure_change_previous_tenure_end; + target.tenure_change_previous_tenure_blocks = result.tenure_change_previous_tenure_blocks; + target.tenure_change_cause = result.tenure_change_cause; + target.tenure_change_pubkey_hash = result.tenure_change_pubkey_hash; + target.tenure_change_signature = result.tenure_change_signature; + target.tenure_change_signers = result.tenure_change_signers; } else { throw new Error(`Received unexpected tx type_id from db query: ${target.type_id}`); } @@ -994,6 +1021,25 @@ function extractTransactionPayload(txData: DecodedTxResult, dbTx: DbTx | DbMempo } break; } + case TxPayloadTypeID.NakamotoCoinbase: { + dbTx.coinbase_payload = txData.payload.payload_buffer; + if (txData.payload.recipient?.type_id === PrincipalTypeID.Standard) { + dbTx.coinbase_alt_recipient = txData.payload.recipient.address; + } else if (txData.payload.recipient?.type_id === PrincipalTypeID.Contract) { + dbTx.coinbase_alt_recipient = `${txData.payload.recipient.address}.${txData.payload.recipient.contract_name}`; + } + dbTx.coinbase_vrf_proof = txData.payload.vrf_proof; + break; + } + case TxPayloadTypeID.TenureChange: { + dbTx.tenure_change_previous_tenure_end = txData.payload.previous_tenure_end; + dbTx.tenure_change_previous_tenure_blocks = txData.payload.previous_tenure_blocks; + dbTx.tenure_change_cause = txData.payload.cause; + dbTx.tenure_change_pubkey_hash = txData.payload.pubkey_hash; + dbTx.tenure_change_signature = txData.payload.signature; + dbTx.tenure_change_signers = txData.payload.signers; + break; + } default: throw new Error(`Unexpected transaction type ID: ${JSON.stringify(txData.payload)}`); } diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 891e41d9aa..6afd6d7f99 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -1699,6 +1699,13 @@ export class PgWriteStore extends PgStore { poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, coinbase_payload: tx.coinbase_payload ?? null, coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, + coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, + tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, + tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, + tenure_change_cause: tx.tenure_change_cause ?? null, + tenure_change_pubkey_hash: tx.tenure_change_pubkey_hash ?? null, + tenure_change_signature: tx.tenure_change_signature ?? null, + tenure_change_signers: tx.tenure_change_signers ?? null, raw_result: tx.raw_result, event_count: tx.event_count, execution_cost_read_count: tx.execution_cost_read_count, @@ -1749,6 +1756,13 @@ export class PgWriteStore extends PgStore { poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, coinbase_payload: tx.coinbase_payload ?? null, coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, + coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, + tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, + tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, + tenure_change_cause: tx.tenure_change_cause ?? null, + tenure_change_pubkey_hash: tx.tenure_change_pubkey_hash ?? null, + tenure_change_signature: tx.tenure_change_signature ?? null, + tenure_change_signers: tx.tenure_change_signers ?? null, }; const result = await sql` INSERT INTO mempool_txs ${sql(values)} @@ -3062,6 +3076,13 @@ export class PgWriteStore extends PgStore { poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, coinbase_payload: tx.coinbase_payload ?? null, coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, + coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, + tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, + tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, + tenure_change_cause: tx.tenure_change_cause ?? null, + tenure_change_pubkey_hash: tx.tenure_change_pubkey_hash ?? null, + tenure_change_signature: tx.tenure_change_signature ?? null, + tenure_change_signers: tx.tenure_change_signers ?? null, raw_result: tx.raw_result, event_count: tx.event_count, execution_cost_read_count: tx.execution_cost_read_count, diff --git a/src/event-stream/reader.ts b/src/event-stream/reader.ts index 58107ffe17..40b7f1eeea 100644 --- a/src/event-stream/reader.ts +++ b/src/event-stream/reader.ts @@ -773,6 +773,20 @@ export function parseMessageTransaction( } break; } + case TxPayloadTypeID.NakamotoCoinbase: { + if (payload.recipient?.type_id === PrincipalTypeID.Standard) { + logger.debug( + `NakamotoCoinbase to alt recipient, standard principal: ${payload.recipient.address}, vrf=${payload.vrf_proof}` + ); + } else if (payload.recipient?.type_id === PrincipalTypeID.Contract) { + logger.debug( + `NakamotoCoinbase to alt recipient, contract principal: ${payload.recipient.address}.${payload.recipient.contract_name}, vrf=${payload.vrf_proof}` + ); + } else { + logger.debug(`NakamotoCoinbase (no alt recipient), vrf=${payload.vrf_proof}`); + } + break; + } case TxPayloadTypeID.SmartContract: { logger.debug( `Smart contract deployed: ${parsedTx.sender_address}.${payload.contract_name}` @@ -807,6 +821,12 @@ export function parseMessageTransaction( ); break; } + case TxPayloadTypeID.TenureChange: { + logger.debug( + `Tenure change: cause=${payload.cause}, prev_tenure_blocks=${payload.previous_tenure_blocks}, prev_tenure_block=${payload.previous_tenure_end}, signers=${payload.signers},` + ); + break; + } default: { throw new NotImplementedError( `extracting data for tx type: ${getEnumDescription( diff --git a/src/rosetta/rosetta-helpers.ts b/src/rosetta/rosetta-helpers.ts index ebeb48f9b3..5427109c1f 100644 --- a/src/rosetta/rosetta-helpers.ts +++ b/src/rosetta/rosetta-helpers.ts @@ -1122,6 +1122,12 @@ export function rawTxToBaseTx(raw_tx: string): BaseTx { case TxPayloadTypeID.PoisonMicroblock: transactionType = DbTxTypeId.PoisonMicroblock; break; + case TxPayloadTypeID.TenureChange: + transactionType = DbTxTypeId.TenureChange; + break; + case TxPayloadTypeID.NakamotoCoinbase: + transactionType = DbTxTypeId.NakamotoCoinbase; + break; } const dbTx: BaseTx = { token_transfer_recipient_address: recipientAddr, diff --git a/src/test-utils/test-builders.ts b/src/test-utils/test-builders.ts index b7f165a393..261b37c8f4 100644 --- a/src/test-utils/test-builders.ts +++ b/src/test-utils/test-builders.ts @@ -159,6 +159,7 @@ export interface TestTxArgs { canonical?: boolean; microblock_canonical?: boolean; coinbase_alt_recipient?: string; + coinbase_vrf_proof?: string; contract_call_contract_id?: string; contract_call_function_name?: string; contract_call_function_args?: string; @@ -213,6 +214,7 @@ function testTx(args?: TestTxArgs): DataStoreTxEventData { origin_hash_mode: 1, coinbase_payload: bufferToHex(Buffer.from('hi')), coinbase_alt_recipient: args?.coinbase_alt_recipient, + coinbase_vrf_proof: args?.coinbase_vrf_proof, event_count: 0, parent_index_block_hash: args?.parent_index_block_hash ?? INDEX_BLOCK_HASH, parent_block_hash: BLOCK_HASH, diff --git a/src/tests/socket-io-tests.ts b/src/tests/socket-io-tests.ts index c72cebdd21..0de1ca978e 100644 --- a/src/tests/socket-io-tests.ts +++ b/src/tests/socket-io-tests.ts @@ -546,6 +546,6 @@ describe('socket-io', () => { }); await disconnectWaiter; - expect(disconnectReason).toBe('ping timeout'); + expect(['ping timeout', 'transport close']).toContain(disconnectReason); }); }); From 4cb6b5641fc7ea295fac029eee0d571226d21248 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 8 Dec 2023 15:18:12 +0100 Subject: [PATCH 27/91] fix: disable stx faucet POST body (#1759) * test: stx faucet endpoint using post body (rather than url query params) * fix: disable stx faucet post body support * docs: remove stx faucet post body from openAPI schema --- docs/openapi.yaml | 15 --------------- src/api/routes/faucets.ts | 16 +++++++++++++--- src/tests-2.4/faucet-stx.ts | 12 ++++++++++++ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 60933f83ac..ecc7f74b8c 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -105,21 +105,6 @@ paths: tags: - Faucets operationId: run_faucet_stx - requestBody: - content: - application/json: - schema: - type: object - properties: - address: - description: STX testnet address - type: string - stacking: - description: Use required number of tokens for stacking - type: boolean - example: - address: ST3M7N9Q9HDRM7RVP1Q26P0EE69358PZZAZD7KMXQ - stacking: false responses: 200: description: Success diff --git a/src/api/routes/faucets.ts b/src/api/routes/faucets.ts index c3656c670f..1e6966abcc 100644 --- a/src/api/routes/faucets.ts +++ b/src/api/routes/faucets.ts @@ -151,15 +151,25 @@ export function createFaucetRouter(db: PgWriteStore): express.Router { router.post( '/stx', asyncHandler(async (req, res) => { + if (!req.query.address && req.body.address) { + // return error for no longer supported post body requests + const url = new URL(`${req.protocol}://${req.get('host')}${req.originalUrl}`); + url.search = new URLSearchParams(req.body).toString(); + res.status(400).json({ + error: `POST body is no longer supported, parameters must be passed as query parameters, e.g. ${url}`, + help: `Example curl request: curl -X POST '${url}'`, + success: false, + }); + return; + } await stxFaucetRequestQueue.add(async () => { - const address: string = req.query.address || req.body.address; + const address: string = req.query.address as string; const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; const lastRequests = await db.getSTXFaucetRequests(address); const privateKey = process.env.FAUCET_PRIVATE_KEY || testnetKeys[0].secretKey; - const isStackingReq = - req.query['stacking'] === 'true' || [true, 'true'].includes(req.body['stacking']); + const isStackingReq = req.query['stacking'] === 'true'; // Guard condition: requests are limited to x times per y minutes. // Only based on address for now, but we're keeping the IP in case diff --git a/src/tests-2.4/faucet-stx.ts b/src/tests-2.4/faucet-stx.ts index b15f6dbfc4..017f420a08 100644 --- a/src/tests-2.4/faucet-stx.ts +++ b/src/tests-2.4/faucet-stx.ts @@ -30,6 +30,18 @@ describe('STX Faucet', () => { expect(reqTx.success).toBe(true); }); + test('STX faucet http request post body', async () => { + const response = await supertest(testEnv.api.server) + .post(`/extended/v1/faucets/stx`) + .send({ address: reqAccount.stxAddr, stacking: true }); + expect(response.status).toBe(400); + const reqTx: any = response.body; + expect(reqTx.success).toBe(false); + expect(reqTx.error).toContain('POST body is no longer supported'); + // check for helpful error message + expect(reqTx.error).toContain(`address=${reqAccount.stxAddr}`); + }); + test('STX faucet tx mined successfully', async () => { const tx = await standByForTxSuccess(reqTx.txId!); expect(tx.token_transfer_recipient_address).toBe(reqAccount.stxAddr); From b3964c0dbf58894b89f1d263c2f3005f4f27767c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 8 Dec 2023 14:31:55 +0000 Subject: [PATCH 28/91] chore(release): 7.3.5 [skip ci] ## [7.3.5](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.4...v7.3.5) (2023-12-08) ### Bug Fixes * disable stx faucet POST body ([#1759](https://github.com/hirosystems/stacks-blockchain-api/issues/1759)) ([4cb6b56](https://github.com/hirosystems/stacks-blockchain-api/commit/4cb6b5641fc7ea295fac029eee0d571226d21248)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb70a4485a..6587656b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.3.5](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.4...v7.3.5) (2023-12-08) + + +### Bug Fixes + +* disable stx faucet POST body ([#1759](https://github.com/hirosystems/stacks-blockchain-api/issues/1759)) ([4cb6b56](https://github.com/hirosystems/stacks-blockchain-api/commit/4cb6b5641fc7ea295fac029eee0d571226d21248)) + ## [7.3.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.3...v7.3.4) (2023-11-14) From 773c01b21a7d4e830d7ed4e58716539c563fecdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Mon, 11 Dec 2023 10:33:07 -0600 Subject: [PATCH 29/91] fix: use the mempool etag for the /nonces endpoint (#1765) --- src/api/routes/address.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/routes/address.ts b/src/api/routes/address.ts index 66d0828dd7..78be21043e 100644 --- a/src/api/routes/address.ts +++ b/src/api/routes/address.ts @@ -570,7 +570,7 @@ export function createAddressRouter(db: PgStore, chainId: ChainID): express.Rout router.get( '/:stx_address/nonces', - cacheHandler, + mempoolCacheHandler, asyncHandler(async (req, res) => { // get recent asset event associated with address const stxAddress = req.params['stx_address']; From dffce2bb5031b481502d7e66c9a0d6ca01c5ec72 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 11 Dec 2023 16:39:43 +0000 Subject: [PATCH 30/91] chore(release): 7.3.6 [skip ci] ## [7.3.6](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.5...v7.3.6) (2023-12-11) ### Bug Fixes * use the mempool etag for the /nonces endpoint ([#1765](https://github.com/hirosystems/stacks-blockchain-api/issues/1765)) ([773c01b](https://github.com/hirosystems/stacks-blockchain-api/commit/773c01b21a7d4e830d7ed4e58716539c563fecdc)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6587656b70..0f85a5c17c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.3.6](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.5...v7.3.6) (2023-12-11) + + +### Bug Fixes + +* use the mempool etag for the /nonces endpoint ([#1765](https://github.com/hirosystems/stacks-blockchain-api/issues/1765)) ([773c01b](https://github.com/hirosystems/stacks-blockchain-api/commit/773c01b21a7d4e830d7ed4e58716539c563fecdc)) + ## [7.3.5](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.4...v7.3.5) (2023-12-08) From cb38b6811c65aa700d4de527329216ba3c2ff6c9 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Tue, 12 Dec 2023 17:12:28 +0100 Subject: [PATCH 31/91] feat: `GET /extended/v1/burn_block` (#1766) * feat: new endpoint to get burn blocks `/extended/v1/burn_block` * feat: return stacks block hashes in burn block results * test: add tests for `/extended/v1/burn_block` * ci: fix openapi lint --- docs/api/blocks/get-burn-blocks.example.json | 19 +++ docs/api/blocks/get-burn-blocks.schema.json | 29 +++++ docs/entities/blocks/burn-block.example.json | 12 ++ docs/entities/blocks/burn-block.schema.json | 38 ++++++ docs/generated.d.ts | 45 +++++++ docs/openapi.yaml | 48 +++++++ src/api/controllers/db-controller.ts | 30 +++++ src/api/init.ts | 2 + src/api/pagination.ts | 5 + src/api/query-helpers.ts | 47 +++++++ src/api/routes/burn-block.ts | 42 +++++++ src/datastore/common.ts | 8 ++ src/datastore/pg-store.ts | 51 ++++++++ src/tests/block-tests.ts | 125 ++++++++++++++++++- 14 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 docs/api/blocks/get-burn-blocks.example.json create mode 100644 docs/api/blocks/get-burn-blocks.schema.json create mode 100644 docs/entities/blocks/burn-block.example.json create mode 100644 docs/entities/blocks/burn-block.schema.json create mode 100644 src/api/routes/burn-block.ts diff --git a/docs/api/blocks/get-burn-blocks.example.json b/docs/api/blocks/get-burn-blocks.example.json new file mode 100644 index 0000000000..999d60268c --- /dev/null +++ b/docs/api/blocks/get-burn-blocks.example.json @@ -0,0 +1,19 @@ +{ + "limit": 1, + "offset": 0, + "total": 21707, + "results": [ + { + "burn_block_time": 1626281749, + "burn_block_time_iso": "2021-07-14T16:55:49.000Z", + "burn_block_hash": "0x0000000000000000000ea16f8e906e85ee1cb4dff1e5424e93843b3cec8b0bcb", + "burn_block_height": 691014, + "stacks_blocks": [ + "0x54647c277eefe60519b407f2c897749005fdb7f831034135063b2ee43fdacb04", + "0xdaf61d2b355f35c94cf019af99aeb73d8e7db7301c7cd693a464ebd1cfc2228c", + "0xb9e9b308cf9621ecbf66ca7b4689fe384b9b67c4588ec827d8163ab602fb935e", + "0x754562cba6ec243f90485e97778ab472f462fd123ef5b83cc79d8759ca8875f5" + ] + } + ] +} diff --git a/docs/api/blocks/get-burn-blocks.schema.json b/docs/api/blocks/get-burn-blocks.schema.json new file mode 100644 index 0000000000..a1802db9ef --- /dev/null +++ b/docs/api/blocks/get-burn-blocks.schema.json @@ -0,0 +1,29 @@ +{ + "description": "GET request that returns burn blocks", + "additionalProperties": false, + "title": "BurnBlockListResponse", + "type": "object", + "required": ["results", "limit", "offset", "total"], + "properties": { + "limit": { + "type": "integer", + "maximum": 30, + "description": "The number of burn blocks to return" + }, + "offset": { + "type": "integer", + "description": "The number to burn blocks to skip (starting at `0`)", + "default": 0 + }, + "total": { + "type": "integer", + "description": "The number of burn blocks available (regardless of filter parameters)" + }, + "results": { + "type": "array", + "items": { + "$ref": "../../entities/blocks/burn-block.schema.json" + } + } + } +} diff --git a/docs/entities/blocks/burn-block.example.json b/docs/entities/blocks/burn-block.example.json new file mode 100644 index 0000000000..12a77d9dc1 --- /dev/null +++ b/docs/entities/blocks/burn-block.example.json @@ -0,0 +1,12 @@ +{ + "burn_block_time": 1594233639, + "burn_block_time_iso": "2020-08-27T16:41:26.000Z", + "burn_block_hash": "0xb154c008df2101023a6d0d54986b3964cee58119eed14f5bed98e15678e18fe2", + "burn_block_height": 654439, + "stacks_blocks": [ + "0x54647c277eefe60519b407f2c897749005fdb7f831034135063b2ee43fdacb04", + "0xdaf61d2b355f35c94cf019af99aeb73d8e7db7301c7cd693a464ebd1cfc2228c", + "0xb9e9b308cf9621ecbf66ca7b4689fe384b9b67c4588ec827d8163ab602fb935e", + "0x754562cba6ec243f90485e97778ab472f462fd123ef5b83cc79d8759ca8875f5" + ] +} diff --git a/docs/entities/blocks/burn-block.schema.json b/docs/entities/blocks/burn-block.schema.json new file mode 100644 index 0000000000..3138ab95d9 --- /dev/null +++ b/docs/entities/blocks/burn-block.schema.json @@ -0,0 +1,38 @@ +{ + "title": "BurnBlock", + "description": "A burn block", + "type": "object", + "additionalProperties": false, + "required": [ + "burn_block_time", + "burn_block_time_iso", + "burn_block_hash", + "burn_block_height", + "stacks_blocks" + ], + "properties": { + "burn_block_time": { + "type": "number", + "description": "Unix timestamp (in seconds) indicating when this block was mined." + }, + "burn_block_time_iso": { + "type": "string", + "description": "An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined." + }, + "burn_block_hash": { + "type": "string", + "description": "Hash of the anchor chain block" + }, + "burn_block_height": { + "type": "integer", + "description": "Height of the anchor chain block" + }, + "stacks_blocks": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Hashes of the Stacks blocks included in the burn block" + } + } +} diff --git a/docs/generated.d.ts b/docs/generated.d.ts index d1c42c1e17..18c1a28aee 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -13,6 +13,7 @@ export type SchemaMergeRootStub = | AddressTransactionsWithTransfersListResponse | AddressTransactionsListResponse | BlockListResponse + | BurnBlockListResponse | BnsError | BnsFetchFileZoneResponse | BnsGetAllNamesResponse @@ -114,6 +115,7 @@ export type SchemaMergeRootStub = | NftBalance | StxBalance | Block + | BurnBlock | BurnchainRewardSlotHolder | BurnchainReward | BurnchainRewardsTotal @@ -1274,6 +1276,49 @@ export interface Block { [k: string]: number | undefined; }; } +/** + * GET request that returns burn blocks + */ +export interface BurnBlockListResponse { + /** + * The number of burn blocks to return + */ + limit: number; + /** + * The number to burn blocks to skip (starting at `0`) + */ + offset: number; + /** + * The number of burn blocks available (regardless of filter parameters) + */ + total: number; + results: BurnBlock[]; +} +/** + * A burn block + */ +export interface BurnBlock { + /** + * Unix timestamp (in seconds) indicating when this block was mined. + */ + burn_block_time: number; + /** + * An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined. + */ + burn_block_time_iso: string; + /** + * Hash of the anchor chain block + */ + burn_block_hash: string; + /** + * Height of the anchor chain block + */ + burn_block_height: number; + /** + * Hashes of the Stacks blocks included in the burn block + */ + stacks_blocks: string[]; +} /** * Error */ diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 16db1e359b..d18f59f1ee 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -612,6 +612,54 @@ paths: schema: $ref: ./api/microblocks/get-unanchored-txs.schema.json + /extended/v1/burn_block: + get: + summary: Get recent burn blocks + description: | + Retrieves a list of recent burn blocks + tags: + - Blocks + operationId: get_burn_block_list + parameters: + - name: limit + in: query + description: max number of burn blocks to fetch + required: false + schema: + type: integer + default: 20 + maximum: 30 + - name: offset + in: query + description: index of first burn block to fetch + required: false + schema: + type: integer + example: 42000 + - name: height + in: query + description: filter by burn block height + required: false + schema: + type: integer + example: 42000 + - name: hash + in: query + description: filter by burn block hash or the constant 'latest' to filter for the most recent burn block + required: false + schema: + type: string + example: "0x4839a8b01cfb39ffcc0d07d3db31e848d5adf5279d529ed5062300b9f353ff79" + responses: + 200: + description: List of burn blocks + content: + application/json: + schema: + $ref: ./api/blocks/get-burn-blocks.schema.json + example: + $ref: ./api/blocks/get-burn-blocks.example.json + /extended/v1/block: get: summary: Get recent blocks diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index ac4ac4711f..03cd994bdb 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -16,6 +16,7 @@ import { AbstractTransaction, BaseTransaction, Block, + BurnBlock, CoinbaseTransactionMetadata, ContractCallTransactionMetadata, MempoolTransaction, @@ -530,6 +531,35 @@ export async function getMicroblockFromDataStore({ }; } +export async function getBurnBlocksFromDataStore(args: { + db: PgStore; + limit: number; + offset: number; + height: number | null; + hash: 'latest' | string | null; +}): Promise<{ total: number; results: BurnBlock[] }> { + const query = await args.db.getBurnBlocks({ + limit: args.limit, + offset: args.offset, + height: args.height, + hash: args.hash, + }); + const results = query.results.map(r => { + const burnBlock: BurnBlock = { + burn_block_time: r.burn_block_time, + burn_block_time_iso: unixEpochToIso(r.burn_block_time), + burn_block_hash: r.burn_block_hash, + burn_block_height: r.burn_block_height, + stacks_blocks: r.stacks_blocks, + }; + return burnBlock; + }); + return { + total: query.total, + results, + }; +} + export async function getMicroblocksFromDataStore(args: { db: PgStore; limit: number; diff --git a/src/api/init.ts b/src/api/init.ts index d2494e1334..42fccd17e9 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -45,6 +45,7 @@ import { createPox3EventsRouter } from './routes/pox3'; import { createStackingRouter } from './routes/stacking'; import { logger, loggerMiddleware } from '../logger'; import { SERVER_VERSION, isPgConnectionError, isProdEnv, waiter } from '@hirosystems/api-toolkit'; +import { createBurnBlockRouter } from './routes/burn-block'; export interface ApiServer { expressApp: express.Express; @@ -184,6 +185,7 @@ export async function startApiServer(opts: { router.use('/tx', createTxRouter(datastore)); router.use('/block', createBlockRouter(datastore)); router.use('/microblock', createMicroblockRouter(datastore)); + router.use('/burn_block', createBurnBlockRouter(datastore)); router.use('/burnchain', createBurnchainRouter(datastore)); router.use('/contract', createContractRouter(datastore)); // same here, exclude account nonce route diff --git a/src/api/pagination.ts b/src/api/pagination.ts index 094e9dbb3c..46e6de21af 100644 --- a/src/api/pagination.ts +++ b/src/api/pagination.ts @@ -35,6 +35,7 @@ export enum ResourceType { Token, Pox2Event, Stacker, + BurnBlock, } const pagingQueryLimits: Record = { @@ -42,6 +43,10 @@ const pagingQueryLimits: Record( + queryParamName: string, + paramRequired: TRequired, + req: Request, + res: Response, + next: NextFunction +): TRequired extends true ? string | never : string | null { + if (!(queryParamName in req.query)) { + if (paramRequired) { + handleBadRequest( + res, + next, + `Request is missing required "${queryParamName}" query parameter` + ); + } else { + return null as TRequired extends true ? string : string | null; + } + } + const hashParamVal = req.query[queryParamName]; + if (typeof hashParamVal !== 'string') { + handleBadRequest( + res, + next, + `Unexpected type for block hash query parameter: ${JSON.stringify(hashParamVal)}` + ); + } + + // Extract the hash part, ignoring '0x' if present + const match = hashParamVal.match(/^(0x)?([a-fA-F0-9]{64})$/i); + if (!match) { + handleBadRequest( + res, + next, + "Invalid hash string. Ensure it is 64 hexadecimal characters long, with an optional '0x' prefix" + ); + } + + // Normalize the string + return '0x' + match[2].toLowerCase(); +} + /** * Parses a block height value from a given request query param. * If an error is encountered while parsing the param then a 400 response with an error message is sent and the function throws. diff --git a/src/api/routes/burn-block.ts b/src/api/routes/burn-block.ts new file mode 100644 index 0000000000..d8939f83a3 --- /dev/null +++ b/src/api/routes/burn-block.ts @@ -0,0 +1,42 @@ +import * as express from 'express'; +import { BurnBlockListResponse } from '@stacks/stacks-blockchain-api-types'; +import { getBurnBlocksFromDataStore } from '../controllers/db-controller'; +import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; +import { getBlockHashQueryParam, getBlockHeightQueryParam } from '../query-helpers'; +import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; +import { asyncHandler } from '../async-handler'; +import { PgStore } from '../../datastore/pg-store'; + +export function createBurnBlockRouter(db: PgStore): express.Router { + const router = express.Router(); + const cacheHandler = getETagCacheHandler(db); + router.get( + '/', + cacheHandler, + asyncHandler(async (req, res, next) => { + const limit = getPagingQueryLimit(ResourceType.BurnBlock, req.query.limit); + const offset = parsePagingQueryInput(req.query.offset ?? 0); + const height = + getBlockHeightQueryParam('height', false, req, res, next) ?? + getBlockHeightQueryParam('block_height', false, req, res, next); + + let hash = req.query.hash === 'latest' ? 'latest' : null; + if (!hash) { + hash = getBlockHashQueryParam('hash', false, req, res, next); + } + + const { results, total } = await getBurnBlocksFromDataStore({ + offset, + limit, + db, + height, + hash, + }); + setETagCacheHeaders(res); + const response: BurnBlockListResponse = { limit, offset, total, results }; + res.json(response); + }) + ); + + return router; +} diff --git a/src/datastore/common.ts b/src/datastore/common.ts index f21a6219cd..c9cedd03e0 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -46,6 +46,14 @@ export interface DbMicroblock extends DbMicroblockPartial { block_hash: string; } +export interface DbBurnBlock { + block_hash: string; + burn_block_time: number; + burn_block_hash: string; + burn_block_height: number; + stacks_blocks: string[]; +} + export interface DbBurnchainReward { canonical: boolean; burn_block_hash: string; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index f5f888c640..809e5c945f 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -29,6 +29,7 @@ import { DbBnsNamespace, DbBnsSubdomain, DbBnsZoneFile, + DbBurnBlock, DbBurnchainReward, DbChainTip, DbEvent, @@ -386,6 +387,56 @@ export class PgStore extends BasePgStore { return { found: true, result: block } as const; } + async getBurnBlocks({ + limit, + offset, + height, + hash, + }: { + limit: number; + offset: number; + height: number | null; + hash: 'latest' | string | null; + }): Promise<{ results: DbBurnBlock[]; total: number }> { + return await this.sqlTransaction(async sql => { + const countQuery = await sql<{ burn_block_height: number; count: number }[]>` + SELECT burn_block_height, block_count AS count FROM chain_tip + `; + const heightFilter = height ? sql`AND burn_block_height = ${height}` : sql``; + const hashFilter = + hash === 'latest' + ? sql`AND burn_block_height = ${countQuery[0].burn_block_height}` + : hash + ? sql`AND burn_block_hash = ${hash}` + : sql``; + + const block_count = countQuery[0].count; + const blocksQuery = await sql` + SELECT DISTINCT ON (burn_block_height) + burn_block_time, + burn_block_hash, + burn_block_height, + ARRAY_AGG(block_hash) OVER ( + PARTITION BY burn_block_height + ORDER BY block_height DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS stacks_blocks + FROM blocks + WHERE canonical = true + ${heightFilter} + ${hashFilter} + ORDER BY burn_block_height DESC, block_height DESC + LIMIT ${limit} + OFFSET ${offset} + `; + const blocks = blocksQuery.map(r => r); + return { + results: blocks, + total: block_count, + }; + }); + } + /** * Returns Block information with metadata, including accepted and streamed microblocks hash * @returns `BlocksWithMetadata` object including list of Blocks with metadata and total count. diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index 980093e012..9241b26e78 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -9,7 +9,7 @@ import { DataStoreBlockUpdateData, } from '../datastore/common'; import { startApiServer, ApiServer } from '../api/init'; -import { I32_MAX } from '../helpers'; +import { I32_MAX, unixEpochToIso } from '../helpers'; import { TestBlockBuilder, TestMicroblockStreamBuilder } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; import { PgSqlClient, bufferToHex } from '@hirosystems/api-toolkit'; @@ -276,6 +276,129 @@ describe('block tests', () => { expect(result.body).toEqual(expectedResp); }); + test('/burn_block', async () => { + const burnBlock1 = { + burn_block_hash: '0x5678111111111111111111111111111111111111111111111111111111111111', + burn_block_height: 5, + burn_block_time: 1702386592, + }; + const burnBlock2 = { + burn_block_hash: '0x5678211111111111111111111111111111111111111111111111111111111111', + burn_block_height: 7, + burn_block_time: 1702386678, + }; + + const stacksBlock1 = { + block_height: 1, + block_hash: '0x1234111111111111111111111111111111111111111111111111111111111111', + index_block_hash: '0xabcd111111111111111111111111111111111111111111111111111111111111', + parent_index_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000000', + burn_block_hash: burnBlock1.burn_block_hash, + burn_block_height: burnBlock1.burn_block_height, + burn_block_time: burnBlock1.burn_block_time, + }; + const stacksBlock2 = { + block_height: 2, + block_hash: '0x1234211111111111111111111111111111111111111111111111111111111111', + index_block_hash: '0xabcd211111111111111111111111111111111111111111111111111111111111', + parent_index_block_hash: stacksBlock1.index_block_hash, + burn_block_hash: burnBlock2.burn_block_hash, + burn_block_height: burnBlock2.burn_block_height, + burn_block_time: burnBlock2.burn_block_time, + }; + const stacksBlock3 = { + block_height: 3, + block_hash: '0x1234311111111111111111111111111111111111111111111111111111111111', + index_block_hash: '0xabcd311111111111111111111111111111111111111111111111111111111111', + parent_index_block_hash: stacksBlock2.index_block_hash, + burn_block_hash: burnBlock2.burn_block_hash, + burn_block_height: burnBlock2.burn_block_height, + burn_block_time: burnBlock2.burn_block_time, + }; + const stacksBlock4 = { + block_height: 4, + block_hash: '0x1234411111111111111111111111111111111111111111111111111111111111', + index_block_hash: '0xabcd411111111111111111111111111111111111111111111111111111111111', + parent_index_block_hash: stacksBlock3.index_block_hash, + burn_block_hash: burnBlock2.burn_block_hash, + burn_block_height: burnBlock2.burn_block_height, + burn_block_time: burnBlock2.burn_block_time, + }; + + const stacksBlocks = [stacksBlock1, stacksBlock2, stacksBlock3, stacksBlock4]; + + for (const block of stacksBlocks) { + const dbBlock = new TestBlockBuilder({ + block_hash: block.block_hash, + index_block_hash: block.index_block_hash, + parent_index_block_hash: block.parent_index_block_hash, + block_height: block.block_height, + burn_block_hash: block.burn_block_hash, + burn_block_height: block.burn_block_height, + burn_block_time: block.burn_block_time, + }).build(); + await db.update(dbBlock); + } + + const result = await supertest(api.server).get(`/extended/v1/burn_block/`); + expect(result.body.results).toEqual([ + { + burn_block_hash: burnBlock2.burn_block_hash, + burn_block_height: burnBlock2.burn_block_height, + burn_block_time: burnBlock2.burn_block_time, + burn_block_time_iso: unixEpochToIso(burnBlock2.burn_block_time), + stacks_blocks: [stacksBlock4.block_hash, stacksBlock3.block_hash, stacksBlock2.block_hash], + }, + { + burn_block_hash: burnBlock1.burn_block_hash, + burn_block_height: burnBlock1.burn_block_height, + burn_block_time: burnBlock1.burn_block_time, + burn_block_time_iso: unixEpochToIso(burnBlock1.burn_block_time), + stacks_blocks: [stacksBlock1.block_hash], + }, + ]); + + // test 'latest' filter + const result2 = await supertest(api.server).get(`/extended/v1/burn_block?hash=latest`); + expect(result2.body.results).toEqual([ + { + burn_block_hash: stacksBlocks.at(-1)?.burn_block_hash, + burn_block_height: stacksBlocks.at(-1)?.burn_block_height, + burn_block_time: stacksBlocks.at(-1)?.burn_block_time, + burn_block_time_iso: unixEpochToIso(stacksBlocks.at(-1)?.burn_block_time ?? 0), + stacks_blocks: [stacksBlock4.block_hash, stacksBlock3.block_hash, stacksBlock2.block_hash], + }, + ]); + + // test hash filter + const result3 = await supertest(api.server).get( + `/extended/v1/burn_block?hash=${stacksBlock1.burn_block_hash}` + ); + expect(result3.body.results).toEqual([ + { + burn_block_hash: stacksBlock1.burn_block_hash, + burn_block_height: stacksBlock1.burn_block_height, + burn_block_time: stacksBlock1.burn_block_time, + burn_block_time_iso: unixEpochToIso(stacksBlock1.burn_block_time), + stacks_blocks: [stacksBlock1.block_hash], + }, + ]); + + // test height filter + const result4 = await supertest(api.server).get( + `/extended/v1/burn_block?height=${stacksBlock1.burn_block_height}` + ); + expect(result4.body.results).toEqual([ + { + burn_block_hash: stacksBlock1.burn_block_hash, + burn_block_height: stacksBlock1.burn_block_height, + burn_block_time: stacksBlock1.burn_block_time, + burn_block_time_iso: unixEpochToIso(stacksBlock1.burn_block_time), + stacks_blocks: [stacksBlock1.block_hash], + }, + ]); + }); + test('block tx list excludes non-canonical', async () => { const block1 = new TestBlockBuilder({ block_hash: '0x0001', index_block_hash: '0x0001' }) .addTx({ tx_id: '0x0001' }) From 285806f46cebd365cc424a7a0155a531f34d7438 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Wed, 13 Dec 2023 12:58:37 +0100 Subject: [PATCH 32/91] feat: pox-4 support (#1754) * feat: handle pox-3 force unlocks * chore: todo note * feat: handle pox-3 force unlocks, pox-4 events, and revoke-delegate-stx event * chore: rename pox-2 file * chore: simplified pox route paths * feat: add migration to create pox4_events table * test: follow redirects in test fetch helper * chore: fix storing different pox version events * test: fix tests with missing pox4_events * chore: move delegations lookup endpoint into pox router * fix: handle pox4_events during reorgs * test: fix pox4events reorg count * chore: update stacks-node image to stacks 3.0 * test: begin transitioning pox tests to use pox-4 * chore: bump stacks-node to wip nakamoto branch * test: switch more tests from pox-3 to pox-4 * fix: tx fee fall back in faucet * test: update delegation check endpoints * chore: isolate error in delegate-revoke test * chore: pox3 to pox4 misc renames * ci: rename 2.4 to 2.5 * test: remove no-longer applicable delegate-stx while stacking test * chore: remove incorrect commend in pox4 test --- .github/workflows/ci.yml | 26 +- .vscode/launch.json | 4 +- .../docker-compose.dev.stacks-blockchain.yml | 2 +- docker/docker-compose.dev.stacks-krypton.yml | 2 +- docs/api/info/get-status.schema.json | 4 + docs/generated.d.ts | 1 + migrations/1701368149776_nakamoto-txs.js | 8 + migrations/1702134678728_pox_4_events.js | 203 +++++++++ package.json | 4 +- src/api/controllers/db-controller.ts | 40 +- src/api/init.ts | 45 +- src/api/query-helpers.ts | 10 + src/api/rosetta-constants.ts | 15 - src/api/routes/faucets.ts | 6 +- src/api/routes/pox.ts | 159 +++++++ src/api/routes/pox2.ts | 77 ---- src/api/routes/pox3.ts | 66 --- src/api/routes/stacking.ts | 72 ---- src/api/routes/status.ts | 1 + src/datastore/common.ts | 105 ++--- src/datastore/helpers.ts | 123 +++--- src/datastore/pg-store.ts | 399 +++++++++++------- src/datastore/pg-write-store.ts | 188 +++------ .../importers/new-block-importer.ts | 14 +- src/event-stream/core-node-message.ts | 1 + src/event-stream/event-server.ts | 58 +-- ...-event-parsing.ts => pox-event-parsing.ts} | 189 +++++---- src/event-stream/reader.ts | 27 +- src/pox-helpers.ts | 45 +- src/rosetta/rosetta-helpers.ts | 17 +- src/test-utils/shared-setup.ts | 4 +- src/test-utils/test-builders.ts | 1 + src/test-utils/test-helpers.ts | 6 +- .../block-zero-handling.ts | 0 src/{tests-2.4 => tests-2.5}/env-setup.ts | 0 src/{tests-2.4 => tests-2.5}/faucet-stx.ts | 0 src/{tests-2.4 => tests-2.5}/global-setup.ts | 12 +- .../global-teardown.ts | 0 .../pox-4-btc-address-formats.ts} | 18 +- .../pox-4-burnchain-delegate-stx.ts} | 14 +- .../pox-4-burnchain-stack-stx.ts} | 6 +- .../pox-4-delegate-aggregation.ts} | 14 +- .../pox-4-delegate-revoked-stacking.ts} | 74 ++-- .../pox-4-delegate-stacking.ts} | 18 +- .../pox-4-rosetta-btc-addr-types.ts} | 4 +- .../pox-4-rosetta-cycle-phases.ts} | 2 +- .../pox-4-rosetta-segwit.ts} | 10 +- .../pox-4-stack-extend-increase.ts} | 10 +- .../construction.ts | 6 +- src/tests-rosetta/offline-api-tests.ts | 4 +- src/tests-rpc/core-rpc-tests.ts | 2 +- src/tests/address-tests.ts | 8 + src/tests/block-tests.ts | 2 + src/tests/cache-control-tests.ts | 2 + src/tests/datastore-tests.ts | 27 ++ src/tests/mempool-tests.ts | 1 + src/tests/microblock-tests.ts | 3 + src/tests/other-tests.ts | 1 + src/tests/search-tests.ts | 4 + src/tests/smart-contract-tests.ts | 6 + src/tests/tx-tests.ts | 17 + stacks-blockchain/docker/Dockerfile | 4 +- ...{jest.config.2.4.js => jest.config.2.5.js} | 16 +- 63 files changed, 1272 insertions(+), 935 deletions(-) create mode 100644 migrations/1702134678728_pox_4_events.js create mode 100644 src/api/routes/pox.ts delete mode 100644 src/api/routes/pox2.ts delete mode 100644 src/api/routes/pox3.ts delete mode 100644 src/api/routes/stacking.ts rename src/event-stream/{pox2-event-parsing.ts => pox-event-parsing.ts} (64%) rename src/{tests-2.4 => tests-2.5}/block-zero-handling.ts (100%) rename src/{tests-2.4 => tests-2.5}/env-setup.ts (100%) rename src/{tests-2.4 => tests-2.5}/faucet-stx.ts (100%) rename src/{tests-2.4 => tests-2.5}/global-setup.ts (82%) rename src/{tests-2.4 => tests-2.5}/global-teardown.ts (100%) rename src/{tests-2.4/pox-3-btc-address-formats.ts => tests-2.5/pox-4-btc-address-formats.ts} (98%) rename src/{tests-2.4/pox-3-burnchain-delegate-stx.ts => tests-2.5/pox-4-burnchain-delegate-stx.ts} (98%) rename src/{tests-2.4/pox-3-burnchain-stack-stx.ts => tests-2.5/pox-4-burnchain-stack-stx.ts} (99%) rename src/{tests-2.4/pox-3-delegate-aggregation.ts => tests-2.5/pox-4-delegate-aggregation.ts} (97%) rename src/{tests-2.4/pox-3-delegate-revoked-stacking.ts => tests-2.5/pox-4-delegate-revoked-stacking.ts} (89%) rename src/{tests-2.4/pox-3-delegate-stacking.ts => tests-2.5/pox-4-delegate-stacking.ts} (96%) rename src/{tests-2.4/pox-3-rosetta-btc-addr-types.ts => tests-2.5/pox-4-rosetta-btc-addr-types.ts} (97%) rename src/{tests-2.4/pox-3-rosetta-cycle-phases.ts => tests-2.5/pox-4-rosetta-cycle-phases.ts} (96%) rename src/{tests-2.4/pox-3-rosetta-segwit.ts => tests-2.5/pox-4-rosetta-segwit.ts} (98%) rename src/{tests-2.4/pox-3-stack-extend-increase.ts => tests-2.5/pox-4-stack-extend-increase.ts} (98%) rename tests/{jest.config.2.4.js => jest.config.2.5.js} (51%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 789774a203..0a3d205330 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -520,7 +520,7 @@ jobs: flag-name: run-${{ github.job }} parallel: true - test-2_4: + test-2_5: strategy: fail-fast: false matrix: @@ -528,16 +528,16 @@ jobs: [ block-zero-handling, faucet-stx, - pox-3-btc-address-formats, - pox-3-delegate-aggregation, - pox-3-delegate-stacking, - pox-3-delegate-revoked-stacking, - pox-3-stack-extend-increase, - pox-3-rosetta-btc-addr-types, - pox-3-rosetta-cycle-phases, - pox-3-rosetta-segwit, - pox-3-burnchain-stack-stx, - pox-3-burnchain-delegate-stx, + pox-4-btc-address-formats, + pox-4-delegate-aggregation, + pox-4-delegate-stacking, + pox-4-delegate-revoked-stacking, + pox-4-stack-extend-increase, + pox-4-rosetta-btc-addr-types, + pox-4-rosetta-cycle-phases, + pox-4-rosetta-segwit, + pox-4-burnchain-stack-stx, + pox-4-burnchain-delegate-stx, ] runs-on: ubuntu-latest steps: @@ -575,7 +575,7 @@ jobs: npm run devenv:logs-krypton -- --no-color &> docker-compose-logs.txt & - name: Run tests - run: npm run test:2.4 -- --testPathPattern "${{ matrix.suite }}" + run: npm run test:2.5 -- --testPathPattern "${{ matrix.suite }}" - name: Print integration environment logs run: cat docker-compose-logs.txt @@ -855,7 +855,7 @@ jobs: - lint - lint-docs - test - - test-2_4 + - test-2_5 - test-bns - test-rosetta - test-rosetta-cli-construction diff --git a/.vscode/launch.json b/.vscode/launch.json index 845f9a4802..42580ff805 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -316,14 +316,14 @@ { "type": "node", "request": "launch", - "name": "Jest: 2.4", + "name": "Jest: 2.5", "program": "${workspaceFolder}/node_modules/.bin/jest", "args": [ "--testTimeout=3600000", "--runInBand", "--no-cache", "--config", - "${workspaceRoot}/tests/jest.config.2.4.js" + "${workspaceRoot}/tests/jest.config.2.5.js", ], "outputCapture": "std", "console": "integratedTerminal", diff --git a/docker/docker-compose.dev.stacks-blockchain.yml b/docker/docker-compose.dev.stacks-blockchain.yml index fc79e5f246..23c338e983 100644 --- a/docker/docker-compose.dev.stacks-blockchain.yml +++ b/docker/docker-compose.dev.stacks-blockchain.yml @@ -1,7 +1,7 @@ version: '3.7' services: stacks-blockchain: - image: "hirosystems/stacks-api-e2e:stacks2.4-f930deb" + image: "hirosystems/stacks-api-e2e:stacks3.0-800259e" restart: on-failure environment: STACKS_EVENT_OBSERVER: host.docker.internal:3700 diff --git a/docker/docker-compose.dev.stacks-krypton.yml b/docker/docker-compose.dev.stacks-krypton.yml index 850950fdbf..58858240bf 100644 --- a/docker/docker-compose.dev.stacks-krypton.yml +++ b/docker/docker-compose.dev.stacks-krypton.yml @@ -1,7 +1,7 @@ version: '3.7' services: stacks-blockchain: - image: "hirosystems/stacks-api-e2e:stacks2.4-f930deb" + image: "hirosystems/stacks-api-e2e:stacks3.0-800259e" ports: - "18443:18443" # bitcoin regtest JSON-RPC interface - "18444:18444" # bitcoin regtest p2p diff --git a/docs/api/info/get-status.schema.json b/docs/api/info/get-status.schema.json index f629d0afd0..24dec15e1e 100644 --- a/docs/api/info/get-status.schema.json +++ b/docs/api/info/get-status.schema.json @@ -23,6 +23,10 @@ "type": "integer", "nullable": true }, + "pox_v3_unlock_height": { + "type": "integer", + "nullable": true + }, "chain_tip": { "$ref": "../../entities/info/chain-tip.schema.json" } diff --git a/docs/generated.d.ts b/docs/generated.d.ts index 18c1a28aee..4e39356ad9 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -1714,6 +1714,7 @@ export interface ServerStatusResponse { status: string; pox_v1_unlock_height?: number; pox_v2_unlock_height?: number; + pox_v3_unlock_height?: number; chain_tip?: ChainTip; } /** diff --git a/migrations/1701368149776_nakamoto-txs.js b/migrations/1701368149776_nakamoto-txs.js index 626757c032..27ec61ddbd 100644 --- a/migrations/1701368149776_nakamoto-txs.js +++ b/migrations/1701368149776_nakamoto-txs.js @@ -1,5 +1,13 @@ /** @param { import("node-pg-migrate").MigrationBuilder } pgm */ exports.up = pgm => { + pgm.addColumn('pox_state', { + pox_v3_unlock_height: { + type: 'bigint', + notNull: true, + default: 0, + }, + }); + pgm.addColumns('txs', { // `nakamoto-coinbase` tx types coinbase_vrf_proof: 'bytea', diff --git a/migrations/1702134678728_pox_4_events.js b/migrations/1702134678728_pox_4_events.js new file mode 100644 index 0000000000..788edd483c --- /dev/null +++ b/migrations/1702134678728_pox_4_events.js @@ -0,0 +1,203 @@ +/** @param { import("node-pg-migrate").MigrationBuilder } pgm */ +exports.up = pgm => { + // Adds pox4_events table which matches previous pox2_events table + pgm.createTable('pox4_events', { + id: { + type: 'bigserial', + primaryKey: true, + }, + event_index: { + type: 'integer', + notNull: true, + }, + tx_id: { + notNull: true, + type: 'bytea', + }, + tx_index: { + type: 'smallint', + notNull: true, + }, + block_height: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + parent_index_block_hash: { + type: 'bytea', + notNull: true, + }, + microblock_hash: { + type: 'bytea', + notNull: true, + }, + microblock_sequence: { + type: 'integer', + notNull: true, + }, + microblock_canonical: { + type: 'boolean', + notNull: true, + }, + canonical: { + type: 'boolean', + notNull: true, + }, + stacker: { + type: 'string', + notNull: true, + }, + locked: { + type: 'numeric', + notNull: true, + }, + balance: { + type: 'numeric', + notNull: true, + }, + burnchain_unlock_height: { + type: 'bigint', + notNull: true, + }, + name: { + type: 'string', + notNull: true, + }, + pox_addr: { + type: 'string', + }, + pox_addr_raw: { + type: 'bytea', + }, + first_cycle_locked: { + // unique to handle-unlock + type: 'numeric', + }, + first_unlocked_cycle: { + // unique to handle-unlock + type: 'numeric', + }, + delegate_to: { + // unique to delegate-stx + type: 'string', + }, + lock_period: { + // unique to stack-stx, delegate-stack-stx + type: 'numeric', + }, + lock_amount: { + // unique to stack-stx, delegate-stack-stx + type: 'numeric', + }, + start_burn_height: { + // unique to stack-stx, delegate-stack-stx + type: 'numeric', + }, + unlock_burn_height: { + // unique to stack-stx, stack-extend, delegate-stack-stx, delegate-stack-extend, delegate-stx + type: 'numeric', + }, + delegator: { + // unique to delegate-stack-stx, delegate-stack-increase, delegate-stack-extend + type: 'string', + }, + increase_by: { + // unique to stack-increase, delegate-stack-increase + type: 'numeric', + }, + total_locked: { + // unique to stack-increase, delegate-stack-increase + type: 'numeric', + }, + extend_count: { + // unique to stack-extend, delegate-stack-extend + type: 'numeric', + }, + reward_cycle: { + // unique to stack-aggregation-* + type: 'numeric', + }, + amount_ustx: { + // unique to stack-aggregation-*, delegate-stx + type: 'numeric', + }, + }); + + pgm.addConstraint( + 'pox4_events', + 'valid_event_specific_columns', + `CHECK ( + CASE name + WHEN 'handle-unlock' THEN + first_cycle_locked IS NOT NULL AND + first_unlocked_cycle IS NOT NULL + WHEN 'stack-stx' THEN + lock_period IS NOT NULL AND + lock_amount IS NOT NULL AND + start_burn_height IS NOT NULL AND + unlock_burn_height IS NOT NULL + WHEN 'stack-increase' THEN + increase_by IS NOT NULL AND + total_locked IS NOT NULL + WHEN 'stack-extend' THEN + extend_count IS NOT NULL AND + unlock_burn_height IS NOT NULL + WHEN 'delegate-stx' THEN + amount_ustx IS NOT NULL AND + delegate_to IS NOT NULL + WHEN 'delegate-stack-stx' THEN + lock_period IS NOT NULL AND + lock_amount IS NOT NULL AND + start_burn_height IS NOT NULL AND + unlock_burn_height IS NOT NULL AND + delegator IS NOT NULL + WHEN 'delegate-stack-increase' THEN + increase_by IS NOT NULL AND + total_locked IS NOT NULL AND + delegator IS NOT NULL + WHEN 'delegate-stack-extend' THEN + extend_count IS NOT NULL AND + unlock_burn_height IS NOT NULL AND + delegator IS NOT NULL + WHEN 'stack-aggregation-commit' THEN + reward_cycle IS NOT NULL AND + amount_ustx IS NOT NULL + WHEN 'stack-aggregation-commit-indexed' THEN + reward_cycle IS NOT NULL AND + amount_ustx IS NOT NULL + WHEN 'stack-aggregation-increase' THEN + reward_cycle IS NOT NULL AND + amount_ustx IS NOT NULL + ELSE false + END + )` + ); + + pgm.createIndex('pox4_events', [ + { name: 'block_height', sort: 'DESC' }, + { name: 'microblock_sequence', sort: 'DESC' }, + { name: 'tx_index', sort: 'DESC' }, + { name: 'event_index', sort: 'DESC' }, + ]); + + pgm.createIndex('pox4_events', 'tx_id'); + pgm.createIndex('pox4_events', 'index_block_hash'); + pgm.createIndex('pox4_events', 'microblock_hash'); + + pgm.createIndex('pox4_events', 'stacker'); + pgm.createIndex('pox4_events', 'burnchain_unlock_height'); + pgm.createIndex('pox4_events', 'pox_addr'); + pgm.createIndex('pox4_events', 'delegator'); + pgm.createIndex('pox4_events', 'name'); + + pgm.createIndex('pox4_events', 'delegate_to'); + pgm.createIndex('pox4_events', 'unlock_burn_height'); +}; + +/** @param { import("node-pg-migrate").MigrationBuilder } pgm */ +exports.down = pgm => { + pgm.dropTable('pox4_events'); +}; diff --git a/package.json b/package.json index 5541d46493..da1ae344c2 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev:follower": "npm run devenv:build && concurrently npm:dev npm:devenv:follower", "test": "cross-env NODE_ENV=test jest --config ./tests/jest.config.js --coverage --runInBand", "test:subnets": "cross-env NODE_ENV=test jest --config ./tests/jest.config.subnets.js --coverage --runInBand", - "test:2.4": "cross-env NODE_ENV=test jest --config ./tests/jest.config.2.4.js --coverage --runInBand", + "test:2.5": "cross-env NODE_ENV=test jest --config ./tests/jest.config.2.5.js --coverage --runInBand", "test:rosetta": "cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta.js --coverage --runInBand", "test:rosetta-construction": "cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta-construction.js --coverage --runInBand", "test:rosetta-cli:data": "cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-data.js --coverage --runInBand", @@ -24,7 +24,7 @@ "test:watch": "cross-env NODE_ENV=test jest --config ./tests/jest.config.js --watch", "test:integration": "concurrently \"docker compose -f docker/docker-compose.dev.postgres.yml up --force-recreate -V\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.js --no-cache --runInBand; npm run devenv:stop:pg\"", "test:integration:subnets": "concurrently --hide \"devenv:deploy:subnets\" \"npm:devenv:deploy:subnets\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.subnets.js --no-cache --runInBand; npm run devenv:stop:subnets\"", - "test:integration:2.4": "concurrently --hide \"devenv:deploy-krypton\" \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.2.4.js --no-cache --runInBand; npm run devenv:stop-krypton\"", + "test:integration:2.5": "concurrently --hide \"devenv:deploy-krypton\" \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.2.5.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:rosetta": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:rosetta-construction": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test jest --config ./tests/jest.config.rosetta-construction.js --no-cache --runInBand; npm run devenv:stop-krypton\"", "test:integration:rosetta-cli:data": "concurrently \"npm:devenv:deploy-krypton\" \"cross-env NODE_ENV=test STACKS_CHAIN_ID=0x80000000 jest --config ./tests/jest.config.rosetta-cli-data.js --no-cache --runInBand; npm run devenv:stop-krypton\"", diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 03cd994bdb..52fea4b546 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -60,14 +60,13 @@ import { BaseTx, DbMinerReward, StxUnlockEvent, - DbPox2Event, - DbPox3Event, + DbPoxSyntheticEvent, } from '../../datastore/common'; import { unwrapOptional, FoundOrNot, unixEpochToIso, EMPTY_HASH_256, ChainID } from '../../helpers'; import { serializePostCondition, serializePostConditionMode } from '../serializers/post-conditions'; import { getOperations, parseTransactionMemo } from '../../rosetta/rosetta-helpers'; import { PgStore } from '../../datastore/pg-store'; -import { Pox2EventName } from '../../pox-helpers'; +import { SyntheticPoxEventName } from '../../pox-helpers'; import { logger } from '../../logger'; export function parseTxTypeStrings(values: string[]): TransactionType[] { @@ -194,7 +193,7 @@ export function getAssetEventTypeString( } } -export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { +export function parsePoxSyntheticEvent(poxEvent: DbPoxSyntheticEvent) { const baseInfo = { block_height: poxEvent.block_height, tx_id: poxEvent.tx_id, @@ -209,7 +208,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { name: poxEvent.name, }; switch (poxEvent.name) { - case Pox2EventName.HandleUnlock: { + case SyntheticPoxEventName.HandleUnlock: { return { ...baseInfo, data: { @@ -218,7 +217,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.StackStx: { + case SyntheticPoxEventName.StackStx: { return { ...baseInfo, data: { @@ -229,7 +228,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.StackIncrease: { + case SyntheticPoxEventName.StackIncrease: { return { ...baseInfo, data: { @@ -238,7 +237,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.StackExtend: { + case SyntheticPoxEventName.StackExtend: { return { ...baseInfo, data: { @@ -247,7 +246,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.DelegateStx: { + case SyntheticPoxEventName.DelegateStx: { return { ...baseInfo, data: { @@ -257,7 +256,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.DelegateStackStx: { + case SyntheticPoxEventName.DelegateStackStx: { return { ...baseInfo, data: { @@ -269,7 +268,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.DelegateStackIncrease: { + case SyntheticPoxEventName.DelegateStackIncrease: { return { ...baseInfo, data: { @@ -279,7 +278,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.DelegateStackExtend: { + case SyntheticPoxEventName.DelegateStackExtend: { return { ...baseInfo, data: { @@ -289,7 +288,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.StackAggregationCommit: { + case SyntheticPoxEventName.StackAggregationCommit: { return { ...baseInfo, data: { @@ -298,7 +297,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.StackAggregationCommitIndexed: { + case SyntheticPoxEventName.StackAggregationCommitIndexed: { return { ...baseInfo, data: { @@ -307,7 +306,7 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } - case Pox2EventName.StackAggregationIncrease: { + case SyntheticPoxEventName.StackAggregationIncrease: { return { ...baseInfo, data: { @@ -316,8 +315,17 @@ export function parsePox2Event(poxEvent: DbPox2Event | DbPox3Event) { }, }; } + case SyntheticPoxEventName.RevokeDelegateStx: { + return { + ...baseInfo, + data: { + amount_ustx: poxEvent.data.amount_ustx.toString(), + delegate_to: poxEvent.data.delegate_to, + }, + }; + } default: - throw new Error(`Unexpected Pox2 event name ${(poxEvent as DbPox2Event).name}`); + throw new Error(`Unexpected Pox2 event name ${(poxEvent as DbPoxSyntheticEvent).name}`); } } diff --git a/src/api/init.ts b/src/api/init.ts index 42fccd17e9..7356ec11ee 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -1,5 +1,6 @@ import { Server, createServer } from 'http'; import { Socket } from 'net'; +import * as querystring from 'querystring'; import * as express from 'express'; import { v4 as uuid } from 'uuid'; import * as cors from 'cors'; @@ -40,12 +41,11 @@ import * as fs from 'fs'; import { PgStore } from '../datastore/pg-store'; import { PgWriteStore } from '../datastore/pg-write-store'; import { WebSocketTransmitter } from './routes/ws/web-socket-transmitter'; -import { createPox2EventsRouter } from './routes/pox2'; -import { createPox3EventsRouter } from './routes/pox3'; -import { createStackingRouter } from './routes/stacking'; +import { createPoxEventsRouter } from './routes/pox'; import { logger, loggerMiddleware } from '../logger'; import { SERVER_VERSION, isPgConnectionError, isProdEnv, waiter } from '@hirosystems/api-toolkit'; import { createBurnBlockRouter } from './routes/burn-block'; +import { getReqQuery } from './query-helpers'; export interface ApiServer { expressApp: express.Express; @@ -197,8 +197,22 @@ export async function startApiServer(opts: { router.use('/status', createStatusRouter(datastore)); router.use('/fee_rate', createFeeRateRouter(datastore)); router.use('/tokens', createTokenRouter(datastore)); - router.use('/pox2_events', createPox2EventsRouter(datastore)); - router.use('/pox3_events', createPox3EventsRouter(datastore)); + + // These could be defined in one route but a url reporting library breaks with regex in middleware paths + router.use('/pox2', createPoxEventsRouter(datastore, 'pox2')); + router.use('/pox3', createPoxEventsRouter(datastore, 'pox3')); + router.use('/pox4', createPoxEventsRouter(datastore, 'pox4')); + const legacyPoxPathRouter: express.RequestHandler = (req, res) => { + // Redirect old pox routes paths to new one above + const newPath = req.path === '/' ? '/events' : req.path; + const baseUrl = req.baseUrl.replace(/(pox[\d])_events/, '$1'); + const redirectPath = `${baseUrl}${newPath}${getReqQuery(req)}`; + return res.redirect(redirectPath); + }; + router.use('/pox2_events', legacyPoxPathRouter); + router.use('/pox3_events', legacyPoxPathRouter); + router.use('/pox4_events', legacyPoxPathRouter); + if (getChainIDNetwork(chainId) === 'testnet' && writeDatastore) { router.use('/faucets', createFaucetRouter(writeDatastore)); } @@ -206,20 +220,13 @@ export async function startApiServer(opts: { })() ); - app.use( - '/extended/beta', - (() => { - const router = express.Router(); - router.use(cors()); - router.use((req, res, next) => { - // Set caching on all routes to be disabled by default, individual routes can override - res.set('Cache-Control', 'no-store'); - next(); - }); - router.use('/stacking', createStackingRouter(datastore)); - return router; - })() - ); + // Redirect to new endpoint for backward compatibility. + // TODO: remove this in the future + app.use('/extended/beta/stacking/:pool_principal/delegations', (req, res) => { + const { pool_principal } = req.params; + const newPath = `/extended/v1/pox3/${pool_principal}/delegations${getReqQuery(req)}`; + return res.redirect(newPath); + }); // Setup direct proxy to core-node RPC endpoints (/v2) // pricing endpoint diff --git a/src/api/query-helpers.ts b/src/api/query-helpers.ts index f055c4bff0..7275d012f9 100644 --- a/src/api/query-helpers.ts +++ b/src/api/query-helpers.ts @@ -392,3 +392,13 @@ export function isValidTxId(tx_id: string) { return false; } } + +/** + * Returns the query string of a request, including the leading '?' character. + * If the request does not have a query string then an empty string is returned. + */ +export function getReqQuery(req: Request): string { + const fullUrl = `http://${req.headers.host}${req.originalUrl}`; + const urlObject = new URL(fullUrl); + return urlObject.search; +} diff --git a/src/api/rosetta-constants.ts b/src/api/rosetta-constants.ts index 8024c16c0e..1e563f654b 100644 --- a/src/api/rosetta-constants.ts +++ b/src/api/rosetta-constants.ts @@ -476,18 +476,3 @@ export const RosettaSchemas: Record = { '@stacks/stacks-blockchain-api-types/api/rosetta/rosetta-construction-combine-response.schema.json', }, }; - -export const PoxContractIdentifier = { - pox1: { - mainnet: 'SP000000000000000000002Q6VF78.pox', - testnet: 'ST000000000000000000002AMW42H.pox', - }, - pox2: { - mainnet: 'SP000000000000000000002Q6VF78.pox-2', - testnet: 'ST000000000000000000002AMW42H.pox-2', - }, - pox3: { - mainnet: 'SP000000000000000000002Q6VF78.pox-3', - testnet: 'ST000000000000000000002AMW42H.pox-3', - }, -} as const; diff --git a/src/api/routes/faucets.ts b/src/api/routes/faucets.ts index c3656c670f..10f9124cab 100644 --- a/src/api/routes/faucets.ts +++ b/src/api/routes/faucets.ts @@ -226,7 +226,11 @@ export function createFaucetRouter(db: PgWriteStore): express.Router { try { return await makeSTXTokenTransfer(txOpts); } catch (error: any) { - if (fee === undefined && (error as Error).message?.includes('NoEstimateAvailable')) { + if ( + fee === undefined && + (error as Error).message && + /estimating transaction fee|NoEstimateAvailable/.test(error.message) + ) { const defaultFee = 200n; return await generateTx(network, nonce, defaultFee); } diff --git a/src/api/routes/pox.ts b/src/api/routes/pox.ts new file mode 100644 index 0000000000..c99b5a7ba1 --- /dev/null +++ b/src/api/routes/pox.ts @@ -0,0 +1,159 @@ +import * as express from 'express'; +import { asyncHandler } from '../async-handler'; +import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; +import { PgStore } from '../../datastore/pg-store'; +import { parsePoxSyntheticEvent } from '../controllers/db-controller'; +import { + getBlockHeightQueryParam, + getBlockParams, + validatePrincipal, + validateRequestHexInput, +} from '../query-helpers'; +import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; +import { PoolDelegationsResponse } from '@stacks/stacks-blockchain-api-types'; + +export function createPoxEventsRouter( + db: PgStore, + poxVersion: 'pox2' | 'pox3' | 'pox4' +): express.Router { + const router = express.Router(); + const cacheHandler = getETagCacheHandler(db); + + const poxTable = ( + { + pox2: 'pox2_events', + pox3: 'pox3_events', + pox4: 'pox4_events', + } as const + )[poxVersion]; + + router.get( + '/events', + cacheHandler, + asyncHandler(async (req, res) => { + const limit = getPagingQueryLimit(ResourceType.Pox2Event, req.query.limit); + const offset = parsePagingQueryInput(req.query.offset ?? 0); + + const queryResults = await db.getPoxSyntheticEvents({ + offset, + limit, + poxTable, + }); + const parsedResult = queryResults.map(r => parsePoxSyntheticEvent(r)); + const response = { + limit, + offset, + results: parsedResult, + }; + setETagCacheHeaders(res); + res.json(response); + }) + ); + + router.get( + '/tx/:tx_id', + cacheHandler, + asyncHandler(async (req, res) => { + const { tx_id } = req.params; + validateRequestHexInput(tx_id); + const queryResults = await db.getPoxSyntheticEventsForTx({ + txId: tx_id, + poxTable, + }); + if (!queryResults.found) { + res.status(404).json({ error: `could not find transaction by ID ${tx_id}` }); + return; + } + const parsedResult = queryResults.result.map(r => parsePoxSyntheticEvent(r)); + const response = { + results: parsedResult, + }; + setETagCacheHeaders(res); + res.json(response); + }) + ); + + router.get( + '/stacker/:principal', + cacheHandler, + asyncHandler(async (req, res) => { + const { principal } = req.params; + validatePrincipal(principal); + const queryResults = await db.getPoxSyntheticEventsForStacker({ + principal, + poxTable, + }); + if (!queryResults.found) { + res.status(404).json({ error: `could not find principal ${principal}` }); + return; + } + const parsedResult = queryResults.result.map(r => parsePoxSyntheticEvent(r)); + const response = { + results: parsedResult, + }; + setETagCacheHeaders(res); + res.json(response); + }) + ); + + router.get( + '/:pool_principal/delegations', + cacheHandler, + asyncHandler(async (req, res, next) => { + // get recent asset event associated with address + const poolPrincipal = req.params['pool_principal']; + validatePrincipal(poolPrincipal); + + const limit = getPagingQueryLimit(ResourceType.Stacker, req.query.limit); + const offset = parsePagingQueryInput(req.query.offset ?? 0); + const afterBlock = getBlockHeightQueryParam('after_block', false, req, res, next) || 0; + + const response = await db.sqlTransaction(async sql => { + const blockParams = getBlockParams(req, res, next); + let blockHeight: number; + if (blockParams.blockHeight !== undefined) { + blockHeight = blockParams.blockHeight; + } else { + blockHeight = await db.getMaxBlockHeight(sql, { + includeUnanchored: blockParams.includeUnanchored ?? false, + }); + } + + const dbBlock = await db.getBlockByHeightInternal(sql, blockHeight); + if (!dbBlock.found) { + const error = `no block at height: ${blockHeight}`; + res.status(404).json({ error: error }); + throw new Error(error); + } + const burnBlockHeight = dbBlock.result.burn_block_height; + + const stackersQuery = await db.getPoxPoolDelegations({ + delegator: poolPrincipal, + blockHeight, + burnBlockHeight, + afterBlockHeight: afterBlock, + limit, + offset, + poxTable, + }); + if (!stackersQuery.found) { + const error = `no stackers found`; + res.status(404).json({ error: error }); + throw new Error(error); + } + + const response: PoolDelegationsResponse = { + limit, + offset, + total: stackersQuery.result.total, + results: stackersQuery.result.stackers, + }; + return response; + }); + setETagCacheHeaders(res); + res.json(response); + }) + ); + + return router; +} diff --git a/src/api/routes/pox2.ts b/src/api/routes/pox2.ts deleted file mode 100644 index 565fa6fe8b..0000000000 --- a/src/api/routes/pox2.ts +++ /dev/null @@ -1,77 +0,0 @@ -import * as express from 'express'; -import { asyncHandler } from '../async-handler'; -import { - BurnchainReward, - BurnchainRewardListResponse, - BurnchainRewardSlotHolder, - BurnchainRewardSlotHolderListResponse, - BurnchainRewardsTotal, -} from '@stacks/stacks-blockchain-api-types'; - -import { isValidBitcoinAddress, tryConvertC32ToBtc } from '../../helpers'; -import { InvalidRequestError, InvalidRequestErrorType } from '../../errors'; -import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; -import { PgStore } from '../../datastore/pg-store'; -import { parsePox2Event } from '../controllers/db-controller'; -import { validatePrincipal, validateRequestHexInput } from '../query-helpers'; - -export function createPox2EventsRouter(db: PgStore): express.Router { - const router = express.Router(); - - router.get( - '/', - asyncHandler(async (req, res) => { - const limit = getPagingQueryLimit(ResourceType.Pox2Event, req.query.limit); - const offset = parsePagingQueryInput(req.query.offset ?? 0); - - const queryResults = await db.getPox2Events({ offset, limit }); - const parsedResult = queryResults.map(r => parsePox2Event(r)); - const response = { - limit, - offset, - results: parsedResult, - }; - res.json(response); - }) - ); - - // TODO: this should probably be a tx route e.g. /extended/v1/tx/:tx_id/pox2_events - router.get( - '/tx/:tx_id', - asyncHandler(async (req, res) => { - const { tx_id } = req.params; - validateRequestHexInput(tx_id); - const queryResults = await db.getPox2EventsForTx({ txId: tx_id }); - if (!queryResults.found) { - res.status(404).json({ error: `could not find transaction by ID ${tx_id}` }); - return; - } - const parsedResult = queryResults.result.map(r => parsePox2Event(r)); - const response = { - results: parsedResult, - }; - res.json(response); - }) - ); - - // TODO: this should probably be an account route e.g. /extended/v1/address/:stx_address/pox2_events - router.get( - '/stacker/:principal', - asyncHandler(async (req, res) => { - const { principal } = req.params; - validatePrincipal(principal); - const queryResults = await db.getPox2EventsForStacker({ principal }); - if (!queryResults.found) { - res.status(404).json({ error: `could not find principal ${principal}` }); - return; - } - const parsedResult = queryResults.result.map(r => parsePox2Event(r)); - const response = { - results: parsedResult, - }; - res.json(response); - }) - ); - - return router; -} diff --git a/src/api/routes/pox3.ts b/src/api/routes/pox3.ts deleted file mode 100644 index c01d305665..0000000000 --- a/src/api/routes/pox3.ts +++ /dev/null @@ -1,66 +0,0 @@ -import * as express from 'express'; -import { asyncHandler } from '../async-handler'; - -import { PgStore } from '../../datastore/pg-store'; -import { parsePox2Event } from '../controllers/db-controller'; -import { ResourceType, getPagingQueryLimit, parsePagingQueryInput } from '../pagination'; -import { validatePrincipal, validateRequestHexInput } from '../query-helpers'; - -export function createPox3EventsRouter(db: PgStore): express.Router { - const router = express.Router(); - - router.get( - '/', - asyncHandler(async (req, res) => { - const limit = getPagingQueryLimit(ResourceType.Pox2Event, req.query.limit); - const offset = parsePagingQueryInput(req.query.offset ?? 0); - - const queryResults = await db.getPox3Events({ offset, limit }); - const parsedResult = queryResults.map(r => parsePox2Event(r)); // parsePox2Event is pox-3 compatible - const response = { - limit, - offset, - results: parsedResult, - }; - res.json(response); - }) - ); - - router.get( - '/tx/:tx_id', - asyncHandler(async (req, res) => { - const { tx_id } = req.params; - validateRequestHexInput(tx_id); - const queryResults = await db.getPox3EventsForTx({ txId: tx_id }); - if (!queryResults.found) { - res.status(404).json({ error: `could not find transaction by ID ${tx_id}` }); - return; - } - const parsedResult = queryResults.result.map(r => parsePox2Event(r)); - const response = { - results: parsedResult, - }; - res.json(response); - }) - ); - - router.get( - '/stacker/:principal', - asyncHandler(async (req, res) => { - const { principal } = req.params; - validatePrincipal(principal); - const queryResults = await db.getPox3EventsForStacker({ principal }); - if (!queryResults.found) { - res.status(404).json({ error: `could not find principal ${principal}` }); - return; - } - const parsedResult = queryResults.result.map(r => parsePox2Event(r)); - const response = { - results: parsedResult, - }; - res.json(response); - }) - ); - - return router; -} diff --git a/src/api/routes/stacking.ts b/src/api/routes/stacking.ts deleted file mode 100644 index c7aea8f68e..0000000000 --- a/src/api/routes/stacking.ts +++ /dev/null @@ -1,72 +0,0 @@ -import * as express from 'express'; -import { asyncHandler } from '../async-handler'; -import { PoolDelegationsResponse } from '@stacks/stacks-blockchain-api-types'; -import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; -import { PgStore } from '../../datastore/pg-store'; -import { getBlockHeightQueryParam, getBlockParams, validatePrincipal } from '../query-helpers'; -import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; - -export function createStackingRouter(db: PgStore): express.Router { - const router = express.Router(); - const cacheHandler = getETagCacheHandler(db); - - router.get( - '/:pool_principal/delegations', - cacheHandler, - asyncHandler(async (req, res, next) => { - // get recent asset event associated with address - const poolPrincipal = req.params['pool_principal']; - validatePrincipal(poolPrincipal); - - const limit = getPagingQueryLimit(ResourceType.Stacker, req.query.limit); - const offset = parsePagingQueryInput(req.query.offset ?? 0); - const afterBlock = getBlockHeightQueryParam('after_block', false, req, res, next) || 0; - - const response = await db.sqlTransaction(async sql => { - const blockParams = getBlockParams(req, res, next); - let blockHeight: number; - if (blockParams.blockHeight !== undefined) { - blockHeight = blockParams.blockHeight; - } else { - blockHeight = await db.getMaxBlockHeight(sql, { - includeUnanchored: blockParams.includeUnanchored ?? false, - }); - } - - const dbBlock = await db.getBlockByHeightInternal(sql, blockHeight); - if (!dbBlock.found) { - const error = `no block at height: ${blockHeight}`; - res.status(404).json({ error: error }); - throw new Error(error); - } - const burnBlockHeight = dbBlock.result.burn_block_height; - - const stackersQuery = await db.getPox3PoolDelegations({ - delegator: poolPrincipal, - blockHeight, - burnBlockHeight, - afterBlockHeight: afterBlock, - limit, - offset, - }); - if (!stackersQuery.found) { - const error = `no stackers found`; - res.status(404).json({ error: error }); - throw new Error(error); - } - - const response: PoolDelegationsResponse = { - limit, - offset, - total: stackersQuery.result.total, - results: stackersQuery.result.stackers, - }; - return response; - }); - setETagCacheHeaders(res); - res.json(response); - }) - ); - - return router; -} diff --git a/src/api/routes/status.ts b/src/api/routes/status.ts index 328cb327ed..a56dd3e788 100644 --- a/src/api/routes/status.ts +++ b/src/api/routes/status.ts @@ -17,6 +17,7 @@ export function createStatusRouter(db: PgStore): express.Router { if (poxForceUnlockHeights.found) { response.pox_v1_unlock_height = poxForceUnlockHeights.result.pox1UnlockHeight as number; response.pox_v2_unlock_height = poxForceUnlockHeights.result.pox2UnlockHeight as number; + response.pox_v3_unlock_height = poxForceUnlockHeights.result.pox3UnlockHeight as number; } const chainTip = await db.getChainTip(); if (chainTip.block_height > 0) { diff --git a/src/datastore/common.ts b/src/datastore/common.ts index c9cedd03e0..e037569330 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -1,6 +1,6 @@ import { ClarityAbi } from '@stacks/transactions'; import { Block } from '@stacks/stacks-blockchain-api-types'; -import { Pox2EventName } from '../pox-helpers'; +import { SyntheticPoxEventName } from '../pox-helpers'; import { PgBytea, PgJsonb, PgNumeric } from '@hirosystems/api-toolkit'; export interface DbBlock { @@ -329,7 +329,9 @@ export interface DbEventBase { canonical: boolean; } -export interface DbPox2BaseEventData { +export type PoxSyntheticEventTable = 'pox2_events' | 'pox3_events' | 'pox4_events'; + +export interface DbPoxSyntheticBaseEventData { stacker: string; locked: bigint; balance: bigint; @@ -338,16 +340,16 @@ export interface DbPox2BaseEventData { pox_addr_raw: string | null; } -export interface DbPox2HandleUnlockEvent extends DbPox2BaseEventData { - name: Pox2EventName.HandleUnlock; +export interface DbPoxSyntheticHandleUnlockEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.HandleUnlock; data: { first_cycle_locked: bigint; first_unlocked_cycle: bigint; }; } -export interface DbPox2StackStxEvent extends DbPox2BaseEventData { - name: Pox2EventName.StackStx; +export interface DbPoxSyntheticStackStxEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.StackStx; data: { lock_amount: bigint; lock_period: bigint; @@ -356,24 +358,24 @@ export interface DbPox2StackStxEvent extends DbPox2BaseEventData { }; } -export interface DbPox2StackIncreaseEvent extends DbPox2BaseEventData { - name: Pox2EventName.StackIncrease; +export interface DbPoxSyntheticStackIncreaseEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.StackIncrease; data: { increase_by: bigint; total_locked: bigint; }; } -export interface DbPox2StackExtendEvent extends DbPox2BaseEventData { - name: Pox2EventName.StackExtend; +export interface DbPoxSyntheticStackExtendEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.StackExtend; data: { extend_count: bigint; unlock_burn_height: bigint; }; } -export interface DbPox2DelegateStxEvent extends DbPox2BaseEventData { - name: Pox2EventName.DelegateStx; +export interface DbPoxSyntheticDelegateStxEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.DelegateStx; data: { amount_ustx: bigint; delegate_to: string; @@ -381,8 +383,8 @@ export interface DbPox2DelegateStxEvent extends DbPox2BaseEventData { }; } -export interface DbPox2DelegateStackStxEvent extends DbPox2BaseEventData { - name: Pox2EventName.DelegateStackStx; +export interface DbPoxSyntheticDelegateStackStxEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.DelegateStackStx; data: { lock_amount: bigint; unlock_burn_height: bigint; @@ -392,8 +394,8 @@ export interface DbPox2DelegateStackStxEvent extends DbPox2BaseEventData { }; } -export interface DbPox2DelegateStackIncreaseEvent extends DbPox2BaseEventData { - name: Pox2EventName.DelegateStackIncrease; +export interface DbPoxSyntheticDelegateStackIncreaseEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.DelegateStackIncrease; data: { increase_by: bigint; total_locked: bigint; @@ -401,8 +403,8 @@ export interface DbPox2DelegateStackIncreaseEvent extends DbPox2BaseEventData { }; } -export interface DbPox2DelegateStackExtendEvent extends DbPox2BaseEventData { - name: Pox2EventName.DelegateStackExtend; +export interface DbPoxSyntheticDelegateStackExtendEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.DelegateStackExtend; data: { unlock_burn_height: bigint; extend_count: bigint; @@ -410,49 +412,57 @@ export interface DbPox2DelegateStackExtendEvent extends DbPox2BaseEventData { }; } -export interface DbPox2StackAggregationCommitEvent extends DbPox2BaseEventData { - name: Pox2EventName.StackAggregationCommit; +export interface DbPoxSyntheticStackAggregationCommitEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.StackAggregationCommit; data: { reward_cycle: bigint; amount_ustx: bigint; }; } -export interface DbPox2StackAggregationCommitIndexedEvent extends DbPox2BaseEventData { - name: Pox2EventName.StackAggregationCommitIndexed; +export interface DbPoxSyntheticStackAggregationCommitIndexedEvent + extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.StackAggregationCommitIndexed; data: { reward_cycle: bigint; amount_ustx: bigint; }; } -export interface DbPox2StackAggregationIncreaseEvent extends DbPox2BaseEventData { - name: Pox2EventName.StackAggregationIncrease; +export interface DbPoxSyntheticStackAggregationIncreaseEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.StackAggregationIncrease; data: { reward_cycle: bigint; amount_ustx: bigint; }; } -export type DbPox2EventData = - | DbPox2HandleUnlockEvent - | DbPox2StackStxEvent - | DbPox2StackIncreaseEvent - | DbPox2StackExtendEvent - | DbPox2DelegateStxEvent - | DbPox2DelegateStackStxEvent - | DbPox2DelegateStackIncreaseEvent - | DbPox2DelegateStackExtendEvent - | DbPox2StackAggregationCommitEvent - | DbPox2StackAggregationCommitIndexedEvent - | DbPox2StackAggregationIncreaseEvent; +export interface DbPoxSyntheticRevokeDelegateStxEvent extends DbPoxSyntheticBaseEventData { + name: SyntheticPoxEventName.RevokeDelegateStx; + data: { + // TODO: determine what data is available for this event type + amount_ustx: bigint; + delegate_to: string; + }; +} -export type DbPox2Event = DbEventBase & DbPox2EventData; +export type DbPoxSyntheticEventData = + | DbPoxSyntheticHandleUnlockEvent + | DbPoxSyntheticStackStxEvent + | DbPoxSyntheticStackIncreaseEvent + | DbPoxSyntheticStackExtendEvent + | DbPoxSyntheticDelegateStxEvent + | DbPoxSyntheticDelegateStackStxEvent + | DbPoxSyntheticDelegateStackIncreaseEvent + | DbPoxSyntheticDelegateStackExtendEvent + | DbPoxSyntheticStackAggregationCommitEvent + | DbPoxSyntheticStackAggregationCommitIndexedEvent + | DbPoxSyntheticStackAggregationIncreaseEvent + | DbPoxSyntheticRevokeDelegateStxEvent; -// todo: should we copy DbPox2EventData for pox3? -export type DbPox3Event = DbEventBase & DbPox2EventData; +export type DbPoxSyntheticEvent = DbEventBase & DbPoxSyntheticEventData; -export interface DbPox3Stacker { +export interface DbPoxStacker { stacker: string; pox_addr?: string; amount_ustx: string; @@ -577,6 +587,7 @@ export interface DataStoreBlockUpdateData { txs: DataStoreTxEventData[]; pox_v1_unlock_height?: number; pox_v2_unlock_height?: number; + pox_v3_unlock_height?: number; } export interface DataStoreMicroblockUpdateData { @@ -594,8 +605,9 @@ export interface DataStoreTxEventData { smartContracts: DbSmartContract[]; names: DbBnsName[]; namespaces: DbBnsNamespace[]; - pox2Events: DbPox2Event[]; - pox3Events: DbPox3Event[]; + pox2Events: DbPoxSyntheticEvent[]; + pox3Events: DbPoxSyntheticEvent[]; + pox4Events: DbPoxSyntheticEvent[]; } export interface DataStoreAttachmentData { @@ -967,6 +979,7 @@ export interface UpdatedEntities { nftEvents: number; pox2Events: number; pox3Events: number; + pox4Events: number; contractLogs: number; smartContracts: number; names: number; @@ -984,6 +997,7 @@ export interface UpdatedEntities { nftEvents: number; pox2Events: number; pox3Events: number; + pox4Events: number; contractLogs: number; smartContracts: number; names: number; @@ -1202,7 +1216,7 @@ export interface RawEventRequestInsertValues { payload: string; } -export interface Pox2EventQueryResult { +export interface PoxSyntheticEventQueryResult { event_index: number; tx_id: string; tx_index: number; @@ -1261,10 +1275,7 @@ export interface Pox2EventQueryResult { amount_ustx: string | null; } -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface Pox3EventQueryResult extends Pox2EventQueryResult {} - -export interface Pox2EventInsertValues { +export interface PoxSyntheticEventInsertValues { event_index: number; tx_id: PgBytea; tx_index: number; diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index ccf0889964..bfc351de19 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -14,19 +14,19 @@ import { DbMempoolTxRaw, DbMicroblock, DbNftEvent, - DbPox2BaseEventData, - DbPox2DelegateStackExtendEvent, - DbPox2DelegateStackIncreaseEvent, - DbPox2DelegateStackStxEvent, - DbPox2DelegateStxEvent, - DbPox2Event, - DbPox2HandleUnlockEvent, - DbPox2StackAggregationCommitEvent, - DbPox2StackAggregationCommitIndexedEvent, - DbPox2StackAggregationIncreaseEvent, - DbPox2StackExtendEvent, - DbPox2StackIncreaseEvent, - DbPox2StackStxEvent, + DbPoxSyntheticBaseEventData, + DbPoxSyntheticDelegateStackExtendEvent, + DbPoxSyntheticDelegateStackIncreaseEvent, + DbPoxSyntheticDelegateStackStxEvent, + DbPoxSyntheticDelegateStxEvent, + DbPoxSyntheticEvent, + DbPoxSyntheticHandleUnlockEvent, + DbPoxSyntheticStackAggregationCommitEvent, + DbPoxSyntheticStackAggregationCommitIndexedEvent, + DbPoxSyntheticStackAggregationIncreaseEvent, + DbPoxSyntheticStackExtendEvent, + DbPoxSyntheticStackIncreaseEvent, + DbPoxSyntheticStackStxEvent, DbSmartContract, DbSmartContractEvent, DbStxEvent, @@ -39,8 +39,9 @@ import { FaucetRequestQueryResult, MempoolTxQueryResult, MicroblockQueryResult, - Pox2EventQueryResult, + PoxSyntheticEventQueryResult, TxQueryResult, + DbPoxSyntheticRevokeDelegateStxEvent, } from './common'; import { CoreNodeDropMempoolTxReasonType, @@ -60,7 +61,7 @@ import * as prom from 'prom-client'; import { NftEvent } from 'docs/generated'; import { getAssetEventTypeString } from '../api/controllers/db-controller'; import { PgStoreEventEmitter } from './pg-store-event-emitter'; -import { Pox2EventName } from '../pox-helpers'; +import { SyntheticPoxEventName } from '../pox-helpers'; import { logger } from '../logger'; import { PgSqlClient } from '@hirosystems/api-toolkit'; @@ -200,6 +201,7 @@ export const TX_METADATA_TABLES = [ 'nft_events', 'pox2_events', 'pox3_events', + 'pox4_events', 'contract_logs', 'stx_lock_events', 'smart_contracts', @@ -208,7 +210,7 @@ export const TX_METADATA_TABLES = [ 'subdomains', ] as const; -export const POX2_EVENT_COLUMNS = [ +export const POX_SYNTHETIC_EVENT_COLUMNS = [ 'event_index', 'tx_id', 'tx_index', @@ -241,8 +243,6 @@ export const POX2_EVENT_COLUMNS = [ 'amount_ustx', ]; -export const POX3_EVENT_COLUMNS = POX2_EVENT_COLUMNS; - /** * Adds a table name prefix to an array of column names. * @param columns - array of column names @@ -606,7 +606,7 @@ export function parseDbEvents( return events; } -export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { +export function parseDbPoxSyntheticEvent(row: PoxSyntheticEventQueryResult): DbPoxSyntheticEvent { const baseEvent: DbEventBase = { event_index: row.event_index, tx_id: row.tx_id, @@ -614,7 +614,7 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { block_height: row.block_height, canonical: row.canonical, }; - const basePox2Event: DbPox2BaseEventData = { + const basePoxEvent: DbPoxSyntheticBaseEventData = { stacker: row.stacker, locked: BigInt(row.locked ?? 0), balance: BigInt(row.balance), @@ -622,11 +622,11 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { pox_addr: row.pox_addr ?? null, pox_addr_raw: row.pox_addr_raw ?? null, }; - const rowName = row.name as Pox2EventName; + const rowName = row.name as SyntheticPoxEventName; switch (rowName) { - case Pox2EventName.HandleUnlock: { - const eventData: DbPox2HandleUnlockEvent = { - ...basePox2Event, + case SyntheticPoxEventName.HandleUnlock: { + const eventData: DbPoxSyntheticHandleUnlockEvent = { + ...basePoxEvent, name: rowName, data: { first_cycle_locked: BigInt(unwrapOptionalProp(row, 'first_unlocked_cycle')), @@ -638,9 +638,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.StackStx: { - const eventData: DbPox2StackStxEvent = { - ...basePox2Event, + case SyntheticPoxEventName.StackStx: { + const eventData: DbPoxSyntheticStackStxEvent = { + ...basePoxEvent, name: rowName, data: { lock_amount: BigInt(unwrapOptionalProp(row, 'lock_amount')), @@ -654,9 +654,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.StackIncrease: { - const eventData: DbPox2StackIncreaseEvent = { - ...basePox2Event, + case SyntheticPoxEventName.StackIncrease: { + const eventData: DbPoxSyntheticStackIncreaseEvent = { + ...basePoxEvent, name: rowName, data: { increase_by: BigInt(unwrapOptionalProp(row, 'increase_by')), @@ -668,9 +668,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.StackExtend: { - const eventData: DbPox2StackExtendEvent = { - ...basePox2Event, + case SyntheticPoxEventName.StackExtend: { + const eventData: DbPoxSyntheticStackExtendEvent = { + ...basePoxEvent, name: rowName, data: { extend_count: BigInt(unwrapOptionalProp(row, 'extend_count')), @@ -682,9 +682,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.DelegateStx: { - const eventData: DbPox2DelegateStxEvent = { - ...basePox2Event, + case SyntheticPoxEventName.DelegateStx: { + const eventData: DbPoxSyntheticDelegateStxEvent = { + ...basePoxEvent, name: rowName, data: { amount_ustx: BigInt(unwrapOptionalProp(row, 'amount_ustx')), @@ -699,9 +699,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.DelegateStackStx: { - const eventData: DbPox2DelegateStackStxEvent = { - ...basePox2Event, + case SyntheticPoxEventName.DelegateStackStx: { + const eventData: DbPoxSyntheticDelegateStackStxEvent = { + ...basePoxEvent, name: rowName, data: { lock_amount: BigInt(unwrapOptionalProp(row, 'lock_amount')), @@ -716,9 +716,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.DelegateStackIncrease: { - const eventData: DbPox2DelegateStackIncreaseEvent = { - ...basePox2Event, + case SyntheticPoxEventName.DelegateStackIncrease: { + const eventData: DbPoxSyntheticDelegateStackIncreaseEvent = { + ...basePoxEvent, name: rowName, data: { increase_by: BigInt(unwrapOptionalProp(row, 'increase_by')), @@ -731,9 +731,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.DelegateStackExtend: { - const eventData: DbPox2DelegateStackExtendEvent = { - ...basePox2Event, + case SyntheticPoxEventName.DelegateStackExtend: { + const eventData: DbPoxSyntheticDelegateStackExtendEvent = { + ...basePoxEvent, name: rowName, data: { unlock_burn_height: BigInt(unwrapOptionalProp(row, 'unlock_burn_height')), @@ -746,9 +746,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.StackAggregationCommit: { - const eventData: DbPox2StackAggregationCommitEvent = { - ...basePox2Event, + case SyntheticPoxEventName.StackAggregationCommit: { + const eventData: DbPoxSyntheticStackAggregationCommitEvent = { + ...basePoxEvent, name: rowName, data: { reward_cycle: BigInt(unwrapOptionalProp(row, 'reward_cycle')), @@ -760,9 +760,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.StackAggregationCommitIndexed: { - const eventData: DbPox2StackAggregationCommitIndexedEvent = { - ...basePox2Event, + case SyntheticPoxEventName.StackAggregationCommitIndexed: { + const eventData: DbPoxSyntheticStackAggregationCommitIndexedEvent = { + ...basePoxEvent, name: rowName, data: { reward_cycle: BigInt(unwrapOptionalProp(row, 'reward_cycle')), @@ -774,9 +774,9 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } - case Pox2EventName.StackAggregationIncrease: { - const eventData: DbPox2StackAggregationIncreaseEvent = { - ...basePox2Event, + case SyntheticPoxEventName.StackAggregationIncrease: { + const eventData: DbPoxSyntheticStackAggregationIncreaseEvent = { + ...basePoxEvent, name: rowName, data: { reward_cycle: BigInt(unwrapOptionalProp(row, 'reward_cycle')), @@ -788,6 +788,21 @@ export function parseDbPox2Event(row: Pox2EventQueryResult): DbPox2Event { ...eventData, }; } + case SyntheticPoxEventName.RevokeDelegateStx: { + const eventData: DbPoxSyntheticRevokeDelegateStxEvent = { + ...basePoxEvent, + name: rowName, + data: { + // TODO: figure out what data is available for this event + amount_ustx: BigInt(unwrapOptionalProp(row, 'amount_ustx')), + delegate_to: unwrapOptionalProp(row, 'delegate_to'), + }, + }; + return { + ...baseEvent, + ...eventData, + }; + } default: { throw new Error(`Unexpected event name ${rowName}`); } diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 809e5c945f..9a081c853f 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -44,9 +44,8 @@ import { DbMicroblock, DbMinerReward, DbNftEvent, - DbPox2Event, - DbPox3Event, - DbPox3Stacker, + DbPoxSyntheticEvent, + DbPoxStacker, DbRewardSlotHolder, DbSearchResult, DbSmartContract, @@ -66,11 +65,11 @@ import { NftEventWithTxMetadata, NftHoldingInfo, NftHoldingInfoWithTxMetadata, - Pox2EventQueryResult, - Pox3EventQueryResult, + PoxSyntheticEventQueryResult, RawTxQueryResult, StxUnlockEvent, TransferQueryResult, + PoxSyntheticEventTable, } from './common'; import { abiColumn, @@ -79,22 +78,21 @@ import { MICROBLOCK_COLUMNS, parseBlockQueryResult, parseDbEvents, - parseDbPox2Event, + parseDbPoxSyntheticEvent, parseFaucetRequestQueryResult, parseMempoolTxQueryResult, parseMicroblockQueryResult, parseQueryResultToSmartContract, parseTxQueryResult, parseTxsWithAssetTransfers, - POX2_EVENT_COLUMNS, - POX3_EVENT_COLUMNS, + POX_SYNTHETIC_EVENT_COLUMNS, prefixedCols, TX_COLUMNS, unsafeCols, validateZonefileHash, } from './helpers'; import { PgNotifier } from './pg-notifier'; -import { Pox2EventName } from '../pox-helpers'; +import { SyntheticPoxEventName } from '../pox-helpers'; import { BasePgStore, PgSqlClient, connectPostgres } from '@hirosystems/api-toolkit'; import { PgServer, @@ -288,11 +286,17 @@ export class PgStore extends BasePgStore { }); } - async getPoxForcedUnlockHeightsInternal( - sql: PgSqlClient - ): Promise> { - const query = await sql<{ pox_v1_unlock_height: string; pox_v2_unlock_height: string }[]>` - SELECT pox_v1_unlock_height, pox_v2_unlock_height + async getPoxForcedUnlockHeightsInternal(sql: PgSqlClient): Promise< + FoundOrNot<{ + pox1UnlockHeight: number | null; + pox2UnlockHeight: number | null; + pox3UnlockHeight: number | null; + }> + > { + const query = await sql< + { pox_v1_unlock_height: string; pox_v2_unlock_height: string; pox_v3_unlock_height: string }[] + >` + SELECT pox_v1_unlock_height, pox_v2_unlock_height, pox_v3_unlock_height FROM pox_state LIMIt 1 `; @@ -301,10 +305,11 @@ export class PgStore extends BasePgStore { } const pox1UnlockHeight = parseInt(query[0].pox_v1_unlock_height) || null; const pox2UnlockHeight = parseInt(query[0].pox_v2_unlock_height) || null; + const pox3UnlockHeight = parseInt(query[0].pox_v3_unlock_height) || null; if (pox2UnlockHeight === 0) { return { found: false }; } - return { found: true, result: { pox1UnlockHeight, pox2UnlockHeight } }; + return { found: true, result: { pox1UnlockHeight, pox2UnlockHeight, pox3UnlockHeight } }; } async getPoxForceUnlockHeights() { @@ -1886,127 +1891,80 @@ export class PgStore extends BasePgStore { return parseQueryResultToSmartContract(row); } - async getPox2Events({ + async getPoxSyntheticEvents({ limit, offset, + poxTable, }: { limit: number; offset: number; - }): Promise { + poxTable: PoxSyntheticEventTable; + }): Promise { return await this.sqlTransaction(async sql => { - const queryResults = await sql` - SELECT ${sql(POX2_EVENT_COLUMNS)} - FROM pox2_events + const queryResults = await sql` + SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} + FROM ${sql(poxTable)} WHERE canonical = true AND microblock_canonical = true ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC LIMIT ${limit} OFFSET ${offset} `; - const result = queryResults.map(result => parseDbPox2Event(result)); + const result = queryResults.map(result => parseDbPoxSyntheticEvent(result)); return result; }); } - /** modified copy of `getPox2Events` */ - async getPox3Events({ - limit, - offset, + async getPoxSyntheticEventsForTx({ + txId, + poxTable, }: { - limit: number; - offset: number; - }): Promise { - return await this.sqlTransaction(async sql => { - const queryResults = await sql` - SELECT ${sql(POX2_EVENT_COLUMNS)} - FROM pox3_events - WHERE canonical = true AND microblock_canonical = true - ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC - LIMIT ${limit} - OFFSET ${offset} - `; - const result = queryResults.map(result => parseDbPox2Event(result)); - return result; - }); - } - - async getPox2EventsForTx({ txId }: { txId: string }): Promise> { - return await this.sqlTransaction(async sql => { - const dbTx = await this.getTx({ txId, includeUnanchored: true }); - if (!dbTx.found) { - return { found: false }; - } - const queryResults = await sql` - SELECT ${sql(POX2_EVENT_COLUMNS)} - FROM pox2_events - WHERE canonical = true AND microblock_canonical = true AND tx_id = ${txId} - ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC - `; - const result = queryResults.map(result => parseDbPox2Event(result)); - return { found: true, result: result }; - }); - } - - /** modified copy of `getPox2EventsForTx` */ - async getPox3EventsForTx({ txId }: { txId: string }): Promise> { + txId: string; + poxTable: PoxSyntheticEventTable; + }): Promise> { return await this.sqlTransaction(async sql => { const dbTx = await this.getTx({ txId, includeUnanchored: true }); if (!dbTx.found) { return { found: false }; } - const queryResults = await sql` - SELECT ${sql(POX2_EVENT_COLUMNS)} - FROM pox3_events + const queryResults = await sql` + SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} + FROM ${sql(poxTable)} WHERE canonical = true AND microblock_canonical = true AND tx_id = ${txId} ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC `; - const result = queryResults.map(result => parseDbPox2Event(result)); - return { found: true, result: result }; - }); - } - - async getPox2EventsForStacker({ - principal, - }: { - principal: string; - }): Promise> { - return await this.sqlTransaction(async sql => { - const queryResults = await sql` - SELECT ${sql(POX2_EVENT_COLUMNS)} - FROM pox2_events - WHERE canonical = true AND microblock_canonical = true AND stacker = ${principal} - ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC - `; - const result = queryResults.map(result => parseDbPox2Event(result)); + const result = queryResults.map(result => parseDbPoxSyntheticEvent(result)); return { found: true, result: result }; }); } - /** modified copy of `getPox2EventsForStacker` */ - async getPox3EventsForStacker({ + async getPoxSyntheticEventsForStacker({ principal, + poxTable, }: { principal: string; - }): Promise> { + poxTable: PoxSyntheticEventTable; + }): Promise> { return await this.sqlTransaction(async sql => { - const queryResults = await sql` - SELECT ${sql(POX2_EVENT_COLUMNS)} - FROM pox3_events + const queryResults = await sql` + SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} + FROM ${sql(poxTable)} WHERE canonical = true AND microblock_canonical = true AND stacker = ${principal} ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC `; - const result = queryResults.map(result => parseDbPox2Event(result)); + const result = queryResults.map(result => parseDbPoxSyntheticEvent(result)); return { found: true, result: result }; }); } - async getPox3PoolDelegations(args: { + async getPoxPoolDelegations(args: { delegator: string; blockHeight: number; burnBlockHeight: number; afterBlockHeight: number; limit: number; offset: number; - }): Promise> { + poxTable: PoxSyntheticEventTable; + }): Promise> { return await this.sqlTransaction(async sql => { const queryResults = await sql< { @@ -2019,14 +1977,14 @@ export class PgStore extends BasePgStore { total_rows: number; }[] >` - WITH ordered_pox3_events AS ( + WITH ordered_pox_events AS ( SELECT stacker, pox_addr, amount_ustx, unlock_burn_height::integer, tx_id, block_height, microblock_sequence, tx_index, event_index - FROM pox3_events + FROM ${sql(args.poxTable)} WHERE canonical = true AND microblock_canonical = true AND - name = ${Pox2EventName.DelegateStx} AND delegate_to = ${args.delegator} AND + name = ${SyntheticPoxEventName.DelegateStx} AND delegate_to = ${args.delegator} AND block_height <= ${args.blockHeight} AND block_height > ${args.afterBlockHeight} AND (unlock_burn_height > ${args.burnBlockHeight} OR unlock_burn_height IS NULL) ORDER BY stacker, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC @@ -2035,7 +1993,7 @@ export class PgStore extends BasePgStore { SELECT DISTINCT ON (stacker) stacker, pox_addr, amount_ustx, unlock_burn_height, tx_id, block_height, microblock_sequence, tx_index, event_index - FROM ordered_pox3_events + FROM ordered_pox_events ORDER BY stacker, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC ) SELECT @@ -2047,7 +2005,7 @@ export class PgStore extends BasePgStore { OFFSET ${args.offset} `; const total = queryResults[0]?.total_rows ?? 0; - const stackers: DbPox3Stacker[] = queryResults.map(result => ({ + const stackers: DbPoxStacker[] = queryResults.map(result => ({ stacker: result.stacker, pox_addr: result.pox_addr || undefined, amount_ustx: result.amount_ustx, @@ -2235,6 +2193,7 @@ export class PgStore extends BasePgStore { let includePox1State = true; let includePox2State = true; + let includePox3State = true; const poxForceUnlockHeights = await this.getPoxForcedUnlockHeightsInternal(sql); if (poxForceUnlockHeights.found) { if ( @@ -2249,6 +2208,12 @@ export class PgStore extends BasePgStore { ) { includePox2State = false; } + if ( + poxForceUnlockHeights.result.pox3UnlockHeight && + burnBlockHeight > poxForceUnlockHeights.result.pox3UnlockHeight + ) { + includePox3State = false; + } } // Once the pox_v1_unlock_height is reached, stop using `stx_lock_events` to determinel locked state, @@ -2287,22 +2252,26 @@ export class PgStore extends BasePgStore { if (includePox2State) { // Query for the latest lock event that still applies to the current burn block height. // Special case for `handle-unlock` which should be returned if it is the last received event. - const pox2EventQuery = await sql` - SELECT ${sql(POX2_EVENT_COLUMNS)} + const pox2EventQuery = await sql` + SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} FROM pox2_events WHERE canonical = true AND microblock_canonical = true AND stacker = ${stxAddress} AND block_height <= ${blockHeight} AND ( - (name != ${Pox2EventName.HandleUnlock} AND burnchain_unlock_height >= ${burnBlockHeight}) + (name != ${ + SyntheticPoxEventName.HandleUnlock + } AND burnchain_unlock_height >= ${burnBlockHeight}) OR - (name = ${Pox2EventName.HandleUnlock} AND burnchain_unlock_height < ${burnBlockHeight}) + (name = ${ + SyntheticPoxEventName.HandleUnlock + } AND burnchain_unlock_height < ${burnBlockHeight}) ) ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC LIMIT 1 `; if (pox2EventQuery.length > 0) { - const pox2Event = parseDbPox2Event(pox2EventQuery[0]); - if (pox2Event.name === Pox2EventName.HandleUnlock) { + const pox2Event = parseDbPoxSyntheticEvent(pox2EventQuery[0]); + if (pox2Event.name === SyntheticPoxEventName.HandleUnlock) { // on a handle-unlock, set all of the locked stx related property to empty/default lockTxId = ''; locked = 0n; @@ -2320,31 +2289,73 @@ export class PgStore extends BasePgStore { } } - // == PoX-3 ================================================================ - // Assuming includePox3State = true; since there is no unlock height for pox3 (yet) + // Once the pox_v3_unlock_height is reached, stop using `pox3_events` to determine locked state. + if (includePox3State) { + // Query for the latest lock event that still applies to the current burn block height. + // Special case for `handle-unlock` which should be returned if it is the last received event. + const pox3EventQuery = await sql` + SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} + FROM pox3_events + WHERE canonical = true AND microblock_canonical = true AND stacker = ${stxAddress} + AND block_height <= ${blockHeight} + AND ( + (name != ${ + SyntheticPoxEventName.HandleUnlock + } AND burnchain_unlock_height >= ${burnBlockHeight}) + OR + (name = ${ + SyntheticPoxEventName.HandleUnlock + } AND burnchain_unlock_height < ${burnBlockHeight}) + ) + ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC + LIMIT 1 + `; + if (pox3EventQuery.length > 0) { + const pox3Event = parseDbPoxSyntheticEvent(pox3EventQuery[0]); + if (pox3Event.name === SyntheticPoxEventName.HandleUnlock) { + // on a handle-unlock, set all of the locked stx related property to empty/default + lockTxId = ''; + locked = 0n; + burnchainUnlockHeight = 0; + lockHeight = 0; + burnchainLockHeight = 0; + } else { + lockTxId = pox3Event.tx_id; + locked = pox3Event.locked; + burnchainUnlockHeight = Number(pox3Event.burnchain_unlock_height); + lockHeight = pox3Event.block_height; + const blockQuery = await this.getBlockByHeightInternal(sql, lockHeight); + burnchainLockHeight = blockQuery.found ? blockQuery.result.burn_block_height : 0; + } + } + } + + // == PoX-4 ================================================================ + // Assuming includePox3State = true; since there is no unlock height for pox4 (yet) // Query for the latest lock event that still applies to the current burn block height. // Special case for `handle-unlock` which should be returned if it is the last received event. - // todo: do we need handle-unlock for pox3? - - // Modified copy of the pox-2 query - const pox3EventQuery = await sql` - SELECT ${sql(POX3_EVENT_COLUMNS)} - FROM pox3_events + const pox4EventQuery = await sql` + SELECT ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} + FROM pox4_events WHERE canonical = true AND microblock_canonical = true AND stacker = ${stxAddress} AND block_height <= ${blockHeight} AND ( - (name != ${Pox2EventName.HandleUnlock} AND burnchain_unlock_height >= ${burnBlockHeight}) + (name != ${ + SyntheticPoxEventName.HandleUnlock + } AND burnchain_unlock_height >= ${burnBlockHeight}) OR - (name = ${Pox2EventName.HandleUnlock} AND burnchain_unlock_height < ${burnBlockHeight}) + (name = ${ + SyntheticPoxEventName.HandleUnlock + } AND burnchain_unlock_height < ${burnBlockHeight}) ) ORDER BY block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC LIMIT 1 `; - if (pox3EventQuery.length > 0) { - const pox3Event = parseDbPox2Event(pox3EventQuery[0]); - if (pox3Event.name === Pox2EventName.HandleUnlock) { + if (pox4EventQuery.length > 0) { + const pox4Event = parseDbPoxSyntheticEvent(pox4EventQuery[0]); + if (pox4Event.name === SyntheticPoxEventName.HandleUnlock) { // on a handle-unlock, set all of the locked stx related property to empty/default lockTxId = ''; locked = 0n; @@ -2352,10 +2363,10 @@ export class PgStore extends BasePgStore { lockHeight = 0; burnchainLockHeight = 0; } else { - lockTxId = pox3Event.tx_id; - locked = pox3Event.locked; - burnchainUnlockHeight = Number(pox3Event.burnchain_unlock_height); - lockHeight = pox3Event.block_height; + lockTxId = pox4Event.tx_id; + locked = pox4Event.locked; + burnchainUnlockHeight = Number(pox4Event.burnchain_unlock_height); + lockHeight = pox4Event.block_height; const blockQuery = await this.getBlockByHeightInternal(sql, lockHeight); burnchainLockHeight = blockQuery.found ? blockQuery.result.burn_block_height : 0; } @@ -4044,10 +4055,12 @@ export class PgStore extends BasePgStore { } let v1UnlockHeight: number | null = null; let v2UnlockHeight: number | null = null; + let v3UnlockHeight: number | null = null; const poxUnlockHeights = await this.getPoxForcedUnlockHeightsInternal(sql); if (poxUnlockHeights.found) { v1UnlockHeight = poxUnlockHeights.result.pox1UnlockHeight; v2UnlockHeight = poxUnlockHeights.result.pox2UnlockHeight; + v3UnlockHeight = poxUnlockHeights.result.pox3UnlockHeight; } type StxLockEventResult = { @@ -4106,8 +4119,8 @@ export class PgStore extends BasePgStore { let poxV2Unlocks: StxLockEventResult[] = []; const checkPox2Unlocks = v2UnlockHeight === null || current_burn_height < v2UnlockHeight; if (checkPox2Unlocks) { - const pox2EventQuery = await sql` - SELECT DISTINCT ON (stacker) stacker, ${sql(POX2_EVENT_COLUMNS)} + const pox2EventQuery = await sql` + SELECT DISTINCT ON (stacker) stacker, ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} FROM pox2_events WHERE canonical = true AND microblock_canonical = true AND block_height <= ${block.block_height} @@ -4116,15 +4129,15 @@ export class PgStore extends BasePgStore { burnchain_unlock_height <= ${current_burn_height} AND burnchain_unlock_height > ${previous_burn_height} AND name IN ${sql([ - Pox2EventName.StackStx, - Pox2EventName.StackIncrease, - Pox2EventName.StackExtend, - Pox2EventName.DelegateStackStx, - Pox2EventName.DelegateStackIncrease, - Pox2EventName.DelegateStackExtend, + SyntheticPoxEventName.StackStx, + SyntheticPoxEventName.StackIncrease, + SyntheticPoxEventName.StackExtend, + SyntheticPoxEventName.DelegateStackStx, + SyntheticPoxEventName.DelegateStackIncrease, + SyntheticPoxEventName.DelegateStackExtend, ])} ) OR ( - name = ${Pox2EventName.HandleUnlock} + name = ${SyntheticPoxEventName.HandleUnlock} AND burnchain_unlock_height < ${current_burn_height} AND burnchain_unlock_height >= ${previous_burn_height} ) @@ -4132,7 +4145,7 @@ export class PgStore extends BasePgStore { ORDER BY stacker, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC `; poxV2Unlocks = pox2EventQuery.map(row => { - const pox2Event = parseDbPox2Event(row); + const pox2Event = parseDbPoxSyntheticEvent(row); const unlockEvent: StxLockEventResult = { locked_amount: pox2Event.locked.toString(), unlock_height: Number(pox2Event.burnchain_unlock_height), @@ -4151,23 +4164,23 @@ export class PgStore extends BasePgStore { current_burn_height > v2UnlockHeight && previous_burn_height <= v2UnlockHeight; if (generatePoxV2ForceUnlocks) { - const pox2EventQuery = await sql` - SELECT DISTINCT ON (stacker) stacker, ${sql(POX2_EVENT_COLUMNS)} + const pox2EventQuery = await sql` + SELECT DISTINCT ON (stacker) stacker, ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} FROM pox2_events WHERE canonical = true AND microblock_canonical = true AND block_height <= ${block.block_height} AND ( - ( name != ${Pox2EventName.HandleUnlock} AND + ( name != ${SyntheticPoxEventName.HandleUnlock} AND burnchain_unlock_height >= ${current_burn_height}) OR - ( name = ${Pox2EventName.HandleUnlock} AND + ( name = ${SyntheticPoxEventName.HandleUnlock} AND burnchain_unlock_height < ${current_burn_height}) ) ORDER BY stacker, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC `; for (const row of pox2EventQuery) { - const pox2Event = parseDbPox2Event(row); - if (pox2Event.name !== Pox2EventName.HandleUnlock) { + const pox2Event = parseDbPoxSyntheticEvent(row); + if (pox2Event.name !== SyntheticPoxEventName.HandleUnlock) { const unlockEvent: StxLockEventResult = { locked_amount: pox2Event.locked.toString(), unlock_height: Number(pox2Event.burnchain_unlock_height), @@ -4181,42 +4194,120 @@ export class PgStore extends BasePgStore { } } - // modified copy of pox2 unlocks query let poxV3Unlocks: StxLockEventResult[] = []; - const pox3EventQuery = await sql` - SELECT DISTINCT ON (stacker) stacker, ${sql(POX3_EVENT_COLUMNS)} + const checkPox3Unlocks = v3UnlockHeight === null || current_burn_height < v3UnlockHeight; + if (checkPox3Unlocks) { + const pox3EventQuery = await sql` + SELECT DISTINCT ON (stacker) stacker, ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} + FROM pox3_events + WHERE canonical = true AND microblock_canonical = true + AND block_height <= ${block.block_height} + AND ( + ( + burnchain_unlock_height <= ${current_burn_height} + AND burnchain_unlock_height > ${previous_burn_height} + AND name IN ${sql([ + SyntheticPoxEventName.StackStx, + SyntheticPoxEventName.StackIncrease, + SyntheticPoxEventName.StackExtend, + SyntheticPoxEventName.DelegateStackStx, + SyntheticPoxEventName.DelegateStackIncrease, + SyntheticPoxEventName.DelegateStackExtend, + ])} + ) OR ( + name = ${SyntheticPoxEventName.HandleUnlock} + AND burnchain_unlock_height < ${current_burn_height} + AND burnchain_unlock_height >= ${previous_burn_height} + ) + ) + ORDER BY stacker, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC + `; + poxV3Unlocks = pox3EventQuery.map(row => { + const pox3Event = parseDbPoxSyntheticEvent(row); + const unlockEvent: StxLockEventResult = { + locked_amount: pox3Event.locked.toString(), + unlock_height: Number(pox3Event.burnchain_unlock_height), + locked_address: pox3Event.stacker, + block_height: pox3Event.block_height, + tx_index: pox3Event.tx_index, + event_index: pox3Event.event_index, + }; + return unlockEvent; + }); + } + + // modified copy of pox2 and pox3 unlocks query + const poxV3ForceUnlocks: StxLockEventResult[] = []; + const generatePoxV3ForceUnlocks = + v3UnlockHeight !== null && + current_burn_height > v3UnlockHeight && + previous_burn_height <= v3UnlockHeight; + if (generatePoxV3ForceUnlocks) { + const pox3EventQuery = await sql` + SELECT DISTINCT ON (stacker) stacker, ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} FROM pox3_events WHERE canonical = true AND microblock_canonical = true AND block_height <= ${block.block_height} + AND ( + ( name != ${SyntheticPoxEventName.HandleUnlock} AND + burnchain_unlock_height >= ${current_burn_height}) + OR + ( name = ${SyntheticPoxEventName.HandleUnlock} AND + burnchain_unlock_height < ${current_burn_height}) + ) + ORDER BY stacker, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC + `; + for (const row of pox3EventQuery) { + const pox3Event = parseDbPoxSyntheticEvent(row); + if (pox3Event.name !== SyntheticPoxEventName.HandleUnlock) { + const unlockEvent: StxLockEventResult = { + locked_amount: pox3Event.locked.toString(), + unlock_height: Number(pox3Event.burnchain_unlock_height), + locked_address: pox3Event.stacker, + block_height: pox3Event.block_height, + tx_index: pox3Event.tx_index, + event_index: pox3Event.event_index, + }; + poxV3ForceUnlocks.push(unlockEvent); + } + } + } + + let poxV4Unlocks: StxLockEventResult[] = []; + const pox4EventQuery = await sql` + SELECT DISTINCT ON (stacker) stacker, ${sql(POX_SYNTHETIC_EVENT_COLUMNS)} + FROM pox4_events + WHERE canonical = true AND microblock_canonical = true + AND block_height <= ${block.block_height} AND ( ( burnchain_unlock_height <= ${current_burn_height} AND burnchain_unlock_height > ${previous_burn_height} AND name IN ${sql([ - Pox2EventName.StackStx, - Pox2EventName.StackIncrease, - Pox2EventName.StackExtend, - Pox2EventName.DelegateStackStx, - Pox2EventName.DelegateStackIncrease, - Pox2EventName.DelegateStackExtend, + SyntheticPoxEventName.StackStx, + SyntheticPoxEventName.StackIncrease, + SyntheticPoxEventName.StackExtend, + SyntheticPoxEventName.DelegateStackStx, + SyntheticPoxEventName.DelegateStackIncrease, + SyntheticPoxEventName.DelegateStackExtend, ])} ) OR ( - name = ${Pox2EventName.HandleUnlock} + name = ${SyntheticPoxEventName.HandleUnlock} AND burnchain_unlock_height < ${current_burn_height} AND burnchain_unlock_height >= ${previous_burn_height} ) ) ORDER BY stacker, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC `; - poxV3Unlocks = pox3EventQuery.map(row => { - const pox3Event = parseDbPox2Event(row) as DbPox3Event; + poxV4Unlocks = pox4EventQuery.map(row => { + const pox4Event = parseDbPoxSyntheticEvent(row); const unlockEvent: StxLockEventResult = { - locked_amount: pox3Event.locked.toString(), - unlock_height: Number(pox3Event.burnchain_unlock_height), - locked_address: pox3Event.stacker, - block_height: pox3Event.block_height, - tx_index: pox3Event.tx_index, - event_index: pox3Event.event_index, + locked_amount: pox4Event.locked.toString(), + unlock_height: Number(pox4Event.burnchain_unlock_height), + locked_address: pox4Event.stacker, + block_height: pox4Event.block_height, + tx_index: pox4Event.tx_index, + event_index: pox4Event.event_index, }; return unlockEvent; }); @@ -4236,6 +4327,8 @@ export class PgStore extends BasePgStore { poxV2Unlocks, poxV2ForceUnlocks, poxV3Unlocks, + poxV3ForceUnlocks, + poxV4Unlocks, ]) { unlocks.forEach(row => { const unlockEvent: StxUnlockEvent = { diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 6afd6d7f99..bd9d6c476b 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -50,15 +50,15 @@ import { DataStoreAttachmentData, DataStoreAttachmentSubdomainData, DataStoreBnsBlockData, - DbPox2Event, - Pox2EventInsertValues, + PoxSyntheticEventInsertValues, DbTxRaw, DbMempoolTxRaw, DbChainTip, - DbPox3Event, RawEventRequestInsertValues, IndexesState, NftCustodyInsertValues, + DbPoxSyntheticEvent, + PoxSyntheticEventTable, } from './common'; import { BLOCK_COLUMNS, @@ -77,7 +77,7 @@ import { PgNotifier } from './pg-notifier'; import { MIGRATIONS_DIR, PgStore } from './pg-store'; import * as zoneFileParser from 'zone-file'; import { parseResolver, parseZoneFileTxt } from '../event-stream/bns/bns-helpers'; -import { Pox2EventName } from '../pox-helpers'; +import { SyntheticPoxEventName } from '../pox-helpers'; import { logger } from '../logger'; import { PgJsonb, @@ -190,6 +190,7 @@ export class PgWriteStore extends PgStore { namespaces: tx.namespaces.map(e => ({ ...e, canonical: false })), pox2Events: tx.pox2Events.map(e => ({ ...e, canonical: false })), pox3Events: tx.pox3Events.map(e => ({ ...e, canonical: false })), + pox4Events: tx.pox4Events.map(e => ({ ...e, canonical: false })), })); data.minerRewards = data.minerRewards.map(mr => ({ ...mr, canonical: false })); } else { @@ -325,6 +326,14 @@ export class PgWriteStore extends PgStore { WHERE pox_v2_unlock_height != ${data.pox_v2_unlock_height} `; } + if (isCanonical && data.pox_v3_unlock_height !== undefined) { + // update the pox_state.pox_v3_unlock_height singleton + await sql` + UPDATE pox_state + SET pox_v3_unlock_height = ${data.pox_v3_unlock_height} + WHERE pox_v3_unlock_height != ${data.pox_v3_unlock_height} + `; + } // When receiving first block, check if "block 0" boot data was received, // if so, update their properties to correspond to "block 1", since we treat @@ -352,10 +361,13 @@ export class PgWriteStore extends PgStore { contractLogEvents.push(...entry.contractLogEvents); await this.updateBatchSmartContractEvent(sql, entry.tx, entry.contractLogEvents); for (const pox2Event of entry.pox2Events) { - await this.updatePox2Event(sql, entry.tx, pox2Event); + await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox2_events', pox2Event); } for (const pox3Event of entry.pox3Events) { - await this.updatePox3Event(sql, entry.tx, pox3Event); + await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox3_events', pox3Event); + } + for (const pox4Event of entry.pox4Events) { + await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox4_events', pox4Event); } for (const stxLockEvent of entry.stxLockEvents) { await this.updateStxLockEvent(sql, entry.tx, stxLockEvent); @@ -651,6 +663,7 @@ export class PgWriteStore extends PgStore { namespaces: entry.namespaces.map(e => ({ ...e, ready_block: blockHeight })), pox2Events: entry.pox2Events.map(e => ({ ...e, block_height: blockHeight })), pox3Events: entry.pox3Events.map(e => ({ ...e, block_height: blockHeight })), + pox4Events: entry.pox4Events.map(e => ({ ...e, block_height: blockHeight })), }); deployedSmartContracts.push(...entry.smartContracts); contractLogEvents.push(...entry.contractLogEvents); @@ -815,8 +828,13 @@ export class PgWriteStore extends PgStore { logger.info('Updated block zero boot data', tablesUpdates); } - async updatePox2Event(sql: PgSqlClient, tx: DbTx, event: DbPox2Event) { - const values: Pox2EventInsertValues = { + async updatePoxSyntheticEvent( + sql: PgSqlClient, + tx: DbTx, + poxTable: PoxSyntheticEventTable, + event: DbPoxSyntheticEvent + ) { + const values: PoxSyntheticEventInsertValues = { event_index: event.event_index, tx_id: event.tx_id, tx_index: event.tx_index, @@ -850,35 +868,35 @@ export class PgWriteStore extends PgStore { }; // Set event-specific columns switch (event.name) { - case Pox2EventName.HandleUnlock: { + case SyntheticPoxEventName.HandleUnlock: { values.first_cycle_locked = event.data.first_cycle_locked.toString(); values.first_unlocked_cycle = event.data.first_unlocked_cycle.toString(); break; } - case Pox2EventName.StackStx: { + case SyntheticPoxEventName.StackStx: { values.lock_period = event.data.lock_period.toString(); values.lock_amount = event.data.lock_amount.toString(); values.start_burn_height = event.data.start_burn_height.toString(); values.unlock_burn_height = event.data.unlock_burn_height.toString(); break; } - case Pox2EventName.StackIncrease: { + case SyntheticPoxEventName.StackIncrease: { values.increase_by = event.data.increase_by.toString(); values.total_locked = event.data.total_locked.toString(); break; } - case Pox2EventName.StackExtend: { + case SyntheticPoxEventName.StackExtend: { values.extend_count = event.data.extend_count.toString(); values.unlock_burn_height = event.data.unlock_burn_height.toString(); break; } - case Pox2EventName.DelegateStx: { + case SyntheticPoxEventName.DelegateStx: { values.amount_ustx = event.data.amount_ustx.toString(); values.delegate_to = event.data.delegate_to; values.unlock_burn_height = event.data.unlock_burn_height?.toString() ?? null; break; } - case Pox2EventName.DelegateStackStx: { + case SyntheticPoxEventName.DelegateStackStx: { values.lock_period = event.data.lock_period.toString(); values.lock_amount = event.data.lock_amount.toString(); values.start_burn_height = event.data.start_burn_height.toString(); @@ -886,147 +904,46 @@ export class PgWriteStore extends PgStore { values.delegator = event.data.delegator; break; } - case Pox2EventName.DelegateStackIncrease: { + case SyntheticPoxEventName.DelegateStackIncrease: { values.increase_by = event.data.increase_by.toString(); values.total_locked = event.data.total_locked.toString(); values.delegator = event.data.delegator; break; } - case Pox2EventName.DelegateStackExtend: { + case SyntheticPoxEventName.DelegateStackExtend: { values.extend_count = event.data.extend_count.toString(); values.unlock_burn_height = event.data.unlock_burn_height.toString(); values.delegator = event.data.delegator; break; } - case Pox2EventName.StackAggregationCommit: { + case SyntheticPoxEventName.StackAggregationCommit: { values.reward_cycle = event.data.reward_cycle.toString(); values.amount_ustx = event.data.amount_ustx.toString(); break; } - case Pox2EventName.StackAggregationCommitIndexed: { + case SyntheticPoxEventName.StackAggregationCommitIndexed: { values.reward_cycle = event.data.reward_cycle.toString(); values.amount_ustx = event.data.amount_ustx.toString(); break; } - case Pox2EventName.StackAggregationIncrease: { + case SyntheticPoxEventName.StackAggregationIncrease: { values.reward_cycle = event.data.reward_cycle.toString(); values.amount_ustx = event.data.amount_ustx.toString(); break; } - default: { - throw new Error(`Unexpected Pox2 event name: ${(event as DbPox2Event).name}`); - } - } - await sql` - INSERT INTO pox2_events ${sql(values)} - `; - } - - // todo: abstract or copy all types - async updatePox3Event(sql: PgSqlClient, tx: DbTx, event: DbPox3Event) { - const values: Pox2EventInsertValues = { - event_index: event.event_index, - tx_id: event.tx_id, - tx_index: event.tx_index, - block_height: event.block_height, - index_block_hash: tx.index_block_hash, - parent_index_block_hash: tx.parent_index_block_hash, - microblock_hash: tx.microblock_hash, - microblock_sequence: tx.microblock_sequence, - microblock_canonical: tx.microblock_canonical, - canonical: event.canonical, - stacker: event.stacker, - locked: event.locked.toString(), - balance: event.balance.toString(), - burnchain_unlock_height: event.burnchain_unlock_height.toString(), - name: event.name, - pox_addr: event.pox_addr, - pox_addr_raw: event.pox_addr_raw, - first_cycle_locked: null, - first_unlocked_cycle: null, - delegate_to: null, - lock_period: null, - lock_amount: null, - start_burn_height: null, - unlock_burn_height: null, - delegator: null, - increase_by: null, - total_locked: null, - extend_count: null, - reward_cycle: null, - amount_ustx: null, - }; - // Set event-specific columns - switch (event.name) { - case Pox2EventName.HandleUnlock: { - values.first_cycle_locked = event.data.first_cycle_locked.toString(); - values.first_unlocked_cycle = event.data.first_unlocked_cycle.toString(); - break; - } - case Pox2EventName.StackStx: { - values.lock_period = event.data.lock_period.toString(); - values.lock_amount = event.data.lock_amount.toString(); - values.start_burn_height = event.data.start_burn_height.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - break; - } - case Pox2EventName.StackIncrease: { - values.increase_by = event.data.increase_by.toString(); - values.total_locked = event.data.total_locked.toString(); - break; - } - case Pox2EventName.StackExtend: { - values.extend_count = event.data.extend_count.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - break; - } - case Pox2EventName.DelegateStx: { + case SyntheticPoxEventName.RevokeDelegateStx: { values.amount_ustx = event.data.amount_ustx.toString(); values.delegate_to = event.data.delegate_to; - values.unlock_burn_height = event.data.unlock_burn_height?.toString() ?? null; - break; - } - case Pox2EventName.DelegateStackStx: { - values.lock_period = event.data.lock_period.toString(); - values.lock_amount = event.data.lock_amount.toString(); - values.start_burn_height = event.data.start_burn_height.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - values.delegator = event.data.delegator; - break; - } - case Pox2EventName.DelegateStackIncrease: { - values.increase_by = event.data.increase_by.toString(); - values.total_locked = event.data.total_locked.toString(); - values.delegator = event.data.delegator; - break; - } - case Pox2EventName.DelegateStackExtend: { - values.extend_count = event.data.extend_count.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - values.delegator = event.data.delegator; - break; - } - case Pox2EventName.StackAggregationCommit: { - values.reward_cycle = event.data.reward_cycle.toString(); - values.amount_ustx = event.data.amount_ustx.toString(); - break; - } - case Pox2EventName.StackAggregationCommitIndexed: { - values.reward_cycle = event.data.reward_cycle.toString(); - values.amount_ustx = event.data.amount_ustx.toString(); - break; - } - case Pox2EventName.StackAggregationIncrease: { - values.reward_cycle = event.data.reward_cycle.toString(); - values.amount_ustx = event.data.amount_ustx.toString(); break; } default: { - throw new Error(`Unexpected Pox3 event name: ${(event as DbPox2Event).name}`); + throw new Error( + `Unexpected Pox synthetic event name: ${(event as DbPoxSyntheticEvent).name}` + ); } } await sql` - INSERT INTO pox3_events ${sql(values)} + INSERT INTO ${sql(poxTable)} ${sql(values)} `; } @@ -2158,10 +2075,13 @@ export class PgWriteStore extends PgStore { await this.updatePrincipalStxTxs(sql, entry.tx, entry.stxEvents); await this.updateBatchSmartContractEvent(sql, entry.tx, entry.contractLogEvents); for (const pox2Event of entry.pox2Events) { - await this.updatePox2Event(sql, entry.tx, pox2Event); + await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox2_events', pox2Event); } for (const pox3Event of entry.pox3Events) { - await this.updatePox3Event(sql, entry.tx, pox3Event); + await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox3_events', pox3Event); + } + for (const pox4Event of entry.pox4Events) { + await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox4_events', pox4Event); } for (const stxLockEvent of entry.stxLockEvents) { await this.updateStxLockEvent(sql, entry.tx, stxLockEvent); @@ -2592,7 +2512,6 @@ export class PgWriteStore extends PgStore { microblocks: [], }); - // todo: do we still need pox2 marking here? const pox2Result = await sql` UPDATE pox2_events SET canonical = ${canonical} @@ -2615,6 +2534,17 @@ export class PgWriteStore extends PgStore { updatedEntities.markedNonCanonical.pox3Events += pox3Result.count; } + const pox4Result = await sql` + UPDATE pox4_events + SET canonical = ${canonical} + WHERE index_block_hash = ${indexBlockHash} AND canonical != ${canonical} + `; + if (canonical) { + updatedEntities.markedCanonical.pox4Events += pox4Result.count; + } else { + updatedEntities.markedNonCanonical.pox4Events += pox4Result.count; + } + const contractLogResult = await sql` UPDATE contract_logs SET canonical = ${canonical} @@ -2819,6 +2749,7 @@ export class PgWriteStore extends PgStore { nftEvents: 0, pox2Events: 0, pox3Events: 0, + pox4Events: 0, contractLogs: 0, smartContracts: 0, names: 0, @@ -2836,6 +2767,7 @@ export class PgWriteStore extends PgStore { nftEvents: 0, pox2Events: 0, pox3Events: 0, + pox4Events: 0, contractLogs: 0, smartContracts: 0, names: 0, diff --git a/src/event-replay/parquet-based/importers/new-block-importer.ts b/src/event-replay/parquet-based/importers/new-block-importer.ts index 7d00a036de..869d6f3d3d 100644 --- a/src/event-replay/parquet-based/importers/new-block-importer.ts +++ b/src/event-replay/parquet-based/importers/new-block-importer.ts @@ -392,7 +392,7 @@ const populateBatchInserters = (db: PgWriteStore) => { const insertPox2Events = async (dbData: DataStoreBlockUpdateData) => { for (const entry of dbData.txs) { for (const pox2Event of entry.pox2Events) { - await db.updatePox2Event(db.sql, entry.tx, pox2Event); + await db.updatePoxSyntheticEvent(db.sql, entry.tx, 'pox2_events', pox2Event); } } }; @@ -400,7 +400,15 @@ const populateBatchInserters = (db: PgWriteStore) => { const insertPox3Events = async (dbData: DataStoreBlockUpdateData) => { for (const entry of dbData.txs) { for (const pox3Event of entry.pox3Events) { - await db.updatePox3Event(db.sql, entry.tx, pox3Event); + await db.updatePoxSyntheticEvent(db.sql, entry.tx, 'pox3_events', pox3Event); + } + } + }; + + const insertPox4Events = async (dbData: DataStoreBlockUpdateData) => { + for (const entry of dbData.txs) { + for (const pox4Event of entry.pox4Events) { + await db.updatePoxSyntheticEvent(db.sql, entry.tx, 'pox4_events', pox4Event); } } }; @@ -438,6 +446,8 @@ const populateBatchInserters = (db: PgWriteStore) => { insertPox2Events(dbData), // Insert pox3_events insertPox3Events(dbData), + // Insert pox4_events + insertPox4Events(dbData), ]); next(); diff --git a/src/event-stream/core-node-message.ts b/src/event-stream/core-node-message.ts index e23e569968..dd5927a0bf 100644 --- a/src/event-stream/core-node-message.ts +++ b/src/event-stream/core-node-message.ts @@ -254,6 +254,7 @@ export interface CoreNodeBlockMessage { }[]; pox_v1_unlock_height?: number; pox_v2_unlock_height?: number; + pox_v3_unlock_height?: number; } export interface CoreNodeParsedTxMessage { diff --git a/src/event-stream/event-server.ts b/src/event-stream/event-server.ts index c0ec3c86c0..7f123f7a29 100644 --- a/src/event-stream/event-server.ts +++ b/src/event-stream/event-server.ts @@ -35,7 +35,7 @@ import { DataStoreTxEventData, DbMicroblock, DataStoreAttachmentData, - DbPox2Event, + DbPoxSyntheticEvent, DbTxStatus, DbBnsSubdomain, } from '../datastore/common'; @@ -70,10 +70,11 @@ import { getTxDbStatus, } from '../datastore/helpers'; import { handleBnsImport } from '../import-v1'; -import { decodePox2PrintEvent } from './pox2-event-parsing'; +import { decodePoxSyntheticPrintEvent } from './pox-event-parsing'; import { logger, loggerMiddleware } from '../logger'; import * as zoneFileParser from 'zone-file'; import { hexToBuffer, isProdEnv, stopwatch } from '@hirosystems/api-toolkit'; +import { POX_2_CONTRACT_NAME, POX_3_CONTRACT_NAME, POX_4_CONTRACT_NAME } from '../pox-helpers'; const IBD_PRUNABLE_ROUTES = ['/new_mempool_tx', '/drop_mempool_tx', '/new_microblocks']; @@ -321,6 +322,7 @@ async function handleBlockMessage( txs: parseDataStoreTxEventData(parsedTxs, msg.events, msg, chainId), pox_v1_unlock_height: msg.pox_v1_unlock_height, pox_v2_unlock_height: msg.pox_v2_unlock_height, + pox_v3_unlock_height: msg.pox_v3_unlock_height, }; await db.update(dbData); @@ -350,6 +352,7 @@ function parseDataStoreTxEventData( namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }; switch (tx.parsed_tx.payload.type_id) { case TxPayloadTypeID.VersionedSmartContract: @@ -435,31 +438,37 @@ function parseDataStoreTxEventData( if (isPoxPrintEvent(event)) { const network = getChainIDNetwork(chainId) === 'mainnet' ? 'mainnet' : 'testnet'; const [, contractName] = event.contract_event.contract_identifier.split('.'); - // todo: switch could be abstracted more - switch (contractName) { - // pox-1 is handled in custom node events - case 'pox-2': { - const poxEventData = decodePox2PrintEvent(event.contract_event.raw_value, network); - if (poxEventData === null) break; - logger.debug(`Pox2 event data:`, poxEventData); - const dbPoxEvent: DbPox2Event = { + // pox-1 is handled in custom node events + const processSyntheticEvent = [ + POX_2_CONTRACT_NAME, + POX_3_CONTRACT_NAME, + POX_4_CONTRACT_NAME, + ].includes(contractName); + if (processSyntheticEvent) { + const poxEventData = decodePoxSyntheticPrintEvent( + event.contract_event.raw_value, + network + ); + if (poxEventData !== null) { + logger.debug(`Synthetic pox event data for ${contractName}:`, poxEventData); + const dbPoxEvent: DbPoxSyntheticEvent = { ...dbEvent, ...poxEventData, }; - dbTx.pox2Events.push(dbPoxEvent); - break; - } - case 'pox-3': { - const decodePox3PrintEvent = decodePox2PrintEvent; // todo: do we want to copy all pox2 methods for pox3? - const poxEventData = decodePox3PrintEvent(event.contract_event.raw_value, network); - if (poxEventData === null) break; - logger.debug(`Pox3 event data:`, poxEventData); - const dbPoxEvent: DbPox2Event = { - ...dbEvent, - ...poxEventData, - }; - dbTx.pox3Events.push(dbPoxEvent); - break; + switch (contractName) { + case POX_2_CONTRACT_NAME: { + dbTx.pox2Events.push(dbPoxEvent); + break; + } + case POX_3_CONTRACT_NAME: { + dbTx.pox3Events.push(dbPoxEvent); + break; + } + case POX_4_CONTRACT_NAME: { + dbTx.pox4Events.push(dbPoxEvent); + break; + } + } } } } @@ -623,6 +632,7 @@ function parseDataStoreTxEventData( tx.stxLockEvents, tx.pox2Events, tx.pox3Events, + tx.pox4Events, ] .flat() .sort((a, b) => a.event_index - b.event_index); diff --git a/src/event-stream/pox2-event-parsing.ts b/src/event-stream/pox-event-parsing.ts similarity index 64% rename from src/event-stream/pox2-event-parsing.ts rename to src/event-stream/pox-event-parsing.ts index 66e4e27525..4581988f0a 100644 --- a/src/event-stream/pox2-event-parsing.ts +++ b/src/event-stream/pox-event-parsing.ts @@ -1,17 +1,18 @@ import { - DbPox2BaseEventData, - DbPox2DelegateStackExtendEvent, - DbPox2DelegateStackIncreaseEvent, - DbPox2DelegateStackStxEvent, - DbPox2DelegateStxEvent, - DbPox2EventData, - DbPox2HandleUnlockEvent, - DbPox2StackAggregationCommitEvent, - DbPox2StackAggregationCommitIndexedEvent, - DbPox2StackAggregationIncreaseEvent, - DbPox2StackExtendEvent, - DbPox2StackIncreaseEvent, - DbPox2StackStxEvent, + DbPoxSyntheticBaseEventData, + DbPoxSyntheticDelegateStackExtendEvent, + DbPoxSyntheticDelegateStackIncreaseEvent, + DbPoxSyntheticDelegateStackStxEvent, + DbPoxSyntheticDelegateStxEvent, + DbPoxSyntheticEventData, + DbPoxSyntheticHandleUnlockEvent, + DbPoxSyntheticRevokeDelegateStxEvent, + DbPoxSyntheticStackAggregationCommitEvent, + DbPoxSyntheticStackAggregationCommitIndexedEvent, + DbPoxSyntheticStackAggregationIncreaseEvent, + DbPoxSyntheticStackExtendEvent, + DbPoxSyntheticStackIncreaseEvent, + DbPoxSyntheticStackStxEvent, } from '../datastore/common'; import { ClarityTypeID, @@ -29,12 +30,15 @@ import { decodeClarityValue, } from 'stacks-encoding-native-js'; import { poxAddressToBtcAddress } from '@stacks/stacking'; -import { Pox2EventName } from '../pox-helpers'; +import { SyntheticPoxEventName } from '../pox-helpers'; import { logger } from '../logger'; import { bufferToHex, coerceToBuffer } from '@hirosystems/api-toolkit'; function tryClarityPoxAddressToBtcAddress( - poxAddr: Pox2Addr | ClarityValueOptionalSome | ClarityValueOptionalNone, + poxAddr: + | PoxSyntheticEventAddr + | ClarityValueOptionalSome + | ClarityValueOptionalNone, network: 'mainnet' | 'testnet' | 'devnet' | 'mocknet' ): { btcAddr: string | null; raw: Buffer } { let btcAddr: string | null = null; @@ -68,12 +72,12 @@ function tryClarityPoxAddressToBtcAddress( }; } -type Pox2Addr = ClarityValueTuple<{ +type PoxSyntheticEventAddr = ClarityValueTuple<{ hashbytes: ClarityValueBuffer; version: ClarityValueBuffer; }>; -type PoX2EventData = ClarityValueTuple<{ +type PoXSyntheticEventData = ClarityValueTuple<{ name: ClarityValueStringAscii; balance: ClarityValueUInt; stacker: ClarityValuePrincipalStandard | ClarityValuePrincipalContract; @@ -82,68 +86,73 @@ type PoX2EventData = ClarityValueTuple<{ data: ClarityValueTuple; }>; -interface Pox2PrintEventTypes { - [Pox2EventName.HandleUnlock]: { +interface PoxSyntheticPrintEventTypes { + [SyntheticPoxEventName.HandleUnlock]: { 'first-cycle-locked': ClarityValueUInt; 'first-unlocked-cycle': ClarityValueUInt; }; - [Pox2EventName.StackStx]: { + [SyntheticPoxEventName.StackStx]: { 'lock-amount': ClarityValueUInt; 'lock-period': ClarityValueUInt; - 'pox-addr': Pox2Addr; + 'pox-addr': PoxSyntheticEventAddr; 'start-burn-height': ClarityValueUInt; 'unlock-burn-height': ClarityValueUInt; }; - [Pox2EventName.StackIncrease]: { + [SyntheticPoxEventName.StackIncrease]: { 'increase-by': ClarityValueUInt; 'total-locked': ClarityValueUInt; }; - [Pox2EventName.StackExtend]: { + [SyntheticPoxEventName.StackExtend]: { 'extend-count': ClarityValueUInt; 'unlock-burn-height': ClarityValueUInt; - 'pox-addr': Pox2Addr; + 'pox-addr': PoxSyntheticEventAddr; }; - [Pox2EventName.DelegateStx]: { + [SyntheticPoxEventName.DelegateStx]: { 'amount-ustx': ClarityValueUInt; 'delegate-to': ClarityValuePrincipalStandard | ClarityValuePrincipalContract; 'unlock-burn-height': ClarityValueOptionalSome | ClarityValueOptionalNone; - 'pox-addr': Pox2Addr | ClarityValueOptionalNone; + 'pox-addr': PoxSyntheticEventAddr | ClarityValueOptionalNone; }; - [Pox2EventName.DelegateStackStx]: { + [SyntheticPoxEventName.DelegateStackStx]: { 'lock-amount': ClarityValueUInt; 'unlock-burn-height': ClarityValueUInt; - 'pox-addr': Pox2Addr; + 'pox-addr': PoxSyntheticEventAddr; 'start-burn-height': ClarityValueUInt; 'lock-period': ClarityValueUInt; delegator: ClarityValuePrincipalStandard | ClarityValuePrincipalContract; }; - [Pox2EventName.DelegateStackIncrease]: { - 'pox-addr': Pox2Addr; + [SyntheticPoxEventName.DelegateStackIncrease]: { + 'pox-addr': PoxSyntheticEventAddr; 'increase-by': ClarityValueUInt; 'total-locked': ClarityValueUInt; delegator: ClarityValuePrincipalStandard | ClarityValuePrincipalContract; }; - [Pox2EventName.DelegateStackExtend]: { - 'pox-addr': Pox2Addr; + [SyntheticPoxEventName.DelegateStackExtend]: { + 'pox-addr': PoxSyntheticEventAddr; 'unlock-burn-height': ClarityValueUInt; 'extend-count': ClarityValueUInt; delegator: ClarityValuePrincipalStandard | ClarityValuePrincipalContract; }; - [Pox2EventName.StackAggregationCommit]: { - 'pox-addr': Pox2Addr; + [SyntheticPoxEventName.StackAggregationCommit]: { + 'pox-addr': PoxSyntheticEventAddr; 'reward-cycle': ClarityValueUInt; 'amount-ustx': ClarityValueUInt; }; - [Pox2EventName.StackAggregationCommitIndexed]: { - 'pox-addr': Pox2Addr; + [SyntheticPoxEventName.StackAggregationCommitIndexed]: { + 'pox-addr': PoxSyntheticEventAddr; 'reward-cycle': ClarityValueUInt; 'amount-ustx': ClarityValueUInt; }; - [Pox2EventName.StackAggregationIncrease]: { - 'pox-addr': Pox2Addr; + [SyntheticPoxEventName.StackAggregationIncrease]: { + 'pox-addr': PoxSyntheticEventAddr; 'reward-cycle': ClarityValueUInt; 'amount-ustx': ClarityValueUInt; }; + [SyntheticPoxEventName.RevokeDelegateStx]: { + 'amount-ustx': ClarityValueUInt; + 'delegate-to': ClarityValuePrincipalStandard | ClarityValuePrincipalContract; + 'pox-addr': PoxSyntheticEventAddr | ClarityValueOptionalNone; + }; } function clarityPrincipalToFullAddress( @@ -163,29 +172,29 @@ function clarityPrincipalToFullAddress( // https://github.com/stacks-network/stacks-blockchain/pull/3318 const PATCH_EVENT_BALANCES = true; -export function decodePox2PrintEvent( +export function decodePoxSyntheticPrintEvent( rawClarityData: string, network: 'mainnet' | 'testnet' | 'devnet' | 'mocknet' -): DbPox2EventData | null { +): DbPoxSyntheticEventData | null { const decoded = decodeClarityValue(rawClarityData); if (decoded.type_id === ClarityTypeID.ResponseError) { - logger.info(`Received ResponseError when decoding Pox2 print event: ${decoded.repr}`); + logger.info(`Received ResponseError when decoding Pox synthetic print event: ${decoded.repr}`); return null; } if (decoded.type_id !== ClarityTypeID.ResponseOk) { const valCommon: ClarityValueAbstract = decoded; throw new Error( - `Unexpected PoX2 event Clarity type ID, expected ResponseOk, got ${valCommon.type_id}: ${valCommon.repr}` + `Unexpected PoX synthetic event Clarity type ID, expected ResponseOk, got ${valCommon.type_id}: ${valCommon.repr}` ); } if (decoded.value.type_id !== ClarityTypeID.Tuple) { throw new Error( - `Unexpected PoX2 event Clarity type ID, expected Tuple, got ${decoded.value.type_id}` + `Unexpected PoX synthetic event Clarity type ID, expected Tuple, got ${decoded.value.type_id}` ); } - const opData = (decoded.value as PoX2EventData).data; + const opData = (decoded.value as PoXSyntheticEventData).data; - const baseEventData: DbPox2BaseEventData = { + const baseEventData: DbPoxSyntheticBaseEventData = { stacker: clarityPrincipalToFullAddress(opData.stacker), locked: BigInt(opData.locked.value), balance: BigInt(opData.balance.value), @@ -194,24 +203,24 @@ export function decodePox2PrintEvent( pox_addr_raw: null, }; - const eventName = opData.name.data as keyof Pox2PrintEventTypes; + const eventName = opData.name.data as keyof PoxSyntheticPrintEventTypes; if (opData.name.type_id !== ClarityTypeID.StringAscii) { throw new Error( - `Unexpected PoX2 event name type, expected StringAscii, got ${opData.name.type_id}` + `Unexpected PoX synthetic event name type, expected StringAscii, got ${opData.name.type_id}` ); } const eventData = opData.data.data; if (opData.data.type_id !== ClarityTypeID.Tuple) { throw new Error( - `Unexpected PoX2 event data payload type, expected Tuple, got ${opData.data.type_id}` + `Unexpected PoX synthetic event data payload type, expected Tuple, got ${opData.data.type_id}` ); } if ('pox-addr' in eventData) { const eventPoxAddr = eventData['pox-addr'] as - | Pox2Addr - | ClarityValueOptionalSome + | PoxSyntheticEventAddr + | ClarityValueOptionalSome | ClarityValueOptionalNone; const encodedArr = tryClarityPoxAddressToBtcAddress(eventPoxAddr, network); baseEventData.pox_addr = encodedArr.btcAddr; @@ -219,9 +228,9 @@ export function decodePox2PrintEvent( } switch (eventName) { - case Pox2EventName.HandleUnlock: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2HandleUnlockEvent = { + case SyntheticPoxEventName.HandleUnlock: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticHandleUnlockEvent = { ...baseEventData, name: eventName, data: { @@ -235,9 +244,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.StackStx: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2StackStxEvent = { + case SyntheticPoxEventName.StackStx: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticStackStxEvent = { ...baseEventData, name: eventName, data: { @@ -254,9 +263,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.StackIncrease: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2StackIncreaseEvent = { + case SyntheticPoxEventName.StackIncrease: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticStackIncreaseEvent = { ...baseEventData, name: eventName, data: { @@ -270,9 +279,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.StackExtend: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2StackExtendEvent = { + case SyntheticPoxEventName.StackExtend: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticStackExtendEvent = { ...baseEventData, name: eventName, data: { @@ -285,9 +294,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.DelegateStx: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2DelegateStxEvent = { + case SyntheticPoxEventName.DelegateStx: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticDelegateStxEvent = { ...baseEventData, name: eventName, data: { @@ -306,9 +315,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.DelegateStackStx: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2DelegateStackStxEvent = { + case SyntheticPoxEventName.DelegateStackStx: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticDelegateStackStxEvent = { ...baseEventData, name: eventName, data: { @@ -326,9 +335,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.DelegateStackIncrease: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2DelegateStackIncreaseEvent = { + case SyntheticPoxEventName.DelegateStackIncrease: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticDelegateStackIncreaseEvent = { ...baseEventData, name: eventName, data: { @@ -343,9 +352,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.DelegateStackExtend: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2DelegateStackExtendEvent = { + case SyntheticPoxEventName.DelegateStackExtend: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticDelegateStackExtendEvent = { ...baseEventData, name: eventName, data: { @@ -359,9 +368,9 @@ export function decodePox2PrintEvent( } return parsedData; } - case Pox2EventName.StackAggregationCommit: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2StackAggregationCommitEvent = { + case SyntheticPoxEventName.StackAggregationCommit: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticStackAggregationCommitEvent = { ...baseEventData, name: eventName, data: { @@ -371,9 +380,9 @@ export function decodePox2PrintEvent( }; return parsedData; } - case Pox2EventName.StackAggregationCommitIndexed: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2StackAggregationCommitIndexedEvent = { + case SyntheticPoxEventName.StackAggregationCommitIndexed: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticStackAggregationCommitIndexedEvent = { ...baseEventData, name: eventName, data: { @@ -383,9 +392,9 @@ export function decodePox2PrintEvent( }; return parsedData; } - case Pox2EventName.StackAggregationIncrease: { - const d = eventData as Pox2PrintEventTypes[typeof eventName]; - const parsedData: DbPox2StackAggregationIncreaseEvent = { + case SyntheticPoxEventName.StackAggregationIncrease: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticStackAggregationIncreaseEvent = { ...baseEventData, name: eventName, data: { @@ -395,7 +404,19 @@ export function decodePox2PrintEvent( }; return parsedData; } + case SyntheticPoxEventName.RevokeDelegateStx: { + const d = eventData as PoxSyntheticPrintEventTypes[typeof eventName]; + const parsedData: DbPoxSyntheticRevokeDelegateStxEvent = { + ...baseEventData, + name: eventName, + data: { + amount_ustx: BigInt(d['amount-ustx'].value), + delegate_to: clarityPrincipalToFullAddress(d['delegate-to']), + }, + }; + return parsedData; + } default: - throw new Error(`Unexpected PoX-2 event data name: ${opData.name.data}`); + throw new Error(`Unexpected PoX synthetic event data name: ${opData.name.data}`); } } diff --git a/src/event-stream/reader.ts b/src/event-stream/reader.ts index 40b7f1eeea..1a2eb06374 100644 --- a/src/event-stream/reader.ts +++ b/src/event-stream/reader.ts @@ -34,8 +34,8 @@ import { } from 'stacks-encoding-native-js'; import { DbMicroblockPartial, - DbPox2DelegateStxEvent, - DbPox2StackStxEvent, + DbPoxSyntheticDelegateStxEvent, + DbPoxSyntheticStackStxEvent, } from '../datastore/common'; import { NotImplementedError } from '../errors'; import { @@ -62,8 +62,8 @@ import { } from '@stacks/transactions'; import { poxAddressToTuple } from '@stacks/stacking'; import { c32ToB58 } from 'c32check'; -import { decodePox2PrintEvent } from './pox2-event-parsing'; -import { Pox2EventName } from '../pox-helpers'; +import { decodePoxSyntheticPrintEvent } from './pox-event-parsing'; +import { PoxContractIdentifiers, SyntheticPoxEventName } from '../pox-helpers'; import { principalCV } from '@stacks/transactions/dist/clarity/types/principalCV'; import { logger } from '../logger'; import { bufferToHex, hexToBuffer } from '@hirosystems/api-toolkit'; @@ -345,7 +345,7 @@ function createTransactionFromCoreBtcStxLockEvent( txResult: string, txId: string, /** also pox-3 compatible */ - stxStacksPox2Event: DbPox2StackStxEvent | undefined + stxStacksPox2Event: DbPoxSyntheticStackStxEvent | undefined ): DecodedTxResult { const resultCv = decodeClarityValue< ClarityValueResponse< @@ -450,7 +450,7 @@ function createTransactionFromCoreBtcStxLockEvent( function createTransactionFromCoreBtcDelegateStxEvent( chainId: ChainID, contractEvent: SmartContractEvent, - decodedEvent: DbPox2DelegateStxEvent, + decodedEvent: DbPoxSyntheticDelegateStxEvent, txResult: string, txId: string ): DecodedTxResult { @@ -652,7 +652,7 @@ export function parseMessageTransaction( (e): e is StxMintEvent => e.type === CoreNodeEventType.StxMintEvent ); - // pox-2 and pox-3 compatible events + // pox-2, pox-3, and pox-4 compatible events const poxEvent = events .filter( (e): e is SmartContractEvent => @@ -660,7 +660,7 @@ export function parseMessageTransaction( ) .map(e => { const network = getChainIDNetwork(chainId); - const decodedEvent = decodePox2PrintEvent(e.contract_event.raw_value, network); + const decodedEvent = decodePoxSyntheticPrintEvent(e.contract_event.raw_value, network); if (decodedEvent) { return { contractEvent: e, @@ -683,7 +683,7 @@ export function parseMessageTransaction( txSender = stxTransferEvent.stx_transfer_event.sender; } else if (stxLockEvent) { const stxStacksPoxEvent = - poxEvent?.decodedEvent.name === Pox2EventName.StackStx + poxEvent?.decodedEvent.name === SyntheticPoxEventName.StackStx ? poxEvent.decodedEvent : undefined; rawTx = createTransactionFromCoreBtcStxLockEvent( @@ -695,7 +695,7 @@ export function parseMessageTransaction( stxStacksPoxEvent ); txSender = stxLockEvent.stx_lock_event.locked_address; - } else if (poxEvent && poxEvent.decodedEvent.name === Pox2EventName.DelegateStx) { + } else if (poxEvent && poxEvent.decodedEvent.name === SyntheticPoxEventName.DelegateStx) { rawTx = createTransactionFromCoreBtcDelegateStxEvent( chainId, poxEvent.contractEvent, @@ -845,10 +845,5 @@ export function parseMessageTransaction( export function isPoxPrintEvent(event: SmartContractEvent): boolean { if (event.contract_event.topic !== 'print') return false; - - const [address, name] = event.contract_event.contract_identifier.split('.'); - return ( - (address == BootContractAddress.mainnet || address == BootContractAddress.testnet) && - name.startsWith('pox') - ); + return PoxContractIdentifiers.includes(event.contract_event.contract_identifier); } diff --git a/src/pox-helpers.ts b/src/pox-helpers.ts index 1fa196f2a4..7cb76f088e 100644 --- a/src/pox-helpers.ts +++ b/src/pox-helpers.ts @@ -1,4 +1,5 @@ -export const enum Pox2EventName { +/** Names for synthetic events generated for the pox-2, pox-3, and pox-4 contracts */ +export enum SyntheticPoxEventName { HandleUnlock = 'handle-unlock', StackStx = 'stack-stx', StackIncrease = 'stack-increase', @@ -10,9 +11,43 @@ export const enum Pox2EventName { StackAggregationCommit = 'stack-aggregation-commit', StackAggregationCommitIndexed = 'stack-aggregation-commit-indexed', StackAggregationIncrease = 'stack-aggregation-increase', + RevokeDelegateStx = 'revoke-delegate-stx', // Only guaranteed to be present in pox-4 } -export const enum Pox2ContractIdentifer { - mainnet = 'SP000000000000000000002Q6VF78.pox-2', - testnet = 'ST000000000000000000002AMW42H.pox-2', -} +const BOOT_ADDR_MAINNET = 'SP000000000000000000002Q6VF78'; +const BOOT_ADDR_TESTNET = 'ST000000000000000000002AMW42H'; + +export const POX_1_CONTRACT_NAME = 'pox'; +export const POX_2_CONTRACT_NAME = 'pox-2'; +export const POX_3_CONTRACT_NAME = 'pox-3'; +export const POX_4_CONTRACT_NAME = 'pox-4'; + +export const PoxContractNames = [ + POX_1_CONTRACT_NAME, + POX_2_CONTRACT_NAME, + POX_3_CONTRACT_NAME, + POX_4_CONTRACT_NAME, +] as const; + +export const PoxContractIdentifier = { + pox1: { + mainnet: `${BOOT_ADDR_MAINNET}.${POX_1_CONTRACT_NAME}`, + testnet: `${BOOT_ADDR_TESTNET}.${POX_1_CONTRACT_NAME}`, + }, + pox2: { + mainnet: `${BOOT_ADDR_MAINNET}.${POX_2_CONTRACT_NAME}`, + testnet: `${BOOT_ADDR_TESTNET}.${POX_2_CONTRACT_NAME}`, + }, + pox3: { + mainnet: `${BOOT_ADDR_MAINNET}.${POX_3_CONTRACT_NAME}`, + testnet: `${BOOT_ADDR_TESTNET}.${POX_3_CONTRACT_NAME}`, + }, + pox4: { + mainnet: `${BOOT_ADDR_MAINNET}.${POX_4_CONTRACT_NAME}`, + testnet: `${BOOT_ADDR_TESTNET}.${POX_4_CONTRACT_NAME}`, + }, +} as const; + +export const PoxContractIdentifiers = Object.values(PoxContractIdentifier).flatMap( + Object.values +) as string[]; diff --git a/src/rosetta/rosetta-helpers.ts b/src/rosetta/rosetta-helpers.ts index 5427109c1f..c00c3ff908 100644 --- a/src/rosetta/rosetta-helpers.ts +++ b/src/rosetta/rosetta-helpers.ts @@ -30,12 +30,7 @@ import { getTxTypeString, parseContractCallMetadata, } from '../api/controllers/db-controller'; -import { - PoxContractIdentifier, - RosettaConstants, - RosettaNetworks, - RosettaOperationType, -} from '../api/rosetta-constants'; +import { RosettaConstants, RosettaNetworks, RosettaOperationType } from '../api/rosetta-constants'; import { BaseTx, DbAssetEventTypeId, @@ -78,6 +73,7 @@ import { parseRecoverableSignatureVrs } from '@stacks/common'; import { logger } from '../logger'; import { hexToBuffer } from '@hirosystems/api-toolkit'; import { RosettaFtMetadata, RosettaFtMetadataClient } from './rosetta-ft-metadata-client'; +import { PoxContractIdentifiers } from '../pox-helpers'; enum CoinAction { CoinSpent = 'coin_spent', @@ -692,14 +688,7 @@ async function makeCallContractOperation( case 'stack-stx': case 'delegate-stx': case 'revoke-delegate-stx': - if ( - stackContractCall.contract_call.contract_id === PoxContractIdentifier.pox1.testnet || - stackContractCall.contract_call.contract_id === PoxContractIdentifier.pox1.mainnet || - stackContractCall.contract_call.contract_id === PoxContractIdentifier.pox2.testnet || - stackContractCall.contract_call.contract_id === PoxContractIdentifier.pox2.mainnet || - stackContractCall.contract_call.contract_id === PoxContractIdentifier.pox3.testnet || - stackContractCall.contract_call.contract_id === PoxContractIdentifier.pox3.mainnet - ) { + if (PoxContractIdentifiers.includes(stackContractCall.contract_call.contract_id)) { parseStackingContractCall(contractCallOp, stackContractCall); } else { parseGenericContractCall(contractCallOp, tx); diff --git a/src/test-utils/shared-setup.ts b/src/test-utils/shared-setup.ts index b842d1276d..8b20d20601 100644 --- a/src/test-utils/shared-setup.ts +++ b/src/test-utils/shared-setup.ts @@ -22,12 +22,12 @@ async function standByForPoxToBeReady(client: StacksCoreRpcClient): Promise { } } -export async function fetchGet(endpoint: string) { +export async function fetchGet(endpoint: string): Promise { const result = await supertest(testEnv.api.server).get(endpoint); + // Follow redirects + if (result.status >= 300 && result.status < 400) { + return await fetchGet(result.header.location as string); + } expect(result.status).toBe(200); expect(result.type).toBe('application/json'); return result.body as TRes; diff --git a/src/tests-2.4/block-zero-handling.ts b/src/tests-2.5/block-zero-handling.ts similarity index 100% rename from src/tests-2.4/block-zero-handling.ts rename to src/tests-2.5/block-zero-handling.ts diff --git a/src/tests-2.4/env-setup.ts b/src/tests-2.5/env-setup.ts similarity index 100% rename from src/tests-2.4/env-setup.ts rename to src/tests-2.5/env-setup.ts diff --git a/src/tests-2.4/faucet-stx.ts b/src/tests-2.5/faucet-stx.ts similarity index 100% rename from src/tests-2.4/faucet-stx.ts rename to src/tests-2.5/faucet-stx.ts diff --git a/src/tests-2.4/global-setup.ts b/src/tests-2.5/global-setup.ts similarity index 82% rename from src/tests-2.4/global-setup.ts rename to src/tests-2.5/global-setup.ts index 2ab33c8fb7..40fdfa3ef6 100644 --- a/src/tests-2.4/global-setup.ts +++ b/src/tests-2.5/global-setup.ts @@ -11,20 +11,20 @@ export interface GlobalTestEnv { eventServer: EventStreamServer; } -async function standByForPox3ToBeReady(client: StacksCoreRpcClient): Promise { +async function standByForPox4ToBeReady(client: StacksCoreRpcClient): Promise { let tries = 0; while (true) { try { tries++; const poxInfo = await client.getPox(); - if (poxInfo.contract_id.includes('pox-3')) { - console.log(`PoX-3 ready.`); + if (poxInfo.contract_id.includes('pox-4')) { + console.log(`PoX-4 ready.`); return; } - console.log(`Waiting on PoX-3 to be ready`); + console.log(`Waiting on PoX-4 to be ready`); await timeout(500); } catch (error) { - console.log(`Waiting on PoX-3 to be ready, retrying after ${error}`); + console.log(`Waiting on PoX-4 to be ready, retrying after ${error}`); await timeout(500); } } @@ -45,7 +45,7 @@ export default async (): Promise => { const eventServer = await startEventServer({ datastore: db, chainId: ChainID.Testnet }); const client = new StacksCoreRpcClient(); - await standByForPox3ToBeReady(client); + await standByForPox4ToBeReady(client); const testEnv: GlobalTestEnv = { db: db, diff --git a/src/tests-2.4/global-teardown.ts b/src/tests-2.5/global-teardown.ts similarity index 100% rename from src/tests-2.4/global-teardown.ts rename to src/tests-2.5/global-teardown.ts diff --git a/src/tests-2.4/pox-3-btc-address-formats.ts b/src/tests-2.5/pox-4-btc-address-formats.ts similarity index 98% rename from src/tests-2.4/pox-3-btc-address-formats.ts rename to src/tests-2.5/pox-4-btc-address-formats.ts index 1a80bf4592..07431ae8b6 100644 --- a/src/tests-2.4/pox-3-btc-address-formats.ts +++ b/src/tests-2.5/pox-4-btc-address-formats.ts @@ -21,13 +21,13 @@ import { } from '../test-utils/test-helpers'; import { hexToBuffer } from '@hirosystems/api-toolkit'; -describe('PoX-3 - Stack using supported bitcoin address formats', () => { +describe('PoX-4 - Stack using supported bitcoin address formats', () => { test('Standby for next cycle', async () => { const poxInfo = await testEnv.client.getPox(); await standByUntilBurnBlock(poxInfo.next_cycle.reward_phase_start_block_height); // a good time to stack }); - describe('PoX-3 - Stacking operations P2SH-P2WPKH', () => { + describe('PoX-4 - Stacking operations P2SH-P2WPKH', () => { const account = testnetKeys[1]; let btcAddr: string; let btcRegtestAccount: VerboseKeyOutput; @@ -84,7 +84,7 @@ describe('PoX-3 - Stack using supported bitcoin address formats', () => { cycleBlockLength = cycleCount * poxInfo.reward_cycle_length; [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('stack-stx tx', async () => { @@ -276,7 +276,7 @@ describe('PoX-3 - Stack using supported bitcoin address formats', () => { }); }); - describe('PoX-3 - Stacking operations P2WPKH', () => { + describe('PoX-4 - Stacking operations P2WPKH', () => { const account = testnetKeys[1]; let btcAddr: string; let btcRegtestAddr: string; @@ -331,7 +331,7 @@ describe('PoX-3 - Stack using supported bitcoin address formats', () => { cycleBlockLength = cycleCount * poxInfo.reward_cycle_length; [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('stack-stx tx', async () => { @@ -524,7 +524,7 @@ describe('PoX-3 - Stack using supported bitcoin address formats', () => { }); }); - describe('PoX-3 - Stacking operations P2WSH', () => { + describe('PoX-4 - Stacking operations P2WSH', () => { const account = testnetKeys[1]; let btcAddr: string; let btcRegtestAddr: string; @@ -584,7 +584,7 @@ describe('PoX-3 - Stack using supported bitcoin address formats', () => { cycleBlockLength = cycleCount * poxInfo.reward_cycle_length; [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('stack-stx tx', async () => { @@ -776,7 +776,7 @@ describe('PoX-3 - Stack using supported bitcoin address formats', () => { }); }); - describe('PoX-3 - Stacking operations P2TR', () => { + describe('PoX-4 - Stacking operations P2TR', () => { const account = testnetKeys[2]; let btcAddr: string; let btcRegtestAddr: string; @@ -836,7 +836,7 @@ describe('PoX-3 - Stack using supported bitcoin address formats', () => { cycleBlockLength = cycleCount * poxInfo.reward_cycle_length; [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('stack-stx tx', async () => { diff --git a/src/tests-2.4/pox-3-burnchain-delegate-stx.ts b/src/tests-2.5/pox-4-burnchain-delegate-stx.ts similarity index 98% rename from src/tests-2.4/pox-3-burnchain-delegate-stx.ts rename to src/tests-2.5/pox-4-burnchain-delegate-stx.ts index 4d1fa5e813..3992482548 100644 --- a/src/tests-2.4/pox-3-burnchain-delegate-stx.ts +++ b/src/tests-2.5/pox-4-burnchain-delegate-stx.ts @@ -35,7 +35,7 @@ import { ApiServer } from '../api/init'; import { StacksNetwork } from '@stacks/network'; import { RPCClient } from 'rpc-bitcoin'; import * as supertest from 'supertest'; -import { Pox2ContractIdentifer } from '../pox-helpers'; +import { PoxContractIdentifier } from '../pox-helpers'; import { ClarityValueUInt, decodeClarityValue } from 'stacks-encoding-native-js'; import { decodeBtcAddress } from '@stacks/stacking'; import { timeout } from '@hirosystems/api-toolkit'; @@ -172,7 +172,7 @@ async function createPox2DelegateStx(args: { }; } -describe('PoX-3 - Stack using Bitcoin-chain ops', () => { +describe('PoX-4 - Stack using Bitcoin-chain ops', () => { const seedAccount = testnetKeys[0]; let db: PgWriteStore; @@ -216,7 +216,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { const poxInfo = await client.getPox(); const [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('Fund STX to new account for testing', async () => { @@ -332,7 +332,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { test('Ensure delegate-stx BitcoinOp parsed', async () => { const pox2Txs = await supertest(api.server) - .get(`/extended/v1/address/${BootContractAddress.testnet}.pox-3/transactions`) + .get(`/extended/v1/address/${BootContractAddress.testnet}.pox-4/transactions`) .expect(200); const delegateStxTxResp = await supertest(api.server) .get(`/extended/v1/tx/${pox2Txs.body.results[0].tx_id}`) @@ -351,7 +351,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { )})))`; expect(delegateStxTx.contract_call).toEqual({ - contract_id: 'ST000000000000000000002AMW42H.pox-3', + contract_id: 'ST000000000000000000002AMW42H.pox-4', function_name: 'delegate-stx', function_signature: '(define-public (delegate-stx (amount-ustx uint) (delegate-to principal) (until-burn-ht (optional uint)) (pox-addr (optional (tuple (hashbytes (buff 32)) (version (buff 1)))))))', @@ -418,7 +418,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { expect(coreBalanceInfo.unlock_height).toBeGreaterThan(0); // validate delegate-stack-stx pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${delegateStackStxTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${delegateStackStxTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -463,7 +463,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { expect(txObj.tx_type).toBe('contract_call'); expect(txObj.tx_status).toBe('success'); expect(txObj.sender_address).toBe(account.stxAddr); - expect(txObj.contract_call.contract_id).toBe(Pox2ContractIdentifer.testnet); + expect(txObj.contract_call.contract_id).toBe(PoxContractIdentifier.pox2.testnet); expect(txObj.contract_call.function_name).toBe('stack-stx'); const callArg1 = txObj.contract_call.function_args![0]; diff --git a/src/tests-2.4/pox-3-burnchain-stack-stx.ts b/src/tests-2.5/pox-4-burnchain-stack-stx.ts similarity index 99% rename from src/tests-2.4/pox-3-burnchain-stack-stx.ts rename to src/tests-2.5/pox-4-burnchain-stack-stx.ts index d129bdbc9c..1667d4a00a 100644 --- a/src/tests-2.4/pox-3-burnchain-stack-stx.ts +++ b/src/tests-2.5/pox-4-burnchain-stack-stx.ts @@ -134,7 +134,7 @@ async function createPox2StackStx(args: { }; } -describe('PoX-3 - Stack using Bitcoin-chain ops', () => { +describe('PoX-4 - Stack using Bitcoin-chain ops', () => { const seedAccount = testnetKeys[0]; let db: PgWriteStore; @@ -169,7 +169,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { const poxInfo = await client.getPox(); const [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('Fund STX to new account for testing', async () => { @@ -299,7 +299,7 @@ describe('PoX-3 - Stack using Bitcoin-chain ops', () => { expect(txObj.tx_type).toBe('contract_call'); expect(txObj.tx_status).toBe('success'); expect(txObj.sender_address).toBe(account.stxAddr); - expect(txObj.contract_call.contract_id).toBe(`${BootContractAddress.testnet}.pox-3`); + expect(txObj.contract_call.contract_id).toBe(`${BootContractAddress.testnet}.pox-4`); expect(txObj.contract_call.function_name).toBe('stack-stx'); const callArg1 = txObj.contract_call.function_args![0]; diff --git a/src/tests-2.4/pox-3-delegate-aggregation.ts b/src/tests-2.5/pox-4-delegate-aggregation.ts similarity index 97% rename from src/tests-2.4/pox-3-delegate-aggregation.ts rename to src/tests-2.5/pox-4-delegate-aggregation.ts index 504914925c..4d48151086 100644 --- a/src/tests-2.4/pox-3-delegate-aggregation.ts +++ b/src/tests-2.5/pox-4-delegate-aggregation.ts @@ -32,7 +32,7 @@ import { } from 'stacks-encoding-native-js'; import { AddressStxBalanceResponse } from '@stacks/stacks-blockchain-api-types'; -describe('PoX-3 - Delegate aggregation increase operations', () => { +describe('PoX-4 - Delegate aggregation increase operations', () => { const seedKey = testnetKeys[4].secretKey; const delegatorKey = '04608922f3ce63971bb120fa9c9454c5bd06370f61414040a737a6ee8ef8a10f01'; const delegateeKey = 'b038e143cf4ee4c079b3c3605a8ed28732e5745c138b728408e80faf7a59b8c201'; @@ -118,7 +118,7 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { // wait until the start of the next cycle so we have enough blocks within the cycle to perform the various txs poxInfo = await standByForNextPoxCycle(); [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('Perform delegate-stx operation', async () => { @@ -153,7 +153,7 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { // validate pool delegations const stackersRes: any = await fetchGet( - `/extended/beta/stacking/${delegatorAccount.stxAddr}/delegations` + `/extended/v1/pox4/${delegatorAccount.stxAddr}/delegations` ); expect(stackersRes).toBeDefined(); expect(stackersRes.total).toBe(1); @@ -220,7 +220,7 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { expect(coreBalanceInfo.unlock_height).toBeGreaterThan(0); // validate delegate-stack-stx pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${delegateStackStxTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${delegateStackStxTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -280,7 +280,7 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { expect(poxCycleAddressIndex).toEqual(0n); // validate stack-aggregation-commit pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${stackAggrCommitTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${stackAggrCommitTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -368,7 +368,7 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { // validate delegate-stack-stx pox2 event for this tx const delegateStackIncreasePoxEvents: any = await fetchGet( - `/extended/v1/pox3_events/tx/${delegateStackIncreaseDbTx.tx_id}` + `/extended/v1/pox4_events/tx/${delegateStackIncreaseDbTx.tx_id}` ); expect(delegateStackIncreasePoxEvents).toBeDefined(); expect(delegateStackIncreasePoxEvents.results).toHaveLength(1); @@ -405,7 +405,7 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { // validate stack-aggregation-commit pox2 event for this tx const stackAggreIncreasePoxEvents: any = await fetchGet( - `/extended/v1/pox3_events/tx/${stackAggrIncreaseTxId}` + `/extended/v1/pox4_events/tx/${stackAggrIncreaseTxId}` ); expect(stackAggreIncreasePoxEvents).toBeDefined(); expect(stackAggreIncreasePoxEvents.results).toHaveLength(1); diff --git a/src/tests-2.4/pox-3-delegate-revoked-stacking.ts b/src/tests-2.5/pox-4-delegate-revoked-stacking.ts similarity index 89% rename from src/tests-2.4/pox-3-delegate-revoked-stacking.ts rename to src/tests-2.5/pox-4-delegate-revoked-stacking.ts index 19951d762c..d29f4c8e76 100644 --- a/src/tests-2.4/pox-3-delegate-revoked-stacking.ts +++ b/src/tests-2.5/pox-4-delegate-revoked-stacking.ts @@ -30,7 +30,7 @@ import { testEnv, } from '../test-utils/test-helpers'; -describe('PoX-3 - Delegate Revoked Stacking', () => { +describe('PoX-4 - Delegate Revoked Stacking', () => { const seedKey = testnetKeys[4].secretKey; const delegatorKey = '72e8e3725324514c38c2931ed337ab9ab8d8abaae83ed2275456790194b1fd3101'; const delegateeKey = '0d174cf0be276cedcf21727611ef2504aed093d8163f65985c07760fda12a7ea01'; @@ -74,6 +74,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { amount: gasAmount, network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const { txId: stxXferId1 } = await testEnv.client.sendTransaction( Buffer.from(stxXfer1.serialize()) @@ -88,6 +89,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, nonce: stxXfer1.auth.spendingCondition.nonce + 1n, + fee: 10000n, }); const { txId: stxXferId2 } = await testEnv.client.sendTransaction( Buffer.from(stxXfer2.serialize()) @@ -113,7 +115,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { poxInfo = await standByForPoxCycle(); [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); const balanceInfo = await testEnv.client.getAccount(STACKER.stxAddr); expect(BigInt(balanceInfo.balance)).toBeGreaterThan(0n); @@ -138,6 +140,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const delegateStackTxResult = await testEnv.client.sendTransaction( Buffer.from(delegateStackTx.serialize()) @@ -163,14 +166,15 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const { txId: delegateStxTxId } = await testEnv.client.sendTransaction( Buffer.from(delegateStxTx.serialize()) ); const delegateStxDbTx = await standByForTxSuccess(delegateStxTxId); - // validate delegate-stx pox3 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${delegateStxDbTx.tx_id}`); + // validate delegate-stx pox4 event for this tx + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${delegateStxDbTx.tx_id}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -222,6 +226,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const { txId: delegateStackStxTxId } = await testEnv.client.sendTransaction( Buffer.from(delegateStackStxTx.serialize()) @@ -234,7 +239,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { expect(coreBalanceInfo.unlock_height).toBeGreaterThan(0); // validate delegate-stack-stx pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${delegateStackStxTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${delegateStackStxTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -271,9 +276,14 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { functionArgs: [], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const revokeTxResult = await testEnv.client.sendTransaction(Buffer.from(revokeTx.serialize())); - await standByForTxSuccess(revokeTxResult.txId); + const revokeStackDbTx = await standByForTxSuccess(revokeTxResult.txId); + + const revokeStackResult = decodeClarityValue(revokeStackDbTx.raw_result); + expect(revokeStackResult.repr).toEqual('(ok true)'); + expect(revokeStackDbTx.status).toBe(DbTxStatus.Success); // revocation doesn't change anything for the previous delegate-stack-stx state const coreBalanceInfo = await testEnv.client.getAccount(STACKER.stxAddr); @@ -299,6 +309,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const delegateStackTxResult = await testEnv.client.sendTransaction( Buffer.from(delegateStackTx.serialize()) @@ -309,47 +320,6 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { expect(delegateStackResult.repr).toEqual('(err 9)'); // ERR_STACKING_PERMISSION_DENIED }); - test('Try to perform delegate-stx - again', async () => { - // make sure stacker is not currently delegating - await expect( - readOnlyFnCall( - [contractAddress, contractName], - 'get-delegation-info', - [standardPrincipalCV(STACKER.stxAddr)], - STACKER.stxAddr - ) - ).rejects.toThrowError( - 'OptionNone result for call to ST000000000000000000002AMW42H,pox-3::get-delegation-info' - ); - - // but stacker is still locked - const coreBalanceInfo = await testEnv.client.getAccount(STACKER.stxAddr); - expect(BigInt(coreBalanceInfo.locked)).toBe(DELEGATE_HALF_AMOUNT); - - // delegate with the full amount - const delegateTx = await makeContractCall({ - senderKey: STACKER.secretKey, - contractAddress, - contractName, - functionName: 'delegate-stx', - functionArgs: [ - uintCV(DELEGATE_FULL_AMOUNT), - standardPrincipalCV(POOL.stxAddr), // delegate-to - noneCV(), // untilBurnBlockHeight - someCV(STACKER.poxAddrClar), // pox-addr - ], - network: testEnv.stacksNetwork, - anchorMode: AnchorMode.OnChainOnly, - }); - const delegateTxResult = await testEnv.client.sendTransaction( - Buffer.from(delegateTx.serialize()) - ); - const delegateDbTx = await standByForTx(delegateTxResult.txId); - expect(delegateDbTx.status).not.toBe(DbTxStatus.Success); - const delegateResult = decodeClarityValue(delegateDbTx.raw_result); - expect(delegateResult.repr).toEqual('(err 3)'); // ERR_STACKING_ALREADY_STACKED - }); - test('Try to perform delegate-stack-increase - without delegation', async () => { const delegateStackIncreaseTx = await makeContractCall({ senderKey: POOL.secretKey, @@ -363,16 +333,17 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const { txId: delegateStackIncreaseTxId } = await testEnv.client.sendTransaction( Buffer.from(delegateStackIncreaseTx.serialize()) ); const delegateStackIncreaseTxResult = await standByForTx(delegateStackIncreaseTxId); - expect(delegateStackIncreaseTxResult.status).not.toBe(DbTxStatus.Success); const delegateStackIncreaseResult = decodeClarityValue( delegateStackIncreaseTxResult.raw_result ); expect(delegateStackIncreaseResult.repr).toEqual('(err 9)'); // ERR_STACKING_PERMISSION_DENIED + expect(delegateStackIncreaseTxResult.status).not.toBe(DbTxStatus.Success); }); test('Try to perform delegate-stack-extend - without delegation', async () => { @@ -388,14 +359,15 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const { txId: delegateStackextendTxId } = await testEnv.client.sendTransaction( Buffer.from(delegateStackextendTx.serialize()) ); const delegateStackextendTxResult = await standByForTx(delegateStackextendTxId); - expect(delegateStackextendTxResult.status).not.toBe(DbTxStatus.Success); const delegateStackextendResult = decodeClarityValue(delegateStackextendTxResult.raw_result); expect(delegateStackextendResult.repr).toEqual('(err 9)'); // ERR_STACKING_PERMISSION_DENIED + expect(delegateStackextendTxResult.status).not.toBe(DbTxStatus.Success); }); test('Try to perform delegate-stack-stx - without delegation', async () => { @@ -416,6 +388,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const { txId: delegateStackStxTxId } = await testEnv.client.sendTransaction( Buffer.from(delegateStackStxTx.serialize()) @@ -441,6 +414,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { ], network: testEnv.stacksNetwork, anchorMode: AnchorMode.OnChainOnly, + fee: 10000n, }); const { txId: stackAggrCommitTxId } = await testEnv.client.sendTransaction( Buffer.from(stackAggrCommitTx.serialize()) @@ -448,7 +422,7 @@ describe('PoX-3 - Delegate Revoked Stacking', () => { await standByForTxSuccess(stackAggrCommitTxId); // validate stack-aggregation-commit pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${stackAggrCommitTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${stackAggrCommitTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( diff --git a/src/tests-2.4/pox-3-delegate-stacking.ts b/src/tests-2.5/pox-4-delegate-stacking.ts similarity index 96% rename from src/tests-2.4/pox-3-delegate-stacking.ts rename to src/tests-2.5/pox-4-delegate-stacking.ts index e5e64e0a5b..8274cd12d4 100644 --- a/src/tests-2.4/pox-3-delegate-stacking.ts +++ b/src/tests-2.5/pox-4-delegate-stacking.ts @@ -24,7 +24,7 @@ import { import { ClarityValueTuple, ClarityValueUInt } from 'stacks-encoding-native-js'; import { AddressStxBalanceResponse } from '@stacks/stacks-blockchain-api-types'; -describe('PoX-3 - Delegate Stacking operations', () => { +describe('PoX-4 - Delegate Stacking operations', () => { const seedKey = testnetKeys[4].secretKey; const delegatorKey = '72e8e3725324514c38c2931ed337ab9ab8d8abaae83ed2275456790194b1fd3101'; const delegateeKey = '0d174cf0be276cedcf21727611ef2504aed093d8163f65985c07760fda12a7ea01'; @@ -110,7 +110,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { poxInfo = await standByForNextPoxCycle(); [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('Perform delegate-stx operation', async () => { @@ -143,7 +143,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { const delegateStxDbTx = await standByForTxSuccess(delegateStxTxId); // validate delegate-stx pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${delegateStxDbTx.tx_id}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${delegateStxDbTx.tx_id}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -162,7 +162,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { // validate pool delegations const stackersRes: any = await fetchGet( - `/extended/beta/stacking/${delegatorAccount.stxAddr}/delegations` + `/extended/v1/pox4/${delegatorAccount.stxAddr}/delegations` ); expect(stackersRes).toBeDefined(); expect(stackersRes.total).toBe(1); @@ -177,7 +177,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { // validate pool delegations respects `after_block` limitter const stackersRes2: any = await fetchGet( - `/extended/beta/stacking/${delegatorAccount.stxAddr}/delegations?after_block=${delegateStxDbTx.block_height}` + `/extended/v1/pox4/${delegatorAccount.stxAddr}/delegations?after_block=${delegateStxDbTx.block_height}` ); expect(stackersRes2).toBeDefined(); expect(stackersRes2.total).toBe(0); @@ -236,7 +236,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { expect(coreBalanceInfo.unlock_height).toBeGreaterThan(0); // validate delegate-stack-stx pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${delegateStackStxTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${delegateStackStxTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -300,7 +300,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { // validate delegate-stack-stx pox2 event for this tx const res: any = await fetchGet( - `/extended/v1/pox3_events/tx/${delegateStackIncreaseDbTx.tx_id}` + `/extended/v1/pox4_events/tx/${delegateStackIncreaseDbTx.tx_id}` ); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); @@ -362,7 +362,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { expect(coreBalanceInfo.unlock_height).toBeGreaterThan(coreBalanceInfoPreIncrease.unlock_height); // validate delegate-stack-extend pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${delegateStackExtendTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${delegateStackExtendTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -414,7 +414,7 @@ describe('PoX-3 - Delegate Stacking operations', () => { const stackAggrCommmitDbTx = await standByForTxSuccess(stackAggrCommitTxId); // validate stack-aggregation-commit pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${stackAggrCommitTxId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${stackAggrCommitTxId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( diff --git a/src/tests-2.4/pox-3-rosetta-btc-addr-types.ts b/src/tests-2.5/pox-4-rosetta-btc-addr-types.ts similarity index 97% rename from src/tests-2.4/pox-3-rosetta-btc-addr-types.ts rename to src/tests-2.5/pox-4-rosetta-btc-addr-types.ts index 1da11dddf6..ffa65abe7e 100644 --- a/src/tests-2.4/pox-3-rosetta-btc-addr-types.ts +++ b/src/tests-2.5/pox-4-rosetta-btc-addr-types.ts @@ -21,7 +21,7 @@ const BTC_ADDRESS_CASES = [ ] as const; describe.each(BTC_ADDRESS_CASES)( - 'PoX-3 - Rosetta - Stack with BTC address format $addressFormat', + 'PoX-4 - Rosetta - Stack with BTC address format $addressFormat', ({ addressFormat }) => { let poxInfo: CoreRpcPoxInfo; const account = testnetKeys[1]; @@ -57,7 +57,7 @@ describe.each(BTC_ADDRESS_CASES)( ustxAmount, }); expect(rosettaStackStx.tx.status).toBe(DbTxStatus.Success); - expect(rosettaStackStx.constructionMetadata.metadata.contract_name).toBe('pox-3'); + expect(rosettaStackStx.constructionMetadata.metadata.contract_name).toBe('pox-4'); }); test('Validate reward set received', async () => { diff --git a/src/tests-2.4/pox-3-rosetta-cycle-phases.ts b/src/tests-2.5/pox-4-rosetta-cycle-phases.ts similarity index 96% rename from src/tests-2.4/pox-3-rosetta-cycle-phases.ts rename to src/tests-2.5/pox-4-rosetta-cycle-phases.ts index 6305cc648f..c117f031f1 100644 --- a/src/tests-2.4/pox-3-rosetta-cycle-phases.ts +++ b/src/tests-2.5/pox-4-rosetta-cycle-phases.ts @@ -11,7 +11,7 @@ const account = testnetKeys[1]; const btcAddr = '2N74VLxyT79VGHiBK2zEg3a9HJG7rEc5F3o'; describe.each(BLOCK_SHIFT_COUNT)( - 'PoX-3 - Rosetta - Stack on any phase of cycle $shift', + 'PoX-4 - Rosetta - Stack on any phase of cycle $shift', ({ shift }) => { test('Standby for cycle phase', async () => { const poxInfo = await testEnv.client.getPox(); diff --git a/src/tests-2.4/pox-3-rosetta-segwit.ts b/src/tests-2.5/pox-4-rosetta-segwit.ts similarity index 98% rename from src/tests-2.4/pox-3-rosetta-segwit.ts rename to src/tests-2.5/pox-4-rosetta-segwit.ts index c878423635..c7f155cf5a 100644 --- a/src/tests-2.4/pox-3-rosetta-segwit.ts +++ b/src/tests-2.5/pox-4-rosetta-segwit.ts @@ -27,7 +27,7 @@ import { } from '../test-utils/test-helpers'; import { hexToBuffer } from '@hirosystems/api-toolkit'; -describe('PoX-3 - Rosetta - Stacking with segwit', () => { +describe('PoX-4 - Rosetta - Stacking with segwit', () => { let btcAddr: string; let btcAddrTestnet: string; const seedAccount = testnetKeys[0]; @@ -131,10 +131,10 @@ describe('PoX-3 - Rosetta - Stacking with segwit', () => { ustxAmount: ustxAmount, }); - expect(stackingResult.constructionMetadata.metadata.contract_name).toBe('pox-3'); + expect(stackingResult.constructionMetadata.metadata.contract_name).toBe('pox-4'); expect(stackingResult.constructionMetadata.metadata.burn_block_height as number).toBeTruthy(); expect(stackingResult.submitResult.transaction_identifier.hash).toBe(stackingResult.txId); - expect(stackingResult.tx.contract_call_contract_id).toBe('ST000000000000000000002AMW42H.pox-3'); + expect(stackingResult.tx.contract_call_contract_id).toBe('ST000000000000000000002AMW42H.pox-4'); }); test('Verify expected amount of STX are locked', async () => { @@ -249,11 +249,11 @@ describe('PoX-3 - Rosetta - Stacking with segwit', () => { ustxAmount, }); - expect(rosettaStackStx.constructionMetadata.metadata.contract_name).toBe('pox-3'); + expect(rosettaStackStx.constructionMetadata.metadata.contract_name).toBe('pox-4'); expect(rosettaStackStx.constructionMetadata.metadata.burn_block_height as number).toBeTruthy(); expect(rosettaStackStx.submitResult.transaction_identifier.hash).toBe(rosettaStackStx.txId); expect(rosettaStackStx.tx.contract_call_contract_id).toBe( - 'ST000000000000000000002AMW42H.pox-3' + 'ST000000000000000000002AMW42H.pox-4' ); // ensure locked reported by stacks-node account RPC balance diff --git a/src/tests-2.4/pox-3-stack-extend-increase.ts b/src/tests-2.5/pox-4-stack-extend-increase.ts similarity index 98% rename from src/tests-2.4/pox-3-stack-extend-increase.ts rename to src/tests-2.5/pox-4-stack-extend-increase.ts index ba18676e09..8fe0bf1ef7 100644 --- a/src/tests-2.4/pox-3-stack-extend-increase.ts +++ b/src/tests-2.5/pox-4-stack-extend-increase.ts @@ -21,7 +21,7 @@ import { import { decodeBtcAddress } from '@stacks/stacking'; import { hexToBuffer } from '@hirosystems/api-toolkit'; -describe('PoX-3 - Stack extend and increase operations', () => { +describe('PoX-4 - Stack extend and increase operations', () => { const account = testnetKeys[1]; let btcAddr: string; let btcRegtestAccount: VerboseKeyOutput; @@ -101,7 +101,7 @@ describe('PoX-3 - Stack extend and increase operations', () => { cycleBlockLength = lockPeriod * poxInfo.reward_cycle_length; [contractAddress, contractName] = poxInfo.contract_id.split('.'); - expect(contractName).toBe('pox-3'); + expect(contractName).toBe('pox-4'); }); test('stack-stx tx', async () => { @@ -173,7 +173,7 @@ describe('PoX-3 - Stack extend and increase operations', () => { expect(coreBalance.unlock_height).toBeGreaterThan(0); // validate the pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${sendTxResult.txId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${sendTxResult.txId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -268,7 +268,7 @@ describe('PoX-3 - Stack extend and increase operations', () => { expect(coreBalance.unlock_height).toBe(expectedUnlockHeight); // validate the pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${sendTxResult.txId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${sendTxResult.txId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( @@ -367,7 +367,7 @@ describe('PoX-3 - Stack extend and increase operations', () => { expect(coreBalance.unlock_height).toBeGreaterThan(coreBalancePreStackExtend.unlock_height); // validate the pox2 event for this tx - const res: any = await fetchGet(`/extended/v1/pox3_events/tx/${sendTxResult.txId}`); + const res: any = await fetchGet(`/extended/v1/pox4_events/tx/${sendTxResult.txId}`); expect(res).toBeDefined(); expect(res.results).toHaveLength(1); expect(res.results[0]).toEqual( diff --git a/src/tests-rosetta-construction/construction.ts b/src/tests-rosetta-construction/construction.ts index 3c40d9d4bd..274fbb8e11 100644 --- a/src/tests-rosetta-construction/construction.ts +++ b/src/tests-rosetta-construction/construction.ts @@ -956,7 +956,7 @@ describe('Rosetta Construction', () => { const sender = testnetKeys[0].stacksAddress; const fee = '270'; const contract_address = 'ST000000000000000000002AMW42H'; - const contract_name = 'pox-3'; + const contract_name = 'pox-4'; const stacking_amount = 5000; const burn_block_height = 200; const number_of_cycles = 5; @@ -1634,7 +1634,7 @@ describe('Rosetta Construction', () => { delegate_to: testnetKeys[1].stacksAddress, size: 260, contract_address: 'ST000000000000000000002AMW42H', - contract_name: 'pox-3', + contract_name: 'pox-4', account_sequence: nonce, recent_block_hash: '0x969e494d5aee0166016836f97bbeb3d9473bea8427e477e9de253f78d3212354', }, @@ -2220,7 +2220,7 @@ describe('Rosetta Construction', () => { // //metadata const contract_address = 'ST000000000000000000002AMW42H'; - const contract_name = 'pox-3'; + const contract_name = 'pox-4'; const metadataRequest: RosettaConstructionMetadataRequest = { network_identifier: { diff --git a/src/tests-rosetta/offline-api-tests.ts b/src/tests-rosetta/offline-api-tests.ts index 73577fa3b4..499e95e6a4 100644 --- a/src/tests-rosetta/offline-api-tests.ts +++ b/src/tests-rosetta/offline-api-tests.ts @@ -822,7 +822,7 @@ describe('Rosetta offline API', () => { const sender = testnetKeys[0].stacksAddress; const fee = '270'; const contract_address = 'ST000000000000000000002AMW42H'; - const contract_name = 'pox-3'; + const contract_name = 'pox-4'; const stacking_amount = 5000; const burn_block_height = 200; const number_of_cycles = 5; @@ -957,7 +957,7 @@ describe('Rosetta offline API', () => { const sender = testnetKeys[0].stacksAddress; const fee = '270'; const contract_address = 'ST000000000000000000002AMW42H'; - const contract_name = 'pox-3'; + const contract_name = 'pox-4'; const stacking_amount = 5000; const burn_block_height = 200; diff --git a/src/tests-rpc/core-rpc-tests.ts b/src/tests-rpc/core-rpc-tests.ts index 22c6009794..cf4c155dfc 100644 --- a/src/tests-rpc/core-rpc-tests.ts +++ b/src/tests-rpc/core-rpc-tests.ts @@ -15,7 +15,7 @@ describe('core RPC tests', () => { test('get pox info', async () => { const poxInfo = await client.getPox(); - expect(poxInfo.contract_id).toBe(`ST000000000000000000002AMW42H.pox-3`); + expect(poxInfo.contract_id).toBe(`ST000000000000000000002AMW42H.pox-4`); }); test('get account nonce', async () => { diff --git a/src/tests/address-tests.ts b/src/tests/address-tests.ts index 4e34f9d3fd..c52ffef9ed 100644 --- a/src/tests/address-tests.ts +++ b/src/tests/address-tests.ts @@ -212,6 +212,7 @@ describe('address tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], })), }); @@ -1169,6 +1170,7 @@ describe('address tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], } as DataStoreTxEventData; }); dataStoreTxs.push({ @@ -1183,6 +1185,7 @@ describe('address tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }); dataStoreTxs.push({ tx: { ...contractCall, raw_tx: '0x' }, @@ -1209,6 +1212,7 @@ describe('address tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }); await db.update({ block: block, @@ -2129,6 +2133,7 @@ describe('address tests', () => { smartContracts: [smartContract], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2378,6 +2383,7 @@ describe('address tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2484,6 +2490,7 @@ describe('address tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2613,6 +2620,7 @@ describe('address tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }); } await db.updateMicroblocks(mbData); diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index 9241b26e78..e501bfe3ca 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -603,6 +603,7 @@ describe('block tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: dbTx2, @@ -616,6 +617,7 @@ describe('block tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }; diff --git a/src/tests/cache-control-tests.ts b/src/tests/cache-control-tests.ts index da9e0e826b..e27211ac87 100644 --- a/src/tests/cache-control-tests.ts +++ b/src/tests/cache-control-tests.ts @@ -147,6 +147,7 @@ describe('cache-control tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -314,6 +315,7 @@ describe('cache-control tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index 6889b0a25c..683651c0de 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -380,6 +380,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -547,6 +548,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -761,6 +763,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], })), }); @@ -958,6 +961,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], })), }); @@ -1235,6 +1239,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: tx2, @@ -1248,6 +1253,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: tx3, @@ -1261,6 +1267,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2013,6 +2020,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2096,6 +2104,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2187,6 +2196,7 @@ describe('postgres datastore', () => { smartContracts: [contract], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2282,6 +2292,7 @@ describe('postgres datastore', () => { smartContracts: [contract], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2403,6 +2414,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2485,6 +2497,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2566,6 +2579,7 @@ describe('postgres datastore', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2809,6 +2823,7 @@ describe('postgres datastore', () => { namespaces: [namespace1], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: { ...tx2, raw_tx: '0x' }, @@ -2822,6 +2837,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -3236,6 +3252,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -3299,6 +3316,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -3544,6 +3562,7 @@ describe('postgres datastore', () => { nftEvents: 0, pox2Events: 0, pox3Events: 0, + pox4Events: 0, contractLogs: 0, smartContracts: 0, names: 0, @@ -3561,6 +3580,7 @@ describe('postgres datastore', () => { nftEvents: 0, pox2Events: 0, pox3Events: 0, + pox4Events: 0, contractLogs: 0, smartContracts: 0, names: 0, @@ -3751,6 +3771,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -3817,6 +3838,7 @@ describe('postgres datastore', () => { ], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -4018,6 +4040,7 @@ describe('postgres datastore', () => { ], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -4299,6 +4322,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -4380,6 +4404,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -4515,6 +4540,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: tx2, @@ -4528,6 +4554,7 @@ describe('postgres datastore', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index 961d4d0756..af8805cbfb 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -537,6 +537,7 @@ describe('mempool tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }; diff --git a/src/tests/microblock-tests.ts b/src/tests/microblock-tests.ts index 06b27304aa..0ed9e74264 100644 --- a/src/tests/microblock-tests.ts +++ b/src/tests/microblock-tests.ts @@ -380,6 +380,7 @@ describe('microblock tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -528,6 +529,7 @@ describe('microblock tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: mbTx2, @@ -541,6 +543,7 @@ describe('microblock tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); diff --git a/src/tests/other-tests.ts b/src/tests/other-tests.ts index bbd6ad784c..217b59bc0d 100644 --- a/src/tests/other-tests.ts +++ b/src/tests/other-tests.ts @@ -127,6 +127,7 @@ describe('other tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); diff --git a/src/tests/search-tests.ts b/src/tests/search-tests.ts index 94c8621339..69b8b62b15 100644 --- a/src/tests/search-tests.ts +++ b/src/tests/search-tests.ts @@ -340,6 +340,7 @@ describe('search tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }; @@ -1253,6 +1254,7 @@ describe('search tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: stxTx2, @@ -1266,6 +1268,7 @@ describe('search tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: smartContractTx, @@ -1279,6 +1282,7 @@ describe('search tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }; diff --git a/src/tests/smart-contract-tests.ts b/src/tests/smart-contract-tests.ts index 195b5fe2b3..4329c827a7 100644 --- a/src/tests/smart-contract-tests.ts +++ b/src/tests/smart-contract-tests.ts @@ -137,6 +137,7 @@ describe('smart contract tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: tx2, @@ -150,6 +151,7 @@ describe('smart contract tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -270,6 +272,7 @@ describe('smart contract tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -377,6 +380,7 @@ describe('smart contract tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -1560,6 +1564,7 @@ describe('smart contract tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: tx2, @@ -1573,6 +1578,7 @@ describe('smart contract tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); diff --git a/src/tests/tx-tests.ts b/src/tests/tx-tests.ts index d56b7a35cf..8a7ed7b0a3 100644 --- a/src/tests/tx-tests.ts +++ b/src/tests/tx-tests.ts @@ -249,6 +249,7 @@ describe('tx tests', () => { smartContracts: [smartContract1], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: dbTx2, @@ -262,6 +263,7 @@ describe('tx tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: dbTx3, @@ -275,6 +277,7 @@ describe('tx tests', () => { smartContracts: [versionedSmartContract1], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -408,6 +411,7 @@ describe('tx tests', () => { smartContracts: [smartContract], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -546,6 +550,7 @@ describe('tx tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -683,6 +688,7 @@ describe('tx tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -854,6 +860,7 @@ describe('tx tests', () => { smartContracts: [smartContract], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -1199,6 +1206,7 @@ describe('tx tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -1439,6 +1447,7 @@ describe('tx tests', () => { smartContracts: [smartContract], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -1637,6 +1646,7 @@ describe('tx tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -1781,6 +1791,7 @@ describe('tx tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -1914,6 +1925,7 @@ describe('tx tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2029,6 +2041,7 @@ describe('tx tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2690,6 +2703,7 @@ describe('tx tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); @@ -2944,6 +2958,7 @@ describe('tx tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, { tx: tx2, @@ -2957,6 +2972,7 @@ describe('tx tests', () => { namespaces: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }; @@ -3248,6 +3264,7 @@ describe('tx tests', () => { smartContracts: [], pox2Events: [], pox3Events: [], + pox4Events: [], }, ], }); diff --git a/stacks-blockchain/docker/Dockerfile b/stacks-blockchain/docker/Dockerfile index e9484f5704..d962f5eb95 100644 --- a/stacks-blockchain/docker/Dockerfile +++ b/stacks-blockchain/docker/Dockerfile @@ -1,7 +1,7 @@ # Pointed to stacks-blockchain `2.1.0.0.0` git tag -FROM --platform=linux/amd64 hirosystems/stacks-api-e2e:stacks2.4-f930deb as build +FROM --platform=linux/amd64 hirosystems/stacks-api-e2e:stacks3.0-800259e as build -FROM --platform=linux/amd64 debian:bullseye +FROM --platform=linux/amd64 debian:bookworm COPY wait-for-it.sh /bin/wait-for-it.sh RUN chmod +x /bin/wait-for-it.sh diff --git a/tests/jest.config.2.4.js b/tests/jest.config.2.5.js similarity index 51% rename from tests/jest.config.2.4.js rename to tests/jest.config.2.5.js index 319503527d..65102bd234 100644 --- a/tests/jest.config.2.4.js +++ b/tests/jest.config.2.5.js @@ -3,19 +3,19 @@ const config = { preset: 'ts-jest', testEnvironment: 'node', rootDir: `${require('path').dirname(__dirname)}/src`, - testMatch: ['/tests-2.4/**/*.ts'], + testMatch: ['/tests-2.5/**/*.ts'], testPathIgnorePatterns: [ - '/tests-2.4/global-setup.ts', - '/tests-2.4/global-teardown.ts', - '/tests-2.4/env-setup.ts', - '/tests-2.4/test-helpers.ts', + '/tests-2.5/global-setup.ts', + '/tests-2.5/global-teardown.ts', + '/tests-2.5/env-setup.ts', + '/tests-2.5/test-helpers.ts', ], collectCoverageFrom: ['/**/*.ts'], coveragePathIgnorePatterns: ['/tests*'], coverageDirectory: '/../coverage', - globalSetup: '/tests-2.4/global-setup.ts', - globalTeardown: '/tests-2.4/global-teardown.ts', - setupFilesAfterEnv: ['/tests-2.4/env-setup.ts'], + globalSetup: '/tests-2.5/global-setup.ts', + globalTeardown: '/tests-2.5/global-teardown.ts', + setupFilesAfterEnv: ['/tests-2.5/env-setup.ts'], testTimeout: 60_000, verbose: true, bail: true, From d94a3f227b003697e85869cffe6d47fdf755c507 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 13 Dec 2023 12:04:21 +0000 Subject: [PATCH 33/91] chore(release): 7.4.0-nakamoto.3 [skip ci] ## [7.4.0-nakamoto.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.2...v7.4.0-nakamoto.3) (2023-12-13) ### Features * `GET /extended/v1/burn_block` ([#1766](https://github.com/hirosystems/stacks-blockchain-api/issues/1766)) ([cb38b68](https://github.com/hirosystems/stacks-blockchain-api/commit/cb38b6811c65aa700d4de527329216ba3c2ff6c9)) * ingestion for `TenureChange` and `NakamotoCoinbase` tx types ([#1753](https://github.com/hirosystems/stacks-blockchain-api/issues/1753)) ([7c45f53](https://github.com/hirosystems/stacks-blockchain-api/commit/7c45f53622338170477948d38f549c2136d830c1)) * pox-4 support ([#1754](https://github.com/hirosystems/stacks-blockchain-api/issues/1754)) ([285806f](https://github.com/hirosystems/stacks-blockchain-api/commit/285806f46cebd365cc424a7a0155a531f34d7438)) --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 188c1f592e..17261f304b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [7.4.0-nakamoto.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.2...v7.4.0-nakamoto.3) (2023-12-13) + + +### Features + +* `GET /extended/v1/burn_block` ([#1766](https://github.com/hirosystems/stacks-blockchain-api/issues/1766)) ([cb38b68](https://github.com/hirosystems/stacks-blockchain-api/commit/cb38b6811c65aa700d4de527329216ba3c2ff6c9)) +* ingestion for `TenureChange` and `NakamotoCoinbase` tx types ([#1753](https://github.com/hirosystems/stacks-blockchain-api/issues/1753)) ([7c45f53](https://github.com/hirosystems/stacks-blockchain-api/commit/7c45f53622338170477948d38f549c2136d830c1)) +* pox-4 support ([#1754](https://github.com/hirosystems/stacks-blockchain-api/issues/1754)) ([285806f](https://github.com/hirosystems/stacks-blockchain-api/commit/285806f46cebd365cc424a7a0155a531f34d7438)) + ## [7.4.0-nakamoto.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.1...v7.4.0-nakamoto.2) (2023-11-17) From 2afb65cbb821658416eb41197ce8b72f239970b4 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Wed, 13 Dec 2023 18:32:55 +0100 Subject: [PATCH 34/91] feat: update to latest TenureChange tx payload (#1767) --- ...nsaction-7-tenure-change-metadata.schema.json | 16 ++++++++++++++-- docs/generated.d.ts | 14 +++++++++++++- migrations/1701368149776_nakamoto-txs.js | 10 ++++++++-- package-lock.json | 8 ++++---- package.json | 2 +- src/api/controllers/db-controller.ts | 16 +++++++++++++--- src/datastore/common.ts | 15 +++++++++++++++ src/datastore/helpers.ts | 13 +++++++++++++ src/datastore/pg-write-store.ts | 9 +++++++++ 9 files changed, 90 insertions(+), 13 deletions(-) diff --git a/docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json b/docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json index 68f6728abb..7087a7915e 100644 --- a/docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json +++ b/docs/entities/transactions/transaction-7-tenure-change-metadata.schema.json @@ -12,8 +12,20 @@ "tenure_change_payload": { "type": "object", "additionalProperties": false, - "required": ["previous_tenure_end", "previous_tenure_blocks", "cause", "pubkey_hash", "signature", "signers"], + "required": ["tenure_consensus_hash", "prev_tenure_consensus_hash", "burn_view_consensus_hash", "previous_tenure_end", "previous_tenure_blocks", "cause", "pubkey_hash", "signature", "signers"], "properties": { + "tenure_consensus_hash": { + "type": "string", + "description": "Consensus hash of this tenure. Corresponds to the sortition in which the miner of this block was chosen." + }, + "prev_tenure_consensus_hash": { + "type": "string", + "description": "Consensus hash of the previous tenure. Corresponds to the sortition of the previous winning block-commit." + }, + "burn_view_consensus_hash": { + "type": "string", + "description": "Current consensus hash on the underlying burnchain. Corresponds to the last-seen sortition." + }, "previous_tenure_end": { "type": "string", "description": "(Hex string) Stacks Block hash" @@ -24,7 +36,7 @@ }, "cause": { "type": "string", - "enum": ["block_found", "no_block_found", "null_miner"], + "enum": ["block_found", "extended"], "description": "Cause of change in mining tenure. Depending on cause, tenure can be ended or extended." }, "pubkey_hash": { diff --git a/docs/generated.d.ts b/docs/generated.d.ts index 4e39356ad9..bf8253d278 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -1132,6 +1132,18 @@ export interface CoinbaseTransactionMetadata { export interface TenureChangeTransactionMetadata { tx_type: "tenure_change"; tenure_change_payload?: { + /** + * Consensus hash of this tenure. Corresponds to the sortition in which the miner of this block was chosen. + */ + tenure_consensus_hash: string; + /** + * Consensus hash of the previous tenure. Corresponds to the sortition of the previous winning block-commit. + */ + prev_tenure_consensus_hash: string; + /** + * Current consensus hash on the underlying burnchain. Corresponds to the last-seen sortition. + */ + burn_view_consensus_hash: string; /** * (Hex string) Stacks Block hash */ @@ -1143,7 +1155,7 @@ export interface TenureChangeTransactionMetadata { /** * Cause of change in mining tenure. Depending on cause, tenure can be ended or extended. */ - cause: "block_found" | "no_block_found" | "null_miner"; + cause: "block_found" | "extended"; /** * (Hex string) The ECDSA public key hash of the current tenure. */ diff --git a/migrations/1701368149776_nakamoto-txs.js b/migrations/1701368149776_nakamoto-txs.js index 27ec61ddbd..0e7d46b267 100644 --- a/migrations/1701368149776_nakamoto-txs.js +++ b/migrations/1701368149776_nakamoto-txs.js @@ -13,6 +13,9 @@ exports.up = pgm => { coinbase_vrf_proof: 'bytea', // `tenure-change` tx types + tenure_change_tenure_consensus_hash: 'bytea', + tenure_change_prev_tenure_consensus_hash: 'bytea', + tenure_change_burn_view_consensus_hash: 'bytea', tenure_change_previous_tenure_end: 'bytea', tenure_change_previous_tenure_blocks: 'integer', tenure_change_cause: 'smallint', @@ -26,6 +29,9 @@ exports.up = pgm => { coinbase_vrf_proof: 'bytea', // `tenure-change` tx types + tenure_change_tenure_consensus_hash: 'bytea', + tenure_change_prev_tenure_consensus_hash: 'bytea', + tenure_change_burn_view_consensus_hash: 'bytea', tenure_change_previous_tenure_end: 'bytea', tenure_change_previous_tenure_blocks: 'integer', tenure_change_cause: 'smallint', @@ -35,7 +41,7 @@ exports.up = pgm => { }); pgm.addConstraint('txs', 'valid_tenure-change', `CHECK (type_id != 7 OR ( - NOT (tenure_change_previous_tenure_end, tenure_change_previous_tenure_blocks, tenure_change_cause, tenure_change_pubkey_hash, tenure_change_signature, tenure_change_signers) IS NULL + NOT (tenure_change_tenure_consensus_hash, tenure_change_prev_tenure_consensus_hash, tenure_change_burn_view_consensus_hash, tenure_change_previous_tenure_end, tenure_change_previous_tenure_blocks, tenure_change_cause, tenure_change_pubkey_hash, tenure_change_signature, tenure_change_signers) IS NULL ))`); pgm.addConstraint('txs', 'valid_nakamoto-coinbase', `CHECK (type_id != 8 OR ( @@ -43,7 +49,7 @@ exports.up = pgm => { ))`); pgm.addConstraint('mempool_txs', 'valid_tenure-change', `CHECK (type_id != 7 OR ( - NOT (tenure_change_previous_tenure_end, tenure_change_previous_tenure_blocks, tenure_change_cause, tenure_change_pubkey_hash, tenure_change_signature, tenure_change_signers) IS NULL + NOT (tenure_change_tenure_consensus_hash, tenure_change_prev_tenure_consensus_hash, tenure_change_burn_view_consensus_hash, tenure_change_previous_tenure_end, tenure_change_previous_tenure_blocks, tenure_change_cause, tenure_change_pubkey_hash, tenure_change_signature, tenure_change_signers) IS NULL ))`); pgm.addConstraint('mempool_txs', 'valid_nakamoto-coinbase', `CHECK (type_id != 8 OR ( diff --git a/package-lock.json b/package-lock.json index 6daeefe001..37c1ddd58c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,7 @@ "socket.io": "4.6.1", "source-map-support": "0.5.21", "split2": "3.2.2", - "stacks-encoding-native-js": "1.1.0-beta.3", + "stacks-encoding-native-js": "1.1.0-beta.4", "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", @@ -12825,9 +12825,9 @@ "dev": true }, "node_modules/stacks-encoding-native-js": { - "version": "1.1.0-beta.3", - "resolved": "https://registry.npmjs.org/stacks-encoding-native-js/-/stacks-encoding-native-js-1.1.0-beta.3.tgz", - "integrity": "sha512-A9Fh/hAs0CK8XTv/F5fyLAcoH2ONTPuHoQO19qfwgvpgJcbsdVKrrdaf/N5604YWilA1SK80bXFV7va5+aBiFw==", + "version": "1.1.0-beta.4", + "resolved": "https://registry.npmjs.org/stacks-encoding-native-js/-/stacks-encoding-native-js-1.1.0-beta.4.tgz", + "integrity": "sha512-YpkLNhamcjn2TzPJ6OQAxqAK2XDFKXGGIBEBOAs5F0zfTDvY6ruL3zb6YjLAqtgtNMuaQZvIErGBXZTh0zgaOA==", "dependencies": { "@types/node": "^16.11.26", "detect-libc": "^2.0.1" diff --git a/package.json b/package.json index da1ae344c2..e88a17fe12 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "socket.io": "4.6.1", "source-map-support": "0.5.21", "split2": "3.2.2", - "stacks-encoding-native-js": "1.1.0-beta.3", + "stacks-encoding-native-js": "1.1.0-beta.4", "strict-event-emitter-types": "2.0.0", "tiny-secp256k1": "2.2.1", "ts-unused-exports": "7.0.3", diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 52fea4b546..8f00ff39f0 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -121,9 +121,7 @@ function getTxTenureChangeCauseString(cause: number) { case 0: return 'block_found'; case 1: - return 'no_block_found'; - case 2: - return 'null_miner'; + return 'extended'; default: throw new Error(`Unexpected tenure change cause value ${cause}`); } @@ -968,6 +966,18 @@ function parseDbTxTypeMetadata(dbTx: DbTx | DbMempoolTx): TransactionMetadata { const metadata: TenureChangeTransactionMetadata = { tx_type: 'tenure_change', tenure_change_payload: { + tenure_consensus_hash: unwrapOptional( + dbTx.tenure_change_tenure_consensus_hash, + () => 'Unexpected nullish tenure_change_tenure_consensus_hash' + ), + prev_tenure_consensus_hash: unwrapOptional( + dbTx.tenure_change_prev_tenure_consensus_hash, + () => 'Unexpected nullish tenure_change_prev_tenure_consensus_hash' + ), + burn_view_consensus_hash: unwrapOptional( + dbTx.tenure_change_burn_view_consensus_hash, + () => 'Unexpected nullish tenure_change_burn_view_consensus_hash' + ), previous_tenure_end: unwrapOptional( dbTx.tenure_change_previous_tenure_end, () => 'Unexpected nullish tenure_change_previous_tenure_end' diff --git a/src/datastore/common.ts b/src/datastore/common.ts index e037569330..64328a89b9 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -150,6 +150,9 @@ export interface BaseTx { abi?: string; /** Only valid for `tenure-change` tx types. */ + tenure_change_tenure_consensus_hash?: string; + tenure_change_prev_tenure_consensus_hash?: string; + tenure_change_burn_view_consensus_hash?: string; tenure_change_previous_tenure_end?: string; tenure_change_previous_tenure_blocks?: number; tenure_change_cause?: number; @@ -868,6 +871,9 @@ export interface MempoolTxQueryResult { coinbase_vrf_proof?: string; // `tenure-change` tx types + tenure_change_tenure_consensus_hash?: string; + tenure_change_prev_tenure_consensus_hash?: string; + tenure_change_burn_view_consensus_hash?: string; tenure_change_previous_tenure_end?: string; tenure_change_previous_tenure_blocks?: number; tenure_change_cause?: number; @@ -939,6 +945,9 @@ export interface TxQueryResult { coinbase_vrf_proof?: string; // `tenure-change` tx types + tenure_change_tenure_consensus_hash?: string; + tenure_change_prev_tenure_consensus_hash?: string; + tenure_change_burn_view_consensus_hash?: string; tenure_change_previous_tenure_end?: string; tenure_change_previous_tenure_blocks?: number; tenure_change_cause?: number; @@ -1071,6 +1080,9 @@ export interface TxInsertValues { coinbase_payload: PgBytea | null; coinbase_alt_recipient: string | null; coinbase_vrf_proof: string | null; + tenure_change_tenure_consensus_hash: string | null; + tenure_change_prev_tenure_consensus_hash: string | null; + tenure_change_burn_view_consensus_hash: string | null; tenure_change_previous_tenure_end: string | null; tenure_change_previous_tenure_blocks: number | null; tenure_change_cause: number | null; @@ -1117,6 +1129,9 @@ export interface MempoolTxInsertValues { coinbase_payload: PgBytea | null; coinbase_alt_recipient: string | null; coinbase_vrf_proof: string | null; + tenure_change_tenure_consensus_hash: string | null; + tenure_change_prev_tenure_consensus_hash: string | null; + tenure_change_burn_view_consensus_hash: string | null; tenure_change_previous_tenure_end: string | null; tenure_change_previous_tenure_blocks: number | null; tenure_change_cause: number | null; diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index bfc351de19..ca8331407f 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -104,6 +104,9 @@ export const TX_COLUMNS = [ 'coinbase_payload', 'coinbase_alt_recipient', 'coinbase_vrf_proof', + 'tenure_change_tenure_consensus_hash', + 'tenure_change_prev_tenure_consensus_hash', + 'tenure_change_burn_view_consensus_hash', 'tenure_change_previous_tenure_end', 'tenure_change_previous_tenure_blocks', 'tenure_change_cause', @@ -149,6 +152,9 @@ export const MEMPOOL_TX_COLUMNS = [ 'coinbase_payload', 'coinbase_alt_recipient', 'coinbase_vrf_proof', + 'tenure_change_tenure_consensus_hash', + 'tenure_change_prev_tenure_consensus_hash', + 'tenure_change_burn_view_consensus_hash', 'tenure_change_previous_tenure_end', 'tenure_change_previous_tenure_blocks', 'tenure_change_cause', @@ -391,6 +397,10 @@ function parseTxTypeSpecificQueryResult( } target.coinbase_vrf_proof = result.coinbase_vrf_proof; } else if (target.type_id === DbTxTypeId.TenureChange) { + target.tenure_change_tenure_consensus_hash = result.tenure_change_tenure_consensus_hash; + target.tenure_change_prev_tenure_consensus_hash = + result.tenure_change_prev_tenure_consensus_hash; + target.tenure_change_burn_view_consensus_hash = result.tenure_change_burn_view_consensus_hash; target.tenure_change_previous_tenure_end = result.tenure_change_previous_tenure_end; target.tenure_change_previous_tenure_blocks = result.tenure_change_previous_tenure_blocks; target.tenure_change_cause = result.tenure_change_cause; @@ -1047,6 +1057,9 @@ function extractTransactionPayload(txData: DecodedTxResult, dbTx: DbTx | DbMempo break; } case TxPayloadTypeID.TenureChange: { + dbTx.tenure_change_tenure_consensus_hash = txData.payload.tenure_consensus_hash; + dbTx.tenure_change_prev_tenure_consensus_hash = txData.payload.prev_tenure_consensus_hash; + dbTx.tenure_change_burn_view_consensus_hash = txData.payload.burn_view_consensus_hash; dbTx.tenure_change_previous_tenure_end = txData.payload.previous_tenure_end; dbTx.tenure_change_previous_tenure_blocks = txData.payload.previous_tenure_blocks; dbTx.tenure_change_cause = txData.payload.cause; diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index bd9d6c476b..2380da21a1 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -1617,6 +1617,9 @@ export class PgWriteStore extends PgStore { coinbase_payload: tx.coinbase_payload ?? null, coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, + tenure_change_tenure_consensus_hash: tx.tenure_change_tenure_consensus_hash ?? null, + tenure_change_prev_tenure_consensus_hash: tx.tenure_change_prev_tenure_consensus_hash ?? null, + tenure_change_burn_view_consensus_hash: tx.tenure_change_burn_view_consensus_hash ?? null, tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, tenure_change_cause: tx.tenure_change_cause ?? null, @@ -1674,6 +1677,9 @@ export class PgWriteStore extends PgStore { coinbase_payload: tx.coinbase_payload ?? null, coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, + tenure_change_tenure_consensus_hash: tx.tenure_change_tenure_consensus_hash ?? null, + tenure_change_prev_tenure_consensus_hash: tx.tenure_change_prev_tenure_consensus_hash ?? null, + tenure_change_burn_view_consensus_hash: tx.tenure_change_burn_view_consensus_hash ?? null, tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, tenure_change_cause: tx.tenure_change_cause ?? null, @@ -3009,6 +3015,9 @@ export class PgWriteStore extends PgStore { coinbase_payload: tx.coinbase_payload ?? null, coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, + tenure_change_tenure_consensus_hash: tx.tenure_change_tenure_consensus_hash ?? null, + tenure_change_prev_tenure_consensus_hash: tx.tenure_change_prev_tenure_consensus_hash ?? null, + tenure_change_burn_view_consensus_hash: tx.tenure_change_burn_view_consensus_hash ?? null, tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, tenure_change_cause: tx.tenure_change_cause ?? null, From ceb7be08daa5ca2d9baaa1a3de9f6c0569987724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Thu, 14 Dec 2023 09:38:29 -0600 Subject: [PATCH 35/91] feat: add `/extended/v2/blocks` endpoint with burn block filters (#1769) * chore: add typebox * feat: add blocks v2 endpoint * chore: add types * fix: v2 query * fix: tests * chore: tweaks * docs: openapi * fix: exports * fix: tests * fix: tokens router * fix: adjust burn block hash regex --- .../blocks/get-nakamoto-blocks.example.json | 26 ++++ .../blocks/get-nakamoto-blocks.schema.json | 29 +++++ .../blocks/nakamoto-block.example.json | 23 ++++ .../blocks/nakamoto-block.schema.json | 99 ++++++++++++++++ docs/generated.d.ts | 93 +++++++++++++++ docs/openapi.yaml | 62 +++++++++- package-lock.json | 13 +- package.json | 1 + src/api/controllers/db-controller.ts | 1 + src/api/init.ts | 112 +++++++++++------- src/api/pagination.ts | 2 +- src/api/routes/v2/blocks.ts | 35 ++++++ src/api/routes/v2/helpers.ts | 49 ++++++++ src/api/routes/v2/schemas.ts | 70 +++++++++++ src/datastore/common.ts | 9 ++ src/datastore/pg-store.ts | 90 +++++++++++++- src/tests/block-tests.ts | 107 +++++++++++++++++ 17 files changed, 767 insertions(+), 54 deletions(-) create mode 100644 docs/api/blocks/get-nakamoto-blocks.example.json create mode 100644 docs/api/blocks/get-nakamoto-blocks.schema.json create mode 100644 docs/entities/blocks/nakamoto-block.example.json create mode 100644 docs/entities/blocks/nakamoto-block.schema.json create mode 100644 src/api/routes/v2/blocks.ts create mode 100644 src/api/routes/v2/helpers.ts create mode 100644 src/api/routes/v2/schemas.ts diff --git a/docs/api/blocks/get-nakamoto-blocks.example.json b/docs/api/blocks/get-nakamoto-blocks.example.json new file mode 100644 index 0000000000..a06672ef54 --- /dev/null +++ b/docs/api/blocks/get-nakamoto-blocks.example.json @@ -0,0 +1,26 @@ +{ + "limit": 1, + "offset": 0, + "total": 21707, + "results": [ + { + "canonical": true, + "height": 21698, + "hash": "0x9be3e38eab9c7d094fd51792383c66706838d6392e95bc05cc730b8f7520e352", + "parent_block_hash": "0x76ee36d1d6c88e56b5c0e80f0d7bc7d3492141faf1b900efb19fcd00457d4654", + "burn_block_time": 1626281749, + "burn_block_time_iso": "2021-07-14T16:55:49.000Z", + "burn_block_hash": "0x0000000000000000000ea16f8e906e85ee1cb4dff1e5424e93843b3cec8b0bcb", + "burn_block_height": 691014, + "miner_txid": "0x118f7122a69441d13e6a3dfd4c3b0f9950be25195bb8126aae7fadea1aa9185d", + "txs": [ + "0x76f58b2eaff65a07a5971b241c4e71fee92ee0f9396809f911f90839f9004cac", + "0x32972d9052b068f218f6e13451f7aff937099b74bbf95fac7d9402295b1b3941", + "0x8cd30724c02a9cc1d8879a34dc136ebfdb2008420badcfb5947b92f85ebce79b", + "0xf5c1577f42d3753a508101e045dd2dc60491eb0aa552e0ecd0ad37cc697143f4", + "0x35e4c20e2838f999e0cf0b40c5fabce154c2df1912a1074150d26784c53f7a20", + "0x501eb42b82e5b7a7350b47fa143cd4e90bb46d43e4a7d22830b2bf2aa70b7922" + ] + } + ] +} diff --git a/docs/api/blocks/get-nakamoto-blocks.schema.json b/docs/api/blocks/get-nakamoto-blocks.schema.json new file mode 100644 index 0000000000..eac4ab5f7a --- /dev/null +++ b/docs/api/blocks/get-nakamoto-blocks.schema.json @@ -0,0 +1,29 @@ +{ + "description": "GET request that returns blocks", + "additionalProperties": false, + "title": "NakamotoBlockListResponse", + "type": "object", + "required": ["results", "limit", "offset", "total"], + "properties": { + "limit": { + "type": "integer", + "maximum": 30, + "description": "The number of blocks to return" + }, + "offset": { + "type": "integer", + "description": "The number to blocks to skip (starting at `0`)", + "default": 0 + }, + "total": { + "type": "integer", + "description": "The number of blocks available" + }, + "results": { + "type": "array", + "items": { + "$ref": "../../entities/blocks/nakamoto-block.schema.json" + } + } + } +} diff --git a/docs/entities/blocks/nakamoto-block.example.json b/docs/entities/blocks/nakamoto-block.example.json new file mode 100644 index 0000000000..67da2c54f3 --- /dev/null +++ b/docs/entities/blocks/nakamoto-block.example.json @@ -0,0 +1,23 @@ +{ + "canonical": true, + "height": 3275, + "hash": "0xe77ba8cf6bb7c0e4f64adc83356289ed467d31a22354907b4bb814590058430f", + "index_block_hash": "0x918697ef63f9d8bdf844c3312b299e72a231cde542f3173f7755bb8c1cdaf3a7", + "parent_block_hash": "0x75ab21ef25cbff2caa14c27d830ed7886a4d1522e1b6f9e5dc3b59ccf73ed49f", + "parent_index_block_hash": "0x4262db117659d1ca9406970c8f44ffd3d8f11f8e18c591d2e3960f4070107756", + "burn_block_time": 1594233639, + "burn_block_time_iso": "2020-08-27T16:41:26.000Z", + "burn_block_hash": "0xb154c008df2101023a6d0d54986b3964cee58119eed14f5bed98e15678e18fe2", + "burn_block_height": 654439, + "miner_txid": "0xd7d56070277ccd87b42acf0c91f915dd181f9db4cf878a4e95518bc397c240cc", + "txs": [ + "0x4262db117659d1ca9406970c8f44ffd3d8f11f8e18c591d2e3960f4070107754", + "0x383632cd3b5464dffb684082750fcfaddd1f52625bbb9f884ed8f45d2b1f0547", + "0xc99fe597e44b8bd15a50eec660c6e679a7144a5a8553d214b9d5f1406d278c22" + ], + "execution_cost_read_count": 2477, + "execution_cost_read_length": 1659409, + "execution_cost_runtime": 2520952000, + "execution_cost_write_count": 608, + "execution_cost_write_length": 80170 +} diff --git a/docs/entities/blocks/nakamoto-block.schema.json b/docs/entities/blocks/nakamoto-block.schema.json new file mode 100644 index 0000000000..96395d87e8 --- /dev/null +++ b/docs/entities/blocks/nakamoto-block.schema.json @@ -0,0 +1,99 @@ +{ + "title": "NakamotoBlock", + "description": "A block", + "type": "object", + "additionalProperties": false, + "required": [ + "canonical", + "height", + "hash", + "index_block_hash", + "parent_block_hash", + "parent_index_block_hash", + "txs", + "burn_block_time", + "burn_block_time_iso", + "burn_block_hash", + "burn_block_height", + "miner_txid", + "execution_cost_read_count", + "execution_cost_read_length", + "execution_cost_runtime", + "execution_cost_write_count", + "execution_cost_write_length" + ], + "properties": { + "canonical": { + "type": "boolean", + "description": "Set to `true` if block corresponds to the canonical chain tip" + }, + "height": { + "type": "integer", + "description": "Height of the block" + }, + "hash": { + "type": "string", + "description": "Hash representing the block" + }, + "index_block_hash": { + "type": "string", + "description": "The only hash that can uniquely identify an anchored block or an unconfirmed state trie" + }, + "parent_block_hash": { + "type": "string", + "description": "Hash of the parent block" + }, + "parent_index_block_hash": { + "type": "string", + "description": "Index block hash of the parent block" + }, + "burn_block_time": { + "type": "number", + "description": "Unix timestamp (in seconds) indicating when this block was mined." + }, + "burn_block_time_iso": { + "type": "string", + "description": "An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined." + }, + "burn_block_hash": { + "type": "string", + "description": "Hash of the anchor chain block" + }, + "burn_block_height": { + "type": "integer", + "description": "Height of the anchor chain block" + }, + "miner_txid": { + "type": "string", + "description": "Anchor chain transaction ID" + }, + "txs": { + "type": "array", + "description": "List of transactions included in the block", + "items": { + "type": "string", + "description": "Transaction ID" + } + }, + "execution_cost_read_count": { + "type": "integer", + "description": "Execution cost read count." + }, + "execution_cost_read_length": { + "type": "integer", + "description": "Execution cost read length." + }, + "execution_cost_runtime": { + "type": "integer", + "description": "Execution cost runtime." + }, + "execution_cost_write_count": { + "type": "integer", + "description": "Execution cost write count." + }, + "execution_cost_write_length": { + "type": "integer", + "description": "Execution cost write length." + } + } +} diff --git a/docs/generated.d.ts b/docs/generated.d.ts index bf8253d278..cb286e5485 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -14,6 +14,7 @@ export type SchemaMergeRootStub = | AddressTransactionsListResponse | BlockListResponse | BurnBlockListResponse + | NakamotoBlockListResponse | BnsError | BnsFetchFileZoneResponse | BnsGetAllNamesResponse @@ -116,6 +117,7 @@ export type SchemaMergeRootStub = | StxBalance | Block | BurnBlock + | NakamotoBlock | BurnchainRewardSlotHolder | BurnchainReward | BurnchainRewardsTotal @@ -1331,6 +1333,97 @@ export interface BurnBlock { */ stacks_blocks: string[]; } +/** + * GET request that returns blocks + */ +export interface NakamotoBlockListResponse { + /** + * The number of blocks to return + */ + limit: number; + /** + * The number to blocks to skip (starting at `0`) + */ + offset: number; + /** + * The number of blocks available + */ + total: number; + results: NakamotoBlock[]; +} +/** + * A block + */ +export interface NakamotoBlock { + /** + * Set to `true` if block corresponds to the canonical chain tip + */ + canonical: boolean; + /** + * Height of the block + */ + height: number; + /** + * Hash representing the block + */ + hash: string; + /** + * The only hash that can uniquely identify an anchored block or an unconfirmed state trie + */ + index_block_hash: string; + /** + * Hash of the parent block + */ + parent_block_hash: string; + /** + * Index block hash of the parent block + */ + parent_index_block_hash: string; + /** + * Unix timestamp (in seconds) indicating when this block was mined. + */ + burn_block_time: number; + /** + * An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined. + */ + burn_block_time_iso: string; + /** + * Hash of the anchor chain block + */ + burn_block_hash: string; + /** + * Height of the anchor chain block + */ + burn_block_height: number; + /** + * Anchor chain transaction ID + */ + miner_txid: string; + /** + * List of transactions included in the block + */ + txs: string[]; + /** + * Execution cost read count. + */ + execution_cost_read_count: number; + /** + * Execution cost read length. + */ + execution_cost_read_length: number; + /** + * Execution cost runtime. + */ + execution_cost_runtime: number; + /** + * Execution cost write count. + */ + execution_cost_write_count: number; + /** + * Execution cost write length. + */ + execution_cost_write_length: number; +} /** * Error */ diff --git a/docs/openapi.yaml b/docs/openapi.yaml index d18f59f1ee..8e0aa5abf4 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -660,10 +660,60 @@ paths: example: $ref: ./api/blocks/get-burn-blocks.example.json + /extended/v2/blocks: + get: + summary: Get blocks + description: | + Retrieves a list of recently mined blocks + tags: + - Blocks + operationId: get_blocks + parameters: + - name: limit + in: query + description: max number of blocks to fetch + required: false + schema: + type: integer + example: 20 + - name: offset + in: query + description: index of first burn block to fetch + required: false + schema: + type: integer + example: 0 + - name: burn_block_hash + in: query + description: filter blocks by burn block hash + required: false + schema: + type: string + example: "0xb154c008df2101023a6d0d54986b3964cee58119eed14f5bed98e15678e18fe2" + - name: burn_block_height + in: query + description: filter blocks by burn block height + required: false + schema: + type: integer + example: 810344 + responses: + 200: + description: List of blocks + content: + application/json: + schema: + $ref: ./api/blocks/get-nakamoto-blocks.schema.json + example: + $ref: ./api/blocks/get-nakamoto-blocks.example.json + /extended/v1/block: get: summary: Get recent blocks + deprecated: true description: | + **NOTE:** This endpoint is deprecated in favor of [Get blocks](#operation/get_blocks). + Retrieves a list of recently mined blocks If you need to actively monitor new blocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. @@ -766,7 +816,11 @@ paths: example: "0x00000000000000000002bba732926cf68b6eda3e2cdbc2a85af79f10efeeeb10" get: summary: Get block by burnchain block hash - description: Retrieves block details of a specific block for a given burnchain block hash + deprecated: true + description: | + **NOTE:** This endpoint is deprecated in favor of [Get blocks](#operation/get_blocks). + + Retrieves block details of a specific block for a given burnchain block hash tags: - Blocks operationId: get_block_by_burn_block_hash @@ -797,7 +851,11 @@ paths: example: 744603 get: summary: Get block by burnchain height - description: Retrieves block details of a specific block for a given burn chain height + deprecated: true + description: | + **NOTE:** This endpoint is deprecated in favor of [Get blocks](#operation/get_blocks). + + Retrieves block details of a specific block for a given burn chain height tags: - Blocks operationId: get_block_by_burn_block_height diff --git a/package-lock.json b/package-lock.json index 37c1ddd58c..1f7613d20a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@promster/server": "6.0.6", "@promster/types": "3.2.3", "@scure/base": "1.1.1", + "@sinclair/typebox": "0.31.28", "@stacks/common": "6.8.1", "@stacks/network": "6.8.1", "@stacks/stacking": "6.9.0", @@ -1832,6 +1833,12 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/schemas/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, "node_modules/@jest/source-map": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", @@ -2549,9 +2556,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + "version": "0.31.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.31.28.tgz", + "integrity": "sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==" }, "node_modules/@sinonjs/commons": { "version": "3.0.0", diff --git a/package.json b/package.json index e88a17fe12..5f39f710a6 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "@promster/server": "6.0.6", "@promster/types": "3.2.3", "@scure/base": "1.1.1", + "@sinclair/typebox": "0.31.28", "@stacks/common": "6.8.1", "@stacks/network": "6.8.1", "@stacks/stacking": "6.9.0", diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 8f00ff39f0..f4743d4857 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -68,6 +68,7 @@ import { getOperations, parseTransactionMemo } from '../../rosetta/rosetta-helpe import { PgStore } from '../../datastore/pg-store'; import { SyntheticPoxEventName } from '../../pox-helpers'; import { logger } from '../../logger'; +import { BlocksQueryParams } from '../routes/v2/schemas'; export function parseTxTypeStrings(values: string[]): TransactionType[] { return values.map(v => { diff --git a/src/api/init.ts b/src/api/init.ts index 7356ec11ee..061ce4bee1 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -1,6 +1,5 @@ import { Server, createServer } from 'http'; import { Socket } from 'net'; -import * as querystring from 'querystring'; import * as express from 'express'; import { v4 as uuid } from 'uuid'; import * as cors from 'cors'; @@ -44,8 +43,9 @@ import { WebSocketTransmitter } from './routes/ws/web-socket-transmitter'; import { createPoxEventsRouter } from './routes/pox'; import { logger, loggerMiddleware } from '../logger'; import { SERVER_VERSION, isPgConnectionError, isProdEnv, waiter } from '@hirosystems/api-toolkit'; -import { createBurnBlockRouter } from './routes/burn-block'; +import { createV2BlocksRouter } from './routes/v2/blocks'; import { getReqQuery } from './query-helpers'; +import { createBurnBlockRouter } from './routes/burn-block'; export interface ApiServer { expressApp: express.Express; @@ -171,9 +171,9 @@ export async function startApiServer(opts: { res.send(errObj).status(404); }); - // Setup extended API v1 routes + // Setup extended API routes app.use( - '/extended/v1', + '/extended', (() => { const router = express.Router(); router.use(cors()); @@ -182,52 +182,72 @@ export async function startApiServer(opts: { res.set('Cache-Control', 'no-store'); next(); }); - router.use('/tx', createTxRouter(datastore)); - router.use('/block', createBlockRouter(datastore)); - router.use('/microblock', createMicroblockRouter(datastore)); - router.use('/burn_block', createBurnBlockRouter(datastore)); - router.use('/burnchain', createBurnchainRouter(datastore)); - router.use('/contract', createContractRouter(datastore)); - // same here, exclude account nonce route - router.use('/address', createAddressRouter(datastore, chainId)); - router.use('/search', createSearchRouter(datastore)); - router.use('/info', createInfoRouter(datastore)); - router.use('/stx_supply', createStxSupplyRouter(datastore)); - router.use('/debug', createDebugRouter(datastore)); - router.use('/status', createStatusRouter(datastore)); - router.use('/fee_rate', createFeeRateRouter(datastore)); - router.use('/tokens', createTokenRouter(datastore)); - - // These could be defined in one route but a url reporting library breaks with regex in middleware paths - router.use('/pox2', createPoxEventsRouter(datastore, 'pox2')); - router.use('/pox3', createPoxEventsRouter(datastore, 'pox3')); - router.use('/pox4', createPoxEventsRouter(datastore, 'pox4')); - const legacyPoxPathRouter: express.RequestHandler = (req, res) => { - // Redirect old pox routes paths to new one above - const newPath = req.path === '/' ? '/events' : req.path; - const baseUrl = req.baseUrl.replace(/(pox[\d])_events/, '$1'); - const redirectPath = `${baseUrl}${newPath}${getReqQuery(req)}`; - return res.redirect(redirectPath); - }; - router.use('/pox2_events', legacyPoxPathRouter); - router.use('/pox3_events', legacyPoxPathRouter); - router.use('/pox4_events', legacyPoxPathRouter); - - if (getChainIDNetwork(chainId) === 'testnet' && writeDatastore) { - router.use('/faucets', createFaucetRouter(writeDatastore)); - } + router.use( + '/v1', + (() => { + const v1 = express.Router(); + v1.use('/tx', createTxRouter(datastore)); + v1.use('/block', createBlockRouter(datastore)); + v1.use('/microblock', createMicroblockRouter(datastore)); + v1.use('/burnchain', createBurnchainRouter(datastore)); + v1.use('/contract', createContractRouter(datastore)); + v1.use('/address', createAddressRouter(datastore, chainId)); + v1.use('/search', createSearchRouter(datastore)); + v1.use('/info', createInfoRouter(datastore)); + v1.use('/stx_supply', createStxSupplyRouter(datastore)); + v1.use('/debug', createDebugRouter(datastore)); + v1.use('/status', createStatusRouter(datastore)); + v1.use('/fee_rate', createFeeRateRouter(datastore)); + v1.use('/tokens', createTokenRouter(datastore)); + v1.use('/burn_block', createBurnBlockRouter(datastore)); + + // These could be defined in one route but a url reporting library breaks with regex in middleware paths + v1.use('/pox2', createPoxEventsRouter(datastore, 'pox2')); + v1.use('/pox3', createPoxEventsRouter(datastore, 'pox3')); + v1.use('/pox4', createPoxEventsRouter(datastore, 'pox4')); + const legacyPoxPathRouter: express.RequestHandler = (req, res) => { + // Redirect old pox routes paths to new one above + const newPath = req.path === '/' ? '/events' : req.path; + const baseUrl = req.baseUrl.replace(/(pox[\d])_events/, '$1'); + const redirectPath = `${baseUrl}${newPath}${getReqQuery(req)}`; + return res.redirect(redirectPath); + }; + v1.use('/pox2_events', legacyPoxPathRouter); + v1.use('/pox3_events', legacyPoxPathRouter); + v1.use('/pox4_events', legacyPoxPathRouter); + + if (getChainIDNetwork(chainId) === 'testnet' && writeDatastore) { + v1.use('/faucets', createFaucetRouter(writeDatastore)); + } + return v1; + })() + ); + router.use( + '/v2', + (() => { + const v2 = express.Router(); + v2.use('/blocks', createV2BlocksRouter(datastore)); + return v2; + })() + ); + router.use( + '/beta', + (() => { + const beta = express.Router(); + // Redirect to new endpoint for backward compatibility. + // TODO: remove this in the future + beta.use('/stacking/:pool_principal/delegations', (req, res) => { + const { pool_principal } = req.params; + const newPath = `/extended/v1/pox3/${pool_principal}/delegations${getReqQuery(req)}`; + return res.redirect(newPath); + }); + return beta; + })() + ); return router; })() ); - // Redirect to new endpoint for backward compatibility. - // TODO: remove this in the future - app.use('/extended/beta/stacking/:pool_principal/delegations', (req, res) => { - const { pool_principal } = req.params; - const newPath = `/extended/v1/pox3/${pool_principal}/delegations${getReqQuery(req)}`; - return res.redirect(newPath); - }); - // Setup direct proxy to core-node RPC endpoints (/v2) // pricing endpoint app.use( diff --git a/src/api/pagination.ts b/src/api/pagination.ts index 46e6de21af..9f5073a2ef 100644 --- a/src/api/pagination.ts +++ b/src/api/pagination.ts @@ -38,7 +38,7 @@ export enum ResourceType { BurnBlock, } -const pagingQueryLimits: Record = { +export const pagingQueryLimits: Record = { [ResourceType.Block]: { defaultLimit: 20, maxLimit: 30, diff --git a/src/api/routes/v2/blocks.ts b/src/api/routes/v2/blocks.ts new file mode 100644 index 0000000000..96df660870 --- /dev/null +++ b/src/api/routes/v2/blocks.ts @@ -0,0 +1,35 @@ +import * as express from 'express'; +import { PgStore } from '../../../datastore/pg-store'; +import { + getETagCacheHandler, + setETagCacheHeaders, +} from '../../../api/controllers/cache-controller'; +import { asyncHandler } from '../../async-handler'; +import { NakamotoBlockListResponse } from 'docs/generated'; +import { BlockLimitParam, BlocksQueryParams, CompiledBlocksQueryParams } from './schemas'; +import { parseDbNakamotoBlock, validRequestQuery } from './helpers'; + +export function createV2BlocksRouter(db: PgStore): express.Router { + const router = express.Router(); + const cacheHandler = getETagCacheHandler(db); + + router.get( + '/', + cacheHandler, + asyncHandler(async (req, res) => { + if (!validRequestQuery(req, res, CompiledBlocksQueryParams)) return; + const query = req.query as BlocksQueryParams; + + const { results, total } = await db.getV2Blocks(query); + const response: NakamotoBlockListResponse = { + limit: query.limit ?? BlockLimitParam.default, + offset: query.offset ?? 0, + total, + results: results.map(r => parseDbNakamotoBlock(r)), + }; + setETagCacheHeaders(res); + res.json(response); + }) + ); + return router; +} diff --git a/src/api/routes/v2/helpers.ts b/src/api/routes/v2/helpers.ts new file mode 100644 index 0000000000..86f3f7c79a --- /dev/null +++ b/src/api/routes/v2/helpers.ts @@ -0,0 +1,49 @@ +import { NakamotoBlock } from 'docs/generated'; +import { BlockWithTransactionIds } from '../../../datastore/common'; +import { unixEpochToIso } from '../../../helpers'; +import { TypeCheck } from '@sinclair/typebox/compiler'; +import { Request, Response } from 'express'; +import { TSchema } from '@sinclair/typebox'; + +/** + * Validate request query parameters with a TypeBox compiled schema + * @param req - Request + * @param res - Response + * @param compiledType - TypeBox compiled schema + * @returns boolean + */ +export function validRequestQuery( + req: Request, + res: Response, + compiledType: TypeCheck +): boolean { + if (!compiledType.Check(req.query)) { + // TODO: Return a more user-friendly error + res.status(400).json({ errors: [...compiledType.Errors(req.query)] }); + return false; + } + return true; +} + +export function parseDbNakamotoBlock(block: BlockWithTransactionIds): NakamotoBlock { + const apiBlock: NakamotoBlock = { + canonical: block.canonical, + height: block.block_height, + hash: block.block_hash, + index_block_hash: block.index_block_hash, + parent_block_hash: block.parent_block_hash, + parent_index_block_hash: block.parent_index_block_hash, + burn_block_time: block.burn_block_time, + burn_block_time_iso: unixEpochToIso(block.burn_block_time), + burn_block_hash: block.burn_block_hash, + burn_block_height: block.burn_block_height, + miner_txid: block.miner_txid, + txs: [...block.tx_ids], + execution_cost_read_count: block.execution_cost_read_count, + execution_cost_read_length: block.execution_cost_read_length, + execution_cost_runtime: block.execution_cost_runtime, + execution_cost_write_count: block.execution_cost_write_count, + execution_cost_write_length: block.execution_cost_write_length, + }; + return apiBlock; +} diff --git a/src/api/routes/v2/schemas.ts b/src/api/routes/v2/schemas.ts new file mode 100644 index 0000000000..5135c27376 --- /dev/null +++ b/src/api/routes/v2/schemas.ts @@ -0,0 +1,70 @@ +import { Type, Static } from '@sinclair/typebox'; +import { TypeCompiler } from '@sinclair/typebox/compiler'; +import { ResourceType, pagingQueryLimits } from '../../../api/pagination'; + +// ========================== +// Parameters +// ========================== + +const OffsetParam = Type.Integer({ + minimum: 0, + title: 'Offset', + description: 'Result offset', +}); + +export const BlockLimitParam = Type.Integer({ + minimum: 1, + maximum: pagingQueryLimits[ResourceType.Block].maxLimit, + default: pagingQueryLimits[ResourceType.Block].defaultLimit, + title: 'Block limit', + description: 'Blocks per page', +}); + +const BurnBlockHashParam = Type.RegExp(/^(0x)?[a-fA-F0-9]{64}$/i, { + title: 'Burn block hash', + description: 'Burn block hash', + examples: ['0000000000000000000452773967cdd62297137cdaf79950c5e8bb0c62075133'], +}); + +const BurnBlockHeightParam = Type.RegExp(/^[0-9]+$/, { + title: 'Burn block height', + description: 'Burn block height', + examples: ['777678'], +}); + +// ========================== +// Query params +// TODO: Migrate these to each endpoint after switching from Express to Fastify +// ========================== + +const PaginationParamsSchema = Type.Object( + { + limit: Type.Optional(BlockLimitParam), + offset: Type.Optional(OffsetParam), + }, + { additionalProperties: false } +); + +const BlocksQueryParamsSchema = Type.Union([ + PaginationParamsSchema, + Type.Composite( + [ + Type.Object({ + burn_block_hash: Type.Union([Type.Literal('latest'), BurnBlockHashParam]), + }), + PaginationParamsSchema, + ], + { additionalProperties: false } + ), + Type.Composite( + [ + Type.Object({ + burn_block_height: Type.Union([Type.Literal('latest'), BurnBlockHeightParam]), + }), + PaginationParamsSchema, + ], + { additionalProperties: false } + ), +]); +export type BlocksQueryParams = Static; +export const CompiledBlocksQueryParams = TypeCompiler.Compile(BlocksQueryParamsSchema); diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 64328a89b9..75022b0370 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -1025,6 +1025,15 @@ export interface TransferQueryResult { amount: string; } +export type DbPaginatedResult = { + total: number; + results: T[]; +}; + +export type BlockWithTransactionIds = DbBlock & { + tx_ids: string[]; +}; + export interface BlocksWithMetadata { results: { block: DbBlock; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 9a081c853f..2ceb05ea4e 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -15,12 +15,14 @@ import { bnsNameFromSubdomain, ChainID, REPO_DIR, + normalizeHashString, } from '../helpers'; import { PgStoreEventEmitter } from './pg-store-event-emitter'; import { AddressNftEventIdentifier, BlockIdentifier, BlockQueryResult, + BlockWithTransactionIds, BlocksWithMetadata, ContractTxQueryResult, DbAssetEventTypeId, @@ -44,8 +46,7 @@ import { DbMicroblock, DbMinerReward, DbNftEvent, - DbPoxSyntheticEvent, - DbPoxStacker, + DbPaginatedResult, DbRewardSlotHolder, DbSearchResult, DbSmartContract, @@ -70,6 +71,8 @@ import { StxUnlockEvent, TransferQueryResult, PoxSyntheticEventTable, + DbPoxStacker, + DbPoxSyntheticEvent, } from './common'; import { abiColumn, @@ -101,6 +104,7 @@ import { getPgConnectionEnvValue, } from './connection'; import * as path from 'path'; +import { BlockLimitParam, BlocksQueryParams } from '../api/routes/v2/schemas'; export const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); @@ -550,6 +554,88 @@ export class PgStore extends BasePgStore { }); } + /** + * Returns Block information with transaction IDs + * @returns Paginated `BlockWithTransactionIds` array + */ + async getV2Blocks(args: BlocksQueryParams): Promise> { + return await this.sqlTransaction(async sql => { + const limit = args.limit ?? BlockLimitParam.default; + const offset = args.offset ?? 0; + const burnBlockHashCond = + 'burn_block_hash' in args + ? sql`burn_block_hash = ${ + args.burn_block_hash === 'latest' + ? sql`(SELECT burn_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : sql`${normalizeHashString(args.burn_block_hash)}` + }` + : undefined; + const burnBlockHeightCond = + 'burn_block_height' in args + ? sql`burn_block_height = ${ + args.burn_block_height === 'latest' + ? sql`(SELECT burn_block_height FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : sql`${args.burn_block_height}` + }` + : undefined; + + // Obtain blocks and transaction counts in the same query. + const blocksQuery = await sql< + (BlockQueryResult & { + tx_ids: string; + microblocks_accepted: string; + microblocks_streamed: string; + total: number; + })[] + >` + WITH block_count AS ( + ${ + 'burn_block_hash' in args + ? sql`SELECT COUNT(*) AS count FROM blocks WHERE canonical = TRUE AND ${burnBlockHashCond}` + : 'burn_block_height' in args + ? sql`SELECT COUNT(*) AS count FROM blocks WHERE canonical = TRUE AND ${burnBlockHeightCond}` + : sql`SELECT block_count AS count FROM chain_tip` + } + ) + SELECT + ${sql(BLOCK_COLUMNS)}, + ( + SELECT STRING_AGG(tx_id,',') + FROM txs + WHERE index_block_hash = blocks.index_block_hash + AND canonical = true + AND microblock_canonical = true + ) AS tx_ids, + (SELECT count FROM block_count)::int AS total + FROM blocks + WHERE canonical = true + AND ${ + 'burn_block_hash' in args + ? burnBlockHashCond + : 'burn_block_height' in args + ? burnBlockHeightCond + : sql`TRUE` + } + ORDER BY block_height DESC + LIMIT ${limit} + OFFSET ${offset} + `; + if (blocksQuery.count === 0) + return { + results: [], + total: 0, + }; + const blocks = blocksQuery.map(b => ({ + ...parseBlockQueryResult(b), + tx_ids: b.tx_ids ? b.tx_ids.split(',') : [], + })); + return { + results: blocks, + total: blocksQuery[0].total, + }; + }); + } + async getBlockTxs(indexBlockHash: string) { const result = await this.sql<{ tx_id: string; tx_index: number }[]>` SELECT tx_id, tx_index diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index e501bfe3ca..f44b27b942 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -630,4 +630,111 @@ describe('block tests', () => { expect(blockQuery.body.execution_cost_write_count).toBe(3); expect(blockQuery.body.execution_cost_write_length).toBe(3); }); + + test('blocks v2 filtered by burn block', async () => { + for (let i = 1; i < 6; i++) { + const block = new TestBlockBuilder({ + block_height: i, + block_hash: `0x000${i}`, + index_block_hash: `0x000${i}`, + parent_index_block_hash: `0x000${i - 1}`, + parent_block_hash: `0x000${i - 1}`, + burn_block_height: 700000, + burn_block_hash: '0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8', + }) + .addTx({ tx_id: `0x000${i}` }) + .build(); + await db.update(block); + } + for (let i = 6; i < 9; i++) { + const block = new TestBlockBuilder({ + block_height: i, + block_hash: `0x000${i}`, + index_block_hash: `0x000${i}`, + parent_index_block_hash: `0x000${i - 1}`, + parent_block_hash: `0x000${i - 1}`, + burn_block_height: 700001, + burn_block_hash: '0x000000000000000000028eacd4e6e58405d5a37d06b5d7b93776f1eab68d2494', + }) + .addTx({ tx_id: `0x001${i}` }) + .build(); + await db.update(block); + } + + // Filter by burn hash + const block5 = { + burn_block_hash: '0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8', + burn_block_height: 700000, + burn_block_time: 94869286, + burn_block_time_iso: '1973-01-03T00:34:46.000Z', + canonical: true, + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + hash: '0x0005', + height: 5, + index_block_hash: '0x0005', + miner_txid: '0x4321', + parent_block_hash: '0x0004', + parent_index_block_hash: '0x0004', + txs: ['0x0005'], + }; + let fetch = await supertest(api.server).get( + `/extended/v2/blocks?burn_block_hash=00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8` + ); + let json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json.total).toEqual(5); + expect(json.results[0]).toStrictEqual(block5); + + // Filter by burn height + fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_height=700000`); + json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json.total).toEqual(5); + expect(json.results[0]).toStrictEqual(block5); + + // Get latest block + const block8 = { + burn_block_hash: '0x000000000000000000028eacd4e6e58405d5a37d06b5d7b93776f1eab68d2494', + burn_block_height: 700001, + burn_block_time: 94869286, + burn_block_time_iso: '1973-01-03T00:34:46.000Z', + canonical: true, + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + hash: '0x0008', + height: 8, + index_block_hash: '0x0008', + miner_txid: '0x4321', + parent_block_hash: '0x0007', + parent_index_block_hash: '0x0007', + txs: ['0x0018'], + }; + fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_hash=latest`); + json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json.total).toEqual(3); + expect(json.results[0]).toStrictEqual(block8); + fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_height=latest`); + json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json.total).toEqual(3); + expect(json.results[0]).toStrictEqual(block8); + + // Can't filter by both params + fetch = await supertest(api.server).get( + `/extended/v2/blocks?burn_block_hash=latest&burn_block_height=latest` + ); + expect(fetch.status).toBe(400); + + // Block hashes are validated + fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_hash=testvalue`); + expect(fetch.status).toBe(400); + }); }); From 5015977471c1e903160850bc0fef2985458d1ba1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 14 Dec 2023 15:44:45 +0000 Subject: [PATCH 36/91] chore(release): 7.4.0-nakamoto.4 [skip ci] ## [7.4.0-nakamoto.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.3...v7.4.0-nakamoto.4) (2023-12-14) ### Features * add `/extended/v2/blocks` endpoint with burn block filters ([#1769](https://github.com/hirosystems/stacks-blockchain-api/issues/1769)) ([ceb7be0](https://github.com/hirosystems/stacks-blockchain-api/commit/ceb7be08daa5ca2d9baaa1a3de9f6c0569987724)) * update to latest TenureChange tx payload ([#1767](https://github.com/hirosystems/stacks-blockchain-api/issues/1767)) ([2afb65c](https://github.com/hirosystems/stacks-blockchain-api/commit/2afb65cbb821658416eb41197ce8b72f239970b4)) --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17261f304b..23f60709b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [7.4.0-nakamoto.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.3...v7.4.0-nakamoto.4) (2023-12-14) + + +### Features + +* add `/extended/v2/blocks` endpoint with burn block filters ([#1769](https://github.com/hirosystems/stacks-blockchain-api/issues/1769)) ([ceb7be0](https://github.com/hirosystems/stacks-blockchain-api/commit/ceb7be08daa5ca2d9baaa1a3de9f6c0569987724)) +* update to latest TenureChange tx payload ([#1767](https://github.com/hirosystems/stacks-blockchain-api/issues/1767)) ([2afb65c](https://github.com/hirosystems/stacks-blockchain-api/commit/2afb65cbb821658416eb41197ce8b72f239970b4)) + ## [7.4.0-nakamoto.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.2...v7.4.0-nakamoto.3) (2023-12-13) From 697895fe9a208cce2d945a92926689f063caca0c Mon Sep 17 00:00:00 2001 From: Charlie <2747302+CharlieC3@users.noreply.github.com> Date: Fri, 15 Dec 2023 09:09:39 -0500 Subject: [PATCH 37/91] chore: package.json & package-lock.json to reduce vulnerabilities (#1771) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-INFLIGHT-6095116 Co-authored-by: snyk-bot --- package-lock.json | 119 ++++++++++------------------------------------ package.json | 2 +- 2 files changed, 26 insertions(+), 95 deletions(-) diff --git a/package-lock.json b/package-lock.json index d085dd8f92..8ca4cdb58f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,7 +53,7 @@ "pg-cursor": "2.7.1", "pino": "8.11.0", "pino-http": "8.3.3", - "pino-pretty": "10.0.0", + "pino-pretty": "^10.3.0", "postgres": "3.3.1", "prom-client": "14.0.1", "rpc-bitcoin": "2.0.0", @@ -3656,7 +3656,8 @@ "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==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "devOptional": true }, "node_modules/base-x": { "version": "3.0.9", @@ -6124,7 +6125,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "devOptional": true }, "node_modules/fsevents": { "version": "2.3.2", @@ -6479,50 +6481,9 @@ } }, "node_modules/help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/help-me/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==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/help-me/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "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/help-me/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" }, "node_modules/hmac-drbg": { "version": "1.0.1", @@ -6832,6 +6793,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "devOptional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -9467,15 +9429,15 @@ } }, "node_modules/pino-pretty": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.0.tgz", - "integrity": "sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.0.tgz", + "integrity": "sha512-JthvQW289q3454mhM3/38wFYGWPiBMR28T3CpDNABzoTQOje9UKS7XCJQSnjWF9LQGQkGd8D7h0oq+qwiM3jFA==", "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^3.0.0", "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", + "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", @@ -15092,7 +15054,8 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "devOptional": true }, "base-x": { "version": "3.0.9", @@ -16986,7 +16949,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "devOptional": true }, "fsevents": { "version": "2.3.2", @@ -17240,43 +17204,9 @@ } }, "help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "requires": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - }, - "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==", - "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==", - "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==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" }, "hmac-drbg": { "version": "1.0.1", @@ -17502,6 +17432,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "devOptional": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -19501,15 +19432,15 @@ } }, "pino-pretty": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.0.tgz", - "integrity": "sha512-zKFjYXBzLaLTEAN1ayKpHXtL5UeRQC7R3lvhKe7fWs7hIVEjKGG/qIXwQt9HmeUp71ogUd/YcW+LmMwRp4KT6Q==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.0.tgz", + "integrity": "sha512-JthvQW289q3454mhM3/38wFYGWPiBMR28T3CpDNABzoTQOje9UKS7XCJQSnjWF9LQGQkGd8D7h0oq+qwiM3jFA==", "requires": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^3.0.0", "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", + "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", diff --git a/package.json b/package.json index 4e73cd6dac..440df442e6 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,7 @@ "pg-cursor": "2.7.1", "pino": "8.11.0", "pino-http": "8.3.3", - "pino-pretty": "10.0.0", + "pino-pretty": "10.3.0", "postgres": "3.3.1", "prom-client": "14.0.1", "rpc-bitcoin": "2.0.0", From bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Fri, 15 Dec 2023 09:15:24 -0600 Subject: [PATCH 38/91] fix: move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` (#1772) * fix: move burn block to v2 * fix: new file * fix: unused exports --- docs/openapi.yaml | 48 +++++++++++------ src/api/controllers/db-controller.ts | 29 ---------- src/api/init.ts | 4 +- src/api/query-helpers.ts | 47 ---------------- src/api/routes/burn-block.ts | 42 --------------- src/api/routes/v2/blocks.ts | 8 +-- src/api/routes/v2/burn-blocks.ts | 55 +++++++++++++++++++ src/api/routes/v2/helpers.ts | 35 +++++++++++- src/api/routes/v2/schemas.ts | 58 +++++++++++++------- src/datastore/common.ts | 2 + src/datastore/pg-store.ts | 80 +++++++++++++++++----------- src/tests/block-tests.ts | 56 +++++++++---------- 12 files changed, 242 insertions(+), 222 deletions(-) delete mode 100644 src/api/routes/burn-block.ts create mode 100644 src/api/routes/v2/burn-blocks.ts diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 8e0aa5abf4..0725a2c89b 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -612,14 +612,14 @@ paths: schema: $ref: ./api/microblocks/get-unanchored-txs.schema.json - /extended/v1/burn_block: + /extended/v2/burn-blocks: get: - summary: Get recent burn blocks + summary: Get burn blocks description: | Retrieves a list of recent burn blocks tags: - Blocks - operationId: get_burn_block_list + operationId: get_burn_blocks parameters: - name: limit in: query @@ -636,20 +636,6 @@ paths: schema: type: integer example: 42000 - - name: height - in: query - description: filter by burn block height - required: false - schema: - type: integer - example: 42000 - - name: hash - in: query - description: filter by burn block hash or the constant 'latest' to filter for the most recent burn block - required: false - schema: - type: string - example: "0x4839a8b01cfb39ffcc0d07d3db31e848d5adf5279d529ed5062300b9f353ff79" responses: 200: description: List of burn blocks @@ -660,6 +646,34 @@ paths: example: $ref: ./api/blocks/get-burn-blocks.example.json + /extended/v2/burn-blocks/{height_or_hash}: + get: + summary: Get burn block + description: Retrieves a single burn block + tags: + - Blocks + operationId: get_burn_block + parameters: + - name: height_or_hash + in: path + description: filter by burn block height, hash, or the constant `latest` to filter for the most recent burn block + required: true + schema: + oneOf: + - type: integer + example: 42000 + - type: string + example: "0x4839a8b01cfb39ffcc0d07d3db31e848d5adf5279d529ed5062300b9f353ff79" + responses: + 200: + description: Burn block + content: + application/json: + schema: + $ref: ./entities/blocks/burn-block.schema.json + example: + $ref: ./entities/blocks/burn-block.example.json + /extended/v2/blocks: get: summary: Get blocks diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index f4743d4857..eecf271f89 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -538,35 +538,6 @@ export async function getMicroblockFromDataStore({ }; } -export async function getBurnBlocksFromDataStore(args: { - db: PgStore; - limit: number; - offset: number; - height: number | null; - hash: 'latest' | string | null; -}): Promise<{ total: number; results: BurnBlock[] }> { - const query = await args.db.getBurnBlocks({ - limit: args.limit, - offset: args.offset, - height: args.height, - hash: args.hash, - }); - const results = query.results.map(r => { - const burnBlock: BurnBlock = { - burn_block_time: r.burn_block_time, - burn_block_time_iso: unixEpochToIso(r.burn_block_time), - burn_block_hash: r.burn_block_hash, - burn_block_height: r.burn_block_height, - stacks_blocks: r.stacks_blocks, - }; - return burnBlock; - }); - return { - total: query.total, - results, - }; -} - export async function getMicroblocksFromDataStore(args: { db: PgStore; limit: number; diff --git a/src/api/init.ts b/src/api/init.ts index 061ce4bee1..29c239ebc9 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -45,7 +45,7 @@ import { logger, loggerMiddleware } from '../logger'; import { SERVER_VERSION, isPgConnectionError, isProdEnv, waiter } from '@hirosystems/api-toolkit'; import { createV2BlocksRouter } from './routes/v2/blocks'; import { getReqQuery } from './query-helpers'; -import { createBurnBlockRouter } from './routes/burn-block'; +import { createV2BurnBlocksRouter } from './routes/v2/burn-blocks'; export interface ApiServer { expressApp: express.Express; @@ -199,7 +199,6 @@ export async function startApiServer(opts: { v1.use('/status', createStatusRouter(datastore)); v1.use('/fee_rate', createFeeRateRouter(datastore)); v1.use('/tokens', createTokenRouter(datastore)); - v1.use('/burn_block', createBurnBlockRouter(datastore)); // These could be defined in one route but a url reporting library breaks with regex in middleware paths v1.use('/pox2', createPoxEventsRouter(datastore, 'pox2')); @@ -227,6 +226,7 @@ export async function startApiServer(opts: { (() => { const v2 = express.Router(); v2.use('/blocks', createV2BlocksRouter(datastore)); + v2.use('/burn-blocks', createV2BurnBlocksRouter(datastore)); return v2; })() ); diff --git a/src/api/query-helpers.ts b/src/api/query-helpers.ts index 7275d012f9..4a1cfe8ff6 100644 --- a/src/api/query-helpers.ts +++ b/src/api/query-helpers.ts @@ -111,53 +111,6 @@ export function getBlockParams( } } -/** - * Parses a block hash value from a given request query param. - * If an error is encountered while parsing the param then a 400 response with an error message is sent and the function throws. - * @param queryParamName - name of the query param - * @param paramRequired - if true then the function will throw and return a 400 if the param is missing, if false then the function will return null if the param is missing - */ -export function getBlockHashQueryParam( - queryParamName: string, - paramRequired: TRequired, - req: Request, - res: Response, - next: NextFunction -): TRequired extends true ? string | never : string | null { - if (!(queryParamName in req.query)) { - if (paramRequired) { - handleBadRequest( - res, - next, - `Request is missing required "${queryParamName}" query parameter` - ); - } else { - return null as TRequired extends true ? string : string | null; - } - } - const hashParamVal = req.query[queryParamName]; - if (typeof hashParamVal !== 'string') { - handleBadRequest( - res, - next, - `Unexpected type for block hash query parameter: ${JSON.stringify(hashParamVal)}` - ); - } - - // Extract the hash part, ignoring '0x' if present - const match = hashParamVal.match(/^(0x)?([a-fA-F0-9]{64})$/i); - if (!match) { - handleBadRequest( - res, - next, - "Invalid hash string. Ensure it is 64 hexadecimal characters long, with an optional '0x' prefix" - ); - } - - // Normalize the string - return '0x' + match[2].toLowerCase(); -} - /** * Parses a block height value from a given request query param. * If an error is encountered while parsing the param then a 400 response with an error message is sent and the function throws. diff --git a/src/api/routes/burn-block.ts b/src/api/routes/burn-block.ts deleted file mode 100644 index d8939f83a3..0000000000 --- a/src/api/routes/burn-block.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as express from 'express'; -import { BurnBlockListResponse } from '@stacks/stacks-blockchain-api-types'; -import { getBurnBlocksFromDataStore } from '../controllers/db-controller'; -import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; -import { getBlockHashQueryParam, getBlockHeightQueryParam } from '../query-helpers'; -import { getETagCacheHandler, setETagCacheHeaders } from '../controllers/cache-controller'; -import { asyncHandler } from '../async-handler'; -import { PgStore } from '../../datastore/pg-store'; - -export function createBurnBlockRouter(db: PgStore): express.Router { - const router = express.Router(); - const cacheHandler = getETagCacheHandler(db); - router.get( - '/', - cacheHandler, - asyncHandler(async (req, res, next) => { - const limit = getPagingQueryLimit(ResourceType.BurnBlock, req.query.limit); - const offset = parsePagingQueryInput(req.query.offset ?? 0); - const height = - getBlockHeightQueryParam('height', false, req, res, next) ?? - getBlockHeightQueryParam('block_height', false, req, res, next); - - let hash = req.query.hash === 'latest' ? 'latest' : null; - if (!hash) { - hash = getBlockHashQueryParam('hash', false, req, res, next); - } - - const { results, total } = await getBurnBlocksFromDataStore({ - offset, - limit, - db, - height, - hash, - }); - setETagCacheHeaders(res); - const response: BurnBlockListResponse = { limit, offset, total, results }; - res.json(response); - }) - ); - - return router; -} diff --git a/src/api/routes/v2/blocks.ts b/src/api/routes/v2/blocks.ts index 96df660870..ea1f5d3a09 100644 --- a/src/api/routes/v2/blocks.ts +++ b/src/api/routes/v2/blocks.ts @@ -6,7 +6,7 @@ import { } from '../../../api/controllers/cache-controller'; import { asyncHandler } from '../../async-handler'; import { NakamotoBlockListResponse } from 'docs/generated'; -import { BlockLimitParam, BlocksQueryParams, CompiledBlocksQueryParams } from './schemas'; +import { BlockLimitParamSchema, BlocksQueryParams, CompiledBlocksQueryParams } from './schemas'; import { parseDbNakamotoBlock, validRequestQuery } from './helpers'; export function createV2BlocksRouter(db: PgStore): express.Router { @@ -20,10 +20,10 @@ export function createV2BlocksRouter(db: PgStore): express.Router { if (!validRequestQuery(req, res, CompiledBlocksQueryParams)) return; const query = req.query as BlocksQueryParams; - const { results, total } = await db.getV2Blocks(query); + const { limit, offset, results, total } = await db.getV2Blocks(query); const response: NakamotoBlockListResponse = { - limit: query.limit ?? BlockLimitParam.default, - offset: query.offset ?? 0, + limit, + offset, total, results: results.map(r => parseDbNakamotoBlock(r)), }; diff --git a/src/api/routes/v2/burn-blocks.ts b/src/api/routes/v2/burn-blocks.ts new file mode 100644 index 0000000000..5b724fdd3a --- /dev/null +++ b/src/api/routes/v2/burn-blocks.ts @@ -0,0 +1,55 @@ +import * as express from 'express'; +import { BurnBlockListResponse } from '@stacks/stacks-blockchain-api-types'; +import { getETagCacheHandler, setETagCacheHeaders } from '../../controllers/cache-controller'; +import { asyncHandler } from '../../async-handler'; +import { PgStore } from '../../../datastore/pg-store'; +import { parseDbBurnBlock, validRequestParams, validRequestQuery } from './helpers'; +import { + BlockPaginationQueryParams, + BurnBlockParams, + CompiledBlockPaginationParams, + CompiledBurnBlockParams, +} from './schemas'; + +export function createV2BurnBlocksRouter(db: PgStore): express.Router { + const router = express.Router(); + const cacheHandler = getETagCacheHandler(db); + + router.get( + '/', + cacheHandler, + asyncHandler(async (req, res) => { + if (!validRequestQuery(req, res, CompiledBlockPaginationParams)) return; + const query = req.query as BlockPaginationQueryParams; + + const { limit, offset, results, total } = await db.getBurnBlocks(query); + const response: BurnBlockListResponse = { + limit, + offset, + total, + results: results.map(r => parseDbBurnBlock(r)), + }; + setETagCacheHeaders(res); + res.json(response); + }) + ); + + router.get( + '/:height_or_hash', + cacheHandler, + asyncHandler(async (req, res) => { + if (!validRequestParams(req, res, CompiledBurnBlockParams)) return; + const params = req.params as BurnBlockParams; + + const block = await db.getBurnBlock(params); + if (!block) { + res.status(404).json({ errors: 'Not found' }); + return; + } + setETagCacheHeaders(res); + res.json(parseDbBurnBlock(block)); + }) + ); + + return router; +} diff --git a/src/api/routes/v2/helpers.ts b/src/api/routes/v2/helpers.ts index 86f3f7c79a..413192c9ab 100644 --- a/src/api/routes/v2/helpers.ts +++ b/src/api/routes/v2/helpers.ts @@ -1,5 +1,5 @@ -import { NakamotoBlock } from 'docs/generated'; -import { BlockWithTransactionIds } from '../../../datastore/common'; +import { BurnBlock, NakamotoBlock } from 'docs/generated'; +import { BlockWithTransactionIds, DbBurnBlock } from '../../../datastore/common'; import { unixEpochToIso } from '../../../helpers'; import { TypeCheck } from '@sinclair/typebox/compiler'; import { Request, Response } from 'express'; @@ -25,6 +25,26 @@ export function validRequestQuery( return true; } +/** + * Validate request path parameters with a TypeBox compiled schema + * @param req - Request + * @param res - Response + * @param compiledType - TypeBox compiled schema + * @returns boolean + */ +export function validRequestParams( + req: Request, + res: Response, + compiledType: TypeCheck +): boolean { + if (!compiledType.Check(req.params)) { + // TODO: Return a more user-friendly error + res.status(400).json({ errors: [...compiledType.Errors(req.params)] }); + return false; + } + return true; +} + export function parseDbNakamotoBlock(block: BlockWithTransactionIds): NakamotoBlock { const apiBlock: NakamotoBlock = { canonical: block.canonical, @@ -47,3 +67,14 @@ export function parseDbNakamotoBlock(block: BlockWithTransactionIds): NakamotoBl }; return apiBlock; } + +export function parseDbBurnBlock(block: DbBurnBlock): BurnBlock { + const burnBlock: BurnBlock = { + burn_block_time: block.burn_block_time, + burn_block_time_iso: unixEpochToIso(block.burn_block_time), + burn_block_hash: block.burn_block_hash, + burn_block_height: block.burn_block_height, + stacks_blocks: block.stacks_blocks, + }; + return burnBlock; +} diff --git a/src/api/routes/v2/schemas.ts b/src/api/routes/v2/schemas.ts index 5135c27376..3a80a9071e 100644 --- a/src/api/routes/v2/schemas.ts +++ b/src/api/routes/v2/schemas.ts @@ -1,4 +1,4 @@ -import { Type, Static } from '@sinclair/typebox'; +import { Type, Static, TSchema } from '@sinclair/typebox'; import { TypeCompiler } from '@sinclair/typebox/compiler'; import { ResourceType, pagingQueryLimits } from '../../../api/pagination'; @@ -6,13 +6,13 @@ import { ResourceType, pagingQueryLimits } from '../../../api/pagination'; // Parameters // ========================== -const OffsetParam = Type.Integer({ +const OffsetParamSchema = Type.Integer({ minimum: 0, title: 'Offset', description: 'Result offset', }); -export const BlockLimitParam = Type.Integer({ +export const BlockLimitParamSchema = Type.Integer({ minimum: 1, maximum: pagingQueryLimits[ResourceType.Block].maxLimit, default: pagingQueryLimits[ResourceType.Block].defaultLimit, @@ -20,51 +20,73 @@ export const BlockLimitParam = Type.Integer({ description: 'Blocks per page', }); -const BurnBlockHashParam = Type.RegExp(/^(0x)?[a-fA-F0-9]{64}$/i, { +const BurnBlockHashParamSchema = Type.RegExp(/^(0x)?[a-fA-F0-9]{64}$/i, { title: 'Burn block hash', description: 'Burn block hash', examples: ['0000000000000000000452773967cdd62297137cdaf79950c5e8bb0c62075133'], }); +type BurnBlockHashParam = Static; +export const CompiledBurnBlockHashParam = TypeCompiler.Compile(BurnBlockHashParamSchema); -const BurnBlockHeightParam = Type.RegExp(/^[0-9]+$/, { +const BurnBlockHeightParamSchema = Type.RegExp(/^[0-9]+$/, { title: 'Burn block height', description: 'Burn block height', examples: ['777678'], }); +type BurnBlockHeightParam = Static; +const CompiledBurnBlockHeightParam = TypeCompiler.Compile(BurnBlockHeightParamSchema); // ========================== -// Query params +// Query and path params // TODO: Migrate these to each endpoint after switching from Express to Fastify // ========================== -const PaginationParamsSchema = Type.Object( - { - limit: Type.Optional(BlockLimitParam), - offset: Type.Optional(OffsetParam), - }, - { additionalProperties: false } -); +const PaginationQueryParamsSchema = (t: T) => + Type.Object( + { + limit: Type.Optional(t), + offset: Type.Optional(OffsetParamSchema), + }, + { additionalProperties: false } + ); + +const BlockPaginationQueryParamsSchema = PaginationQueryParamsSchema(BlockLimitParamSchema); +export type BlockPaginationQueryParams = Static; +export const CompiledBlockPaginationParams = TypeCompiler.Compile(BlockPaginationQueryParamsSchema); const BlocksQueryParamsSchema = Type.Union([ - PaginationParamsSchema, + BlockPaginationQueryParamsSchema, Type.Composite( [ Type.Object({ - burn_block_hash: Type.Union([Type.Literal('latest'), BurnBlockHashParam]), + burn_block_hash: Type.Union([Type.Literal('latest'), BurnBlockHashParamSchema]), }), - PaginationParamsSchema, + BlockPaginationQueryParamsSchema, ], { additionalProperties: false } ), Type.Composite( [ Type.Object({ - burn_block_height: Type.Union([Type.Literal('latest'), BurnBlockHeightParam]), + burn_block_height: Type.Union([Type.Literal('latest'), BurnBlockHeightParamSchema]), }), - PaginationParamsSchema, + BlockPaginationQueryParamsSchema, ], { additionalProperties: false } ), ]); export type BlocksQueryParams = Static; export const CompiledBlocksQueryParams = TypeCompiler.Compile(BlocksQueryParamsSchema); + +const BurnBlockParamsSchema = Type.Object( + { + height_or_hash: Type.Union([ + Type.Literal('latest'), + BurnBlockHashParamSchema, + BurnBlockHeightParamSchema, + ]), + }, + { additionalProperties: false } +); +export type BurnBlockParams = Static; +export const CompiledBurnBlockParams = TypeCompiler.Compile(BurnBlockParamsSchema); diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 75022b0370..83b4f85ca4 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -1026,6 +1026,8 @@ export interface TransferQueryResult { } export type DbPaginatedResult = { + limit: number; + offset: number; total: number; results: T[]; }; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 2ceb05ea4e..22d4d1362a 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -104,7 +104,13 @@ import { getPgConnectionEnvValue, } from './connection'; import * as path from 'path'; -import { BlockLimitParam, BlocksQueryParams } from '../api/routes/v2/schemas'; +import { + BlockLimitParamSchema, + BlockPaginationQueryParams, + BlocksQueryParams, + BurnBlockParams, + CompiledBurnBlockHashParam, +} from '../api/routes/v2/schemas'; export const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); @@ -396,31 +402,14 @@ export class PgStore extends BasePgStore { return { found: true, result: block } as const; } - async getBurnBlocks({ - limit, - offset, - height, - hash, - }: { - limit: number; - offset: number; - height: number | null; - hash: 'latest' | string | null; - }): Promise<{ results: DbBurnBlock[]; total: number }> { + async getBurnBlocks(args: BlockPaginationQueryParams): Promise> { return await this.sqlTransaction(async sql => { - const countQuery = await sql<{ burn_block_height: number; count: number }[]>` - SELECT burn_block_height, block_count AS count FROM chain_tip - `; - const heightFilter = height ? sql`AND burn_block_height = ${height}` : sql``; - const hashFilter = - hash === 'latest' - ? sql`AND burn_block_height = ${countQuery[0].burn_block_height}` - : hash - ? sql`AND burn_block_hash = ${hash}` - : sql``; - - const block_count = countQuery[0].count; - const blocksQuery = await sql` + const limit = args.limit ?? BlockLimitParamSchema.default; + const offset = args.offset ?? 0; + const blocksQuery = await sql<(DbBurnBlock & { total: number })[]>` + WITH block_count AS ( + SELECT burn_block_height, block_count AS count FROM chain_tip + ) SELECT DISTINCT ON (burn_block_height) burn_block_time, burn_block_hash, @@ -429,23 +418,50 @@ export class PgStore extends BasePgStore { PARTITION BY burn_block_height ORDER BY block_height DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING - ) AS stacks_blocks + ) AS stacks_blocks, + (SELECT count FROM block_count)::int AS total FROM blocks WHERE canonical = true - ${heightFilter} - ${hashFilter} ORDER BY burn_block_height DESC, block_height DESC LIMIT ${limit} OFFSET ${offset} `; const blocks = blocksQuery.map(r => r); return { + limit, + offset, results: blocks, - total: block_count, + total: blocks[0].total, }; }); } + async getBurnBlock(args: BurnBlockParams): Promise { + return await this.sqlTransaction(async sql => { + const filter = + args.height_or_hash === 'latest' + ? sql`burn_block_hash = (SELECT burn_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : CompiledBurnBlockHashParam.Check(args.height_or_hash) + ? sql`burn_block_hash = ${args.height_or_hash}` + : sql`burn_block_height = ${args.height_or_hash}`; + const blockQuery = await sql` + SELECT DISTINCT ON (burn_block_height) + burn_block_time, + burn_block_hash, + burn_block_height, + ARRAY_AGG(block_hash) OVER ( + PARTITION BY burn_block_height + ORDER BY block_height DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS stacks_blocks + FROM blocks + WHERE canonical = true AND ${filter} + LIMIT 1 + `; + if (blockQuery.count > 0) return blockQuery[0]; + }); + } + /** * Returns Block information with metadata, including accepted and streamed microblocks hash * @returns `BlocksWithMetadata` object including list of Blocks with metadata and total count. @@ -560,7 +576,7 @@ export class PgStore extends BasePgStore { */ async getV2Blocks(args: BlocksQueryParams): Promise> { return await this.sqlTransaction(async sql => { - const limit = args.limit ?? BlockLimitParam.default; + const limit = args.limit ?? BlockLimitParamSchema.default; const offset = args.offset ?? 0; const burnBlockHashCond = 'burn_block_hash' in args @@ -622,6 +638,8 @@ export class PgStore extends BasePgStore { `; if (blocksQuery.count === 0) return { + limit, + offset, results: [], total: 0, }; @@ -630,6 +648,8 @@ export class PgStore extends BasePgStore { tx_ids: b.tx_ids ? b.tx_ids.split(',') : [], })); return { + limit, + offset, results: blocks, total: blocksQuery[0].total, }; diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index f44b27b942..5fd9a65afb 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -340,7 +340,7 @@ describe('block tests', () => { await db.update(dbBlock); } - const result = await supertest(api.server).get(`/extended/v1/burn_block/`); + const result = await supertest(api.server).get(`/extended/v2/burn-blocks`); expect(result.body.results).toEqual([ { burn_block_hash: burnBlock2.burn_block_hash, @@ -359,44 +359,38 @@ describe('block tests', () => { ]); // test 'latest' filter - const result2 = await supertest(api.server).get(`/extended/v1/burn_block?hash=latest`); - expect(result2.body.results).toEqual([ - { - burn_block_hash: stacksBlocks.at(-1)?.burn_block_hash, - burn_block_height: stacksBlocks.at(-1)?.burn_block_height, - burn_block_time: stacksBlocks.at(-1)?.burn_block_time, - burn_block_time_iso: unixEpochToIso(stacksBlocks.at(-1)?.burn_block_time ?? 0), - stacks_blocks: [stacksBlock4.block_hash, stacksBlock3.block_hash, stacksBlock2.block_hash], - }, - ]); + const result2 = await supertest(api.server).get(`/extended/v2/burn-blocks/latest`); + expect(result2.body).toEqual({ + burn_block_hash: stacksBlocks.at(-1)?.burn_block_hash, + burn_block_height: stacksBlocks.at(-1)?.burn_block_height, + burn_block_time: stacksBlocks.at(-1)?.burn_block_time, + burn_block_time_iso: unixEpochToIso(stacksBlocks.at(-1)?.burn_block_time ?? 0), + stacks_blocks: [stacksBlock4.block_hash, stacksBlock3.block_hash, stacksBlock2.block_hash], + }); // test hash filter const result3 = await supertest(api.server).get( - `/extended/v1/burn_block?hash=${stacksBlock1.burn_block_hash}` + `/extended/v2/burn-blocks/${stacksBlock1.burn_block_hash}` ); - expect(result3.body.results).toEqual([ - { - burn_block_hash: stacksBlock1.burn_block_hash, - burn_block_height: stacksBlock1.burn_block_height, - burn_block_time: stacksBlock1.burn_block_time, - burn_block_time_iso: unixEpochToIso(stacksBlock1.burn_block_time), - stacks_blocks: [stacksBlock1.block_hash], - }, - ]); + expect(result3.body).toEqual({ + burn_block_hash: stacksBlock1.burn_block_hash, + burn_block_height: stacksBlock1.burn_block_height, + burn_block_time: stacksBlock1.burn_block_time, + burn_block_time_iso: unixEpochToIso(stacksBlock1.burn_block_time), + stacks_blocks: [stacksBlock1.block_hash], + }); // test height filter const result4 = await supertest(api.server).get( - `/extended/v1/burn_block?height=${stacksBlock1.burn_block_height}` + `/extended/v2/burn-blocks/${stacksBlock1.burn_block_height}` ); - expect(result4.body.results).toEqual([ - { - burn_block_hash: stacksBlock1.burn_block_hash, - burn_block_height: stacksBlock1.burn_block_height, - burn_block_time: stacksBlock1.burn_block_time, - burn_block_time_iso: unixEpochToIso(stacksBlock1.burn_block_time), - stacks_blocks: [stacksBlock1.block_hash], - }, - ]); + expect(result4.body).toEqual({ + burn_block_hash: stacksBlock1.burn_block_hash, + burn_block_height: stacksBlock1.burn_block_height, + burn_block_time: stacksBlock1.burn_block_time, + burn_block_time_iso: unixEpochToIso(stacksBlock1.burn_block_time), + stacks_blocks: [stacksBlock1.block_hash], + }); }); test('block tx list excludes non-canonical', async () => { From 4c7333bc951e77f61b8bb1abea24448f743f00f4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 15 Dec 2023 15:21:23 +0000 Subject: [PATCH 39/91] chore(release): 7.4.0-nakamoto.5 [skip ci] ## [7.4.0-nakamoto.5](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.4...v7.4.0-nakamoto.5) (2023-12-15) ### Bug Fixes * move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` ([#1772](https://github.com/hirosystems/stacks-blockchain-api/issues/1772)) ([bf2ef0a](https://github.com/hirosystems/stacks-blockchain-api/commit/bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23f60709b1..011042d701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-nakamoto.5](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.4...v7.4.0-nakamoto.5) (2023-12-15) + + +### Bug Fixes + +* move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` ([#1772](https://github.com/hirosystems/stacks-blockchain-api/issues/1772)) ([bf2ef0a](https://github.com/hirosystems/stacks-blockchain-api/commit/bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5)) + ## [7.4.0-nakamoto.4](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.3...v7.4.0-nakamoto.4) (2023-12-14) From e532a5e173340f732536b9236d60585501f2da5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Fri, 15 Dec 2023 11:10:41 -0600 Subject: [PATCH 40/91] feat: add `/extended/v2/blocks/:height_or_hash` (#1774) * docs: openapi * feat: get single block --- docs/openapi.yaml | 41 ++++++++++++++++++++-- src/api/routes/v2/blocks.ts | 27 +++++++++++++-- src/datastore/pg-store.ts | 43 ++++++++++++++++++----- src/tests/block-tests.ts | 68 +++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 12 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 0725a2c89b..00ed7c2d30 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -720,6 +720,35 @@ paths: $ref: ./api/blocks/get-nakamoto-blocks.schema.json example: $ref: ./api/blocks/get-nakamoto-blocks.example.json + + /extended/v2/blocks/{height_or_hash}: + get: + summary: Get block + description: | + Retrieves a single block + tags: + - Blocks + operationId: get_block + parameters: + - name: height_or_hash + in: path + description: filter by block height, hash, index block hash or the constant `latest` to filter for the most recent block + required: true + schema: + oneOf: + - type: integer + example: 42000 + - type: string + example: "0x4839a8b01cfb39ffcc0d07d3db31e848d5adf5279d529ed5062300b9f353ff79" + responses: + 200: + description: Block + content: + application/json: + schema: + $ref: ./entities/blocks/nakamoto-block.schema.json + example: + $ref: ./entities/blocks/nakamoto-block.example.json /extended/v1/block: get: @@ -769,8 +798,12 @@ paths: type: string example: "0x4839a8b01cfb39ffcc0d07d3db31e848d5adf5279d529ed5062300b9f353ff79" get: + deprecated: true summary: Get block by hash - description: Retrieves block details of a specific block for a given chain height. You can use the hash from your latest block ('get_block_list' API) to get your block details. + description: | + **NOTE:** This endpoint is deprecated in favor of [Get block](#operation/get_block). + + Retrieves block details of a specific block for a given chain height. You can use the hash from your latest block ('get_block_list' API) to get your block details. tags: - Blocks operationId: get_block_by_hash @@ -799,8 +832,12 @@ paths: type: number example: 10000 get: + deprecated: true summary: Get block by height - description: Retrieves block details of a specific block at a given block height + description: | + **NOTE:** This endpoint is deprecated in favor of [Get block](#operation/get_block). + + Retrieves block details of a specific block at a given block height tags: - Blocks operationId: get_block_by_height diff --git a/src/api/routes/v2/blocks.ts b/src/api/routes/v2/blocks.ts index ea1f5d3a09..652fc19766 100644 --- a/src/api/routes/v2/blocks.ts +++ b/src/api/routes/v2/blocks.ts @@ -6,8 +6,13 @@ import { } from '../../../api/controllers/cache-controller'; import { asyncHandler } from '../../async-handler'; import { NakamotoBlockListResponse } from 'docs/generated'; -import { BlockLimitParamSchema, BlocksQueryParams, CompiledBlocksQueryParams } from './schemas'; -import { parseDbNakamotoBlock, validRequestQuery } from './helpers'; +import { + BlocksQueryParams, + BurnBlockParams, + CompiledBlocksQueryParams, + CompiledBurnBlockParams, +} from './schemas'; +import { parseDbNakamotoBlock, validRequestParams, validRequestQuery } from './helpers'; export function createV2BlocksRouter(db: PgStore): express.Router { const router = express.Router(); @@ -31,5 +36,23 @@ export function createV2BlocksRouter(db: PgStore): express.Router { res.json(response); }) ); + + router.get( + '/:height_or_hash', + cacheHandler, + asyncHandler(async (req, res) => { + if (!validRequestParams(req, res, CompiledBurnBlockParams)) return; + const params = req.params as BurnBlockParams; + + const block = await db.getV2Block(params); + if (!block) { + res.status(404).json({ errors: 'Not found' }); + return; + } + setETagCacheHeaders(res); + res.json(parseDbNakamotoBlock(block)); + }) + ); + return router; } diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 22d4d1362a..eabc8d8b09 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -465,6 +465,7 @@ export class PgStore extends BasePgStore { /** * Returns Block information with metadata, including accepted and streamed microblocks hash * @returns `BlocksWithMetadata` object including list of Blocks with metadata and total count. + * @deprecated use `getV2Blocks` */ async getBlocksWithMetadata({ limit, @@ -596,14 +597,7 @@ export class PgStore extends BasePgStore { : undefined; // Obtain blocks and transaction counts in the same query. - const blocksQuery = await sql< - (BlockQueryResult & { - tx_ids: string; - microblocks_accepted: string; - microblocks_streamed: string; - total: number; - })[] - >` + const blocksQuery = await sql<(BlockQueryResult & { tx_ids: string; total: number })[]>` WITH block_count AS ( ${ 'burn_block_hash' in args @@ -656,6 +650,39 @@ export class PgStore extends BasePgStore { }); } + async getV2Block(args: BurnBlockParams): Promise { + return await this.sqlTransaction(async sql => { + const filter = + args.height_or_hash === 'latest' + ? sql`index_block_hash = (SELECT index_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : CompiledBurnBlockHashParam.Check(args.height_or_hash) + ? sql`( + block_hash = ${normalizeHashString(args.height_or_hash)} + OR index_block_hash = ${normalizeHashString(args.height_or_hash)} + )` + : sql`block_height = ${args.height_or_hash}`; + const blockQuery = await sql<(BlockQueryResult & { tx_ids: string })[]>` + SELECT + ${sql(BLOCK_COLUMNS)}, + ( + SELECT STRING_AGG(tx_id,',') + FROM txs + WHERE index_block_hash = blocks.index_block_hash + AND canonical = true + AND microblock_canonical = true + ) AS tx_ids + FROM blocks + WHERE canonical = true AND ${filter} + LIMIT 1 + `; + if (blockQuery.count > 0) + return { + ...parseBlockQueryResult(blockQuery[0]), + tx_ids: blockQuery[0].tx_ids ? blockQuery[0].tx_ids.split(',') : [], + }; + }); + } + async getBlockTxs(indexBlockHash: string) { const result = await this.sql<{ tx_id: string; tx_index: number }[]>` SELECT tx_id, tx_index diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index 5fd9a65afb..3bef070e7c 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -731,4 +731,72 @@ describe('block tests', () => { fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_hash=testvalue`); expect(fetch.status).toBe(400); }); + + test('blocks v2 retrieved by hash or height', async () => { + for (let i = 1; i < 6; i++) { + const block = new TestBlockBuilder({ + block_height: i, + block_hash: `0x000000000000000000000000000000000000000000000000000000000000000${i}`, + index_block_hash: `0x000000000000000000000000000000000000000000000000000000000000011${i}`, + parent_index_block_hash: `0x000000000000000000000000000000000000000000000000000000000000011${ + i - 1 + }`, + parent_block_hash: `0x000000000000000000000000000000000000000000000000000000000000000${ + i - 1 + }`, + burn_block_height: 700000, + burn_block_hash: '0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8', + }) + .addTx({ tx_id: `0x000${i}` }) + .build(); + await db.update(block); + } + + // Get latest + const block5 = { + burn_block_hash: '0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8', + burn_block_height: 700000, + burn_block_time: 94869286, + burn_block_time_iso: '1973-01-03T00:34:46.000Z', + canonical: true, + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + hash: '0x0000000000000000000000000000000000000000000000000000000000000005', + height: 5, + index_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000115', + miner_txid: '0x4321', + parent_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000004', + parent_index_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000114', + txs: ['0x0005'], + }; + let fetch = await supertest(api.server).get(`/extended/v2/blocks/latest`); + let json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json).toStrictEqual(block5); + + // Get by height + fetch = await supertest(api.server).get(`/extended/v2/blocks/5`); + json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json).toStrictEqual(block5); + + // Get by hash + fetch = await supertest(api.server).get( + `/extended/v2/blocks/0x0000000000000000000000000000000000000000000000000000000000000005` + ); + json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json).toStrictEqual(block5); + + // Get by index block hash + fetch = await supertest(api.server).get( + `/extended/v2/blocks/0x0000000000000000000000000000000000000000000000000000000000000115` + ); + json = JSON.parse(fetch.text); + expect(fetch.status).toBe(200); + expect(json).toStrictEqual(block5); + }); }); From c2f95d33c1ae9c4d54d8bf1363149e8977b4c3f8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 15 Dec 2023 17:16:39 +0000 Subject: [PATCH 41/91] chore(release): 7.4.0-nakamoto.6 [skip ci] ## [7.4.0-nakamoto.6](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.5...v7.4.0-nakamoto.6) (2023-12-15) ### Features * add `/extended/v2/blocks/:height_or_hash` ([#1774](https://github.com/hirosystems/stacks-blockchain-api/issues/1774)) ([e532a5e](https://github.com/hirosystems/stacks-blockchain-api/commit/e532a5e173340f732536b9236d60585501f2da5f)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 011042d701..203e0233b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-nakamoto.6](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.5...v7.4.0-nakamoto.6) (2023-12-15) + + +### Features + +* add `/extended/v2/blocks/:height_or_hash` ([#1774](https://github.com/hirosystems/stacks-blockchain-api/issues/1774)) ([e532a5e](https://github.com/hirosystems/stacks-blockchain-api/commit/e532a5e173340f732536b9236d60585501f2da5f)) + ## [7.4.0-nakamoto.5](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.4...v7.4.0-nakamoto.5) (2023-12-15) From 18f74b7b77c95a81c2f6d47641af229c5c833b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Fri, 15 Dec 2023 11:48:19 -0600 Subject: [PATCH 42/91] fix: remove deprecated token endpoints (#1775) * fix: remove deprecated token endpoints * fix: broken import * chore: remove FT tag from openapi [skip ci] --- .../get-address-nft-events.example.json | 13 - .../get-address-nft-events.schema.json | 28 --- ...e-tokens-metadata-list.example.schema.json | 18 -- ...-fungible-tokens-metadata-list.schema.json | 33 --- ...e-tokens-metadata-list.example.schema.json | 16 -- ...-fungible-tokens-metadata-list.schema.json | 33 --- .../tokens/fungible-token.schema.example.json | 11 - .../tokens/fungible-token.schema.json | 54 ---- .../non-fungible-token.schema.example.json | 9 - .../tokens/non-fungible-token.schema.json | 44 ---- docs/generated.d.ts | 161 ++---------- docs/openapi.yaml | 192 -------------- src/api/routes/address.ts | 60 ----- src/datastore/pg-store.ts | 50 ---- src/rosetta/rosetta-helpers.ts | 1 - src/tests/address-tests.ts | 234 ------------------ .../read-load-profiling/sampled-requests.txt | 9 - 17 files changed, 23 insertions(+), 943 deletions(-) delete mode 100644 docs/api/address/get-address-nft-events.example.json delete mode 100644 docs/api/address/get-address-nft-events.schema.json delete mode 100644 docs/api/tokens/get-fungible-tokens-metadata-list.example.schema.json delete mode 100644 docs/api/tokens/get-fungible-tokens-metadata-list.schema.json delete mode 100644 docs/api/tokens/get-non-fungible-tokens-metadata-list.example.schema.json delete mode 100644 docs/api/tokens/get-non-fungible-tokens-metadata-list.schema.json delete mode 100644 docs/entities/tokens/fungible-token.schema.example.json delete mode 100644 docs/entities/tokens/fungible-token.schema.json delete mode 100644 docs/entities/tokens/non-fungible-token.schema.example.json delete mode 100644 docs/entities/tokens/non-fungible-token.schema.json diff --git a/docs/api/address/get-address-nft-events.example.json b/docs/api/address/get-address-nft-events.example.json deleted file mode 100644 index 079a20605a..0000000000 --- a/docs/api/address/get-address-nft-events.example.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "limit": 20, - "offset": 0, - "total": 1, - "nft_events": [ - { - "sender": "none", - "recipient": "ST1HB64MAJ1MBV4CQ80GF01DZS4T1DSMX20ADCRA4", - "asset_identifier": "some-asset", - "value": { "hex": "0x00", "repr": "0" } - } - ] -} diff --git a/docs/api/address/get-address-nft-events.schema.json b/docs/api/address/get-address-nft-events.schema.json deleted file mode 100644 index ea1a083e6a..0000000000 --- a/docs/api/address/get-address-nft-events.schema.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "type": "object", - "title": "AddressNftListResponse", - "additionalProperties": false, - "required": [ - "limit", - "offset", - "total", - "nft_events" - ], - "properties": { - "limit": { - "type": "integer" - }, - "offset": { - "type": "integer" - }, - "total": { - "type": "integer" - }, - "nft_events": { - "type": "array", - "items": { - "$ref": "../../entities/nft-events/nft-event.schema.json" - } - } - } -} diff --git a/docs/api/tokens/get-fungible-tokens-metadata-list.example.schema.json b/docs/api/tokens/get-fungible-tokens-metadata-list.example.schema.json deleted file mode 100644 index d0f0c1ea4c..0000000000 --- a/docs/api/tokens/get-fungible-tokens-metadata-list.example.schema.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "limit": 1, - "offset": 0, - "total": 500, - "results": [ - { - "token_uri": "https://heystack.xyz/token-metadata.json", - "name": "Heystack", - "description": "Heystack is a SIP-010-compliant fungible token on the Stacks Blockchain, used on the Heystack app", - "image_uri": "https://heystack.xyz/assets/Stacks128w.png", - "image_canonical_uri": "https://heystack.xyz/assets/Stacks128w.png", - "tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0", - "sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA", - "symbol": "HEY", - "decimals": 5 - } - ] -} diff --git a/docs/api/tokens/get-fungible-tokens-metadata-list.schema.json b/docs/api/tokens/get-fungible-tokens-metadata-list.schema.json deleted file mode 100644 index f38108e826..0000000000 --- a/docs/api/tokens/get-fungible-tokens-metadata-list.schema.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "description": "List of fungible tokens metadata", - "title": "FungibleTokensMetadataList", - "type": "object", - "additionalProperties": false, - "required": [ - "results", - "limit", - "offset", - "total" - ], - "properties": { - "limit": { - "type": "integer", - "maximum": 200, - "description": "The number of tokens metadata to return" - }, - "offset": { - "type": "integer", - "description": "The number to tokens metadata to skip (starting at `0`)" - }, - "total": { - "type": "integer", - "description": "The number of tokens metadata available" - }, - "results": { - "type": "array", - "items": { - "$ref": "../../entities/tokens/fungible-token.schema.json" - } - } - } -} diff --git a/docs/api/tokens/get-non-fungible-tokens-metadata-list.example.schema.json b/docs/api/tokens/get-non-fungible-tokens-metadata-list.example.schema.json deleted file mode 100644 index 4130b33a76..0000000000 --- a/docs/api/tokens/get-non-fungible-tokens-metadata-list.example.schema.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "limit": 1, - "offset": 0, - "total": 500, - "results": [ - { - "token_uri": "https://pool.friedger.de/nft.json", - "name": "Friedger Pool", - "description": "Enjoying the stacking pool.", - "image_uri": "https://pool.friedger.de/nft.webp", - "image_canonical_uri": "https://pool.friedger.de/nft.webp", - "tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0", - "sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA" - } - ] -} diff --git a/docs/api/tokens/get-non-fungible-tokens-metadata-list.schema.json b/docs/api/tokens/get-non-fungible-tokens-metadata-list.schema.json deleted file mode 100644 index 7c3b8f4b41..0000000000 --- a/docs/api/tokens/get-non-fungible-tokens-metadata-list.schema.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "description": "List of non fungible tokens metadata", - "title": "NonFungibleTokensMetadataList", - "additionalProperties": false, - "type": "object", - "required": [ - "results", - "limit", - "offset", - "total" - ], - "properties": { - "limit": { - "type": "integer", - "maximum": 200, - "description": "The number of tokens metadata to return" - }, - "offset": { - "type": "integer", - "description": "The number to tokens metadata to skip (starting at `0`)" - }, - "total": { - "type": "integer", - "description": "The number of tokens metadata available" - }, - "results": { - "type": "array", - "items": { - "$ref": "../../entities/tokens/non-fungible-token.schema.json" - } - } - } -} diff --git a/docs/entities/tokens/fungible-token.schema.example.json b/docs/entities/tokens/fungible-token.schema.example.json deleted file mode 100644 index cffa6ab3a0..0000000000 --- a/docs/entities/tokens/fungible-token.schema.example.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "token_uri": "https://heystack.xyz/token-metadata.json", - "name": "Heystack", - "description": "Heystack is a SIP-010-compliant fungible token on the Stacks Blockchain, used on the Heystack app", - "image_uri": "https://heystack.xyz/assets/Stacks128w.png", - "image_canonical_uri": "https://heystack.xyz/assets/Stacks128w.png", - "tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0", - "sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA", - "symbol": "HEY", - "decimals": 5 -} diff --git a/docs/entities/tokens/fungible-token.schema.json b/docs/entities/tokens/fungible-token.schema.json deleted file mode 100644 index 18411ba0d5..0000000000 --- a/docs/entities/tokens/fungible-token.schema.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "title": "FungibleTokenMetadata", - "type": "object", - "additionalProperties": false, - "required": [ - "token_uri", - "name", - "description", - "image_uri", - "image_canonical_uri", - "symbol", - "decimals", - "tx_id", - "sender_address" - ], - "properties": { - "token_uri": { - "type": "string", - "description": "An optional string that is a valid URI which resolves to this token's metadata. Can be empty." - }, - "name": { - "type": "string", - "description": "Identifies the asset to which this token represents" - }, - "description": { - "type": "string", - "description": "Describes the asset to which this token represents" - }, - "image_uri": { - "type": "string", - "description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI." - }, - "image_canonical_uri": { - "type": "string", - "description": "The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." - }, - "symbol": { - "type": "string", - "description": "A shorter representation of a token. This is sometimes referred to as a \"ticker\". Examples: \"STX\", \"COOL\", etc. Typically, a token could be referred to as $SYMBOL when referencing it in writing." - }, - "decimals": { - "type": "number", - "description": "The number of decimal places in a token." - }, - "tx_id": { - "type": "string", - "description": "Tx id that deployed the contract" - }, - "sender_address": { - "type": "string", - "description": "principle that deployed the contract" - } - } -} diff --git a/docs/entities/tokens/non-fungible-token.schema.example.json b/docs/entities/tokens/non-fungible-token.schema.example.json deleted file mode 100644 index 57f9613e1c..0000000000 --- a/docs/entities/tokens/non-fungible-token.schema.example.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "token_uri": "https://pool.friedger.de/nft.json", - "name": "Friedger Pool", - "description": "Enjoying the stacking pool.", - "image_uri": "https://pool.friedger.de/nft.webp", - "image_canonical_uri": "https://pool.friedger.de/nft.webp", - "tx_id": "0xef2ac1126e16f46843228b1dk4830e19eb7599129e4jf392cab9e65ae83a45c0", - "sender_address": "ST399W7Z9WS0GMSNQGJGME5JAENKN56D65VGMGKGA" -} diff --git a/docs/entities/tokens/non-fungible-token.schema.json b/docs/entities/tokens/non-fungible-token.schema.json deleted file mode 100644 index e59137bd7f..0000000000 --- a/docs/entities/tokens/non-fungible-token.schema.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "title": "NonFungibleTokenMetadata", - "type": "object", - "additionalProperties": false, - "required": [ - "token_uri", - "name", - "description", - "image_uri", - "image_canonical_uri", - "tx_id", - "sender_address" - ], - "properties": { - "token_uri": { - "type": "string", - "description": "An optional string that is a valid URI which resolves to this token's metadata. Can be empty." - }, - "name": { - "type": "string", - "description": "Identifies the asset to which this token represents" - }, - "description": { - "type": "string", - "description": "Describes the asset to which this token represents" - }, - "image_uri": { - "type": "string", - "description": "A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI." - }, - "image_canonical_uri": { - "type": "string", - "description": "The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." - }, - "tx_id": { - "type": "string", - "description": "Tx id that deployed the contract" - }, - "sender_address": { - "type": "string", - "description": "principle that deployed the contract" - } - } -} diff --git a/docs/generated.d.ts b/docs/generated.d.ts index cb286e5485..97538fa4c5 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -7,7 +7,6 @@ export type SchemaMergeRootStub = | AddressAssetsListResponse | AddressBalanceResponse - | AddressNftListResponse | AddressStxBalanceResponse | AddressStxInboundListResponse | AddressTransactionsWithTransfersListResponse @@ -97,11 +96,9 @@ export type SchemaMergeRootStub = | { [k: string]: unknown | undefined; } - | FungibleTokensMetadataList | NonFungibleTokenHistoryEventList | NonFungibleTokenHoldingsList | NonFungibleTokenMintList - | NonFungibleTokensMetadataList | MempoolTransactionStatsResponse | MempoolTransactionListResponse | GetRawTransactionResult @@ -180,7 +177,6 @@ export type SchemaMergeRootStub = | TransactionIdentifier | RosettaTransaction | PoolDelegation - | FungibleTokenMetadata | NonFungibleTokenHistoryEventWithTxId | NonFungibleTokenHistoryEventWithTxMetadata | NonFungibleTokenHistoryEvent @@ -190,7 +186,6 @@ export type SchemaMergeRootStub = | NonFungibleTokenMintWithTxId | NonFungibleTokenMintWithTxMetadata | NonFungibleTokenMint - | NonFungibleTokenMetadata | AbstractTransactionEvent | TransactionEventAssetType | TransactionEventAsset @@ -849,35 +844,6 @@ export interface AddressUnlockSchedule { amount: string; block_height: number; } -export interface AddressNftListResponse { - limit: number; - offset: number; - total: number; - nft_events: NftEvent[]; -} -export interface NftEvent { - sender?: string; - recipient?: string; - asset_identifier: string; - asset_event_type: string; - /** - * Identifier of the NFT - */ - value: { - /** - * Hex string representing the identifier of the NFT - */ - hex: string; - /** - * Readable string of the NFT identifier - */ - repr: string; - }; - tx_id: string; - tx_index: number; - block_height: number; - event_index: number; -} /** * GET request that returns a list of inbound STX transfers with a memo */ @@ -3106,62 +3072,6 @@ export interface PoolDelegation { */ tx_id: string; } -/** - * List of fungible tokens metadata - */ -export interface FungibleTokensMetadataList { - /** - * The number of tokens metadata to return - */ - limit: number; - /** - * The number to tokens metadata to skip (starting at `0`) - */ - offset: number; - /** - * The number of tokens metadata available - */ - total: number; - results: FungibleTokenMetadata[]; -} -export interface FungibleTokenMetadata { - /** - * An optional string that is a valid URI which resolves to this token's metadata. Can be empty. - */ - token_uri: string; - /** - * Identifies the asset to which this token represents - */ - name: string; - /** - * Describes the asset to which this token represents - */ - description: string; - /** - * A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI. - */ - image_uri: string; - /** - * The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive. - */ - image_canonical_uri: string; - /** - * A shorter representation of a token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, a token could be referred to as $SYMBOL when referencing it in writing. - */ - symbol: string; - /** - * The number of decimal places in a token. - */ - decimals: number; - /** - * Tx id that deployed the contract - */ - tx_id: string; - /** - * principle that deployed the contract - */ - sender_address: string; -} /** * List of Non-Fungible Token history events */ @@ -3320,54 +3230,6 @@ export interface NonFungibleTokenMintWithTxMetadata { }; tx: Transaction; } -/** - * List of non fungible tokens metadata - */ -export interface NonFungibleTokensMetadataList { - /** - * The number of tokens metadata to return - */ - limit: number; - /** - * The number to tokens metadata to skip (starting at `0`) - */ - offset: number; - /** - * The number of tokens metadata available - */ - total: number; - results: NonFungibleTokenMetadata[]; -} -export interface NonFungibleTokenMetadata { - /** - * An optional string that is a valid URI which resolves to this token's metadata. Can be empty. - */ - token_uri: string; - /** - * Identifies the asset to which this token represents - */ - name: string; - /** - * Describes the asset to which this token represents - */ - description: string; - /** - * A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI. - */ - image_uri: string; - /** - * The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive. - */ - image_canonical_uri: string; - /** - * Tx id that deployed the contract - */ - tx_id: string; - /** - * principle that deployed the contract - */ - sender_address: string; -} /** * GET request that returns stats on mempool transactions */ @@ -3587,6 +3449,29 @@ export interface ReadOnlyFunctionArgs { */ arguments: string[]; } +export interface NftEvent { + sender?: string; + recipient?: string; + asset_identifier: string; + asset_event_type: string; + /** + * Identifier of the NFT + */ + value: { + /** + * Hex string representing the identifier of the NFT + */ + hex: string; + /** + * Readable string of the NFT identifier + */ + repr: string; + }; + tx_id: string; + tx_index: number; + block_height: number; + event_index: number; +} /** * Instead of utilizing HTTP status codes to describe node errors (which often do not have a good analog), rich errors are returned using this object. Both the code and message fields can be individually used to correctly identify an error. Implementations MUST use unique values for both fields. */ diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 00ed7c2d30..d79d3ed633 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -25,11 +25,6 @@ tags: description: Endpoints to request STX or BTC tokens (not possible on Mainnet) - name: Fees description: Read-only endpoints to obtain fee details - - name: Fungible Tokens - description: Read-only endpoints to obtain fungible token details - externalDocs: - description: Stacks Documentation - Tokens - url: https://docs.stacks.co/write-smart-contracts/tokens - name: Info description: Read-only endpoints to obtain network, Proof-of-Transfer, Stacking, STX token, and node information - name: Microblocks @@ -1815,63 +1810,6 @@ paths: example: $ref: ./api/address/get-address-stx-inbound.example.json - /extended/v1/address/{principal}/nft_events: - get: - summary: Get nft events - deprecated: true - description: | - **NOTE:** This endpoint is deprecated in favor of [Non-Fungible Token holdings](#operation/get_nft_holdings). - - Retrieves a list of all nfts owned by an address, contains the clarity value of the identifier of the nft. - tags: - - Accounts - operationId: get_account_nft - parameters: - - name: principal - in: path - description: Stacks address or a Contract identifier - required: true - schema: - type: string - example: "SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0" - - name: limit - in: query - description: number of items to return - required: false - schema: - type: integer - - name: offset - in: query - description: number of items to skip - required: false - schema: - type: integer - example: 42000 - - name: unanchored - in: query - description: Include transaction data from unanchored (i.e. unconfirmed) microblocks - required: false - schema: - type: boolean - example: true - default: false - - name: until_block - in: query - description: returned data representing the state up until that point in time, rather than the current block. Note - Use either of the query parameters but not both at a time. - required: false - schema: - type: string - example: 60000 - responses: - 200: - description: Success - content: - application/json: - schema: - $ref: ./api/address/get-address-nft-events.schema.json - example: - $ref: ./api/address/get-address-nft-events.example.json - /v2/accounts/{principal}: get: summary: Get account info @@ -3145,43 +3083,6 @@ paths: example: $ref: ./api/transaction/get-mempool-transactions.example.json - /extended/v1/tokens/ft/metadata: - get: - operationId: get_ft_metadata_list - summary: Fungible tokens metadata list - deprecated: true - description: | - **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). - - Retrieves list of fungible tokens with their metadata. More information on Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#fungible-tokens). - tags: - - Fungible Tokens - parameters: - - name: limit - in: query - description: max number of tokens to fetch. - required: false - schema: - type: integer - example: 100 - maximum: 200 - - name: offset - in: query - description: index of first tokens to fetch - required: false - schema: - type: integer - example: 42000 - responses: - 200: - description: List of fungible tokens metadata - content: - application/json: - schema: - $ref: ./api/tokens/get-fungible-tokens-metadata-list.schema.json - example: - $ref: ./api/tokens/get-fungible-tokens-metadata-list.example.schema.json - /extended/v1/tokens/nft/holdings: get: operationId: get_nft_holdings @@ -3388,99 +3289,6 @@ paths: value: $ref: ./api/tokens/get-non-fungible-token-mints-tx-metadata.example.schema.json - /extended/v1/tokens/nft/metadata: - get: - operationId: get_nft_metadata_list - summary: Non fungible tokens metadata list - deprecated: true - description: | - **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). - - Retrieves a list of non fungible tokens with their metadata. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). - tags: - - Non-Fungible Tokens - parameters: - - name: limit - in: query - description: max number of tokens to fetch - required: false - schema: - type: integer - example: 1 - - name: offset - in: query - description: index of first tokens to fetch - required: false - schema: - type: integer - example: 42000 - responses: - 200: - description: List of non fungible tokens metadata - content: - application/json: - schema: - $ref: ./api/tokens/get-non-fungible-tokens-metadata-list.schema.json - example: - $ref: ./api/tokens/get-non-fungible-tokens-metadata-list.example.schema.json - - /extended/v1/tokens/{contractId}/nft/metadata: - get: - operationId: get_contract_nft_metadata - summary: Non fungible tokens metadata for contract ID - deprecated: true - description: | - **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). - - Retrieves metadata for non fungible tokens for a given contract id. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). - tags: - - Non-Fungible Tokens - parameters: - - name: contractId - in: path - description: token's contract id - required: true - schema: - type: string - responses: - 200: - description: Non fungible tokens metadata for contract id - content: - application/json: - schema: - $ref: ./entities/tokens/non-fungible-token.schema.json - example: - $ref: ./entities/tokens/non-fungible-token.schema.example.json - - /extended/v1/tokens/{contractId}/ft/metadata: - get: - operationId: get_contract_ft_metadata - summary: Fungible tokens metadata for contract id - deprecated: true - description: | - **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). - - Retrieves the metadata for fungible tokens for a given contract id - tags: - - Fungible Tokens - parameters: - - name: contractId - in: path - description: token's contract id - required: true - schema: - type: string - example: "SPSCWDV3RKV5ZRN1FQD84YE1NQFEDJ9R1F4DYQ11.newyorkcitycoin-token-v2" - responses: - 200: - description: Fungible tokens metadata for contract id - content: - application/json: - schema: - $ref: ./entities/tokens/fungible-token.schema.json - example: - $ref: ./entities/tokens/fungible-token.schema.example.json - /extended/v1/fee_rate: post: operationId: fetch_fee_rate diff --git a/src/api/routes/address.ts b/src/api/routes/address.ts index 7ef60c2361..a4061b0911 100644 --- a/src/api/routes/address.ts +++ b/src/api/routes/address.ts @@ -11,7 +11,6 @@ import { } from '../query-helpers'; import { ChainID, formatMapToObject, getSendManyContract, isValidPrincipal } from '../../helpers'; import { - getAssetEventTypeString, getTxFromDataStore, parseDbEvent, parseDbMempoolTx, @@ -25,12 +24,10 @@ import { AddressStxBalanceResponse, AddressStxInboundListResponse, InboundStxTransfer, - AddressNftListResponse, MempoolTransactionListResponse, AddressTransactionWithTransfers, AddressTransactionsWithTransfersListResponse, AddressNonces, - NftEvent, } from '@stacks/stacks-blockchain-api-types'; import { decodeClarityValueToRepr } from 'stacks-encoding-native-js'; import { validate } from '../validate'; @@ -472,63 +469,6 @@ export function createAddressRouter(db: PgStore, chainId: ChainID): express.Rout }) ); - /** - * @deprecated Use `/extended/v1/tokens/nft/holdings` instead. - */ - router.get( - '/:stx_address/nft_events', - cacheHandler, - asyncHandler(async (req, res, next) => { - // get recent asset event associated with address - const stxAddress = req.params['stx_address']; - validatePrincipal(stxAddress); - - const limit = getPagingQueryLimit(ResourceType.Event, req.query.limit); - const offset = parsePagingQueryInput(req.query.offset ?? 0); - const includeUnanchored = isUnanchoredRequest(req, res, next); - const untilBlock = parseUntilBlockQuery(req, res, next); - - const nftListResponse = await db.sqlTransaction(async sql => { - const blockHeight = await getBlockHeight(untilBlock, req, res, next, db); - - const response = await db.getAddressNFTEvent({ - stxAddress, - limit, - offset, - blockHeight, - includeUnanchored, - }); - const nft_events = response.results.map(row => { - const parsedClarityValue = decodeClarityValueToRepr(row.value); - const r: NftEvent = { - sender: row.sender, - recipient: row.recipient, - asset_identifier: row.asset_identifier, - value: { - hex: row.value, - repr: parsedClarityValue, - }, - tx_id: row.tx_id, - block_height: row.block_height, - event_index: row.event_index, - asset_event_type: getAssetEventTypeString(row.asset_event_type_id), - tx_index: row.tx_index, - }; - return r; - }); - const nftListResponse: AddressNftListResponse = { - nft_events: nft_events, - total: response.total, - limit: limit, - offset: offset, - }; - return nftListResponse; - }); - setETagCacheHeaders(res); - res.json(nftListResponse); - }) - ); - router.get( '/:address/mempool', mempoolCacheHandler, diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index eabc8d8b09..9a3539a4c2 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -3540,56 +3540,6 @@ export class PgStore extends BasePgStore { return { found: true, result: result[0] } as const; } - /** - * @deprecated Use `getNftHoldings` instead. - */ - async getAddressNFTEvent(args: { - stxAddress: string; - limit: number; - offset: number; - blockHeight: number; - includeUnanchored: boolean; - }): Promise<{ results: AddressNftEventIdentifier[]; total: number }> { - // Join against `nft_custody` materialized view only if we're looking for canonical results. - const result = await this.sql<(AddressNftEventIdentifier & { count: number })[]>` - WITH address_transfers AS ( - SELECT asset_identifier, value, sender, recipient, block_height, microblock_sequence, tx_index, event_index, tx_id, asset_event_type_id - FROM nft_events - WHERE canonical = true AND microblock_canonical = true - AND recipient = ${args.stxAddress} AND block_height <= ${args.blockHeight} - ), - last_nft_transfers AS ( - SELECT DISTINCT ON(asset_identifier, value) asset_identifier, value, recipient - FROM nft_events - WHERE canonical = true AND microblock_canonical = true - AND block_height <= ${args.blockHeight} - ORDER BY asset_identifier, value, block_height DESC, microblock_sequence DESC, tx_index DESC, event_index DESC - ) - SELECT sender, recipient, asset_identifier, value, at.event_index, asset_event_type_id, at.block_height, at.tx_id, (COUNT(*) OVER())::INTEGER AS count - FROM address_transfers AS at - INNER JOIN ${args.includeUnanchored ? this.sql`last_nft_transfers` : this.sql`nft_custody`} - USING (asset_identifier, value, recipient) - ORDER BY at.block_height DESC, at.microblock_sequence DESC, at.tx_index DESC, event_index DESC - LIMIT ${args.limit} OFFSET ${args.offset} - `; - - const count = result.length > 0 ? result[0].count : 0; - - const nftEvents = result.map(row => ({ - sender: row.sender, - recipient: row.recipient, - asset_identifier: row.asset_identifier, - value: row.value, - block_height: row.block_height, - tx_id: row.tx_id, - event_index: row.event_index, - asset_event_type_id: row.asset_event_type_id, - tx_index: row.tx_index, - })); - - return { results: nftEvents, total: count }; - } - async getTxListDetails({ txIds, includeUnanchored, diff --git a/src/rosetta/rosetta-helpers.ts b/src/rosetta/rosetta-helpers.ts index c00c3ff908..3ad4cc3553 100644 --- a/src/rosetta/rosetta-helpers.ts +++ b/src/rosetta/rosetta-helpers.ts @@ -1,6 +1,5 @@ import { ContractCallTransaction, - FungibleTokenMetadata, RosettaAccountIdentifier, RosettaCurrency, RosettaOperation, diff --git a/src/tests/address-tests.ts b/src/tests/address-tests.ts index c52ffef9ed..00db2d577a 100644 --- a/src/tests/address-tests.ts +++ b/src/tests/address-tests.ts @@ -2268,7 +2268,6 @@ describe('address tests', () => { '/transactions_with_transfers', '/assets', '/stx_inbound', - '/nft_events', ]; //check for mutually exclusive unachored and and until_block @@ -2290,239 +2289,6 @@ describe('address tests', () => { } }); - test('Success: nft events for address', async () => { - const addr1 = 'ST3J8EVYHVKH6XXPD61EE8XEHW4Y2K83861225AB1'; - const addr2 = 'ST1HB64MAJ1MBV4CQ80GF01DZS4T1DSMX20ADCRA4'; - - const dbBlock: DbBlock = { - block_hash: '0xff', - index_block_hash: '0x1234', - parent_index_block_hash: '0x5678', - parent_block_hash: '0x5678', - parent_microblock_hash: '', - parent_microblock_sequence: 0, - block_height: 1, - burn_block_time: 1594647995, - burn_block_hash: '0x1234', - burn_block_height: 123, - miner_txid: '0x4321', - canonical: true, - execution_cost_read_count: 0, - execution_cost_read_length: 0, - execution_cost_runtime: 0, - execution_cost_write_count: 0, - execution_cost_write_length: 0, - }; - const stxTx: DbTxRaw = { - tx_id: '0x1111000000000000000000000000000000000000000000000000000000000000', - tx_index: 0, - anchor_mode: 3, - nonce: 0, - raw_tx: '0x', - index_block_hash: dbBlock.index_block_hash, - block_hash: dbBlock.block_hash, - block_height: dbBlock.block_height, - burn_block_time: dbBlock.burn_block_time, - parent_burn_block_time: 1626122935, - type_id: DbTxTypeId.TokenTransfer, - token_transfer_amount: 1n, - token_transfer_memo: bufferToHex(Buffer.from('hi')), - token_transfer_recipient_address: 'none', - status: 1, - raw_result: '0x0100000000000000000000000000000001', // u1 - canonical: true, - microblock_canonical: true, - microblock_sequence: I32_MAX, - microblock_hash: '', - parent_index_block_hash: dbBlock.parent_index_block_hash, - parent_block_hash: dbBlock.parent_block_hash, - post_conditions: '0x01f5', - fee_rate: 1234n, - sponsored: false, - sponsor_address: undefined, - sender_address: addr1, - origin_hash_mode: 1, - event_count: 10, - execution_cost_read_count: 0, - execution_cost_read_length: 0, - execution_cost_runtime: 0, - execution_cost_write_count: 0, - execution_cost_write_length: 0, - }; - const nftEvents: DbNftEvent[] = []; - for (let i = 0; i < 10; i++) { - nftEvents.push({ - canonical: true, - event_type: DbEventTypeId.NonFungibleTokenAsset, - asset_event_type_id: DbAssetEventTypeId.Transfer, - event_index: 0, - tx_id: stxTx.tx_id, - tx_index: 1, - block_height: dbBlock.block_height, - asset_identifier: 'some-asset', - value: '0x0000000000000000000000000000000000', - recipient: addr1, - sender: 'none', - }); - } - - await db.update({ - block: dbBlock, - microblocks: [], - minerRewards: [], - txs: [ - { - tx: stxTx, - stxLockEvents: [], - stxEvents: [], - ftEvents: [], - nftEvents: nftEvents, - contractLogEvents: [], - smartContracts: [], - names: [], - namespaces: [], - pox2Events: [], - pox3Events: [], - pox4Events: [], - }, - ], - }); - - const limit = 2; - const offset = 0; - // test nft for given addresses - const result = await supertest(api.server).get( - `/extended/v1/address/${addr1}/nft_events?limit=${limit}&offset=${offset}` - ); - expect(result.status).toBe(200); - expect(result.type).toBe('application/json'); - expect(result.body.total).toEqual(10); - expect(result.body.nft_events.length).toEqual(2); - expect(result.body.nft_events[0].recipient).toBe(addr1); - expect(result.body.nft_events[0].tx_id).toBe( - '0x1111000000000000000000000000000000000000000000000000000000000000' - ); - expect(result.body.nft_events[0].block_height).toBe(1); - expect(result.body.nft_events[0].value.repr).toBe('0'); - - const dbBlock2: DbBlock = { - block_hash: '0xffff', - index_block_hash: '0x123466', - parent_index_block_hash: '0x1234', - parent_block_hash: '0xff', - parent_microblock_hash: '', - parent_microblock_sequence: 0, - block_height: 2, - burn_block_time: 1594649995, - burn_block_hash: '0x123456', - burn_block_height: 124, - miner_txid: '0x4321', - canonical: true, - execution_cost_read_count: 0, - execution_cost_read_length: 0, - execution_cost_runtime: 0, - execution_cost_write_count: 0, - execution_cost_write_length: 0, - }; - const stxTx1: DbTxRaw = { - tx_id: '0x1111100000000000000000000000000000000000000000000000000000000001', - tx_index: 0, - anchor_mode: 3, - nonce: 0, - raw_tx: '0x', - index_block_hash: dbBlock2.index_block_hash, - block_hash: dbBlock2.block_hash, - block_height: dbBlock2.block_height, - burn_block_time: dbBlock2.burn_block_time, - parent_burn_block_time: 1626124935, - type_id: DbTxTypeId.TokenTransfer, - token_transfer_amount: 1n, - token_transfer_memo: bufferToHex(Buffer.from('hi')), - token_transfer_recipient_address: 'none', - status: 1, - raw_result: '0x0100000000000000000000000000000001', // u1 - canonical: true, - microblock_canonical: true, - microblock_sequence: I32_MAX, - microblock_hash: '', - parent_index_block_hash: dbBlock2.parent_index_block_hash, - parent_block_hash: dbBlock2.parent_block_hash, - post_conditions: '0x01f5', - fee_rate: 1234n, - sponsored: false, - sponsor_address: undefined, - sender_address: addr2, - origin_hash_mode: 1, - event_count: 1, - execution_cost_read_count: 0, - execution_cost_read_length: 0, - execution_cost_runtime: 0, - execution_cost_write_count: 0, - execution_cost_write_length: 0, - }; - const nftEvent2: DbNftEvent = { - canonical: true, - event_type: DbEventTypeId.NonFungibleTokenAsset, - asset_event_type_id: DbAssetEventTypeId.Transfer, - event_index: 1, - tx_id: stxTx1.tx_id, - tx_index: 2, - block_height: dbBlock2.block_height, - asset_identifier: 'some-asset', - value: '0x0000000000000000000000000000000000', - recipient: addr2, - sender: 'none', - }; - await db.update({ - block: dbBlock2, - microblocks: [], - minerRewards: [], - txs: [ - { - tx: stxTx1, - stxLockEvents: [], - stxEvents: [], - ftEvents: [], - nftEvents: [nftEvent2], - contractLogEvents: [], - smartContracts: [], - names: [], - namespaces: [], - pox2Events: [], - pox3Events: [], - pox4Events: [], - }, - ], - }); - - const result1 = await supertest(api.server).get(`/extended/v1/address/${addr2}/nft_events`); - expect(result1.status).toBe(200); - expect(result1.type).toBe('application/json'); - expect(result1.body.total).toEqual(1); - expect(result1.body.nft_events.length).toEqual(1); - expect(result1.body.nft_events[0].recipient).toBe(addr2); - expect(result1.body.nft_events[0].tx_id).toBe( - '0x1111100000000000000000000000000000000000000000000000000000000001' - ); - expect(result1.body.nft_events[0].block_height).toBe(2); - expect(result.body.nft_events[0].value.repr).toBe('0'); - - //check ownership for addr - const result2 = await supertest(api.server).get(`/extended/v1/address/${addr1}/nft_events`); - expect(result2.status).toBe(200); - expect(result2.type).toBe('application/json'); - expect(result2.body.nft_events.length).toEqual(0); - expect(result2.body.total).toEqual(0); - }); - - test('nft invalid address', async () => { - const result = await supertest(api.server).get( - `/extended/v1/address/invalid-address/nft_events` - ); - expect(result.status).toBe(400); - expect(result.type).toBe('application/json'); - }); - test('/transactions materialized view separates anchored and unanchored counts correctly', async () => { const contractId = 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft'; diff --git a/utils/read-load-profiling/sampled-requests.txt b/utils/read-load-profiling/sampled-requests.txt index a4c46e913a..9a922f4da6 100644 --- a/utils/read-load-profiling/sampled-requests.txt +++ b/utils/read-load-profiling/sampled-requests.txt @@ -2,7 +2,6 @@ /extended/v1/address/SP2ZSTSSE61NZTRGWVB18MEQ26AMQ0Z7R70Z2ND36/transactions_with_transfers?limit=50&unanchored=true /extended/v1/address/SP2Y4WPD4JDQ9A9HCADNTNTE6NTEKCCNDBA373XHY/transactions_with_transfers?limit=50&unanchored=true /extended/v1/block/0x10bc1ba06366077c85b096bfa7b0e4f2f9df1fe3182e1cec8ffa7ee79a11bf92?unanchored=true -/extended/v1/address/SP1TA84JTP4YRFWBK7PYKBA33H3YB60XP654RAR7M/nft_events?limit=50&offset=0 /extended/v1/tx/0x0429af694679c329ba6a7ec0e0c540148b99e720db286589df2b07844c459e62?unanchored=true /extended/v1/tx/0xcacb7888089d814974cfdc8ee65ca639f65e7911eeb7f26f05bd4139797be390?event_offset=0&event_limit=200 /extended/v1/tx/0x2632ee0489174c5e2900b33f0c40dda2c1abcf6f41bb0aa91441e678c4478ea3?unanchored=true @@ -169,7 +168,6 @@ /extended/v1/block/0x983157ca681cfc98fcb3f655e2bbef2805977fc9a869495da5a71e98ad8b544e?unanchored=true /extended/v1/address/SP374RMXRCP8SZCWYT21KX7ETY3V2WSQPNGEZ7GF8/balances /extended/v1/address/SP3W3F6SS0G0BSFE1AWA1S7C66EY744W1BJMNT96M/balances -/extended/v1/tokens/ft/metadata?unanchored=true /extended/v1/address/SP1QDGYS3D54VK3QX7E0TB11BS6M5JRHGDQJVX01X/balances /extended/v1/tx/0x2cab8e5fe2ec4457a1dbb21bfb351d8342e02b2c7123cf1290ebb817fd531e93?unanchored=true /extended/v1/address/SP1Y56N007J3H18CA2N5T5E4XY3K4V5WD030H0NXC/stx?unanchored=true @@ -436,7 +434,6 @@ /extended/v1/address/SP1G9JDXSSWM0EHP2FNMEB5GQ06WA54TMDVM1CNMG/stx /extended/v1/address/SP1FEAD66PAAYHQRZG4G6FV0RY1RWBA7SJV6NFXVD/stx?unanchored=true /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft -/extended/v1/tokens/ft/metadata?unanchored=true /extended/v1/address/SP3H3X8ZPY9XJE7Q7DREH7F0RXJJH3EFWBMC8ETFY/transactions_with_transfers?limit=50&unanchored=true /extended/v1/tx/mempool?limit=200&address=SP7383KRJA9AQAY9WS1AKAPG4KAR9ERQM3586AZ3&unanchored=true /extended/v1/contract/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1?unanchored=true @@ -766,7 +763,6 @@ /extended/v1/address/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft/transactions?limit=30&offset=0&unanchored=true /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft /extended/v1/tx/0x07f603ca4b210e0a17bd31b56a27f7a98502e1e4db8873ca65574660b0fb15e9?event_offset=0&event_limit=200 -/extended/v1/tokens/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-token-xbtc-usda/ft/metadata?unanchored=true /extended/v1/address/SP15BBZH3TSP1KT7RNNJ86566WD2K8GT8AH93V3V7/transactions?limit=50 /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft /extended/v1/tx/0x8fb7bee09eff178935d1e174ac565ae75a47d074baa2f19f6386ec8daf478bb3?event_offset=0&event_limit=200 @@ -813,9 +809,7 @@ /extended/v1/address/SP2XZ5NT9R6W7PAD9Z72MZA8RRDD168AP28N9CNMV/stx?unanchored=true /extended/v1/address/SP2XZ5NT9R6W7PAD9Z72MZA8RRDD168AP28N9CNMV/transactions_with_transfers?limit=50&unanchored=true /extended/v1/tx/mempool?limit=30&offset=0&unanchored=true -/extended/v1/tokens/ft/metadata?unanchored=true /extended/v1/address/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-v2-1/balances?unanchored=true -/extended/v1/tokens/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.wrapped-stx-token/ft/metadata?unanchored=true /extended/v1/address/SPJW1XE278YMCEYMXB8ZFGJMH8ZVAAEDP2S2PJYG.stacks-art-market-v2/transactions?limit=30&offset=0&unanchored=true /extended/v1/tx/mempool?limit=30&offset=0&unanchored=true /extended/v1/tx/0xc259761a2c7435388a283d15d989f4ec5e8dac7994d0599862009ae95d988fc4?unanchored=true @@ -823,7 +817,6 @@ /extended/v1/tx/0x76901f23e486881a855d44c58ea2e9632066d93742e0b63de0b7b6aebfb78c58?unanchored=true /extended/v1/block/0x112d73352fbc27ef4f75bd2b1023d0b16e03ce6d3c169ed8e233fac64c9e5c4b?unanchored=true /extended/v1/address/SP3YK7KWMYRCDMV5M4792T0T7DERQXHJJGGEPV1N8/balances?unanchored=true -/extended/v1/tokens/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-swap-token-wstx-diko/ft/metadata?unanchored=true /extended/v1/address/SP15BBZH3TSP1KT7RNNJ86566WD2K8GT8AH93V3V7/balances /extended/v1/tx/0x350a207e00756a50527216c19682540d46318785efedcec07804ebbd1b28c8ba?unanchored=true /extended/v1/contract/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft?unanchored=true @@ -959,11 +952,9 @@ /extended/v1/tx/mempool?limit=200&address=SP1WGEZBR8BCXRA9X6QS3X24X8HPVPF9P1Q8MYTEB /extended/v1/tx/0xc9517fc98a26de0498a4dce5e14007cd200da97acf8ee80f55ace095af87f5b5?unanchored=true /extended/v1/address/SP37G983VM8T3RPSSQTVA798Y3GPJEXEJK8FJ7M03/transactions_with_transfers?limit=50&unanchored=true -/extended/v1/tokens/ft/metadata?unanchored=true /extended/v1/address/SPV6J95VNA11FAQ3ATFV8JTP78SFGRS6V2EB0SWN/transactions?limit=30&unanchored=true /extended/v1/address/SP2KAF9RF86PVX3NEE27DFV1CQX0T4WGR41X3S45C.wasteland-apes-nft/transactions?limit=30&offset=0&unanchored=true /extended/v1/block/0xdbf829d5d1a3f17b35faf0ff0336587e7ac10a8b21a2e001eae539a592351a65?unanchored=true -/extended/v1/tokens/SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.age000-governance-token/ft/metadata?unanchored=true /extended/v1/address/SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.arkadiko-stake-registry-v1-1/transactions?limit=30&offset=0&unanchored=true /extended/v1/tx/mempool?address=SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.megapont-ape-club-nft /extended/v1/address/SP14V9BXQR5A6M32REYYFDBQQE7FA0Q2R41GD90NK/balances?unanchored=true From bf99e90fa56ed04e6cb6bcc83559658f9e551183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Mon, 18 Dec 2023 09:23:05 -0600 Subject: [PATCH 43/91] fix: insert block transaction data in batches (#1760) * chore: first pass of batching * fix: tests * refactor: rename bns tx header type * chore: more refactors * chore: upgrade toolkit * chore: upgrade api toolkit * fix: do not wait for pg notifications * fix: parquet function calls * fix: bns test imports * fix: batch size * fix: pox event writes * chore: reorganize pox3 unlock height --- package-lock.json | 74 +- package.json | 2 +- src/datastore/common.ts | 7 +- src/datastore/helpers.ts | 162 ++ src/datastore/pg-write-store.ts | 1351 ++++++++--------- src/event-replay/helpers.ts | 12 +- .../importers/attachment-new-importer.ts | 2 +- .../importers/new-block-importer.ts | 27 +- .../parquet-based/importers/raw-importer.ts | 2 +- src/helpers.ts | 65 - src/import-v1/index.ts | 25 +- src/tests-bns/api.ts | 16 +- src/tests-bns/v1-import-tests.ts | 5 +- src/tests/datastore-tests.ts | 25 +- src/tests/other-tests.ts | 2 +- src/tests/search-tests.ts | 8 +- src/tests/tx-tests.ts | 20 +- 17 files changed, 852 insertions(+), 953 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1f7613d20a..f52f83a861 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/json-schema-ref-parser": "9.0.9", - "@hirosystems/api-toolkit": "1.2.2", + "@hirosystems/api-toolkit": "1.3.3", "@promster/express": "6.0.0", "@promster/server": "6.0.6", "@promster/types": "3.2.3", @@ -128,48 +128,6 @@ "utf-8-validate": "5.0.7" } }, - "../api-toolkit": { - "name": "@hirosystems/api-toolkit", - "version": "1.1.0", - "extraneous": true, - "license": "Apache 2.0", - "dependencies": { - "@fastify/cors": "^8.0.0", - "@fastify/swagger": "^8.3.1", - "@fastify/type-provider-typebox": "^3.2.0", - "fastify": "^4.3.0", - "fastify-metrics": "^10.2.0", - "node-pg-migrate": "^6.2.2", - "pino": "^8.11.0", - "postgres": "^3.3.4" - }, - "bin": { - "api-toolkit-git-info": "bin/api-toolkit-git-info.js" - }, - "devDependencies": { - "@commitlint/cli": "^17.5.0", - "@commitlint/config-conventional": "^17.4.4", - "@stacks/eslint-config": "^1.2.0", - "@types/jest": "^29.5.0", - "@typescript-eslint/eslint-plugin": "^5.56.0", - "@typescript-eslint/parser": "^5.56.0", - "babel-jest": "^29.5.0", - "copyfiles": "^2.4.1", - "eslint": "^8.36.0", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-tsdoc": "^0.2.17", - "husky": "^8.0.3", - "jest": "^29.5.0", - "prettier": "^2.8.6", - "rimraf": "^4.4.1", - "ts-jest": "^29.0.5", - "ts-node": "^10.9.1", - "typescript": "^5.0.2" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -1234,9 +1192,9 @@ } }, "node_modules/@fastify/cors": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-8.4.0.tgz", - "integrity": "sha512-MlVvMTenltToByTpLwlWtO+7dQ3l2J+1OpmGrx9JpSNWo1d+dhfNCOi23zHhxdFhtpDzfwGwCsKu9DTeG7k7nQ==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-8.4.1.tgz", + "integrity": "sha512-iYQJtrY3pFiDS5mo5zRaudzg2OcUdJ96PD6xfkKOOEilly5nnrFZx/W6Sce2T79xxlEn2qpU3t5+qS2phS369w==", "dependencies": { "fastify-plugin": "^4.0.0", "mnemonist": "0.39.5" @@ -1273,9 +1231,9 @@ } }, "node_modules/@fastify/swagger/node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "engines": { "node": ">= 14" } @@ -1289,9 +1247,9 @@ } }, "node_modules/@hirosystems/api-toolkit": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@hirosystems/api-toolkit/-/api-toolkit-1.2.2.tgz", - "integrity": "sha512-HLaodPN6dHUAkrOwECsMwQicBMhJn8CYlS0QwC4SC3smclno3fB0oKm1QYZFQEDy2KV3IPTAh70B/vkpib/Kkw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@hirosystems/api-toolkit/-/api-toolkit-1.3.3.tgz", + "integrity": "sha512-0/JjQ54twLdVqf8+hB+8IAKn8JdCdlMfT3BqUWha5qMrjlC3KX+kAl+88+CqpoibY/lgYJ9fs+70KG/weHt3LQ==", "dependencies": { "@fastify/cors": "^8.0.0", "@fastify/swagger": "^8.3.1", @@ -1378,9 +1336,9 @@ } }, "node_modules/@hirosystems/api-toolkit/node_modules/postgres": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.2.tgz", - "integrity": "sha512-0UcCGvDBSaAzLeWwiq+QVmiGfOPTosFb+sxJUUtd+7Pi/ByFPuz6Gq05LbS0sM1ghMWC5atuks3pfl34g0qmFw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.3.tgz", + "integrity": "sha512-iHJn4+M9vbTdHSdDzNkC0crHq+1CUdFhx+YqCE+SqWxPjm+Zu63jq7yZborOBF64c8pc58O5uMudyL1FQcHacA==", "engines": { "node": ">=12" }, @@ -6964,9 +6922,9 @@ } }, "node_modules/fastify-metrics": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/fastify-metrics/-/fastify-metrics-10.3.2.tgz", - "integrity": "sha512-02SEIGH02zfguqRMho0LB8L7YVAj5cIgWM0iqZslIErqaUWc1iHVAOC+YXYG3S2DZU6VHdFaMyuxjEOCQHAETA==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/fastify-metrics/-/fastify-metrics-10.3.3.tgz", + "integrity": "sha512-TmMcfrMWBSbA7yk31tFtJnWKtNXLSO7jmTRIjPX9HKC4pLmyd0JnOQ3r9XCYnev6NL9/eVRXxNfrsqQdKTLZkw==", "dependencies": { "fastify-plugin": "^4.3.0", "prom-client": "^14.2.0" diff --git a/package.json b/package.json index 5f39f710a6..a2973ec0c4 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,7 @@ }, "dependencies": { "@apidevtools/json-schema-ref-parser": "9.0.9", - "@hirosystems/api-toolkit": "1.2.2", + "@hirosystems/api-toolkit": "1.3.3", "@promster/express": "6.0.0", "@promster/server": "6.0.6", "@promster/types": "3.2.3", diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 83b4f85ca4..773051bbac 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -632,6 +632,11 @@ export interface DataStoreBnsBlockData { microblock_canonical: boolean; } +export type DataStoreBnsBlockTxData = DataStoreBnsBlockData & { + tx_id: string; + tx_index: number; +}; + export interface DataStoreAttachmentSubdomainData { attachment?: DataStoreAttachmentData; blockData?: DataStoreBnsBlockData; @@ -976,7 +981,7 @@ export interface FaucetRequestQueryResult { occurred_at: string; } -export interface UpdatedEntities { +export interface ReOrgUpdatedEntities { markedCanonical: { blocks: number; microblocks: number; diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index ca8331407f..af92983f71 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -2,6 +2,7 @@ import { parseEnum, unwrapOptionalProp } from '../helpers'; import { BlockQueryResult, ContractTxQueryResult, + DataStoreBlockUpdateData, DbBlock, DbEvent, DbEventBase, @@ -42,6 +43,7 @@ import { PoxSyntheticEventQueryResult, TxQueryResult, DbPoxSyntheticRevokeDelegateStxEvent, + ReOrgUpdatedEntities, } from './common'; import { CoreNodeDropMempoolTxReasonType, @@ -1229,3 +1231,163 @@ export function convertTxQueryResultToDbMempoolTx(txs: TxQueryResult[]): DbMempo } return dbMempoolTxs; } + +export function setTotalBlockUpdateDataExecutionCost(data: DataStoreBlockUpdateData) { + const cost = data.txs.reduce( + (previousValue, currentValue) => { + const { + execution_cost_read_count, + execution_cost_read_length, + execution_cost_runtime, + execution_cost_write_count, + execution_cost_write_length, + } = previousValue; + return { + execution_cost_read_count: + execution_cost_read_count + currentValue.tx.execution_cost_read_count, + execution_cost_read_length: + execution_cost_read_length + currentValue.tx.execution_cost_read_length, + execution_cost_runtime: execution_cost_runtime + currentValue.tx.execution_cost_runtime, + execution_cost_write_count: + execution_cost_write_count + currentValue.tx.execution_cost_write_count, + execution_cost_write_length: + execution_cost_write_length + currentValue.tx.execution_cost_write_length, + }; + }, + { + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + } + ); + data.block.execution_cost_read_count = cost.execution_cost_read_count; + data.block.execution_cost_read_length = cost.execution_cost_read_length; + data.block.execution_cost_runtime = cost.execution_cost_runtime; + data.block.execution_cost_write_count = cost.execution_cost_write_count; + data.block.execution_cost_write_length = cost.execution_cost_write_length; +} + +export function markBlockUpdateDataAsNonCanonical(data: DataStoreBlockUpdateData): void { + data.block = { ...data.block, canonical: false }; + data.microblocks = data.microblocks.map(mb => ({ ...mb, canonical: false })); + data.txs = data.txs.map(tx => ({ + tx: { ...tx.tx, canonical: false }, + stxLockEvents: tx.stxLockEvents.map(e => ({ ...e, canonical: false })), + stxEvents: tx.stxEvents.map(e => ({ ...e, canonical: false })), + ftEvents: tx.ftEvents.map(e => ({ ...e, canonical: false })), + nftEvents: tx.nftEvents.map(e => ({ ...e, canonical: false })), + contractLogEvents: tx.contractLogEvents.map(e => ({ ...e, canonical: false })), + smartContracts: tx.smartContracts.map(e => ({ ...e, canonical: false })), + names: tx.names.map(e => ({ ...e, canonical: false })), + namespaces: tx.namespaces.map(e => ({ ...e, canonical: false })), + pox2Events: tx.pox2Events.map(e => ({ ...e, canonical: false })), + pox3Events: tx.pox3Events.map(e => ({ ...e, canonical: false })), + pox4Events: tx.pox4Events.map(e => ({ ...e, canonical: false })), + })); + data.minerRewards = data.minerRewards.map(mr => ({ ...mr, canonical: false })); +} + +export function newReOrgUpdatedEntities(): ReOrgUpdatedEntities { + return { + markedCanonical: { + blocks: 0, + microblocks: 0, + minerRewards: 0, + txs: 0, + stxLockEvents: 0, + stxEvents: 0, + ftEvents: 0, + nftEvents: 0, + pox2Events: 0, + pox3Events: 0, + pox4Events: 0, + contractLogs: 0, + smartContracts: 0, + names: 0, + namespaces: 0, + subdomains: 0, + }, + markedNonCanonical: { + blocks: 0, + microblocks: 0, + minerRewards: 0, + txs: 0, + stxLockEvents: 0, + stxEvents: 0, + ftEvents: 0, + nftEvents: 0, + pox2Events: 0, + pox3Events: 0, + pox4Events: 0, + contractLogs: 0, + smartContracts: 0, + names: 0, + namespaces: 0, + subdomains: 0, + }, + }; +} + +export function logReorgResultInfo(updatedEntities: ReOrgUpdatedEntities) { + const updates = [ + ['blocks', updatedEntities.markedCanonical.blocks, updatedEntities.markedNonCanonical.blocks], + [ + 'microblocks', + updatedEntities.markedCanonical.microblocks, + updatedEntities.markedNonCanonical.microblocks, + ], + ['txs', updatedEntities.markedCanonical.txs, updatedEntities.markedNonCanonical.txs], + [ + 'miner-rewards', + updatedEntities.markedCanonical.minerRewards, + updatedEntities.markedNonCanonical.minerRewards, + ], + [ + 'stx-lock events', + updatedEntities.markedCanonical.stxLockEvents, + updatedEntities.markedNonCanonical.stxLockEvents, + ], + [ + 'stx-token events', + updatedEntities.markedCanonical.stxEvents, + updatedEntities.markedNonCanonical.stxEvents, + ], + [ + 'non-fungible-token events', + updatedEntities.markedCanonical.nftEvents, + updatedEntities.markedNonCanonical.nftEvents, + ], + [ + 'fungible-token events', + updatedEntities.markedCanonical.ftEvents, + updatedEntities.markedNonCanonical.ftEvents, + ], + [ + 'contract logs', + updatedEntities.markedCanonical.contractLogs, + updatedEntities.markedNonCanonical.contractLogs, + ], + [ + 'smart contracts', + updatedEntities.markedCanonical.smartContracts, + updatedEntities.markedNonCanonical.smartContracts, + ], + ['names', updatedEntities.markedCanonical.names, updatedEntities.markedNonCanonical.names], + [ + 'namespaces', + updatedEntities.markedCanonical.namespaces, + updatedEntities.markedNonCanonical.namespaces, + ], + [ + 'subdomains', + updatedEntities.markedCanonical.subdomains, + updatedEntities.markedNonCanonical.subdomains, + ], + ]; + const markedCanonical = updates.map(e => `${e[1]} ${e[0]}`).join(', '); + logger.debug(`Entities marked as canonical: ${markedCanonical}`); + const markedNonCanonical = updates.map(e => `${e[2]} ${e[0]}`).join(', '); + logger.debug(`Entities marked as non-canonical: ${markedNonCanonical}`); +} diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 2380da21a1..3da53808d5 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -1,4 +1,4 @@ -import { getOrAdd, batchIterate, I32_MAX, getIbdBlockHeight } from '../helpers'; +import { getOrAdd, I32_MAX, getIbdBlockHeight } from '../helpers'; import { DbBlock, DbTx, @@ -45,7 +45,7 @@ import { FaucetRequestInsertValues, MicroblockInsertValues, TxQueryResult, - UpdatedEntities, + ReOrgUpdatedEntities, BlockQueryResult, DataStoreAttachmentData, DataStoreAttachmentSubdomainData, @@ -57,12 +57,15 @@ import { RawEventRequestInsertValues, IndexesState, NftCustodyInsertValues, + DataStoreBnsBlockTxData, DbPoxSyntheticEvent, PoxSyntheticEventTable, } from './common'; import { BLOCK_COLUMNS, + setTotalBlockUpdateDataExecutionCost, convertTxQueryResultToDbMempoolTx, + markBlockUpdateDataAsNonCanonical, MEMPOOL_TX_COLUMNS, MICROBLOCK_COLUMNS, parseBlockQueryResult, @@ -72,6 +75,8 @@ import { TX_COLUMNS, TX_METADATA_TABLES, validateZonefileHash, + newReOrgUpdatedEntities, + logReorgResultInfo, } from './helpers'; import { PgNotifier } from './pg-notifier'; import { MIGRATIONS_DIR, PgStore } from './pg-store'; @@ -82,13 +87,16 @@ import { logger } from '../logger'; import { PgJsonb, PgSqlClient, + batchIterate, connectPostgres, isProdEnv, + isTestEnv, runMigrations, } from '@hirosystems/api-toolkit'; import { PgServer, getConnectionArgs, getConnectionConfig } from './connection'; const MIGRATIONS_TABLE = 'pgmigrations'; +const INSERT_BATCH_SIZE = 500; class MicroblockGapError extends Error { constructor(message: string) { @@ -167,112 +175,30 @@ export class PgWriteStore extends PgStore { async update(data: DataStoreBlockUpdateData): Promise { let garbageCollectedMempoolTxs: string[] = []; let batchedTxData: DataStoreTxEventData[] = []; - const deployedSmartContracts: DbSmartContract[] = []; - const contractLogEvents: DbSmartContractEvent[] = []; await this.sqlWriteTransaction(async sql => { const chainTip = await this.getChainTip(); await this.handleReorg(sql, data.block, chainTip.block_height); - // If the incoming block is not of greater height than current chain tip, then store data as non-canonical. + const isCanonical = data.block.block_height > chainTip.block_height; if (!isCanonical) { - data.block = { ...data.block, canonical: false }; - data.microblocks = data.microblocks.map(mb => ({ ...mb, canonical: false })); - data.txs = data.txs.map(tx => ({ - tx: { ...tx.tx, canonical: false }, - stxLockEvents: tx.stxLockEvents.map(e => ({ ...e, canonical: false })), - stxEvents: tx.stxEvents.map(e => ({ ...e, canonical: false })), - ftEvents: tx.ftEvents.map(e => ({ ...e, canonical: false })), - nftEvents: tx.nftEvents.map(e => ({ ...e, canonical: false })), - contractLogEvents: tx.contractLogEvents.map(e => ({ ...e, canonical: false })), - smartContracts: tx.smartContracts.map(e => ({ ...e, canonical: false })), - names: tx.names.map(e => ({ ...e, canonical: false })), - namespaces: tx.namespaces.map(e => ({ ...e, canonical: false })), - pox2Events: tx.pox2Events.map(e => ({ ...e, canonical: false })), - pox3Events: tx.pox3Events.map(e => ({ ...e, canonical: false })), - pox4Events: tx.pox4Events.map(e => ({ ...e, canonical: false })), - })); - data.minerRewards = data.minerRewards.map(mr => ({ ...mr, canonical: false })); + markBlockUpdateDataAsNonCanonical(data); } else { - // When storing newly mined canonical txs, remove them from the mempool table. - const candidateTxIds = data.txs.map(d => d.tx.tx_id); - const removedTxsResult = await this.pruneMempoolTxs(sql, candidateTxIds); - if (removedTxsResult.removedTxs.length > 0) { + const txIds = data.txs.map(d => d.tx.tx_id); + const pruneRes = await this.pruneMempoolTxs(sql, txIds); + if (pruneRes.removedTxs.length > 0) logger.debug( - `Removed ${removedTxsResult.removedTxs.length} txs from mempool table during new block ingestion` + `Removed ${pruneRes.removedTxs.length} txs from mempool table during new block ingestion` ); - } } + setTotalBlockUpdateDataExecutionCost(data); - //calculate total execution cost of the block - const totalCost = data.txs.reduce( - (previousValue, currentValue) => { - const { - execution_cost_read_count, - execution_cost_read_length, - execution_cost_runtime, - execution_cost_write_count, - execution_cost_write_length, - } = previousValue; - - return { - execution_cost_read_count: - execution_cost_read_count + currentValue.tx.execution_cost_read_count, - execution_cost_read_length: - execution_cost_read_length + currentValue.tx.execution_cost_read_length, - execution_cost_runtime: execution_cost_runtime + currentValue.tx.execution_cost_runtime, - execution_cost_write_count: - execution_cost_write_count + currentValue.tx.execution_cost_write_count, - execution_cost_write_length: - execution_cost_write_length + currentValue.tx.execution_cost_write_length, - }; - }, - { - execution_cost_read_count: 0, - execution_cost_read_length: 0, - execution_cost_runtime: 0, - execution_cost_write_count: 0, - execution_cost_write_length: 0, - } - ); - - data.block.execution_cost_read_count = totalCost.execution_cost_read_count; - data.block.execution_cost_read_length = totalCost.execution_cost_read_length; - data.block.execution_cost_runtime = totalCost.execution_cost_runtime; - data.block.execution_cost_write_count = totalCost.execution_cost_write_count; - data.block.execution_cost_write_length = totalCost.execution_cost_write_length; - - batchedTxData = data.txs; - - // Find microblocks that weren't already inserted via the unconfirmed microblock event. - // This happens when a stacks-node is syncing and receives confirmed microblocks with their anchor block at the same time. - if (data.microblocks.length > 0) { - const existingMicroblocksQuery = await sql<{ microblock_hash: string }[]>` - SELECT microblock_hash - FROM microblocks - WHERE parent_index_block_hash = ${data.block.parent_index_block_hash} - AND microblock_hash IN ${sql(data.microblocks.map(mb => mb.microblock_hash))} - `; - const existingMicroblockHashes = new Set( - existingMicroblocksQuery.map(r => r.microblock_hash) - ); - - const missingMicroblocks = data.microblocks.filter( - mb => !existingMicroblockHashes.has(mb.microblock_hash) - ); - if (missingMicroblocks.length > 0) { - const missingMicroblockHashes = new Set(missingMicroblocks.map(mb => mb.microblock_hash)); - const missingTxs = data.txs.filter(entry => - missingMicroblockHashes.has(entry.tx.microblock_hash) - ); - await this.insertMicroblockData(sql, missingMicroblocks, missingTxs); - - // Clear already inserted microblock txs from the anchor-block update data to avoid duplicate inserts. - batchedTxData = batchedTxData.filter(entry => { - return !missingMicroblockHashes.has(entry.tx.microblock_hash); - }); - } - } + // Insert microblocks, if any. Clear already inserted microblock txs from the anchor-block + // update data to avoid duplicate inserts. + const insertedMicroblockHashes = await this.insertMicroblocksFromBlockUpdate(sql, data); + batchedTxData = data.txs.filter(entry => { + return !insertedMicroblockHashes.has(entry.tx.microblock_hash); + }); // When processing an immediately-non-canonical block, do not orphan and possible existing microblocks // which may be still considered canonical by the canonical block at this height. @@ -308,31 +234,8 @@ export class PgWriteStore extends PgStore { const matchingTx = acceptedMicroblockTxs.find(tx => tx.tx_id === entry.tx.tx_id); return !matchingTx; }); - } - if (isCanonical && data.pox_v1_unlock_height !== undefined) { - // update the pox_state.pox_v1_unlock_height singleton - await sql` - UPDATE pox_state - SET pox_v1_unlock_height = ${data.pox_v1_unlock_height} - WHERE pox_v1_unlock_height != ${data.pox_v1_unlock_height} - `; - } - if (isCanonical && data.pox_v2_unlock_height !== undefined) { - // update the pox_state.pox_v2_unlock_height singleton - await sql` - UPDATE pox_state - SET pox_v2_unlock_height = ${data.pox_v2_unlock_height} - WHERE pox_v2_unlock_height != ${data.pox_v2_unlock_height} - `; - } - if (isCanonical && data.pox_v3_unlock_height !== undefined) { - // update the pox_state.pox_v3_unlock_height singleton - await sql` - UPDATE pox_state - SET pox_v3_unlock_height = ${data.pox_v3_unlock_height} - WHERE pox_v3_unlock_height != ${data.pox_v3_unlock_height} - `; + await this.updatePoxStateUnlockHeight(sql, data); } // When receiving first block, check if "block 0" boot data was received, @@ -344,50 +247,22 @@ export class PgWriteStore extends PgStore { await this.fixBlockZeroData(sql, data.block); } } - - // TODO(mb): sanity tests on tx_index on batchedTxData, re-normalize if necessary - - // TODO(mb): copy the batchedTxData to outside the sql transaction fn so they can be emitted in txUpdate event below - - const blocksUpdated = await this.updateBlock(sql, data.block); - if (blocksUpdated !== 0) { - for (const minerRewards of data.minerRewards) { - await this.updateMinerReward(sql, minerRewards); - } + if ((await this.updateBlock(sql, data.block)) !== 0) { + await this.updateMinerRewards(sql, data.minerRewards); for (const entry of batchedTxData) { await this.updateTx(sql, entry.tx); - await this.updateBatchStxEvents(sql, entry.tx, entry.stxEvents); + await this.updateStxEvents(sql, entry.tx, entry.stxEvents); await this.updatePrincipalStxTxs(sql, entry.tx, entry.stxEvents); - contractLogEvents.push(...entry.contractLogEvents); - await this.updateBatchSmartContractEvent(sql, entry.tx, entry.contractLogEvents); - for (const pox2Event of entry.pox2Events) { - await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox2_events', pox2Event); - } - for (const pox3Event of entry.pox3Events) { - await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox3_events', pox3Event); - } - for (const pox4Event of entry.pox4Events) { - await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox4_events', pox4Event); - } - for (const stxLockEvent of entry.stxLockEvents) { - await this.updateStxLockEvent(sql, entry.tx, stxLockEvent); - } - for (const ftEvent of entry.ftEvents) { - await this.updateFtEvent(sql, entry.tx, ftEvent); - } - for (const nftEvent of entry.nftEvents) { - await this.updateNftEvent(sql, entry.tx, nftEvent, false); - } - deployedSmartContracts.push(...entry.smartContracts); - for (const smartContract of entry.smartContracts) { - await this.updateSmartContract(sql, entry.tx, smartContract); - } - for (const namespace of entry.namespaces) { - await this.updateNamespaces(sql, entry.tx, namespace); - } - for (const bnsName of entry.names) { - await this.updateNames(sql, entry.tx, bnsName); - } + await this.updateSmartContractEvents(sql, entry.tx, entry.contractLogEvents); + await this.updatePoxSyntheticEvents(sql, entry.tx, 'pox2_events', entry.pox2Events); + await this.updatePoxSyntheticEvents(sql, entry.tx, 'pox3_events', entry.pox3Events); + await this.updatePoxSyntheticEvents(sql, entry.tx, 'pox4_events', entry.pox4Events); + await this.updateStxLockEvents(sql, entry.tx, entry.stxLockEvents); + await this.updateFtEvents(sql, entry.tx, entry.ftEvents); + await this.updateNftEvents(sql, entry.tx, entry.nftEvents); + await this.updateSmartContracts(sql, entry.tx, entry.smartContracts); + await this.updateNamespaces(sql, entry.tx, entry.namespaces); + await this.updateNames(sql, entry.tx, entry.names); } const mempoolGarbageResults = await this.deleteGarbageCollectedMempoolTxs(sql); if (mempoolGarbageResults.deletedTxs.length > 0) { @@ -418,63 +293,136 @@ export class PgWriteStore extends PgStore { tx_count = (SELECT tx_count FROM new_tx_count), tx_count_unanchored = (SELECT tx_count FROM new_tx_count) `; + + await this.refreshMaterializedView('mempool_digest'); }); // Do we have an IBD height defined in ENV? If so, check if this block update reached it. const ibdHeight = getIbdBlockHeight(); this.isIbdBlockHeightReached = ibdHeight ? data.block.block_height > ibdHeight : true; + // Send block updates but don't block current execution unless we're testing. + if (isTestEnv) await this.sendBlockNotifications({ data, garbageCollectedMempoolTxs }); + else void this.sendBlockNotifications({ data, garbageCollectedMempoolTxs }); + } - await this.refreshMaterializedView('mempool_digest'); - - // Skip sending `PgNotifier` updates altogether if we're in the genesis block since this block is the - // event replay of the v1 blockchain. - if ((data.block.block_height > 1 || !isProdEnv) && this.notifier) { - await this.notifier.sendBlock({ blockHash: data.block.block_hash }); - for (const tx of data.txs) { - await this.notifier.sendTx({ txId: tx.tx.tx_id }); - } - for (const txId of garbageCollectedMempoolTxs) { - await this.notifier.sendTx({ txId: txId }); - } - for (const smartContract of deployedSmartContracts) { + /** + * Send block update via Postgres NOTIFY + * @param args - Block data + */ + private async sendBlockNotifications(args: { + data: DataStoreBlockUpdateData; + garbageCollectedMempoolTxs: string[]; + }): Promise { + // Skip sending `PgNotifier` updates altogether if we're in the genesis block since this block + // is the event replay of the v1 blockchain. + if (!this.notifier || !(args.data.block.block_height > 1 || !isProdEnv)) return; + await this.notifier.sendBlock({ blockHash: args.data.block.block_hash }); + for (const tx of args.data.txs) { + await this.notifier.sendTx({ txId: tx.tx.tx_id }); + for (const smartContract of tx.smartContracts) { await this.notifier.sendSmartContract({ contractId: smartContract.contract_id, }); } - for (const logEvent of contractLogEvents) { + for (const logEvent of tx.contractLogEvents) { await this.notifier.sendSmartContractLog({ txId: logEvent.tx_id, eventIndex: logEvent.event_index, }); } - await this.emitAddressTxUpdates(data.txs); - for (const nftEvent of data.txs.map(tx => tx.nftEvents).flat()) { - await this.notifier.sendNftEvent({ - txId: nftEvent.tx_id, - eventIndex: nftEvent.event_index, - }); - } + } + for (const txId of args.garbageCollectedMempoolTxs) { + await this.notifier.sendTx({ txId: txId }); + } + await this.emitAddressTxUpdates(args.data.txs); + for (const nftEvent of args.data.txs.map(tx => tx.nftEvents).flat()) { + await this.notifier.sendNftEvent({ + txId: nftEvent.tx_id, + eventIndex: nftEvent.event_index, + }); } } - async updateMinerReward(sql: PgSqlClient, minerReward: DbMinerReward): Promise { - const values: MinerRewardInsertValues = { - block_hash: minerReward.block_hash, - index_block_hash: minerReward.index_block_hash, - from_index_block_hash: minerReward.from_index_block_hash, - mature_block_height: minerReward.mature_block_height, - canonical: minerReward.canonical, - recipient: minerReward.recipient, - // If `miner_address` is null then it means pre-Stacks2.1 data, and the `recipient` can be accurately used - miner_address: minerReward.miner_address ?? minerReward.recipient, - coinbase_amount: minerReward.coinbase_amount.toString(), - tx_fees_anchored: minerReward.tx_fees_anchored.toString(), - tx_fees_streamed_confirmed: minerReward.tx_fees_streamed_confirmed.toString(), - tx_fees_streamed_produced: minerReward.tx_fees_streamed_produced.toString(), - }; - const result = await sql` - INSERT INTO miner_rewards ${sql(values)} + /** + * Find and insert microblocks that weren't already inserted via the unconfirmed `/new_microblock` + * event. This happens when a stacks-node is syncing and receives confirmed microblocks with their + * anchor block at the same time. + * @param sql - SQL client + * @param data - Block data to insert + * @returns Set of microblock hashes that were inserted in this update + */ + private async insertMicroblocksFromBlockUpdate( + sql: PgSqlClient, + data: DataStoreBlockUpdateData + ): Promise> { + if (data.microblocks.length == 0) return new Set(); + const existingMicroblocksQuery = await sql<{ microblock_hash: string }[]>` + SELECT DISTINCT microblock_hash + FROM microblocks + WHERE parent_index_block_hash = ${data.block.parent_index_block_hash} + AND microblock_hash IN ${sql(data.microblocks.map(mb => mb.microblock_hash))} `; - return result.count; + const existingHashes = existingMicroblocksQuery.map(i => i.microblock_hash); + const missingMicroblocks = data.microblocks.filter( + mb => !existingHashes.includes(mb.microblock_hash) + ); + if (missingMicroblocks.length > 0) { + const missingMicroblockHashes = new Set(missingMicroblocks.map(mb => mb.microblock_hash)); + const missingTxs = data.txs.filter(entry => + missingMicroblockHashes.has(entry.tx.microblock_hash) + ); + await this.insertMicroblockData(sql, missingMicroblocks, missingTxs); + return missingMicroblockHashes; + } + return new Set(); + } + + private async updatePoxStateUnlockHeight(sql: PgSqlClient, data: DataStoreBlockUpdateData) { + if (data.pox_v1_unlock_height !== undefined) { + // update the pox_state.pox_v1_unlock_height singleton + await sql` + UPDATE pox_state + SET pox_v1_unlock_height = ${data.pox_v1_unlock_height} + WHERE pox_v1_unlock_height != ${data.pox_v1_unlock_height} + `; + } + if (data.pox_v2_unlock_height !== undefined) { + // update the pox_state.pox_v2_unlock_height singleton + await sql` + UPDATE pox_state + SET pox_v2_unlock_height = ${data.pox_v2_unlock_height} + WHERE pox_v2_unlock_height != ${data.pox_v2_unlock_height} + `; + } + if (data.pox_v3_unlock_height !== undefined) { + // update the pox_state.pox_v3_unlock_height singleton + await sql` + UPDATE pox_state + SET pox_v3_unlock_height = ${data.pox_v3_unlock_height} + WHERE pox_v3_unlock_height != ${data.pox_v3_unlock_height} + `; + } + } + + async updateMinerRewards(sql: PgSqlClient, minerRewards: DbMinerReward[]): Promise { + for (const batch of batchIterate(minerRewards, INSERT_BATCH_SIZE)) { + const values: MinerRewardInsertValues[] = batch.map(minerReward => ({ + block_hash: minerReward.block_hash, + index_block_hash: minerReward.index_block_hash, + from_index_block_hash: minerReward.from_index_block_hash, + mature_block_height: minerReward.mature_block_height, + canonical: minerReward.canonical, + recipient: minerReward.recipient, + // If `miner_address` is null then it means pre-Stacks2.1 data, and the `recipient` can be accurately used + miner_address: minerReward.miner_address ?? minerReward.recipient, + coinbase_amount: minerReward.coinbase_amount.toString(), + tx_fees_anchored: minerReward.tx_fees_anchored.toString(), + tx_fees_streamed_confirmed: minerReward.tx_fees_streamed_confirmed.toString(), + tx_fees_streamed_produced: minerReward.tx_fees_streamed_produced.toString(), + })); + await sql` + INSERT INTO miner_rewards ${sql(values)} + `; + } } async updateBlock(sql: PgSqlClient, block: DbBlock): Promise { @@ -828,150 +776,156 @@ export class PgWriteStore extends PgStore { logger.info('Updated block zero boot data', tablesUpdates); } - async updatePoxSyntheticEvent( + async updatePoxSyntheticEvents( sql: PgSqlClient, tx: DbTx, poxTable: PoxSyntheticEventTable, - event: DbPoxSyntheticEvent + events: DbPoxSyntheticEvent[] ) { - const values: PoxSyntheticEventInsertValues = { - event_index: event.event_index, - tx_id: event.tx_id, - tx_index: event.tx_index, - block_height: event.block_height, - index_block_hash: tx.index_block_hash, - parent_index_block_hash: tx.parent_index_block_hash, - microblock_hash: tx.microblock_hash, - microblock_sequence: tx.microblock_sequence, - microblock_canonical: tx.microblock_canonical, - canonical: event.canonical, - stacker: event.stacker, - locked: event.locked.toString(), - balance: event.balance.toString(), - burnchain_unlock_height: event.burnchain_unlock_height.toString(), - name: event.name, - pox_addr: event.pox_addr, - pox_addr_raw: event.pox_addr_raw, - first_cycle_locked: null, - first_unlocked_cycle: null, - delegate_to: null, - lock_period: null, - lock_amount: null, - start_burn_height: null, - unlock_burn_height: null, - delegator: null, - increase_by: null, - total_locked: null, - extend_count: null, - reward_cycle: null, - amount_ustx: null, - }; - // Set event-specific columns - switch (event.name) { - case SyntheticPoxEventName.HandleUnlock: { - values.first_cycle_locked = event.data.first_cycle_locked.toString(); - values.first_unlocked_cycle = event.data.first_unlocked_cycle.toString(); - break; - } - case SyntheticPoxEventName.StackStx: { - values.lock_period = event.data.lock_period.toString(); - values.lock_amount = event.data.lock_amount.toString(); - values.start_burn_height = event.data.start_burn_height.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - break; - } - case SyntheticPoxEventName.StackIncrease: { - values.increase_by = event.data.increase_by.toString(); - values.total_locked = event.data.total_locked.toString(); - break; - } - case SyntheticPoxEventName.StackExtend: { - values.extend_count = event.data.extend_count.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - break; - } - case SyntheticPoxEventName.DelegateStx: { - values.amount_ustx = event.data.amount_ustx.toString(); - values.delegate_to = event.data.delegate_to; - values.unlock_burn_height = event.data.unlock_burn_height?.toString() ?? null; - break; - } - case SyntheticPoxEventName.DelegateStackStx: { - values.lock_period = event.data.lock_period.toString(); - values.lock_amount = event.data.lock_amount.toString(); - values.start_burn_height = event.data.start_burn_height.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - values.delegator = event.data.delegator; - break; - } - case SyntheticPoxEventName.DelegateStackIncrease: { - values.increase_by = event.data.increase_by.toString(); - values.total_locked = event.data.total_locked.toString(); - values.delegator = event.data.delegator; - break; - } - case SyntheticPoxEventName.DelegateStackExtend: { - values.extend_count = event.data.extend_count.toString(); - values.unlock_burn_height = event.data.unlock_burn_height.toString(); - values.delegator = event.data.delegator; - break; - } - case SyntheticPoxEventName.StackAggregationCommit: { - values.reward_cycle = event.data.reward_cycle.toString(); - values.amount_ustx = event.data.amount_ustx.toString(); - break; - } - case SyntheticPoxEventName.StackAggregationCommitIndexed: { - values.reward_cycle = event.data.reward_cycle.toString(); - values.amount_ustx = event.data.amount_ustx.toString(); - break; - } - case SyntheticPoxEventName.StackAggregationIncrease: { - values.reward_cycle = event.data.reward_cycle.toString(); - values.amount_ustx = event.data.amount_ustx.toString(); - break; - } - case SyntheticPoxEventName.RevokeDelegateStx: { - values.amount_ustx = event.data.amount_ustx.toString(); - values.delegate_to = event.data.delegate_to; - break; - } - default: { - throw new Error( - `Unexpected Pox synthetic event name: ${(event as DbPoxSyntheticEvent).name}` - ); - } + for (const batch of batchIterate(events, INSERT_BATCH_SIZE)) { + const values = batch.map(event => { + const value: PoxSyntheticEventInsertValues = { + event_index: event.event_index, + tx_id: event.tx_id, + tx_index: event.tx_index, + block_height: event.block_height, + index_block_hash: tx.index_block_hash, + parent_index_block_hash: tx.parent_index_block_hash, + microblock_hash: tx.microblock_hash, + microblock_sequence: tx.microblock_sequence, + microblock_canonical: tx.microblock_canonical, + canonical: event.canonical, + stacker: event.stacker, + locked: event.locked.toString(), + balance: event.balance.toString(), + burnchain_unlock_height: event.burnchain_unlock_height.toString(), + name: event.name, + pox_addr: event.pox_addr, + pox_addr_raw: event.pox_addr_raw, + first_cycle_locked: null, + first_unlocked_cycle: null, + delegate_to: null, + lock_period: null, + lock_amount: null, + start_burn_height: null, + unlock_burn_height: null, + delegator: null, + increase_by: null, + total_locked: null, + extend_count: null, + reward_cycle: null, + amount_ustx: null, + }; + // Set event-specific columns + switch (event.name) { + case SyntheticPoxEventName.HandleUnlock: { + value.first_cycle_locked = event.data.first_cycle_locked.toString(); + value.first_unlocked_cycle = event.data.first_unlocked_cycle.toString(); + break; + } + case SyntheticPoxEventName.StackStx: { + value.lock_period = event.data.lock_period.toString(); + value.lock_amount = event.data.lock_amount.toString(); + value.start_burn_height = event.data.start_burn_height.toString(); + value.unlock_burn_height = event.data.unlock_burn_height.toString(); + break; + } + case SyntheticPoxEventName.StackIncrease: { + value.increase_by = event.data.increase_by.toString(); + value.total_locked = event.data.total_locked.toString(); + break; + } + case SyntheticPoxEventName.StackExtend: { + value.extend_count = event.data.extend_count.toString(); + value.unlock_burn_height = event.data.unlock_burn_height.toString(); + break; + } + case SyntheticPoxEventName.DelegateStx: { + value.amount_ustx = event.data.amount_ustx.toString(); + value.delegate_to = event.data.delegate_to; + value.unlock_burn_height = event.data.unlock_burn_height?.toString() ?? null; + break; + } + case SyntheticPoxEventName.DelegateStackStx: { + value.lock_period = event.data.lock_period.toString(); + value.lock_amount = event.data.lock_amount.toString(); + value.start_burn_height = event.data.start_burn_height.toString(); + value.unlock_burn_height = event.data.unlock_burn_height.toString(); + value.delegator = event.data.delegator; + break; + } + case SyntheticPoxEventName.DelegateStackIncrease: { + value.increase_by = event.data.increase_by.toString(); + value.total_locked = event.data.total_locked.toString(); + value.delegator = event.data.delegator; + break; + } + case SyntheticPoxEventName.DelegateStackExtend: { + value.extend_count = event.data.extend_count.toString(); + value.unlock_burn_height = event.data.unlock_burn_height.toString(); + value.delegator = event.data.delegator; + break; + } + case SyntheticPoxEventName.StackAggregationCommit: { + value.reward_cycle = event.data.reward_cycle.toString(); + value.amount_ustx = event.data.amount_ustx.toString(); + break; + } + case SyntheticPoxEventName.StackAggregationCommitIndexed: { + value.reward_cycle = event.data.reward_cycle.toString(); + value.amount_ustx = event.data.amount_ustx.toString(); + break; + } + case SyntheticPoxEventName.StackAggregationIncrease: { + value.reward_cycle = event.data.reward_cycle.toString(); + value.amount_ustx = event.data.amount_ustx.toString(); + break; + } + case SyntheticPoxEventName.RevokeDelegateStx: { + value.amount_ustx = event.data.amount_ustx.toString(); + value.delegate_to = event.data.delegate_to; + break; + } + default: { + throw new Error( + `Unexpected Pox synthetic event name: ${(event as DbPoxSyntheticEvent).name}` + ); + } + } + return value; + }); + await sql` + INSERT INTO ${sql(poxTable)} ${sql(values)} + `; } - await sql` - INSERT INTO ${sql(poxTable)} ${sql(values)} - `; } - async updateStxLockEvent(sql: PgSqlClient, tx: DbTx, event: DbStxLockEvent) { - const values: StxLockEventInsertValues = { - event_index: event.event_index, - tx_id: event.tx_id, - tx_index: event.tx_index, - block_height: event.block_height, - index_block_hash: tx.index_block_hash, - parent_index_block_hash: tx.parent_index_block_hash, - microblock_hash: tx.microblock_hash, - microblock_sequence: tx.microblock_sequence, - microblock_canonical: tx.microblock_canonical, - canonical: event.canonical, - locked_amount: event.locked_amount.toString(), - unlock_height: event.unlock_height, - locked_address: event.locked_address, - contract_name: event.contract_name, - }; - await sql` - INSERT INTO stx_lock_events ${sql(values)} - `; + async updateStxLockEvents(sql: PgSqlClient, tx: DbTx, events: DbStxLockEvent[]) { + for (const batch of batchIterate(events, INSERT_BATCH_SIZE)) { + const values: StxLockEventInsertValues[] = batch.map(event => ({ + event_index: event.event_index, + tx_id: event.tx_id, + tx_index: event.tx_index, + block_height: event.block_height, + index_block_hash: tx.index_block_hash, + parent_index_block_hash: tx.parent_index_block_hash, + microblock_hash: tx.microblock_hash, + microblock_sequence: tx.microblock_sequence, + microblock_canonical: tx.microblock_canonical, + canonical: event.canonical, + locked_amount: event.locked_amount.toString(), + unlock_height: event.unlock_height, + locked_address: event.locked_address, + contract_name: event.contract_name, + })); + await sql` + INSERT INTO stx_lock_events ${sql(values)} + `; + } } - async updateBatchStxEvents(sql: PgSqlClient, tx: DbTx, events: DbStxEvent[]) { - const batchSize = 500; // (matt) benchmark: 21283 per second (15 seconds) - for (const eventBatch of batchIterate(events, batchSize)) { + async updateStxEvents(sql: PgSqlClient, tx: DbTx, events: DbStxEvent[]) { + for (const eventBatch of batchIterate(events, INSERT_BATCH_SIZE)) { const values: StxEventInsertValues[] = eventBatch.map(event => ({ event_index: event.event_index, tx_id: event.tx_id, @@ -1034,8 +988,7 @@ export class PgWriteStore extends PgStore { ].filter((p): p is string => !!p) // Remove undefined ); // Insert stx_event data - const batchSize = 500; - for (const eventBatch of batchIterate(events, batchSize)) { + for (const eventBatch of batchIterate(events, INSERT_BATCH_SIZE)) { const principals: string[] = []; for (const event of eventBatch) { if (event.sender) principals.push(event.sender); @@ -1183,93 +1136,128 @@ export class PgWriteStore extends PgStore { `; } - async updateFtEvent(sql: PgSqlClient, tx: DbTx, event: DbFtEvent) { - const values: FtEventInsertValues = { - event_index: event.event_index, - tx_id: event.tx_id, - tx_index: event.tx_index, - block_height: event.block_height, - index_block_hash: tx.index_block_hash, - parent_index_block_hash: tx.parent_index_block_hash, - microblock_hash: tx.microblock_hash, - microblock_sequence: tx.microblock_sequence, - microblock_canonical: tx.microblock_canonical, - canonical: event.canonical, - asset_event_type_id: event.asset_event_type_id, - sender: event.sender ?? null, - recipient: event.recipient ?? null, - asset_identifier: event.asset_identifier, - amount: event.amount.toString(), - }; - await sql` - INSERT INTO ft_events ${sql(values)} - `; + async updateFtEvents(sql: PgSqlClient, tx: DbTx, events: DbFtEvent[]) { + for (const batch of batchIterate(events, INSERT_BATCH_SIZE)) { + const values: FtEventInsertValues[] = batch.map(event => ({ + event_index: event.event_index, + tx_id: event.tx_id, + tx_index: event.tx_index, + block_height: event.block_height, + index_block_hash: tx.index_block_hash, + parent_index_block_hash: tx.parent_index_block_hash, + microblock_hash: tx.microblock_hash, + microblock_sequence: tx.microblock_sequence, + microblock_canonical: tx.microblock_canonical, + canonical: event.canonical, + asset_event_type_id: event.asset_event_type_id, + sender: event.sender ?? null, + recipient: event.recipient ?? null, + asset_identifier: event.asset_identifier, + amount: event.amount.toString(), + })); + await sql` + INSERT INTO ft_events ${sql(values)} + `; + } } - async updateNftEvent(sql: PgSqlClient, tx: DbTx, event: DbNftEvent, microblock: boolean) { - const custody: NftCustodyInsertValues = { - asset_identifier: event.asset_identifier, - value: event.value, - tx_id: event.tx_id, - index_block_hash: tx.index_block_hash, - parent_index_block_hash: tx.parent_index_block_hash, - microblock_hash: tx.microblock_hash, - microblock_sequence: tx.microblock_sequence, - recipient: event.recipient ?? null, - event_index: event.event_index, - tx_index: event.tx_index, - block_height: event.block_height, - }; - const values: NftEventInsertValues = { - ...custody, - microblock_canonical: tx.microblock_canonical, - canonical: event.canonical, - sender: event.sender ?? null, - asset_event_type_id: event.asset_event_type_id, - }; - await sql` - INSERT INTO nft_events ${sql(values)} - `; - if (tx.canonical && tx.microblock_canonical && event.canonical) { - const table = microblock ? sql`nft_custody_unanchored` : sql`nft_custody`; + async updateNftEvents( + sql: PgSqlClient, + tx: DbTx, + events: DbNftEvent[], + microblock: boolean = false + ) { + for (const batch of batchIterate(events, INSERT_BATCH_SIZE)) { + const custodyInsertsMap = new Map(); + const nftEventInserts: NftEventInsertValues[] = []; + for (const event of batch) { + const custodyItem: NftCustodyInsertValues = { + asset_identifier: event.asset_identifier, + value: event.value, + tx_id: event.tx_id, + index_block_hash: tx.index_block_hash, + parent_index_block_hash: tx.parent_index_block_hash, + microblock_hash: tx.microblock_hash, + microblock_sequence: tx.microblock_sequence, + recipient: event.recipient ?? null, + event_index: event.event_index, + tx_index: event.tx_index, + block_height: event.block_height, + }; + // Avoid duplicates on NFT custody inserts, because we could run into an `ON CONFLICT DO + // UPDATE command cannot affect row a second time` error otherwise. + const custodyKey = `${event.asset_identifier}_${event.value}`; + const currCustody = custodyInsertsMap.get(custodyKey); + if (currCustody) { + if ( + custodyItem.block_height > currCustody.block_height || + (custodyItem.block_height == currCustody.block_height && + custodyItem.microblock_sequence > currCustody.microblock_sequence) || + (custodyItem.block_height == currCustody.block_height && + custodyItem.microblock_sequence == currCustody.microblock_sequence && + custodyItem.tx_index > currCustody.tx_index) || + (custodyItem.block_height == currCustody.block_height && + custodyItem.microblock_sequence == currCustody.microblock_sequence && + custodyItem.tx_index == currCustody.tx_index && + custodyItem.event_index > currCustody.event_index) + ) { + custodyInsertsMap.set(custodyKey, custodyItem); + } + } else { + custodyInsertsMap.set(custodyKey, custodyItem); + } + const valuesItem: NftEventInsertValues = { + ...custodyItem, + microblock_canonical: tx.microblock_canonical, + canonical: event.canonical, + sender: event.sender ?? null, + asset_event_type_id: event.asset_event_type_id, + }; + nftEventInserts.push(valuesItem); + } await sql` - INSERT INTO ${table} ${sql(custody)} - ON CONFLICT ON CONSTRAINT ${table}_unique DO UPDATE SET - tx_id = EXCLUDED.tx_id, - index_block_hash = EXCLUDED.index_block_hash, - parent_index_block_hash = EXCLUDED.parent_index_block_hash, - microblock_hash = EXCLUDED.microblock_hash, - microblock_sequence = EXCLUDED.microblock_sequence, - recipient = EXCLUDED.recipient, - event_index = EXCLUDED.event_index, - tx_index = EXCLUDED.tx_index, - block_height = EXCLUDED.block_height - WHERE - ( - EXCLUDED.block_height > ${table}.block_height - ) - OR ( - EXCLUDED.block_height = ${table}.block_height - AND EXCLUDED.microblock_sequence > ${table}.microblock_sequence - ) - OR ( - EXCLUDED.block_height = ${table}.block_height - AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence - AND EXCLUDED.tx_index > ${table}.tx_index - ) - OR ( - EXCLUDED.block_height = ${table}.block_height - AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence - AND EXCLUDED.tx_index = ${table}.tx_index - AND EXCLUDED.event_index > ${table}.event_index - ) + INSERT INTO nft_events ${sql(nftEventInserts)} `; + if (tx.canonical && tx.microblock_canonical) { + const table = microblock ? sql`nft_custody_unanchored` : sql`nft_custody`; + await sql` + INSERT INTO ${table} ${sql(Array.from(custodyInsertsMap.values()))} + ON CONFLICT ON CONSTRAINT ${table}_unique DO UPDATE SET + tx_id = EXCLUDED.tx_id, + index_block_hash = EXCLUDED.index_block_hash, + parent_index_block_hash = EXCLUDED.parent_index_block_hash, + microblock_hash = EXCLUDED.microblock_hash, + microblock_sequence = EXCLUDED.microblock_sequence, + recipient = EXCLUDED.recipient, + event_index = EXCLUDED.event_index, + tx_index = EXCLUDED.tx_index, + block_height = EXCLUDED.block_height + WHERE + ( + EXCLUDED.block_height > ${table}.block_height + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence > ${table}.microblock_sequence + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence + AND EXCLUDED.tx_index > ${table}.tx_index + ) + OR ( + EXCLUDED.block_height = ${table}.block_height + AND EXCLUDED.microblock_sequence = ${table}.microblock_sequence + AND EXCLUDED.tx_index = ${table}.tx_index + AND EXCLUDED.event_index > ${table}.event_index + ) + `; + } } } - async updateBatchSmartContractEvent(sql: PgSqlClient, tx: DbTx, events: DbSmartContractEvent[]) { - const batchSize = 500; // (matt) benchmark: 21283 per second (15 seconds) - for (const eventBatch of batchIterate(events, batchSize)) { + async updateSmartContractEvents(sql: PgSqlClient, tx: DbTx, events: DbSmartContractEvent[]) { + for (const eventBatch of batchIterate(events, INSERT_BATCH_SIZE)) { const values: SmartContractEventInsertValues[] = eventBatch.map(event => ({ event_index: event.event_index, tx_id: event.tx_id, @@ -1737,202 +1725,193 @@ export class PgWriteStore extends PgStore { } } - async updateSmartContract(sql: PgSqlClient, tx: DbTx, smartContract: DbSmartContract) { - const values: SmartContractInsertValues = { - tx_id: smartContract.tx_id, - canonical: smartContract.canonical, - clarity_version: smartContract.clarity_version, - contract_id: smartContract.contract_id, - block_height: smartContract.block_height, - index_block_hash: tx.index_block_hash, - source_code: smartContract.source_code, - abi: smartContract.abi ? JSON.parse(smartContract.abi) ?? 'null' : 'null', - parent_index_block_hash: tx.parent_index_block_hash, - microblock_hash: tx.microblock_hash, - microblock_sequence: tx.microblock_sequence, - microblock_canonical: tx.microblock_canonical, - }; - await sql` - INSERT INTO smart_contracts ${sql(values)} - `; + async updateSmartContracts(sql: PgSqlClient, tx: DbTx, smartContracts: DbSmartContract[]) { + for (const batch of batchIterate(smartContracts, INSERT_BATCH_SIZE)) { + const values: SmartContractInsertValues[] = batch.map(smartContract => ({ + tx_id: smartContract.tx_id, + canonical: smartContract.canonical, + clarity_version: smartContract.clarity_version, + contract_id: smartContract.contract_id, + block_height: smartContract.block_height, + index_block_hash: tx.index_block_hash, + source_code: smartContract.source_code, + abi: smartContract.abi ? JSON.parse(smartContract.abi) ?? 'null' : 'null', + parent_index_block_hash: tx.parent_index_block_hash, + microblock_hash: tx.microblock_hash, + microblock_sequence: tx.microblock_sequence, + microblock_canonical: tx.microblock_canonical, + })); + await sql` + INSERT INTO smart_contracts ${sql(values)} + `; + } } - async updateNames( - sql: PgSqlClient, - blockData: { - index_block_hash: string; - parent_index_block_hash: string; - microblock_hash: string; - microblock_sequence: number; - microblock_canonical: boolean; - }, - bnsName: DbBnsName - ) { - const { - name, - address, - registered_at, - expire_block, - zonefile, - zonefile_hash, - namespace_id, - tx_id, - tx_index, - event_index, - status, - canonical, - } = bnsName; - // Try to figure out the name's expiration block based on its namespace's lifetime. - let expireBlock = expire_block; - const namespaceLifetime = await sql<{ lifetime: number }[]>` - SELECT lifetime - FROM namespaces - WHERE namespace_id = ${namespace_id} - AND canonical = true AND microblock_canonical = true - ORDER BY namespace_id, ready_block DESC, microblock_sequence DESC, tx_index DESC - LIMIT 1 - `; - if (namespaceLifetime.length > 0) { - expireBlock = registered_at + namespaceLifetime[0].lifetime; - } - // If the name was transferred, keep the expiration from the last register/renewal we had (if - // any). - if (status === 'name-transfer') { - const prevExpiration = await sql<{ expire_block: number }[]>` - SELECT expire_block - FROM names - WHERE name = ${name} - AND canonical = TRUE AND microblock_canonical = TRUE - ORDER BY registered_at DESC, microblock_sequence DESC, tx_index DESC + async updateNames(sql: PgSqlClient, tx: DataStoreBnsBlockTxData, names: DbBnsName[]) { + // TODO: Move these to CTE queries for optimization + for (const bnsName of names) { + const { + name, + address, + registered_at, + expire_block, + zonefile, + zonefile_hash, + namespace_id, + tx_id, + tx_index, + event_index, + status, + canonical, + } = bnsName; + // Try to figure out the name's expiration block based on its namespace's lifetime. + let expireBlock = expire_block; + const namespaceLifetime = await sql<{ lifetime: number }[]>` + SELECT lifetime + FROM namespaces + WHERE namespace_id = ${namespace_id} + AND canonical = true AND microblock_canonical = true + ORDER BY namespace_id, ready_block DESC, microblock_sequence DESC, tx_index DESC LIMIT 1 `; - if (prevExpiration.length > 0) { - expireBlock = prevExpiration[0].expire_block; + if (namespaceLifetime.length > 0) { + expireBlock = registered_at + namespaceLifetime[0].lifetime; + } + // If the name was transferred, keep the expiration from the last register/renewal we had (if + // any). + if (status === 'name-transfer') { + const prevExpiration = await sql<{ expire_block: number }[]>` + SELECT expire_block + FROM names + WHERE name = ${name} + AND canonical = TRUE AND microblock_canonical = TRUE + ORDER BY registered_at DESC, microblock_sequence DESC, tx_index DESC + LIMIT 1 + `; + if (prevExpiration.length > 0) { + expireBlock = prevExpiration[0].expire_block; + } } - } - // If we didn't receive a zonefile, keep the last valid one. - let finalZonefile = zonefile; - let finalZonefileHash = zonefile_hash; - if (finalZonefileHash === '') { - const lastZonefile = await sql<{ zonefile: string; zonefile_hash: string }[]>` - SELECT z.zonefile, z.zonefile_hash - FROM zonefiles AS z - INNER JOIN names AS n USING (name, tx_id, index_block_hash) - WHERE z.name = ${name} - AND n.canonical = TRUE - AND n.microblock_canonical = TRUE - ORDER BY n.registered_at DESC, n.microblock_sequence DESC, n.tx_index DESC - LIMIT 1 - `; - if (lastZonefile.length > 0) { - finalZonefile = lastZonefile[0].zonefile; - finalZonefileHash = lastZonefile[0].zonefile_hash; + // If we didn't receive a zonefile, keep the last valid one. + let finalZonefile = zonefile; + let finalZonefileHash = zonefile_hash; + if (finalZonefileHash === '') { + const lastZonefile = await sql<{ zonefile: string; zonefile_hash: string }[]>` + SELECT z.zonefile, z.zonefile_hash + FROM zonefiles AS z + INNER JOIN names AS n USING (name, tx_id, index_block_hash) + WHERE z.name = ${name} + AND n.canonical = TRUE + AND n.microblock_canonical = TRUE + ORDER BY n.registered_at DESC, n.microblock_sequence DESC, n.tx_index DESC + LIMIT 1 + `; + if (lastZonefile.length > 0) { + finalZonefile = lastZonefile[0].zonefile; + finalZonefileHash = lastZonefile[0].zonefile_hash; + } } + const validZonefileHash = validateZonefileHash(finalZonefileHash); + const zonefileValues: BnsZonefileInsertValues = { + name: name, + zonefile: finalZonefile, + zonefile_hash: validZonefileHash, + tx_id: tx_id, + index_block_hash: tx.index_block_hash, + }; + await sql` + INSERT INTO zonefiles ${sql(zonefileValues)} + ON CONFLICT ON CONSTRAINT unique_name_zonefile_hash_tx_id_index_block_hash DO + UPDATE SET zonefile = EXCLUDED.zonefile + `; + const nameValues: BnsNameInsertValues = { + name: name, + address: address, + registered_at: registered_at, + expire_block: expireBlock, + zonefile_hash: validZonefileHash, + namespace_id: namespace_id, + tx_index: tx_index, + tx_id: tx_id, + event_index: event_index ?? null, + status: status ?? null, + canonical: canonical, + index_block_hash: tx.index_block_hash, + parent_index_block_hash: tx.parent_index_block_hash, + microblock_hash: tx.microblock_hash, + microblock_sequence: tx.microblock_sequence, + microblock_canonical: tx.microblock_canonical, + }; + await sql` + INSERT INTO names ${sql(nameValues)} + ON CONFLICT ON CONSTRAINT unique_name_tx_id_index_block_hash_microblock_hash_event_index DO + UPDATE SET + address = EXCLUDED.address, + registered_at = EXCLUDED.registered_at, + expire_block = EXCLUDED.expire_block, + zonefile_hash = EXCLUDED.zonefile_hash, + namespace_id = EXCLUDED.namespace_id, + tx_index = EXCLUDED.tx_index, + event_index = EXCLUDED.event_index, + status = EXCLUDED.status, + canonical = EXCLUDED.canonical, + parent_index_block_hash = EXCLUDED.parent_index_block_hash, + microblock_sequence = EXCLUDED.microblock_sequence, + microblock_canonical = EXCLUDED.microblock_canonical + `; } - const validZonefileHash = validateZonefileHash(finalZonefileHash); - const zonefileValues: BnsZonefileInsertValues = { - name: name, - zonefile: finalZonefile, - zonefile_hash: validZonefileHash, - tx_id: tx_id, - index_block_hash: blockData.index_block_hash, - }; - await sql` - INSERT INTO zonefiles ${sql(zonefileValues)} - ON CONFLICT ON CONSTRAINT unique_name_zonefile_hash_tx_id_index_block_hash DO - UPDATE SET zonefile = EXCLUDED.zonefile - `; - const nameValues: BnsNameInsertValues = { - name: name, - address: address, - registered_at: registered_at, - expire_block: expireBlock, - zonefile_hash: validZonefileHash, - namespace_id: namespace_id, - tx_index: tx_index, - tx_id: tx_id, - event_index: event_index ?? null, - status: status ?? null, - canonical: canonical, - index_block_hash: blockData.index_block_hash, - parent_index_block_hash: blockData.parent_index_block_hash, - microblock_hash: blockData.microblock_hash, - microblock_sequence: blockData.microblock_sequence, - microblock_canonical: blockData.microblock_canonical, - }; - await sql` - INSERT INTO names ${sql(nameValues)} - ON CONFLICT ON CONSTRAINT unique_name_tx_id_index_block_hash_microblock_hash_event_index DO - UPDATE SET - address = EXCLUDED.address, - registered_at = EXCLUDED.registered_at, - expire_block = EXCLUDED.expire_block, - zonefile_hash = EXCLUDED.zonefile_hash, - namespace_id = EXCLUDED.namespace_id, - tx_index = EXCLUDED.tx_index, - event_index = EXCLUDED.event_index, - status = EXCLUDED.status, - canonical = EXCLUDED.canonical, - parent_index_block_hash = EXCLUDED.parent_index_block_hash, - microblock_sequence = EXCLUDED.microblock_sequence, - microblock_canonical = EXCLUDED.microblock_canonical - `; } async updateNamespaces( sql: PgSqlClient, - blockData: { - index_block_hash: string; - parent_index_block_hash: string; - microblock_hash: string; - microblock_sequence: number; - microblock_canonical: boolean; - }, - bnsNamespace: DbBnsNamespace + tx: DataStoreBnsBlockTxData, + namespaces: DbBnsNamespace[] ) { - const values: BnsNamespaceInsertValues = { - namespace_id: bnsNamespace.namespace_id, - launched_at: bnsNamespace.launched_at ?? null, - address: bnsNamespace.address, - reveal_block: bnsNamespace.reveal_block, - ready_block: bnsNamespace.ready_block, - buckets: bnsNamespace.buckets, - base: bnsNamespace.base.toString(), - coeff: bnsNamespace.coeff.toString(), - nonalpha_discount: bnsNamespace.nonalpha_discount.toString(), - no_vowel_discount: bnsNamespace.no_vowel_discount.toString(), - lifetime: bnsNamespace.lifetime, - status: bnsNamespace.status ?? null, - tx_index: bnsNamespace.tx_index, - tx_id: bnsNamespace.tx_id, - canonical: bnsNamespace.canonical, - index_block_hash: blockData.index_block_hash, - parent_index_block_hash: blockData.parent_index_block_hash, - microblock_hash: blockData.microblock_hash, - microblock_sequence: blockData.microblock_sequence, - microblock_canonical: blockData.microblock_canonical, - }; - await sql` - INSERT INTO namespaces ${sql(values)} - ON CONFLICT ON CONSTRAINT unique_namespace_id_tx_id_index_block_hash_microblock_hash DO - UPDATE SET - launched_at = EXCLUDED.launched_at, - address = EXCLUDED.address, - reveal_block = EXCLUDED.reveal_block, - ready_block = EXCLUDED.ready_block, - buckets = EXCLUDED.buckets, - base = EXCLUDED.base, - coeff = EXCLUDED.coeff, - nonalpha_discount = EXCLUDED.nonalpha_discount, - no_vowel_discount = EXCLUDED.no_vowel_discount, - lifetime = EXCLUDED.lifetime, - status = EXCLUDED.status, - tx_index = EXCLUDED.tx_index, - canonical = EXCLUDED.canonical, - parent_index_block_hash = EXCLUDED.parent_index_block_hash, - microblock_sequence = EXCLUDED.microblock_sequence, - microblock_canonical = EXCLUDED.microblock_canonical - `; + for (const batch of batchIterate(namespaces, INSERT_BATCH_SIZE)) { + const values: BnsNamespaceInsertValues[] = batch.map(namespace => ({ + namespace_id: namespace.namespace_id, + launched_at: namespace.launched_at ?? null, + address: namespace.address, + reveal_block: namespace.reveal_block, + ready_block: namespace.ready_block, + buckets: namespace.buckets, + base: namespace.base.toString(), + coeff: namespace.coeff.toString(), + nonalpha_discount: namespace.nonalpha_discount.toString(), + no_vowel_discount: namespace.no_vowel_discount.toString(), + lifetime: namespace.lifetime, + status: namespace.status ?? null, + tx_index: namespace.tx_index, + tx_id: namespace.tx_id, + canonical: namespace.canonical, + index_block_hash: tx.index_block_hash, + parent_index_block_hash: tx.parent_index_block_hash, + microblock_hash: tx.microblock_hash, + microblock_sequence: tx.microblock_sequence, + microblock_canonical: tx.microblock_canonical, + })); + await sql` + INSERT INTO namespaces ${sql(values)} + ON CONFLICT ON CONSTRAINT unique_namespace_id_tx_id_index_block_hash_microblock_hash DO + UPDATE SET + launched_at = EXCLUDED.launched_at, + address = EXCLUDED.address, + reveal_block = EXCLUDED.reveal_block, + ready_block = EXCLUDED.ready_block, + buckets = EXCLUDED.buckets, + base = EXCLUDED.base, + coeff = EXCLUDED.coeff, + nonalpha_discount = EXCLUDED.nonalpha_discount, + no_vowel_discount = EXCLUDED.no_vowel_discount, + lifetime = EXCLUDED.lifetime, + status = EXCLUDED.status, + tx_index = EXCLUDED.tx_index, + canonical = EXCLUDED.canonical, + parent_index_block_hash = EXCLUDED.parent_index_block_hash, + microblock_sequence = EXCLUDED.microblock_sequence, + microblock_canonical = EXCLUDED.microblock_canonical + `; + } } async updateBatchTokenOfferingLocked(sql: PgSqlClient, lockedInfos: DbTokenOfferingLocked[]) { @@ -2077,36 +2056,18 @@ export class PgWriteStore extends PgStore { ); } - await this.updateBatchStxEvents(sql, entry.tx, entry.stxEvents); + await this.updateStxEvents(sql, entry.tx, entry.stxEvents); await this.updatePrincipalStxTxs(sql, entry.tx, entry.stxEvents); - await this.updateBatchSmartContractEvent(sql, entry.tx, entry.contractLogEvents); - for (const pox2Event of entry.pox2Events) { - await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox2_events', pox2Event); - } - for (const pox3Event of entry.pox3Events) { - await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox3_events', pox3Event); - } - for (const pox4Event of entry.pox4Events) { - await this.updatePoxSyntheticEvent(sql, entry.tx, 'pox4_events', pox4Event); - } - for (const stxLockEvent of entry.stxLockEvents) { - await this.updateStxLockEvent(sql, entry.tx, stxLockEvent); - } - for (const ftEvent of entry.ftEvents) { - await this.updateFtEvent(sql, entry.tx, ftEvent); - } - for (const nftEvent of entry.nftEvents) { - await this.updateNftEvent(sql, entry.tx, nftEvent, true); - } - for (const smartContract of entry.smartContracts) { - await this.updateSmartContract(sql, entry.tx, smartContract); - } - for (const namespace of entry.namespaces) { - await this.updateNamespaces(sql, entry.tx, namespace); - } - for (const bnsName of entry.names) { - await this.updateNames(sql, entry.tx, bnsName); - } + await this.updateSmartContractEvents(sql, entry.tx, entry.contractLogEvents); + await this.updatePoxSyntheticEvents(sql, entry.tx, 'pox2_events', entry.pox2Events); + await this.updatePoxSyntheticEvents(sql, entry.tx, 'pox3_events', entry.pox3Events); + await this.updatePoxSyntheticEvents(sql, entry.tx, 'pox4_events', entry.pox4Events); + await this.updateStxLockEvents(sql, entry.tx, entry.stxLockEvents); + await this.updateFtEvents(sql, entry.tx, entry.ftEvents); + await this.updateNftEvents(sql, entry.tx, entry.nftEvents, true); + await this.updateSmartContracts(sql, entry.tx, entry.smartContracts); + await this.updateNamespaces(sql, entry.tx, entry.namespaces); + await this.updateNames(sql, entry.tx, entry.names); } } @@ -2383,10 +2344,7 @@ export class PgWriteStore extends PgStore { * @param txIds - List of transactions to update in the mempool */ async pruneMempoolTxs(sql: PgSqlClient, txIds: string[]): Promise<{ removedTxs: string[] }> { - if (txIds.length === 0) { - // Avoid an unnecessary query. - return { removedTxs: [] }; - } + if (txIds.length === 0) return { removedTxs: [] }; for (const txId of txIds) { logger.debug(`Pruning mempool tx: ${txId}`); } @@ -2433,7 +2391,7 @@ export class PgWriteStore extends PgStore { sql: PgSqlClient, indexBlockHash: string, canonical: boolean, - updatedEntities: UpdatedEntities + updatedEntities: ReOrgUpdatedEntities ): Promise<{ txsMarkedCanonical: string[]; txsMarkedNonCanonical: string[] }> { const txResult = await sql` UPDATE txs @@ -2615,8 +2573,8 @@ export class PgWriteStore extends PgStore { async restoreOrphanedChain( sql: PgSqlClient, indexBlockHash: string, - updatedEntities: UpdatedEntities - ): Promise { + updatedEntities: ReOrgUpdatedEntities + ): Promise { // Restore the previously orphaned block to canonical const restoredBlockResult = await sql` UPDATE blocks @@ -2742,46 +2700,8 @@ export class PgWriteStore extends PgStore { sql: PgSqlClient, block: DbBlock, chainTipHeight: number - ): Promise { - const updatedEntities: UpdatedEntities = { - markedCanonical: { - blocks: 0, - microblocks: 0, - minerRewards: 0, - txs: 0, - stxLockEvents: 0, - stxEvents: 0, - ftEvents: 0, - nftEvents: 0, - pox2Events: 0, - pox3Events: 0, - pox4Events: 0, - contractLogs: 0, - smartContracts: 0, - names: 0, - namespaces: 0, - subdomains: 0, - }, - markedNonCanonical: { - blocks: 0, - microblocks: 0, - minerRewards: 0, - txs: 0, - stxLockEvents: 0, - stxEvents: 0, - ftEvents: 0, - nftEvents: 0, - pox2Events: 0, - pox3Events: 0, - pox4Events: 0, - contractLogs: 0, - smartContracts: 0, - names: 0, - namespaces: 0, - subdomains: 0, - }, - }; - + ): Promise { + const updatedEntities = newReOrgUpdatedEntities(); // Check if incoming block's parent is canonical if (block.block_height > 1) { const parentResult = await sql< @@ -2796,26 +2716,23 @@ export class PgWriteStore extends PgStore { WHERE block_height = ${block.block_height - 1} AND index_block_hash = ${block.parent_index_block_hash} `; - - if (parentResult.length > 1) { + if (parentResult.length > 1) throw new Error( `DB contains multiple blocks at height ${block.block_height - 1} and index_hash ${ block.parent_index_block_hash }` ); - } - if (parentResult.length === 0) { + if (parentResult.length === 0) throw new Error( `DB does not contain a parent block at height ${block.block_height - 1} with index_hash ${ block.parent_index_block_hash }` ); - } - - // This blocks builds off a previously orphaned chain. Restore canonical status for this chain. + // This blocks builds off a previously orphaned chain. Restore canonical status for this + // chain. if (!parentResult[0].canonical && block.block_height > chainTipHeight) { await this.restoreOrphanedChain(sql, parentResult[0].index_block_hash, updatedEntities); - this.logReorgResultInfo(updatedEntities); + logReorgResultInfo(updatedEntities); } // Reflect updated transaction totals in `chain_tip` table. const txCountDelta = @@ -2829,68 +2746,6 @@ export class PgWriteStore extends PgStore { return updatedEntities; } - logReorgResultInfo(updatedEntities: UpdatedEntities) { - const updates = [ - ['blocks', updatedEntities.markedCanonical.blocks, updatedEntities.markedNonCanonical.blocks], - [ - 'microblocks', - updatedEntities.markedCanonical.microblocks, - updatedEntities.markedNonCanonical.microblocks, - ], - ['txs', updatedEntities.markedCanonical.txs, updatedEntities.markedNonCanonical.txs], - [ - 'miner-rewards', - updatedEntities.markedCanonical.minerRewards, - updatedEntities.markedNonCanonical.minerRewards, - ], - [ - 'stx-lock events', - updatedEntities.markedCanonical.stxLockEvents, - updatedEntities.markedNonCanonical.stxLockEvents, - ], - [ - 'stx-token events', - updatedEntities.markedCanonical.stxEvents, - updatedEntities.markedNonCanonical.stxEvents, - ], - [ - 'non-fungible-token events', - updatedEntities.markedCanonical.nftEvents, - updatedEntities.markedNonCanonical.nftEvents, - ], - [ - 'fungible-token events', - updatedEntities.markedCanonical.ftEvents, - updatedEntities.markedNonCanonical.ftEvents, - ], - [ - 'contract logs', - updatedEntities.markedCanonical.contractLogs, - updatedEntities.markedNonCanonical.contractLogs, - ], - [ - 'smart contracts', - updatedEntities.markedCanonical.smartContracts, - updatedEntities.markedNonCanonical.smartContracts, - ], - ['names', updatedEntities.markedCanonical.names, updatedEntities.markedNonCanonical.names], - [ - 'namespaces', - updatedEntities.markedCanonical.namespaces, - updatedEntities.markedNonCanonical.namespaces, - ], - [ - 'subdomains', - updatedEntities.markedCanonical.subdomains, - updatedEntities.markedNonCanonical.subdomains, - ], - ]; - const markedCanonical = updates.map(e => `${e[1]} ${e[0]}`).join(', '); - logger.debug(`Entities marked as canonical: ${markedCanonical}`); - const markedNonCanonical = updates.map(e => `${e[2]} ${e[0]}`).join(', '); - logger.debug(`Entities marked as non-canonical: ${markedNonCanonical}`); - } - /** * Refreshes a Postgres materialized view. * @param viewName - Materialized view name diff --git a/src/event-replay/helpers.ts b/src/event-replay/helpers.ts index 3cec50ea4b..6a418f3ac7 100644 --- a/src/event-replay/helpers.ts +++ b/src/event-replay/helpers.ts @@ -1,14 +1,6 @@ import { PgWriteStore } from '../datastore/pg-write-store'; -import * as fs from 'fs'; -import * as readline from 'readline'; -import { DataStoreBnsBlockData, DbTxTypeId } from '../datastore/common'; +import { DataStoreBnsBlockTxData, DbTxTypeId } from '../datastore/common'; import { readLinesReversed } from './reverse-file-stream'; -import { CoreNodeBlockMessage } from '../event-stream/core-node-message'; - -export type BnsGenesisBlock = DataStoreBnsBlockData & { - tx_id: string; - tx_index: number; -}; /** * Traverse a TSV file in reverse to find the last received `/new_block` node message and return @@ -40,7 +32,7 @@ export async function findTsvBlockHeight(filePath: string): Promise { export async function getBnsGenesisBlockFromBlockMessage( db: PgWriteStore -): Promise { +): Promise { const genesisBlock = await db.getBlock({ height: 1 }); if (!genesisBlock.found) { throw new Error('Could not find genesis block'); diff --git a/src/event-replay/parquet-based/importers/attachment-new-importer.ts b/src/event-replay/parquet-based/importers/attachment-new-importer.ts index 43a5e2a0a1..76e484c8e1 100644 --- a/src/event-replay/parquet-based/importers/attachment-new-importer.ts +++ b/src/event-replay/parquet-based/importers/attachment-new-importer.ts @@ -3,7 +3,6 @@ import { Readable, Writable } from 'stream'; import { pipeline } from 'stream/promises'; -import { batchIterate } from '../../../helpers'; import { PgWriteStore } from '../../../datastore/pg-write-store'; import { parseAttachment } from '../../../event-stream/event-server'; import { logger } from '../../../logger'; @@ -11,6 +10,7 @@ import { CoreNodeAttachmentMessage } from '../../../event-stream/core-node-messa import { DataStoreAttachmentSubdomainData } from '../../../datastore/common'; import { DatasetStore } from '../dataset/store'; import { I32_MAX } from '../../../helpers'; +import { batchIterate } from '@hirosystems/api-toolkit'; const batchInserters: BatchInserter[] = []; diff --git a/src/event-replay/parquet-based/importers/new-block-importer.ts b/src/event-replay/parquet-based/importers/new-block-importer.ts index 869d6f3d3d..ff7e76a005 100644 --- a/src/event-replay/parquet-based/importers/new-block-importer.ts +++ b/src/event-replay/parquet-based/importers/new-block-importer.ts @@ -17,9 +17,10 @@ import { } from '../../../datastore/common'; import { validateZonefileHash } from '../../../datastore/helpers'; import { logger } from '../../../logger'; -import { getApiConfiguredChainID, batchIterate } from '../../../helpers'; +import { getApiConfiguredChainID } from '../../../helpers'; import { CoreNodeBlockMessage } from '../../../event-stream/core-node-message'; import { DatasetStore } from '../dataset/store'; +import { batchIterate } from '@hirosystems/api-toolkit'; const chainID = getApiConfiguredChainID(); @@ -361,9 +362,7 @@ const populateBatchInserters = (db: PgWriteStore) => { const insertSmartContracts = async (dbData: DataStoreBlockUpdateData) => { for (const entry of dbData.txs) { - for (const smartContract of entry.smartContracts) { - await db.updateSmartContract(db.sql, entry.tx, smartContract); - } + await db.updateSmartContracts(db.sql, entry.tx, entry.smartContracts); } }; @@ -377,39 +376,29 @@ const populateBatchInserters = (db: PgWriteStore) => { const insertStxLockEvents = async (dbData: DataStoreBlockUpdateData) => { for (const entry of dbData.txs) { - for (const stxLockEvent of entry.stxLockEvents) { - await db.updateStxLockEvent(db.sql, entry.tx, stxLockEvent); - } + await db.updateStxLockEvents(db.sql, entry.tx, entry.stxLockEvents); } }; const insertMinerRewards = async (dbData: DataStoreBlockUpdateData) => { - for (const minerReward of dbData.minerRewards) { - await db.updateMinerReward(db.sql, minerReward); - } + await db.updateMinerRewards(db.sql, dbData.minerRewards); }; const insertPox2Events = async (dbData: DataStoreBlockUpdateData) => { for (const entry of dbData.txs) { - for (const pox2Event of entry.pox2Events) { - await db.updatePoxSyntheticEvent(db.sql, entry.tx, 'pox2_events', pox2Event); - } + await db.updatePoxSyntheticEvents(db.sql, entry.tx, 'pox2_events', entry.pox2Events); } }; const insertPox3Events = async (dbData: DataStoreBlockUpdateData) => { for (const entry of dbData.txs) { - for (const pox3Event of entry.pox3Events) { - await db.updatePoxSyntheticEvent(db.sql, entry.tx, 'pox3_events', pox3Event); - } + await db.updatePoxSyntheticEvents(db.sql, entry.tx, 'pox3_events', entry.pox3Events); } }; const insertPox4Events = async (dbData: DataStoreBlockUpdateData) => { for (const entry of dbData.txs) { - for (const pox4Event of entry.pox4Events) { - await db.updatePoxSyntheticEvent(db.sql, entry.tx, 'pox4_events', pox4Event); - } + await db.updatePoxSyntheticEvents(db.sql, entry.tx, 'pox4_events', entry.pox4Events); } }; diff --git a/src/event-replay/parquet-based/importers/raw-importer.ts b/src/event-replay/parquet-based/importers/raw-importer.ts index 9fc4480509..d86f966314 100644 --- a/src/event-replay/parquet-based/importers/raw-importer.ts +++ b/src/event-replay/parquet-based/importers/raw-importer.ts @@ -3,8 +3,8 @@ import { pipeline } from 'stream/promises'; import { PgWriteStore } from '../../../datastore/pg-write-store'; import { RawEventRequestInsertValues } from '../../../datastore/common'; import { logger } from '../../../logger'; -import { batchIterate } from '../../../helpers'; import { DatasetStore } from '../dataset/store'; +import { batchIterate } from '@hirosystems/api-toolkit'; const batchInserters: BatchInserter[] = []; diff --git a/src/helpers.ts b/src/helpers.ts index ac8ab8216a..2273814ab8 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -440,71 +440,6 @@ export function assertNotNullish( return true; } -/** - * Iterate over an array, yielding multiple items at a time. If the size of the given array - * is not divisible by the given batch size, then the length of the last items returned will - * be smaller than the given batch size, i.e.: - * ```typescript - * items.length % batchSize - * ``` - * @param items - The array to iterate over. - * @param batchSize - Maximum number of items to return at a time. - */ -export function* batchIterate( - items: T[], - batchSize: number, - printBenchmark = isDevEnv -): Generator { - if (items.length === 0) { - return; - } - const startTime = Date.now(); - for (let i = 0; i < items.length; ) { - const itemsRemaining = items.length - i; - const sliceSize = Math.min(batchSize, itemsRemaining); - yield items.slice(i, i + sliceSize); - i += sliceSize; - } - - if (printBenchmark) { - const itemsPerSecond = Math.round((items.length / (Date.now() - startTime)) * 1000); - const caller = new Error().stack?.split('at ')[3].trim(); - logger.debug(`Iterated ${itemsPerSecond} items/second at ${caller}`); - } -} - -export async function* asyncBatchIterate( - items: AsyncIterable, - batchSize: number, - printBenchmark = isDevEnv -): AsyncGenerator { - const startTime = Date.now(); - let itemCount = 0; - let itemBatch: T[] = []; - for await (const item of items) { - itemBatch.push(item); - itemCount++; - if (itemBatch.length >= batchSize) { - yield itemBatch; - itemBatch = []; - if (printBenchmark) { - const itemsPerSecond = Math.round((itemCount / (Date.now() - startTime)) * 1000); - const caller = new Error().stack?.split('at ')[3].trim(); - logger.debug(`Iterated ${itemsPerSecond} items/second at ${caller}`); - } - } - } - if (itemBatch.length > 0) { - yield itemBatch; - } -} - -export async function* asyncIterableToGenerator(iter: AsyncIterable) { - for await (const entry of iter) { - yield entry; - } -} - function intMax(args: bigint[]): bigint; function intMax(args: number[]): number; function intMax(args: bigint[] | number[]): any { diff --git a/src/import-v1/index.ts b/src/import-v1/index.ts index 327e0de4d0..d016578cd3 100644 --- a/src/import-v1/index.ts +++ b/src/import-v1/index.ts @@ -8,17 +8,18 @@ import * as zlib from 'zlib'; import { bitcoinToStacksAddress } from 'stacks-encoding-native-js'; import * as split2 from 'split2'; import { + DataStoreBnsBlockTxData, DbBnsName, DbBnsNamespace, DbBnsSubdomain, DbConfigState, DbTokenOfferingLocked, } from '../datastore/common'; -import { asyncBatchIterate, asyncIterableToGenerator, I32_MAX, REPO_DIR } from '../helpers'; -import { BnsGenesisBlock, getBnsGenesisBlockFromBlockMessage } from '../event-replay/helpers'; +import { REPO_DIR } from '../helpers'; +import { getBnsGenesisBlockFromBlockMessage } from '../event-replay/helpers'; import { PgWriteStore } from '../datastore/pg-write-store'; import { logger } from '../logger'; -import { PgSqlClient } from '@hirosystems/api-toolkit'; +import { PgSqlClient, asyncBatchIterate, asyncIterableToGenerator } from '@hirosystems/api-toolkit'; const finished = util.promisify(stream.finished); const pipeline = util.promisify(stream.pipeline); @@ -78,13 +79,13 @@ class ChainProcessor extends stream.Writable { namespace: Map; db: PgWriteStore; sql: PgSqlClient; - genesisBlock: BnsGenesisBlock; + genesisBlock: DataStoreBnsBlockTxData; constructor( sql: PgSqlClient, db: PgWriteStore, zhashes: Map, - genesisBlock: BnsGenesisBlock + genesisBlock: DataStoreBnsBlockTxData ) { super(); this.zhashes = zhashes; @@ -159,7 +160,7 @@ class ChainProcessor extends stream.Writable { canonical: true, status: 'name-register', }; - await this.db.updateNames(this.sql, this.genesisBlock, obj); + await this.db.updateNames(this.sql, this.genesisBlock, [obj]); this.rowCount += 1; if (obj.zonefile === '') { logger.debug( @@ -186,7 +187,7 @@ class ChainProcessor extends stream.Writable { canonical: true, }; this.namespace.set(obj.namespace_id, obj); - await this.db.updateNamespaces(this.sql, this.genesisBlock, obj); + await this.db.updateNamespaces(this.sql, this.genesisBlock, [obj]); this.rowCount += 1; } } @@ -230,9 +231,9 @@ function btcToStxAddress(btcAddress: string) { } class SubdomainTransform extends stream.Transform { - genesisBlock: BnsGenesisBlock; + genesisBlock: DataStoreBnsBlockTxData; - constructor(genesisBlock: BnsGenesisBlock) { + constructor(genesisBlock: DataStoreBnsBlockTxData) { super({ objectMode: true, highWaterMark: SUBDOMAIN_BATCH_SIZE }); this.genesisBlock = genesisBlock; } @@ -304,7 +305,7 @@ async function valid(fileName: string): Promise { return true; } -async function* readSubdomains(importDir: string, genesisBlock: BnsGenesisBlock) { +async function* readSubdomains(importDir: string, genesisBlock: DataStoreBnsBlockTxData) { const metaIter = asyncIterableToGenerator( stream.pipeline( fs.createReadStream(path.join(importDir, 'subdomains.csv')), @@ -416,7 +417,7 @@ async function validateBnsImportDir(importDir: string, importFiles: string[]) { export async function importV1BnsNames( db: PgWriteStore, importDir: string, - genesisBlock: BnsGenesisBlock + genesisBlock: DataStoreBnsBlockTxData ) { const configState = await db.getConfigState(); if (configState.bns_names_onchain_imported) { @@ -444,7 +445,7 @@ export async function importV1BnsNames( export async function importV1BnsSubdomains( db: PgWriteStore, importDir: string, - genesisBlock: BnsGenesisBlock + genesisBlock: DataStoreBnsBlockTxData ) { const configState = await db.getConfigState(); if (configState.bns_subdomains_imported) { diff --git a/src/tests-bns/api.ts b/src/tests-bns/api.ts index 28438175c1..b379839af8 100644 --- a/src/tests-bns/api.ts +++ b/src/tests-bns/api.ts @@ -129,8 +129,10 @@ describe('BNS API tests', () => { microblock_hash: '', microblock_sequence: I32_MAX, microblock_canonical: true, + tx_id: '', + tx_index: 0, }, - namespace + [namespace] ); const namespace2: DbBnsNamespace = { namespace_id: 'blockstack', @@ -157,8 +159,10 @@ describe('BNS API tests', () => { microblock_hash: '', microblock_sequence: I32_MAX, microblock_canonical: true, + tx_id: '', + tx_index: 0, }, - namespace2 + [namespace2] ); }); @@ -434,8 +438,10 @@ describe('BNS API tests', () => { microblock_hash: '', microblock_sequence: I32_MAX, microblock_canonical: true, + tx_id: '', + tx_index: 0, }, - dbName + [dbName] ); const query1 = await supertest(api.server).get(`/v1/names/invalid/zonefile/${zonefileHash}`); @@ -531,8 +537,10 @@ describe('BNS API tests', () => { microblock_hash: '', microblock_sequence: I32_MAX, microblock_canonical: true, + tx_id: '', + tx_index: 0, }, - dbName2 + [dbName2] ); const query1 = await supertest(api.server).get(`/v1/addresses/${blockchain}/${address}`); diff --git a/src/tests-bns/v1-import-tests.ts b/src/tests-bns/v1-import-tests.ts index cb67dfaf39..accb52ca30 100644 --- a/src/tests-bns/v1-import-tests.ts +++ b/src/tests-bns/v1-import-tests.ts @@ -4,8 +4,7 @@ import { ChainID } from '@stacks/transactions'; import { importV1BnsNames, importV1BnsSubdomains } from '../import-v1'; import * as assert from 'assert'; import { TestBlockBuilder } from '../test-utils/test-builders'; -import { DataStoreBlockUpdateData } from '../datastore/common'; -import { BnsGenesisBlock } from '../event-replay/helpers'; +import { DataStoreBlockUpdateData, DataStoreBnsBlockTxData } from '../datastore/common'; import { PgWriteStore } from '../datastore/pg-write-store'; import { migrate } from '../test-utils/test-helpers'; @@ -30,7 +29,7 @@ describe('BNS V1 import', () => { }); test('v1-import', async () => { - const genesis: BnsGenesisBlock = { + const genesis: DataStoreBnsBlockTxData = { index_block_hash: block.block.index_block_hash, parent_index_block_hash: block.block.parent_index_block_hash, microblock_canonical: true, diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index 683651c0de..34804796e0 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -19,6 +19,7 @@ import { DbBnsSubdomain, DbTokenOfferingLocked, DbTx, + DataStoreBnsBlockTxData, } from '../datastore/common'; import { getBlocksWithMetadata, parseDbEvent } from '../api/controllers/db-controller'; import * as assert from 'assert'; @@ -95,9 +96,7 @@ describe('postgres datastore', () => { createMinerReward('addrB', 0n, 30n, 40n, 7n), createMinerReward('addrB', 99999n, 92n, 93n, 0n, false), ]; - for (const reward of minerRewards) { - await db.updateMinerReward(client, reward); - } + await db.updateMinerRewards(client, minerRewards); const tx: DbTxRaw = { tx_id: '0x1234', @@ -196,9 +195,7 @@ describe('postgres datastore', () => { createStxLockEvent('addrA', 222n, 1), createStxLockEvent('addrB', 333n, 1), ]; - for (const stxLockEvent of stxLockEvents) { - await db.updateStxLockEvent(client, tx, stxLockEvent); - } + await db.updateStxLockEvents(client, tx, stxLockEvents); await db.updateTx(client, tx); await db.updateTx(client, tx2); @@ -3515,9 +3512,7 @@ describe('postgres datastore', () => { } // insert miner rewards directly - for (const minerReward of [minerReward1]) { - await db.updateMinerReward(client, minerReward); - } + await db.updateMinerRewards(client, [minerReward1]); // insert txs directly for (const tx of [tx1, tx2]) { @@ -3525,9 +3520,7 @@ describe('postgres datastore', () => { } // insert stx lock events directly - for (const event of [stxLockEvent1]) { - await db.updateStxLockEvent(client, tx1, event); - } + await db.updateStxLockEvents(client, tx1, [stxLockEvent1]); const block5: DbBlock = { block_hash: '0x55', @@ -4616,8 +4609,8 @@ describe('postgres datastore', () => { microblock_hash: '0x00', microblock_sequence: I32_MAX, microblock_canonical: true, - }, - namespace + } as DataStoreBnsBlockTxData, + [namespace] ); const { results } = await db.getNamespaceList({ includeUnanchored: false }); expect(results.length).toBe(1); @@ -4672,8 +4665,8 @@ describe('postgres datastore', () => { microblock_hash: '0x00', microblock_sequence: I32_MAX, microblock_canonical: true, - }, - name + } as DataStoreBnsBlockTxData, + [name] ); const { results } = await db.getNamespaceNamesList({ namespace: 'abc', diff --git a/src/tests/other-tests.ts b/src/tests/other-tests.ts index 217b59bc0d..a4a7f9a8a3 100644 --- a/src/tests/other-tests.ts +++ b/src/tests/other-tests.ts @@ -183,7 +183,7 @@ describe('other tests', () => { tx_fees_streamed_confirmed: 2_000_000_000_000n, tx_fees_streamed_produced: 3_000_000_000_000n, }; - await db.updateMinerReward(client, minerReward1); + await db.updateMinerRewards(client, [minerReward1]); const expectedTotalStx3 = stxMintEvent1.amount + stxMintEvent2.amount - diff --git a/src/tests/search-tests.ts b/src/tests/search-tests.ts index 69b8b62b15..ea1d5d0b3c 100644 --- a/src/tests/search-tests.ts +++ b/src/tests/search-tests.ts @@ -770,7 +770,7 @@ describe('search tests', () => { recipient: addr5, sender: 'none', }; - await db.updateFtEvent(client, stxTx1, ftEvent1); + await db.updateFtEvents(client, stxTx1, [ftEvent1]); // test address as a ft event recipient const searchResult5 = await supertest(api.server).get(`/extended/v1/search/${addr5}`); @@ -798,7 +798,7 @@ describe('search tests', () => { recipient: 'none', sender: addr6, }; - await db.updateFtEvent(client, stxTx1, ftEvent2); + await db.updateFtEvents(client, stxTx1, [ftEvent2]); // test address as a ft event sender const searchResult6 = await supertest(api.server).get(`/extended/v1/search/${addr6}`); @@ -826,7 +826,7 @@ describe('search tests', () => { recipient: addr7, sender: 'none', }; - await db.updateNftEvent(client, stxTx1, nftEvent1, false); + await db.updateNftEvents(client, stxTx1, [nftEvent1], false); // test address as a nft event recipient const searchResult7 = await supertest(api.server).get(`/extended/v1/search/${addr7}`); @@ -854,7 +854,7 @@ describe('search tests', () => { recipient: 'none', sender: addr8, }; - await db.updateNftEvent(client, stxTx1, nftEvent2, false); + await db.updateNftEvents(client, stxTx1, [nftEvent2], false); // test address as a nft event sender const searchResult8 = await supertest(api.server).get(`/extended/v1/search/${addr8}`); diff --git a/src/tests/tx-tests.ts b/src/tests/tx-tests.ts index 8a7ed7b0a3..445196d51c 100644 --- a/src/tests/tx-tests.ts +++ b/src/tests/tx-tests.ts @@ -1045,15 +1045,17 @@ describe('tx tests', () => { fungible_tokens: [], non_fungible_tokens: [], }; - await db.updateSmartContract(client, dbTx, { - tx_id: dbTx.tx_id, - canonical: true, - clarity_version: null, - contract_id: 'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y.hello-world', - block_height: dbBlock.block_height, - source_code: '()', - abi: JSON.stringify(contractAbi), - }); + await db.updateSmartContracts(client, dbTx, [ + { + tx_id: dbTx.tx_id, + canonical: true, + clarity_version: null, + contract_id: 'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y.hello-world', + block_height: dbBlock.block_height, + source_code: '()', + abi: JSON.stringify(contractAbi), + }, + ]); const txQuery = await getTxFromDataStore(db, { txId: dbTx.tx_id, includeUnanchored: false }); expect(txQuery.found).toBe(true); if (!txQuery.found) { From da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 19 Dec 2023 10:02:02 -0600 Subject: [PATCH 44/91] feat: add `tx_count` property to `/extended/v2/blocks` (#1778) * fix: move to tx_count * docs: add new transactions endpoint docs * fix: unused exports * feat: transactions per block * test: 404 on block --- .../blocks/nakamoto-block.example.json | 6 +- .../blocks/nakamoto-block.schema.json | 11 +- docs/generated.d.ts | 4 +- docs/openapi.yaml | 29 +++++ migrations/1702913457527_block-tx-count.js | 26 ++++ src/api/routes/v2/blocks.ts | 53 +++++++- src/api/routes/v2/burn-blocks.ts | 16 ++- src/api/routes/v2/helpers.ts | 49 +------ src/api/routes/v2/schemas.ts | 77 +++++++++-- src/datastore/common.ts | 19 +-- src/datastore/helpers.ts | 2 + src/datastore/pg-store.ts | 100 ++++++++++----- src/datastore/pg-write-store.ts | 2 + src/event-stream/event-server.ts | 2 + src/test-utils/test-builders.ts | 5 +- src/tests/address-tests.ts | 3 + src/tests/block-tests.ts | 8 +- src/tests/cache-control-tests.ts | 1 + src/tests/datastore-tests.ts | 41 ++++++ src/tests/mempool-tests.ts | 5 + src/tests/microblock-tests.ts | 1 + src/tests/other-tests.ts | 1 + src/tests/search-tests.ts | 4 + src/tests/smart-contract-tests.ts | 4 + src/tests/tx-tests.ts | 120 ++++++++++++++++++ src/tests/v2-proxy-tests.ts | 1 + 26 files changed, 453 insertions(+), 137 deletions(-) create mode 100644 migrations/1702913457527_block-tx-count.js diff --git a/docs/entities/blocks/nakamoto-block.example.json b/docs/entities/blocks/nakamoto-block.example.json index 67da2c54f3..f2cd985407 100644 --- a/docs/entities/blocks/nakamoto-block.example.json +++ b/docs/entities/blocks/nakamoto-block.example.json @@ -10,11 +10,7 @@ "burn_block_hash": "0xb154c008df2101023a6d0d54986b3964cee58119eed14f5bed98e15678e18fe2", "burn_block_height": 654439, "miner_txid": "0xd7d56070277ccd87b42acf0c91f915dd181f9db4cf878a4e95518bc397c240cc", - "txs": [ - "0x4262db117659d1ca9406970c8f44ffd3d8f11f8e18c591d2e3960f4070107754", - "0x383632cd3b5464dffb684082750fcfaddd1f52625bbb9f884ed8f45d2b1f0547", - "0xc99fe597e44b8bd15a50eec660c6e679a7144a5a8553d214b9d5f1406d278c22" - ], + "tx_count": 3, "execution_cost_read_count": 2477, "execution_cost_read_length": 1659409, "execution_cost_runtime": 2520952000, diff --git a/docs/entities/blocks/nakamoto-block.schema.json b/docs/entities/blocks/nakamoto-block.schema.json index 96395d87e8..41f9a38ced 100644 --- a/docs/entities/blocks/nakamoto-block.schema.json +++ b/docs/entities/blocks/nakamoto-block.schema.json @@ -11,6 +11,7 @@ "parent_block_hash", "parent_index_block_hash", "txs", + "tx_count", "burn_block_time", "burn_block_time_iso", "burn_block_hash", @@ -67,13 +68,9 @@ "type": "string", "description": "Anchor chain transaction ID" }, - "txs": { - "type": "array", - "description": "List of transactions included in the block", - "items": { - "type": "string", - "description": "Transaction ID" - } + "tx_count": { + "type": "integer", + "description": "Number of transactions included in the block" }, "execution_cost_read_count": { "type": "integer", diff --git a/docs/generated.d.ts b/docs/generated.d.ts index 97538fa4c5..933fe0dc8d 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -1366,9 +1366,9 @@ export interface NakamotoBlock { */ miner_txid: string; /** - * List of transactions included in the block + * Number of transactions included in the block */ - txs: string[]; + tx_count: number; /** * Execution cost read count. */ diff --git a/docs/openapi.yaml b/docs/openapi.yaml index d79d3ed633..1a2fadfdb8 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -745,6 +745,35 @@ paths: example: $ref: ./entities/blocks/nakamoto-block.example.json + /extended/v2/blocks/{height_or_hash}/transactions: + get: + summary: Get block transactions + description: | + Retrieves transactions confirmed in a single block + tags: + - Blocks + operationId: get_block_transactions + parameters: + - name: height_or_hash + in: path + description: filter by block height, hash, index block hash or the constant `latest` to filter for the most recent block + required: true + schema: + oneOf: + - type: integer + example: 42000 + - type: string + example: "0x4839a8b01cfb39ffcc0d07d3db31e848d5adf5279d529ed5062300b9f353ff79" + responses: + 200: + description: List of transactions + content: + application/json: + schema: + $ref: ./api/transaction/get-transactions.schema.json + example: + $ref: ./api/transaction/get-transactions.example.json + /extended/v1/block: get: summary: Get recent blocks diff --git a/migrations/1702913457527_block-tx-count.js b/migrations/1702913457527_block-tx-count.js new file mode 100644 index 0000000000..3410704e9e --- /dev/null +++ b/migrations/1702913457527_block-tx-count.js @@ -0,0 +1,26 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.addColumns('blocks', { + tx_count: { + type: 'int', + default: 1, + }, + }); + pgm.sql(` + UPDATE blocks SET tx_count = ( + SELECT COUNT(*)::int + FROM txs + WHERE index_block_hash = blocks.index_block_hash + AND canonical = TRUE + AND microblock_canonical = TRUE + ) + `); + pgm.alterColumn('blocks', 'tx_count', { notNull: true }); +}; + +exports.down = pgm => { + pgm.dropColumn('blocks', ['tx_count']); +}; diff --git a/src/api/routes/v2/blocks.ts b/src/api/routes/v2/blocks.ts index 652fc19766..9a78c302e0 100644 --- a/src/api/routes/v2/blocks.ts +++ b/src/api/routes/v2/blocks.ts @@ -5,14 +5,20 @@ import { setETagCacheHeaders, } from '../../../api/controllers/cache-controller'; import { asyncHandler } from '../../async-handler'; -import { NakamotoBlockListResponse } from 'docs/generated'; +import { NakamotoBlockListResponse, TransactionResults } from 'docs/generated'; import { BlocksQueryParams, - BurnBlockParams, + BlockParams, CompiledBlocksQueryParams, - CompiledBurnBlockParams, + CompiledBlockParams, + CompiledTransactionPaginationQueryParams, + TransactionPaginationQueryParams, + validRequestQuery, + validRequestParams, } from './schemas'; -import { parseDbNakamotoBlock, validRequestParams, validRequestQuery } from './helpers'; +import { parseDbNakamotoBlock } from './helpers'; +import { InvalidRequestError } from '../../../errors'; +import { parseDbTx } from '../../../api/controllers/db-controller'; export function createV2BlocksRouter(db: PgStore): express.Router { const router = express.Router(); @@ -41,8 +47,8 @@ export function createV2BlocksRouter(db: PgStore): express.Router { '/:height_or_hash', cacheHandler, asyncHandler(async (req, res) => { - if (!validRequestParams(req, res, CompiledBurnBlockParams)) return; - const params = req.params as BurnBlockParams; + if (!validRequestParams(req, res, CompiledBlockParams)) return; + const params = req.params as BlockParams; const block = await db.getV2Block(params); if (!block) { @@ -54,5 +60,40 @@ export function createV2BlocksRouter(db: PgStore): express.Router { }) ); + router.get( + '/:height_or_hash/transactions', + cacheHandler, + asyncHandler(async (req, res) => { + if ( + !validRequestParams(req, res, CompiledBlockParams) || + !validRequestQuery(req, res, CompiledTransactionPaginationQueryParams) + ) + return; + const params = req.params as BlockParams; + const query = req.query as TransactionPaginationQueryParams; + + try { + const { limit, offset, results, total } = await db.getV2BlockTransactions({ + ...params, + ...query, + }); + const response: TransactionResults = { + limit, + offset, + total, + results: results.map(r => parseDbTx(r)), + }; + setETagCacheHeaders(res); + res.json(response); + } catch (error) { + if (error instanceof InvalidRequestError) { + res.status(404).json({ errors: error.message }); + return; + } + throw error; + } + }) + ); + return router; } diff --git a/src/api/routes/v2/burn-blocks.ts b/src/api/routes/v2/burn-blocks.ts index 5b724fdd3a..1f2d5c323e 100644 --- a/src/api/routes/v2/burn-blocks.ts +++ b/src/api/routes/v2/burn-blocks.ts @@ -3,12 +3,14 @@ import { BurnBlockListResponse } from '@stacks/stacks-blockchain-api-types'; import { getETagCacheHandler, setETagCacheHeaders } from '../../controllers/cache-controller'; import { asyncHandler } from '../../async-handler'; import { PgStore } from '../../../datastore/pg-store'; -import { parseDbBurnBlock, validRequestParams, validRequestQuery } from './helpers'; +import { parseDbBurnBlock } from './helpers'; import { BlockPaginationQueryParams, - BurnBlockParams, - CompiledBlockPaginationParams, - CompiledBurnBlockParams, + BlockParams, + CompiledBlockPaginationQueryParams, + CompiledBlockParams, + validRequestParams, + validRequestQuery, } from './schemas'; export function createV2BurnBlocksRouter(db: PgStore): express.Router { @@ -19,7 +21,7 @@ export function createV2BurnBlocksRouter(db: PgStore): express.Router { '/', cacheHandler, asyncHandler(async (req, res) => { - if (!validRequestQuery(req, res, CompiledBlockPaginationParams)) return; + if (!validRequestQuery(req, res, CompiledBlockPaginationQueryParams)) return; const query = req.query as BlockPaginationQueryParams; const { limit, offset, results, total } = await db.getBurnBlocks(query); @@ -38,8 +40,8 @@ export function createV2BurnBlocksRouter(db: PgStore): express.Router { '/:height_or_hash', cacheHandler, asyncHandler(async (req, res) => { - if (!validRequestParams(req, res, CompiledBurnBlockParams)) return; - const params = req.params as BurnBlockParams; + if (!validRequestParams(req, res, CompiledBlockParams)) return; + const params = req.params as BlockParams; const block = await db.getBurnBlock(params); if (!block) { diff --git a/src/api/routes/v2/helpers.ts b/src/api/routes/v2/helpers.ts index 413192c9ab..41d0ce2a2e 100644 --- a/src/api/routes/v2/helpers.ts +++ b/src/api/routes/v2/helpers.ts @@ -1,51 +1,8 @@ import { BurnBlock, NakamotoBlock } from 'docs/generated'; -import { BlockWithTransactionIds, DbBurnBlock } from '../../../datastore/common'; +import { DbBlock, DbBurnBlock } from '../../../datastore/common'; import { unixEpochToIso } from '../../../helpers'; -import { TypeCheck } from '@sinclair/typebox/compiler'; -import { Request, Response } from 'express'; -import { TSchema } from '@sinclair/typebox'; -/** - * Validate request query parameters with a TypeBox compiled schema - * @param req - Request - * @param res - Response - * @param compiledType - TypeBox compiled schema - * @returns boolean - */ -export function validRequestQuery( - req: Request, - res: Response, - compiledType: TypeCheck -): boolean { - if (!compiledType.Check(req.query)) { - // TODO: Return a more user-friendly error - res.status(400).json({ errors: [...compiledType.Errors(req.query)] }); - return false; - } - return true; -} - -/** - * Validate request path parameters with a TypeBox compiled schema - * @param req - Request - * @param res - Response - * @param compiledType - TypeBox compiled schema - * @returns boolean - */ -export function validRequestParams( - req: Request, - res: Response, - compiledType: TypeCheck -): boolean { - if (!compiledType.Check(req.params)) { - // TODO: Return a more user-friendly error - res.status(400).json({ errors: [...compiledType.Errors(req.params)] }); - return false; - } - return true; -} - -export function parseDbNakamotoBlock(block: BlockWithTransactionIds): NakamotoBlock { +export function parseDbNakamotoBlock(block: DbBlock): NakamotoBlock { const apiBlock: NakamotoBlock = { canonical: block.canonical, height: block.block_height, @@ -58,7 +15,7 @@ export function parseDbNakamotoBlock(block: BlockWithTransactionIds): NakamotoBl burn_block_hash: block.burn_block_hash, burn_block_height: block.burn_block_height, miner_txid: block.miner_txid, - txs: [...block.tx_ids], + tx_count: block.tx_count, execution_cost_read_count: block.execution_cost_read_count, execution_cost_read_length: block.execution_cost_read_length, execution_cost_runtime: block.execution_cost_runtime, diff --git a/src/api/routes/v2/schemas.ts b/src/api/routes/v2/schemas.ts index 3a80a9071e..50d3f12d69 100644 --- a/src/api/routes/v2/schemas.ts +++ b/src/api/routes/v2/schemas.ts @@ -1,6 +1,50 @@ import { Type, Static, TSchema } from '@sinclair/typebox'; import { TypeCompiler } from '@sinclair/typebox/compiler'; import { ResourceType, pagingQueryLimits } from '../../../api/pagination'; +import { Request, Response } from 'express'; +import * as Ajv from 'ajv'; + +const ajv = new Ajv({ coerceTypes: true }); + +/** + * Validate request query parameters with a TypeBox compiled schema + * @param req - Request + * @param res - Response + * @param compiledType - Ajv compiled schema + * @returns boolean + */ +export function validRequestQuery( + req: Request, + res: Response, + compiledType: Ajv.ValidateFunction +): boolean { + if (!compiledType(req.query)) { + // TODO: Return a more user-friendly error + res.status(400).json({ errors: compiledType.errors }); + return false; + } + return true; +} + +/** + * Validate request path parameters with a TypeBox compiled schema + * @param req - Request + * @param res - Response + * @param compiledType - Ajv compiled schema + * @returns boolean + */ +export function validRequestParams( + req: Request, + res: Response, + compiledType: Ajv.ValidateFunction +): boolean { + if (!compiledType(req.params)) { + // TODO: Return a more user-friendly error + res.status(400).json({ errors: compiledType.errors }); + return false; + } + return true; +} // ========================== // Parameters @@ -20,21 +64,26 @@ export const BlockLimitParamSchema = Type.Integer({ description: 'Blocks per page', }); +export const TransactionLimitParamSchema = Type.Integer({ + minimum: 1, + maximum: pagingQueryLimits[ResourceType.Tx].maxLimit, + default: pagingQueryLimits[ResourceType.Tx].defaultLimit, + title: 'Transaction limit', + description: 'Transactions per page', +}); + const BurnBlockHashParamSchema = Type.RegExp(/^(0x)?[a-fA-F0-9]{64}$/i, { title: 'Burn block hash', description: 'Burn block hash', examples: ['0000000000000000000452773967cdd62297137cdaf79950c5e8bb0c62075133'], }); -type BurnBlockHashParam = Static; -export const CompiledBurnBlockHashParam = TypeCompiler.Compile(BurnBlockHashParamSchema); +export const CompiledBurnBlockHashParam = ajv.compile(BurnBlockHashParamSchema); const BurnBlockHeightParamSchema = Type.RegExp(/^[0-9]+$/, { title: 'Burn block height', description: 'Burn block height', examples: ['777678'], }); -type BurnBlockHeightParam = Static; -const CompiledBurnBlockHeightParam = TypeCompiler.Compile(BurnBlockHeightParamSchema); // ========================== // Query and path params @@ -52,7 +101,17 @@ const PaginationQueryParamsSchema = (t: T) => const BlockPaginationQueryParamsSchema = PaginationQueryParamsSchema(BlockLimitParamSchema); export type BlockPaginationQueryParams = Static; -export const CompiledBlockPaginationParams = TypeCompiler.Compile(BlockPaginationQueryParamsSchema); +export const CompiledBlockPaginationQueryParams = ajv.compile(BlockPaginationQueryParamsSchema); + +const TransactionPaginationQueryParamsSchema = PaginationQueryParamsSchema( + TransactionLimitParamSchema +); +export type TransactionPaginationQueryParams = Static< + typeof TransactionPaginationQueryParamsSchema +>; +export const CompiledTransactionPaginationQueryParams = ajv.compile( + TransactionPaginationQueryParamsSchema +); const BlocksQueryParamsSchema = Type.Union([ BlockPaginationQueryParamsSchema, @@ -76,9 +135,9 @@ const BlocksQueryParamsSchema = Type.Union([ ), ]); export type BlocksQueryParams = Static; -export const CompiledBlocksQueryParams = TypeCompiler.Compile(BlocksQueryParamsSchema); +export const CompiledBlocksQueryParams = ajv.compile(BlocksQueryParamsSchema); -const BurnBlockParamsSchema = Type.Object( +const BlockParamsSchema = Type.Object( { height_or_hash: Type.Union([ Type.Literal('latest'), @@ -88,5 +147,5 @@ const BurnBlockParamsSchema = Type.Object( }, { additionalProperties: false } ); -export type BurnBlockParams = Static; -export const CompiledBurnBlockParams = TypeCompiler.Compile(BurnBlockParamsSchema); +export type BlockParams = Static; +export const CompiledBlockParams = ajv.compile(BlockParamsSchema); diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 773051bbac..981fa6a7ef 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -23,6 +23,7 @@ export interface DbBlock { execution_cost_runtime: number; execution_cost_write_count: number; execution_cost_write_length: number; + tx_count: number; } /** An interface representing the microblock data that can be constructed _only_ from the /new_microblocks payload */ @@ -571,18 +572,6 @@ export interface NftEventWithTxMetadata { tx?: DbTx; } -export interface AddressNftEventIdentifier { - sender: string; - recipient: string; - asset_identifier: string; - value: string; - block_height: number; - tx_id: string; - event_index: number; - tx_index: number; - asset_event_type_id: number; -} - export interface DataStoreBlockUpdateData { block: DbBlock; microblocks: DbMicroblock[]; @@ -806,6 +795,7 @@ export interface BlockQueryResult { execution_cost_runtime: string; execution_cost_write_count: string; execution_cost_write_length: string; + tx_count: number; } export interface MicroblockQueryResult { @@ -1037,10 +1027,6 @@ export type DbPaginatedResult = { results: T[]; }; -export type BlockWithTransactionIds = DbBlock & { - tx_ids: string[]; -}; - export interface BlocksWithMetadata { results: { block: DbBlock; @@ -1174,6 +1160,7 @@ export interface BlockInsertValues { execution_cost_runtime: number; execution_cost_write_count: number; execution_cost_write_length: number; + tx_count: number; } export interface MicroblockInsertValues { diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index af92983f71..e35cabe9ee 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -183,6 +183,7 @@ export const BLOCK_COLUMNS = [ 'execution_cost_runtime', 'execution_cost_write_count', 'execution_cost_write_length', + 'tx_count', ]; export const MICROBLOCK_COLUMNS = [ @@ -464,6 +465,7 @@ export function parseBlockQueryResult(row: BlockQueryResult): DbBlock { execution_cost_runtime: Number.parseInt(row.execution_cost_runtime), execution_cost_write_count: Number.parseInt(row.execution_cost_write_count), execution_cost_write_length: Number.parseInt(row.execution_cost_write_length), + tx_count: row.tx_count, }; return block; } diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 9a3539a4c2..22ed88617a 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -19,10 +19,8 @@ import { } from '../helpers'; import { PgStoreEventEmitter } from './pg-store-event-emitter'; import { - AddressNftEventIdentifier, BlockIdentifier, BlockQueryResult, - BlockWithTransactionIds, BlocksWithMetadata, ContractTxQueryResult, DbAssetEventTypeId, @@ -73,6 +71,7 @@ import { PoxSyntheticEventTable, DbPoxStacker, DbPoxSyntheticEvent, + TxQueryResult, } from './common'; import { abiColumn, @@ -108,9 +107,12 @@ import { BlockLimitParamSchema, BlockPaginationQueryParams, BlocksQueryParams, - BurnBlockParams, + BlockParams, + TransactionPaginationQueryParams, + TransactionLimitParamSchema, CompiledBurnBlockHashParam, } from '../api/routes/v2/schemas'; +import { InvalidRequestError, InvalidRequestErrorType } from '../errors'; export const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); @@ -389,7 +391,7 @@ export class PgStore extends BasePgStore { async getCurrentBlockInternal(sql: PgSqlClient): Promise> { const result = await sql` - SELECT ${sql(BLOCK_COLUMNS)} + SELECT ${sql(BLOCK_COLUMNS.map(c => `b.${c}`))} FROM blocks b INNER JOIN chain_tip t USING (index_block_hash, block_hash, block_height, burn_block_height) LIMIT 1 @@ -436,12 +438,12 @@ export class PgStore extends BasePgStore { }); } - async getBurnBlock(args: BurnBlockParams): Promise { + async getBurnBlock(args: BlockParams): Promise { return await this.sqlTransaction(async sql => { const filter = args.height_or_hash === 'latest' ? sql`burn_block_hash = (SELECT burn_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` - : CompiledBurnBlockHashParam.Check(args.height_or_hash) + : CompiledBurnBlockHashParam(args.height_or_hash) ? sql`burn_block_hash = ${args.height_or_hash}` : sql`burn_block_height = ${args.height_or_hash}`; const blockQuery = await sql` @@ -573,9 +575,9 @@ export class PgStore extends BasePgStore { /** * Returns Block information with transaction IDs - * @returns Paginated `BlockWithTransactionIds` array + * @returns Paginated `DbBlock` array */ - async getV2Blocks(args: BlocksQueryParams): Promise> { + async getV2Blocks(args: BlocksQueryParams): Promise> { return await this.sqlTransaction(async sql => { const limit = args.limit ?? BlockLimitParamSchema.default; const offset = args.offset ?? 0; @@ -597,7 +599,7 @@ export class PgStore extends BasePgStore { : undefined; // Obtain blocks and transaction counts in the same query. - const blocksQuery = await sql<(BlockQueryResult & { tx_ids: string; total: number })[]>` + const blocksQuery = await sql<(BlockQueryResult & { total: number })[]>` WITH block_count AS ( ${ 'burn_block_hash' in args @@ -609,13 +611,6 @@ export class PgStore extends BasePgStore { ) SELECT ${sql(BLOCK_COLUMNS)}, - ( - SELECT STRING_AGG(tx_id,',') - FROM txs - WHERE index_block_hash = blocks.index_block_hash - AND canonical = true - AND microblock_canonical = true - ) AS tx_ids, (SELECT count FROM block_count)::int AS total FROM blocks WHERE canonical = true @@ -637,10 +632,7 @@ export class PgStore extends BasePgStore { results: [], total: 0, }; - const blocks = blocksQuery.map(b => ({ - ...parseBlockQueryResult(b), - tx_ids: b.tx_ids ? b.tx_ids.split(',') : [], - })); + const blocks = blocksQuery.map(b => parseBlockQueryResult(b)); return { limit, offset, @@ -650,39 +642,77 @@ export class PgStore extends BasePgStore { }); } - async getV2Block(args: BurnBlockParams): Promise { + async getV2Block(args: BlockParams): Promise { return await this.sqlTransaction(async sql => { const filter = args.height_or_hash === 'latest' ? sql`index_block_hash = (SELECT index_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` - : CompiledBurnBlockHashParam.Check(args.height_or_hash) + : CompiledBurnBlockHashParam(args.height_or_hash) ? sql`( block_hash = ${normalizeHashString(args.height_or_hash)} OR index_block_hash = ${normalizeHashString(args.height_or_hash)} )` : sql`block_height = ${args.height_or_hash}`; - const blockQuery = await sql<(BlockQueryResult & { tx_ids: string })[]>` - SELECT - ${sql(BLOCK_COLUMNS)}, - ( - SELECT STRING_AGG(tx_id,',') - FROM txs - WHERE index_block_hash = blocks.index_block_hash - AND canonical = true - AND microblock_canonical = true - ) AS tx_ids + const blockQuery = await sql` + SELECT ${sql(BLOCK_COLUMNS)} FROM blocks WHERE canonical = true AND ${filter} LIMIT 1 `; - if (blockQuery.count > 0) + if (blockQuery.count > 0) return parseBlockQueryResult(blockQuery[0]); + }); + } + + async getV2BlockTransactions( + args: BlockParams & TransactionPaginationQueryParams + ): Promise> { + return await this.sqlTransaction(async sql => { + const limit = args.limit ?? TransactionLimitParamSchema.default; + const offset = args.offset ?? 0; + const filter = + args.height_or_hash === 'latest' + ? sql`index_block_hash = (SELECT index_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : CompiledBurnBlockHashParam(args.height_or_hash) + ? sql`( + block_hash = ${normalizeHashString(args.height_or_hash)} + OR index_block_hash = ${normalizeHashString(args.height_or_hash)} + )` + : sql`block_height = ${args.height_or_hash}`; + const blockCheck = await sql`SELECT index_block_hash FROM blocks WHERE ${filter} LIMIT 1`; + if (blockCheck.count === 0) + throw new InvalidRequestError(`Block not found`, InvalidRequestErrorType.invalid_param); + const txsQuery = await sql<(TxQueryResult & { total: number })[]>` + WITH tx_count AS ( + SELECT tx_count AS total FROM blocks WHERE canonical = TRUE AND ${filter} + ) + SELECT ${sql(TX_COLUMNS)}, (SELECT total FROM tx_count)::int AS total + FROM txs + WHERE canonical = true + AND microblock_canonical = true + AND ${filter} + ORDER BY microblock_sequence ASC, tx_index ASC + LIMIT ${limit} + OFFSET ${offset} + `; + if (txsQuery.count === 0) return { - ...parseBlockQueryResult(blockQuery[0]), - tx_ids: blockQuery[0].tx_ids ? blockQuery[0].tx_ids.split(',') : [], + limit, + offset, + results: [], + total: 0, }; + return { + limit, + offset, + results: txsQuery.map(t => parseTxQueryResult(t)), + total: txsQuery[0].total, + }; }); } + /** + * @deprecated Only used in tests + */ async getBlockTxs(indexBlockHash: string) { const result = await this.sql<{ tx_id: string; tx_index: number }[]>` SELECT tx_id, tx_index diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 3da53808d5..1eac2ac2fc 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -444,6 +444,7 @@ export class PgWriteStore extends PgStore { execution_cost_runtime: block.execution_cost_runtime, execution_cost_write_count: block.execution_cost_write_count, execution_cost_write_length: block.execution_cost_write_length, + tx_count: block.tx_count, }; const result = await sql` INSERT INTO blocks ${sql(values)} @@ -2791,6 +2792,7 @@ export class PgWriteStore extends PgStore { execution_cost_runtime: block.execution_cost_runtime, execution_cost_write_count: block.execution_cost_write_count, execution_cost_write_length: block.execution_cost_write_length, + tx_count: block.tx_count, })); await sql` INSERT INTO blocks ${sql(values)} diff --git a/src/event-stream/event-server.ts b/src/event-stream/event-server.ts index 7f123f7a29..56b6b648d9 100644 --- a/src/event-stream/event-server.ts +++ b/src/event-stream/event-server.ts @@ -259,6 +259,7 @@ async function handleBlockMessage( execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: msg.transactions.length, }; logger.debug(`Received block ${msg.block_hash} (${msg.block_height}) from node`, dbBlock); @@ -1064,6 +1065,7 @@ export function parseNewBlockMessage(chainId: ChainID, msg: CoreNodeBlockMessage execution_cost_runtime: totalCost.execution_cost_runtime, execution_cost_write_count: totalCost.execution_cost_write_count, execution_cost_write_length: totalCost.execution_cost_write_length, + tx_count: msg.transactions.length, }; const dbMinerRewards: DbMinerReward[] = []; diff --git a/src/test-utils/test-builders.ts b/src/test-utils/test-builders.ts index 98f2db2a63..0fd51fc2ed 100644 --- a/src/test-utils/test-builders.ts +++ b/src/test-utils/test-builders.ts @@ -122,6 +122,7 @@ function testBlock(args?: TestBlockArgs): DbBlock { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; } @@ -743,7 +744,9 @@ export class TestBlockBuilder { } build(): DataStoreBlockUpdateData { - return this.data; + const data = this.data; + data.block.tx_count = this.txIndex + 1; + return data; } } diff --git a/src/tests/address-tests.ts b/src/tests/address-tests.ts index 00db2d577a..64b197c841 100644 --- a/src/tests/address-tests.ts +++ b/src/tests/address-tests.ts @@ -89,6 +89,7 @@ describe('address tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; let indexIdIndex = 0; const createStxTx = ( @@ -867,6 +868,7 @@ describe('address tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; let indexIdIndex = 0; @@ -2038,6 +2040,7 @@ describe('address tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const txBuilder = await makeContractCall({ contractAddress: 'ST11NJTTKGVT6D1HY4NJRVQWMQM7TVAR091EJ8P2Y', diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index 3bef070e7c..44616f58d8 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -83,6 +83,7 @@ describe('block tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, block); const tx: DbTxRaw = { @@ -519,6 +520,7 @@ describe('block tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const dbTx1: DbTxRaw = { ...dbBlock, @@ -673,7 +675,7 @@ describe('block tests', () => { miner_txid: '0x4321', parent_block_hash: '0x0004', parent_index_block_hash: '0x0004', - txs: ['0x0005'], + tx_count: 1, }; let fetch = await supertest(api.server).get( `/extended/v2/blocks?burn_block_hash=00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8` @@ -708,7 +710,7 @@ describe('block tests', () => { miner_txid: '0x4321', parent_block_hash: '0x0007', parent_index_block_hash: '0x0007', - txs: ['0x0018'], + tx_count: 1, }; fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_hash=latest`); json = JSON.parse(fetch.text); @@ -770,7 +772,7 @@ describe('block tests', () => { miner_txid: '0x4321', parent_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000004', parent_index_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000114', - txs: ['0x0005'], + tx_count: 1, }; let fetch = await supertest(api.server).get(`/extended/v2/blocks/latest`); let json = JSON.parse(fetch.text); diff --git a/src/tests/cache-control-tests.ts b/src/tests/cache-control-tests.ts index e27211ac87..12cb6fb14c 100644 --- a/src/tests/cache-control-tests.ts +++ b/src/tests/cache-control-tests.ts @@ -95,6 +95,7 @@ describe('cache-control tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTxRaw = { tx_id: '0x1234', diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index 34804796e0..ce2617c73e 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -273,6 +273,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTxRaw = { tx_id: '0x1234', @@ -436,6 +437,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTxRaw = { tx_id: '0x1234', @@ -605,6 +607,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, block); const blockQuery = await db.getBlock({ hash: block.block_hash }); @@ -670,6 +673,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; let indexIdIndex = 0; @@ -929,6 +933,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const txs1 = [ createStxTx('addrA', 'addrB', 100, dbBlock1), @@ -1001,6 +1006,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTxRaw = { tx_id: '0x1234', @@ -1966,6 +1972,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTx = { tx_id: '0x1234', @@ -2045,6 +2052,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTx = { tx_id: '0x421234', @@ -2129,6 +2137,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTx = { tx_id: '0x421234', @@ -2221,6 +2230,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTxRaw = { tx_id: '0x421234', @@ -2355,6 +2365,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTx = { tx_id: '0x421234', @@ -2439,6 +2450,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTx = { tx_id: '0x421234', @@ -2522,6 +2534,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTx = { tx_id: '0x421234', @@ -2604,6 +2617,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, dbBlock); @@ -2673,6 +2687,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTx = { tx_id: '0x421234', @@ -3042,6 +3057,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block2: DbBlock = { block_hash: '0x22', @@ -3061,6 +3077,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block3: DbBlock = { block_hash: '0x33', @@ -3080,6 +3097,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block3B: DbBlock = { ...block3, @@ -3105,6 +3123,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block4: DbBlock = { block_hash: '0x44', @@ -3124,6 +3143,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block5: DbBlock = { block_hash: '0x55', @@ -3143,6 +3163,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block6: DbBlock = { block_hash: '0x66', @@ -3162,6 +3183,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1Mempool: DbMempoolTxRaw = { @@ -3349,6 +3371,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block2: DbBlock = { block_hash: '0x22', @@ -3368,6 +3391,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block3: DbBlock = { block_hash: '0x33', @@ -3387,6 +3411,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block3B: DbBlock = { ...block3, @@ -3412,6 +3437,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const minerReward1: DbMinerReward = { @@ -3540,6 +3566,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const reorgResult = await db.handleReorg(client, block5, 0); @@ -3611,6 +3638,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const block2: DbBlock = { block_hash: '0x22', @@ -3630,6 +3658,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const minerReward1: DbMinerReward = { @@ -3903,6 +3932,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.update({ block: block3, microblocks: [], minerRewards: [], txs: [] }); @@ -3924,6 +3954,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx3: DbTxRaw = { tx_id: '0x03', @@ -4129,6 +4160,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.update({ block: block3b, microblocks: [], minerRewards: [], txs: [] }); const blockQuery2 = await db.getBlock({ hash: block3b.block_hash }); @@ -4166,6 +4198,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.update({ block: block4b, microblocks: [], minerRewards: [], txs: [] }); @@ -4262,6 +4295,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTxRaw = { tx_id: '0x421234', @@ -4344,6 +4378,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTxRaw = { tx_id: '0x421234', @@ -4425,6 +4460,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTxRaw = { tx_id: '0x421234', @@ -4577,6 +4613,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.update({ block: dbBlock, @@ -4636,6 +4673,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.update({ block: dbBlock, @@ -4696,6 +4734,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.update({ block: dbBlock, @@ -4756,6 +4795,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, block); const blockQuery = await db.getBlock({ hash: block.block_hash }); @@ -4859,6 +4899,7 @@ describe('postgres datastore', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, block); const blockQuery = await db.getBlock({ hash: block.block_hash }); diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index af8805cbfb..fd33072c2d 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -500,6 +500,7 @@ describe('mempool tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const dbTx1: DbTxRaw = { ...mempoolTx1, @@ -1190,6 +1191,7 @@ describe('mempool tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, dbBlock); const senderAddress = 'SP25YGP221F01S9SSCGN114MKDAK9VRK8P3KXGEMB'; @@ -1262,6 +1264,7 @@ describe('mempool tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, dbBlock); const senderAddress = 'SP25YGP221F01S9SSCGN114MKDAK9VRK8P3KXGEMB'; @@ -1480,6 +1483,7 @@ describe('mempool tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const dbBlock2: DbBlock = { block_hash: '0x2123', @@ -1499,6 +1503,7 @@ describe('mempool tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const mempoolTx: DbMempoolTxRaw = { tx_id: txId, diff --git a/src/tests/microblock-tests.ts b/src/tests/microblock-tests.ts index 0ed9e74264..2f6bfe176d 100644 --- a/src/tests/microblock-tests.ts +++ b/src/tests/microblock-tests.ts @@ -282,6 +282,7 @@ describe('microblock tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTxRaw = { diff --git a/src/tests/other-tests.ts b/src/tests/other-tests.ts index a4a7f9a8a3..d64bf877de 100644 --- a/src/tests/other-tests.ts +++ b/src/tests/other-tests.ts @@ -60,6 +60,7 @@ describe('other tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTxRaw = { tx_id: '0x1234', diff --git a/src/tests/search-tests.ts b/src/tests/search-tests.ts index ea1d5d0b3c..5135630497 100644 --- a/src/tests/search-tests.ts +++ b/src/tests/search-tests.ts @@ -60,6 +60,7 @@ describe('search tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, block); const tx: DbTxRaw = { @@ -267,6 +268,7 @@ describe('search tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx: DbTxRaw = { @@ -597,6 +599,7 @@ describe('search tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.updateBlock(client, block); @@ -1033,6 +1036,7 @@ describe('search tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const stxTx1: DbTxRaw = { diff --git a/src/tests/smart-contract-tests.ts b/src/tests/smart-contract-tests.ts index 4329c827a7..d3b32161af 100644 --- a/src/tests/smart-contract-tests.ts +++ b/src/tests/smart-contract-tests.ts @@ -60,6 +60,7 @@ describe('smart contract tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTxRaw = { tx_id: '0x421234', @@ -208,6 +209,7 @@ describe('smart contract tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const txId1 = '0x421234'; const smartContract1: DbSmartContract = { @@ -315,6 +317,7 @@ describe('smart contract tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const txId1 = '0x421234'; const smartContract1: DbSmartContract = { @@ -420,6 +423,7 @@ describe('smart contract tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; const tx1: DbTxRaw = { tx_id: '0x421235', diff --git a/src/tests/tx-tests.ts b/src/tests/tx-tests.ts index 445196d51c..4677ae66d6 100644 --- a/src/tests/tx-tests.ts +++ b/src/tests/tx-tests.ts @@ -145,6 +145,7 @@ describe('tx tests', () => { burn_block_hash: '0x0000000000000000000342c6f7e9313ffa6f0a92618edaf86351ca265aee1c7a', burn_block_height: 1, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 1210, execution_cost_read_length: 1919542, @@ -328,6 +329,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -483,6 +485,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -621,6 +624,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -759,6 +763,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -949,6 +954,7 @@ describe('tx tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; await db.update({ block: dbBlock, @@ -1135,6 +1141,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -1333,6 +1340,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -1578,6 +1586,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -1723,6 +1732,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -1868,6 +1878,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -1983,6 +1994,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -2634,6 +2646,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -2879,6 +2892,7 @@ describe('tx tests', () => { burn_block_hash: '0x0000000000000000000342c6f7e9313ffa6f0a92618edaf86351ca265aee1c7a', burn_block_height: 1, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 1210, execution_cost_read_length: 1919542, @@ -3208,6 +3222,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, @@ -3283,6 +3298,110 @@ describe('tx tests', () => { expect(result1.body.results[0].index_block_hash).toBe('0xdeadbeef'); }); + test('fetch transactions from v2 block', async () => { + await db.update( + new TestBlockBuilder({ + block_hash: '0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8', + index_block_hash: '0xdeadbeef', + parent_index_block_hash: '0x00', + parent_block_hash: '0xff0011', + parent_microblock_hash: '', + parent_microblock_sequence: 0, + block_height: 1, + burn_block_time: 94869286, + burn_block_hash: '0x1234', + burn_block_height: 123, + miner_txid: '0x4321', + canonical: true, + }) + .addTx({ + tx_id: '0x1234', + tx_index: 0, + nonce: 0, + type_id: DbTxTypeId.Coinbase, + status: 1, + raw_result: '0x0100000000000000000000000000000001', // u1 + canonical: true, + microblock_canonical: true, + microblock_sequence: I32_MAX, + microblock_hash: '', + fee_rate: 1234n, + sender_address: 'sender-addr', + }) + .addTx({ + tx_id: '0x1235', + tx_index: 1, + nonce: 0, + type_id: DbTxTypeId.Coinbase, + status: 1, + raw_result: '0x0100000000000000000000000000000001', // u1 + canonical: true, + microblock_canonical: true, + microblock_sequence: I32_MAX, + microblock_hash: '', + fee_rate: 1234n, + sender_address: 'sender-addr', + }) + .build() + ); + let result = await supertest(api.server).get( + `/extended/v2/blocks/0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8/transactions?limit=20&offset=0` + ); + expect(result.status).toBe(200); + expect(result.type).toBe('application/json'); + let json = JSON.parse(result.text); + expect(json.total).toBe(2); + expect(json.results[0]).toStrictEqual({ + anchor_mode: 'any', + block_hash: '0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8', + block_height: 1, + burn_block_time: 94869286, + burn_block_time_iso: '1973-01-03T00:34:46.000Z', + canonical: true, + coinbase_payload: { + alt_recipient: null, + data: '0x6869', + }, + event_count: 0, + events: [], + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + fee_rate: '1234', + is_unanchored: false, + microblock_canonical: true, + microblock_hash: '0x', + microblock_sequence: 2147483647, + nonce: 0, + parent_block_hash: '0x123456', + parent_burn_block_time: 94869286, + parent_burn_block_time_iso: '1973-01-03T00:34:46.000Z', + post_condition_mode: 'allow', + post_conditions: [], + sender_address: 'sender-addr', + sponsored: false, + tx_id: '0x1234', + tx_index: 0, + tx_result: { + hex: '0x0100000000000000000000000000000001', + repr: 'u1', + }, + tx_status: 'success', + tx_type: 'coinbase', + }); + + // Try a non-existent block + result = await supertest(api.server).get( + `/extended/v2/blocks/0x00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee999999/transactions?limit=20&offset=0` + ); + expect(result.status).toBe(404); + expect(result.type).toBe('application/json'); + json = JSON.parse(result.text); + expect(json.errors).toBe('Block not found'); + }); + test('fetch transactions from block', async () => { const not_updated_tx_id = '0x1111'; const tx_not_found = { @@ -3300,6 +3419,7 @@ describe('tx tests', () => { burn_block_hash: '0x1234', burn_block_height: 123, miner_txid: '0x4321', + tx_count: 1, canonical: true, execution_cost_read_count: 0, execution_cost_read_length: 0, diff --git a/src/tests/v2-proxy-tests.ts b/src/tests/v2-proxy-tests.ts index da5aad053e..5d2a32e0bf 100644 --- a/src/tests/v2-proxy-tests.ts +++ b/src/tests/v2-proxy-tests.ts @@ -74,6 +74,7 @@ describe('v2-proxy tests', () => { execution_cost_runtime: 0, execution_cost_write_count: 0, execution_cost_write_length: 0, + tx_count: 1, }; // Ensure db has a block so that current block height queries return a found result From 656b79eaf3c8ab5893c4fd45c61ccce388ae57cd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 19 Dec 2023 16:08:28 +0000 Subject: [PATCH 45/91] chore(release): 7.4.0-nakamoto.7 [skip ci] ## [7.4.0-nakamoto.7](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.6...v7.4.0-nakamoto.7) (2023-12-19) ### Features * add `tx_count` property to `/extended/v2/blocks` ([#1778](https://github.com/hirosystems/stacks-blockchain-api/issues/1778)) ([da4cd56](https://github.com/hirosystems/stacks-blockchain-api/commit/da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f)) ### Bug Fixes * insert block transaction data in batches ([#1760](https://github.com/hirosystems/stacks-blockchain-api/issues/1760)) ([bf99e90](https://github.com/hirosystems/stacks-blockchain-api/commit/bf99e90fa56ed04e6cb6bcc83559658f9e551183)) * remove deprecated token endpoints ([#1775](https://github.com/hirosystems/stacks-blockchain-api/issues/1775)) ([18f74b7](https://github.com/hirosystems/stacks-blockchain-api/commit/18f74b7b77c95a81c2f6d47641af229c5c833b8f)) --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 203e0233b3..58eebe6889 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [7.4.0-nakamoto.7](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.6...v7.4.0-nakamoto.7) (2023-12-19) + + +### Features + +* add `tx_count` property to `/extended/v2/blocks` ([#1778](https://github.com/hirosystems/stacks-blockchain-api/issues/1778)) ([da4cd56](https://github.com/hirosystems/stacks-blockchain-api/commit/da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f)) + + +### Bug Fixes + +* insert block transaction data in batches ([#1760](https://github.com/hirosystems/stacks-blockchain-api/issues/1760)) ([bf99e90](https://github.com/hirosystems/stacks-blockchain-api/commit/bf99e90fa56ed04e6cb6bcc83559658f9e551183)) +* remove deprecated token endpoints ([#1775](https://github.com/hirosystems/stacks-blockchain-api/issues/1775)) ([18f74b7](https://github.com/hirosystems/stacks-blockchain-api/commit/18f74b7b77c95a81c2f6d47641af229c5c833b8f)) + ## [7.4.0-nakamoto.6](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.5...v7.4.0-nakamoto.6) (2023-12-15) From db859ae980368db22b9d1c4c7096918d5f7f4c4b Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Thu, 21 Dec 2023 14:16:00 +0100 Subject: [PATCH 46/91] fix: do not load duckdb binary unless required (#1776) * fix: do not load duckdb binary unless required * chore: ignore buggy ts-unused-export line --- src/event-replay/parquet-based/replay-controller.ts | 1 + src/index.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/event-replay/parquet-based/replay-controller.ts b/src/event-replay/parquet-based/replay-controller.ts index 7943cba2f5..945297fa4b 100644 --- a/src/event-replay/parquet-based/replay-controller.ts +++ b/src/event-replay/parquet-based/replay-controller.ts @@ -26,6 +26,7 @@ import { MIGRATIONS_DIR } from '../../datastore/pg-store'; * * It also has functions to prepare and finalize the database for an event-replay. */ +// ts-unused-exports:disable-next-line export class ReplayController { private readonly db; private readonly dataset; diff --git a/src/index.ts b/src/index.ts index cf220a553f..822951e4de 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,6 @@ import { PgStore } from './datastore/pg-store'; import { PgWriteStore } from './datastore/pg-write-store'; import { registerMempoolPromStats } from './datastore/helpers'; import { logger } from './logger'; -import { ReplayController } from './event-replay/parquet-based/replay-controller'; import { isProdEnv, numberToHex, @@ -284,6 +283,7 @@ async function handleProgramArgs() { args.options.force ); } else if (args.operand === 'from-parquet-events') { + const { ReplayController } = await import('./event-replay/parquet-based/replay-controller'); const replay = await ReplayController.init(); await replay.prepare(); await replay.do(); From e4c080c15585ddfd0b3b183c43d409a7f7e6e523 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 21 Dec 2023 13:22:16 +0000 Subject: [PATCH 47/91] chore(release): 7.4.0-nakamoto.8 [skip ci] ## [7.4.0-nakamoto.8](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.7...v7.4.0-nakamoto.8) (2023-12-21) ### Bug Fixes * do not load duckdb binary unless required ([#1776](https://github.com/hirosystems/stacks-blockchain-api/issues/1776)) ([db859ae](https://github.com/hirosystems/stacks-blockchain-api/commit/db859ae980368db22b9d1c4c7096918d5f7f4c4b)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58eebe6889..ea27820cb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-nakamoto.8](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.7...v7.4.0-nakamoto.8) (2023-12-21) + + +### Bug Fixes + +* do not load duckdb binary unless required ([#1776](https://github.com/hirosystems/stacks-blockchain-api/issues/1776)) ([db859ae](https://github.com/hirosystems/stacks-blockchain-api/commit/db859ae980368db22b9d1c4c7096918d5f7f4c4b)) + ## [7.4.0-nakamoto.7](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.6...v7.4.0-nakamoto.7) (2023-12-19) From d36b1c2d37b050eb826e1c80e5ef4674ca0ea699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 26 Dec 2023 12:26:59 -0600 Subject: [PATCH 48/91] fix: vercel preview builds (#1783) * test: env echo * fix: attempt direct comparison * fix: var is a string * fix: remove debug --- .github/workflows/vercel.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/vercel.yml b/.github/workflows/vercel.yml index b22e55ab0b..eec3a9cdc8 100644 --- a/.github/workflows/vercel.yml +++ b/.github/workflows/vercel.yml @@ -19,9 +19,6 @@ jobs: name: ${{ github.ref_name == 'master' && 'Production' || 'Preview' }} url: ${{ github.ref_name == 'master' && 'https://stacks-blockchain-api.vercel.app/' || 'https://stacks-blockchain-api-pbcblockstack-blockstack.vercel.app/' }} - env: - PROD: ${{ github.ref_name == 'master' }} - steps: - uses: actions/checkout@v2 with: @@ -53,14 +50,14 @@ jobs: run: npm install --global vercel@latest - name: Pull Vercel environment information - run: vercel pull --yes --environment=${{ env.PROD && 'production' || 'preview' }} --token=${{ secrets.VERCEL_TOKEN }} + run: vercel pull --yes --environment=${{ github.ref_name == 'master' && 'production' || 'preview' }} --token=${{ secrets.VERCEL_TOKEN }} - name: Build project artifacts - run: vercel build ${{ env.PROD && '--prod' || '' }} --token=${{ secrets.VERCEL_TOKEN }} + run: vercel build ${{ github.ref_name == 'master' && '--prod' || '' }} --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy project artifacts to Vercel id: deploy - run: vercel ${{ env.PROD && '--prod' || 'deploy' }} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} | awk '{print "deployment_url="$1}' >> $GITHUB_OUTPUT + run: vercel ${{ github.ref_name == 'master' && '--prod' || 'deploy' }} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} | awk '{print "deployment_url="$1}' >> $GITHUB_OUTPUT - name: Add comment with Vercel deployment URL if: ${{ github.event_name == 'pull_request' }} From acfa79014f17ade9bb01ea5031bc90dfb111e72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 26 Dec 2023 12:29:20 -0600 Subject: [PATCH 49/91] ci: build vercel manually (#1784) --- .github/workflows/vercel.yml | 68 ++++++++++++++++++++++++++++++++++++ vercel.json | 5 +++ 2 files changed, 73 insertions(+) create mode 100644 .github/workflows/vercel.yml create mode 100644 vercel.json diff --git a/.github/workflows/vercel.yml b/.github/workflows/vercel.yml new file mode 100644 index 0000000000..eec3a9cdc8 --- /dev/null +++ b/.github/workflows/vercel.yml @@ -0,0 +1,68 @@ +name: Vercel + +env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + +on: + push: + branches: + - master + - beta + pull_request: + +jobs: + vercel: + runs-on: ubuntu-latest + + environment: + name: ${{ github.ref_name == 'master' && 'Production' || 'Preview' }} + url: ${{ github.ref_name == 'master' && 'https://stacks-blockchain-api.vercel.app/' || 'https://stacks-blockchain-api-pbcblockstack-blockstack.vercel.app/' }} + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Use Node.js + uses: actions/setup-node@v2 + with: + node-version-file: '.nvmrc' + + - name: Cache node modules + uses: actions/cache@v2 + env: + cache-name: cache-node-modules + with: + path: | + ~/.npm + **/node_modules + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + + - name: Install deps + run: npm ci --audit=false + + - name: Install Vercel CLI + run: npm install --global vercel@latest + + - name: Pull Vercel environment information + run: vercel pull --yes --environment=${{ github.ref_name == 'master' && 'production' || 'preview' }} --token=${{ secrets.VERCEL_TOKEN }} + + - name: Build project artifacts + run: vercel build ${{ github.ref_name == 'master' && '--prod' || '' }} --token=${{ secrets.VERCEL_TOKEN }} + + - name: Deploy project artifacts to Vercel + id: deploy + run: vercel ${{ github.ref_name == 'master' && '--prod' || 'deploy' }} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} | awk '{print "deployment_url="$1}' >> $GITHUB_OUTPUT + + - name: Add comment with Vercel deployment URL + if: ${{ github.event_name == 'pull_request' }} + uses: thollander/actions-comment-pull-request@v2 + with: + comment_tag: vercel + message: | + Vercel deployment URL: ${{ steps.deploy.outputs.deployment_url }} :rocket: diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000000..45c873bf51 --- /dev/null +++ b/vercel.json @@ -0,0 +1,5 @@ +{ + "git": { + "deploymentEnabled": false + } +} From eb36b33e541a24f499343ccd011e6137f5f3de08 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 26 Dec 2023 18:32:57 +0000 Subject: [PATCH 50/91] chore(release): 7.4.0-nakamoto.9 [skip ci] ## [7.4.0-nakamoto.9](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.8...v7.4.0-nakamoto.9) (2023-12-26) ### Bug Fixes * vercel preview builds ([#1783](https://github.com/hirosystems/stacks-blockchain-api/issues/1783)) ([d36b1c2](https://github.com/hirosystems/stacks-blockchain-api/commit/d36b1c2d37b050eb826e1c80e5ef4674ca0ea699)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea27820cb7..45fa95f37b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-nakamoto.9](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.8...v7.4.0-nakamoto.9) (2023-12-26) + + +### Bug Fixes + +* vercel preview builds ([#1783](https://github.com/hirosystems/stacks-blockchain-api/issues/1783)) ([d36b1c2](https://github.com/hirosystems/stacks-blockchain-api/commit/d36b1c2d37b050eb826e1c80e5ef4674ca0ea699)) + ## [7.4.0-nakamoto.8](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.7...v7.4.0-nakamoto.8) (2023-12-21) From d3f0b64d019d8eaa5269adbdb1200d1208d3e59c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 26 Dec 2023 12:59:45 -0600 Subject: [PATCH 51/91] ci: generate openapi json through vercel (#1785) --- docs/package-lock.json | 2254 +++++++++++++++++++++++++++++++++++++--- docs/package.json | 3 +- 2 files changed, 2091 insertions(+), 166 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index 8afbd2c07b..8805a40f28 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -12,8 +12,9 @@ "@apidevtools/json-schema-ref-parser": "9.0.7", "@apidevtools/swagger-cli": "4.0.4", "@types/json-schema-merge-allof": "0.6.0", - "@types/node": "^16.18.3", + "@types/node": "16.18.3", "ajv": "6.12.6", + "any-json": "^3.1.0", "chalk": "4.1.1", "del": "5.1.0", "glob": "7.1.6", @@ -503,6 +504,22 @@ "node": ">= 0.6" } }, + "node_modules/adler-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", + "integrity": "sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==", + "dev": true, + "dependencies": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + }, + "bin": { + "adler32": "bin/adler32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -589,6 +606,55 @@ "node": ">=0.10.0" } }, + "node_modules/any-json": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/any-json/-/any-json-3.1.0.tgz", + "integrity": "sha512-p4sFflxj6pQzn7T1omWd63GI7bNRmoDgpqxQWJIWNEOWp2+Z8PYtUY/DTGu7QA3MnSBpf7E+cDT3ZNQmeg+WNg==", + "dev": true, + "dependencies": { + "cson": "^4.1.0", + "dashdash": "^1.14.1", + "fast-csv": "^2.4.0", + "format-unicorn": "^1.1.0", + "hjson": "^2.4.1", + "ini": "^1.3.4", + "js-yaml": "^3.7.0", + "json5": "^0.5.1", + "strip-json-comments": "^2.0.1", + "toml-j0.4": "^1.0.10", + "tomlify-j0.4": "^2.1.1", + "typescript": "^2.4.2", + "util.promisify": "^1.0.0", + "xlsjs": "^0.7.5", + "xlsx": "^0.11.3", + "xml2js": "0.4.17" + }, + "bin": { + "any-json": "out/lib/run.js" + } + }, + "node_modules/any-json/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/any-json/node_modules/typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -789,6 +855,16 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/arguments-extended": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/arguments-extended/-/arguments-extended-0.0.3.tgz", + "integrity": "sha512-MNYdPKgCiywbgHAmNsYr1tSNLtfbSdwE1akZV+33hU9A8RG0lO5HAK9oMnw7y7bjYUhc04dJpcIBMUaPPYYtXg==", + "dev": true, + "dependencies": { + "extended": "~0.0.3", + "is-extended": "~0.0.8" + } + }, "node_modules/arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -840,6 +916,19 @@ "node": ">=0.10.0" } }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -858,6 +947,17 @@ "node": ">=0.10.0" } }, + "node_modules/array-extended": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/array-extended/-/array-extended-0.0.11.tgz", + "integrity": "sha512-Fe4Ti2YgM1onQgrcCD8dUhFuZgHQxzqylSl1C5IDJVVVqY5D07h8RghIXL9sZ6COZ0e+oTL5IusTv5eXABJ9Kw==", + "dev": true, + "dependencies": { + "arguments-extended": "~0.0.3", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "node_modules/array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -966,6 +1066,46 @@ "node": ">=0.10.0" } }, + "node_modules/array.prototype.reduce": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", + "integrity": "sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -975,6 +1115,15 @@ "node": ">=0.10.0" } }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -1035,6 +1184,18 @@ "node": ">= 4.5.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/babel-plugin-styled-components": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz", @@ -1393,13 +1554,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1464,6 +1626,21 @@ "node": ">=0.10.0" } }, + "node_modules/cfb": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-0.11.1.tgz", + "integrity": "sha512-1GEqpcO365hTRpP+GzHXNiUF5SB7qmY5aVYwrJm8ISx27HzHpaFlTQhnOCMNhqP0WPkHR0OGE9WDSqtksV4anw==", + "dev": true, + "dependencies": { + "commander": "" + }, + "bin": { + "cfb": "bin/cfb.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/chalk": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", @@ -1862,6 +2039,29 @@ "node": ">=0.10.0" } }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "dev": true, + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/collection-map": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", @@ -1916,6 +2116,15 @@ "color-support": "bin.js" } }, + "node_modules/colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -2053,6 +2262,18 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -2075,6 +2296,35 @@ "node": ">=4.8" } }, + "node_modules/cson": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cson/-/cson-4.1.0.tgz", + "integrity": "sha512-WJE4sajPn19i2NVs7PUjODPoEcwE7NEmVDsXYxyYca7UOcWcGIZM7xPtI0VQeOWxNbCLI+uvuP0BetJJfsspxQ==", + "dev": true, + "dependencies": { + "coffee-script": "^1.12.4", + "cson-parser": "^1.3.4", + "extract-opts": "^3.3.1", + "requirefresh": "^2.1.0", + "safefs": "^4.1.0" + }, + "bin": { + "cson2json": "bin/cson2json", + "json2cson": "bin/json2cson" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cson-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.3.5.tgz", + "integrity": "sha512-Pchz4dDkyafUL4V3xBuP9Os8Hu9VU96R+MxuTKh7NR+D866UiWrhBiSLbfuvwApEaJzpXhXTr3iPe4lFtXLzcQ==", + "dev": true, + "dependencies": { + "coffee-script": "^1.10.0" + } + }, "node_modules/css-color-keywords": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", @@ -2119,6 +2369,29 @@ "type": "^1.0.1" } }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-extended": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/date-extended/-/date-extended-0.0.6.tgz", + "integrity": "sha512-v9a2QLTVn1GQGXf02TQaSvNfeXA/V1FL2Tr0OQYqjI5+L9T5jEtCpLYG01sxFk+m1OtwMxydkKa8NKcflANAoQ==", + "dev": true, + "dependencies": { + "array-extended": "~0.0.3", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "node_modules/dateformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", @@ -2161,6 +2434,12 @@ "integrity": "sha1-/UPHNelnuAEzBohKVvvmZZlraBc=", "dev": true }, + "node_modules/declare.js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/declare.js/-/declare.js-0.0.8.tgz", + "integrity": "sha512-O659hy1gcHef7JnwtqdQlrj2c5DAEgtxm8pgFXofW7eUE1L4FjsSLlziovWcrOJAOFlEPaOJshY+0hBWCG/AnA==", + "dev": true + }, "node_modules/decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -2200,16 +2479,35 @@ "node": ">= 0.10" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { - "object-keys": "^1.0.12" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-property": { @@ -2368,6 +2666,47 @@ "node": ">=0.10.0" } }, + "node_modules/eachr": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eachr/-/eachr-3.3.0.tgz", + "integrity": "sha512-yKWuGwOE283CTgbEuvqXXusLH4VBXnY2nZbDkeWev+cpAXY6zCIADSPLdvfkAROc0t8S4l07U1fateCdEDuuvg==", + "dev": true, + "dependencies": { + "editions": "^2.2.0", + "typechecker": "^4.9.0" + }, + "engines": { + "node": ">=0.10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/editions": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", + "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==", + "dev": true, + "dependencies": { + "errlop": "^2.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/editions/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -2438,6 +2777,18 @@ "once": "^1.4.0" } }, + "node_modules/errlop": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz", + "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==", + "dev": true, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2448,31 +2799,50 @@ } }, "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", + "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -2481,6 +2851,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -2622,6 +3012,15 @@ "node": ">=6" } }, + "node_modules/exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -2858,6 +3257,24 @@ "node": ">=0.10.0" } }, + "node_modules/extended": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/extended/-/extended-0.0.6.tgz", + "integrity": "sha512-rvAV3BDGsV1SYGzUOu7aO0k82quhfl0QAyZudYhAcTeIr1rPbBnyOhOlkCLwLpDfP7HyKAWAPNSjRb9p7lE3rg==", + "dev": true, + "dependencies": { + "extender": "~0.0.5" + } + }, + "node_modules/extender": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/extender/-/extender-0.0.10.tgz", + "integrity": "sha512-iPLUHZJaNW6RuOShQX33ZpewEUIlijFBcsXnKWyiYERKWPsFxfKgx8J0xRz29hKQWPFFPACgBW6cHM7Ke1pfaA==", + "dev": true, + "dependencies": { + "declare.js": "~0.0.4" + } + }, "node_modules/extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -2910,6 +3327,23 @@ "node": ">=0.10.0" } }, + "node_modules/extract-opts": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/extract-opts/-/extract-opts-3.4.0.tgz", + "integrity": "sha512-M7Y+1cJDkzOWqvGH5F/V2qgkD6+uitW3NV9rQGl+pLSVuXZ4IDDQgxxMeLPKcWUyfypBWczIILiroSuhXG7Ytg==", + "dev": true, + "dependencies": { + "eachr": "^3.2.0", + "editions": "^2.2.0", + "typechecker": "^4.9.0" + }, + "engines": { + "node": ">=0.10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, "node_modules/faker": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", @@ -2931,6 +3365,22 @@ "node": ">= 0.10" } }, + "node_modules/fast-csv": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-2.5.0.tgz", + "integrity": "sha512-M/9ezLU9/uDwvDZTt9sNFJa0iLDUsbhYJwPtnE0D9MjeuB6DY9wRCyUPZta9iI6cSz5wBWGaUPL61QH8h92cNA==", + "dev": true, + "dependencies": { + "extended": "0.0.6", + "is-extended": "0.0.10", + "object-extended": "0.0.7", + "safer-buffer": "^2.1.2", + "string-extended": "0.0.8" + }, + "engines": { + "node": ">=4.0.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", @@ -3281,6 +3731,15 @@ "readable-stream": "^2.3.6" } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -3308,6 +3767,12 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, + "node_modules/format-unicorn": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/format-unicorn/-/format-unicorn-1.1.1.tgz", + "integrity": "sha512-MEjmrLmOsxswQC+TLVgGRZTRw+QSwMTQ0aqnkWPMAw1jKcO710mET0GMwoxrm0GxN0nSSBSUVaxC4MNYyrDXHQ==", + "dev": true + }, "node_modules/format-util": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz", @@ -3323,6 +3788,15 @@ "node": ">= 0.6" } }, + "node_modules/frac": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/frac/-/frac-0.3.1.tgz", + "integrity": "sha512-1Lzf2jOjhIkRaa013KlxNOn2D9FemmQNeYUDpEIyPeFXmpLvbZXJOlaayMBT6JKXx+afQFgQ1QJ4kaF7Z07QFQ==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -3383,10 +3857,40 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-caller-file": { "version": "2.0.5", @@ -3398,14 +3902,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3653,6 +4158,21 @@ "node": ">=4" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", @@ -3684,6 +4204,18 @@ "node": ">= 0.10" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", @@ -3969,9 +4501,9 @@ } }, "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4000,17 +4532,41 @@ "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, - "dependencies": { - "sparkles": "^1.0.0" - }, + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, "engines": { "node": ">= 0.4" @@ -4097,6 +4653,27 @@ "node": ">=0.10.0" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hjson": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/hjson/-/hjson-2.4.3.tgz", + "integrity": "sha512-gpLABogUGlxNdW/PwdEYRBMsfU3Jvl96qkXx2D+GZIg0xllpNkuscV53Ibb1Wk4goyY6Hfm63yMRaNUExFe0hw==", + "dev": true, + "bin": { + "hjson": "bin/hjson" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -4207,13 +4784,13 @@ } }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -4281,6 +4858,20 @@ "node": ">=0.10.0" } }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -4334,9 +4925,9 @@ "dev": true }, "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "engines": { "node": ">= 0.4" @@ -4440,6 +5031,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-extended": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/is-extended/-/is-extended-0.0.10.tgz", + "integrity": "sha512-qp+HR+L9QXbgFurvqiVgD+JiGyUboRgICNzCXmbiLtZBFVSNFbxRsI4q7Be9mCWTO5PoO1IxoWp5sl+j5b83FA==", + "dev": true, + "dependencies": { + "extended": "~0.0.3" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4516,9 +5116,9 @@ } }, "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" @@ -4601,10 +5201,13 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4648,6 +5251,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -6718,10 +7336,21 @@ "node": ">=0.10.0" } }, + "node_modules/object-extended": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/object-extended/-/object-extended-0.0.7.tgz", + "integrity": "sha512-2LJYIacEXoZ1glGkAZuvA/4pfJM4Y1ShReAo9jWpBSuz89TiUCdiPqhGJJ6m97F3WjhCSRwrbgaxYEAm9dRYBw==", + "dev": true, + "dependencies": { + "array-extended": "~0.0.4", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "node_modules/object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6749,14 +7378,14 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -6781,6 +7410,25 @@ "node": ">=0.10.0" } }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz", + "integrity": "sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==", + "dev": true, + "dependencies": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "safe-array-concat": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", @@ -7374,6 +8022,18 @@ "node": ">= 0.8" } }, + "node_modules/printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "dev": true, + "bin": { + "printj": "bin/printj.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/prismjs": { "version": "1.25.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", @@ -11207,6 +11867,23 @@ "node": ">=0.10.0" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", @@ -11317,6 +11994,21 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "node_modules/requirefresh": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/requirefresh/-/requirefresh-2.3.0.tgz", + "integrity": "sha512-oskKAg0pSlPnJAkFMrcqrHeCGzYunl4Hkl+N/NW3nnFWDHRg97yb475HtF5ax8LP9i8QvVkenVIhjNb+h+P7nA==", + "dev": true, + "dependencies": { + "editions": "^2.2.0" + }, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, "node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -11419,6 +12111,30 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -11434,12 +12150,49 @@ "ret": "~0.1.10" } }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safefs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/safefs/-/safefs-4.2.0.tgz", + "integrity": "sha512-1amPBO92jw/hWS+gH/u7z7EL7YxaJ8WecBQl49tMQ6Y6EQfndxNNKwlPqDOcwpUetdmK6nKLoVdjybVScRwq5A==", + "dev": true, + "dependencies": { + "editions": "^2.2.0", + "graceful-fs": "^4.2.3" + }, + "engines": { + "node": ">=0.12" + }, + "funding": { + "type": "cooperative", + "url": "https://bevry.me/fund" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", + "dev": true + }, "node_modules/scheduler": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", @@ -11585,6 +12338,35 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -12501,6 +13283,23 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/ssf": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.8.2.tgz", + "integrity": "sha512-+ZkFDAG+ImJ48DcZvabx6YTrZ67DKkM0kbyOOtH73mbUEvNhQWWgRZrHC8+k7GuGKWQnACYLi7bj0eCt1jmosQ==", + "dev": true, + "dependencies": { + "colors": "0.6.2", + "frac": "0.3.1", + "voc": "" + }, + "bin": { + "ssf": "bin/ssf.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -12633,6 +13432,18 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/string-extended": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/string-extended/-/string-extended-0.0.8.tgz", + "integrity": "sha512-CK46p3AxBvBhJbBi6WrF9bCcaWH20E4NwlLSzpooG2nXWvcP2gy2YR8VN6fSwZyrbcvL4S4zoNKbR0QG52X4rw==", + "dev": true, + "dependencies": { + "array-extended": "~0.0.5", + "date-extended": "~0.0.3", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "node_modules/string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -12664,27 +13475,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12972,6 +13802,18 @@ "node": ">= 0.10" } }, + "node_modules/toml-j0.4": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/toml-j0.4/-/toml-j0.4-1.1.1.tgz", + "integrity": "sha512-lYK5otg0+cto8YmsWcPEfeiTiC/VU6P6HA6ooaYI9K/KYT24Jg0BrYtRZK1K3cwakSMyh6nttfJL9RmQH0gyCg==", + "dev": true + }, + "node_modules/tomlify-j0.4": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tomlify-j0.4/-/tomlify-j0.4-2.2.1.tgz", + "integrity": "sha512-0kCocYX8ujnbK6jQ9e+g9GLiCIfVkFaCB3DCTQDP7J79gPVZVmZgQZ/KUNe1a6hUfrmHHaErVGUjedfpaX5EZw==", + "dev": true + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -13041,6 +13883,86 @@ "node": ">= 0.6" } }, + "node_modules/typechecker": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-4.11.0.tgz", + "integrity": "sha512-lz39Mc/d1UBcF/uQFL5P8L+oWdIn/stvkUgHf0tPRW4aEwGGErewNXo2Nb6We2WslWifn00rhcHbbRWRcTGhuw==", + "dev": true, + "dependencies": { + "editions": "^2.2.0" + }, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -13061,14 +13983,14 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" }, "funding": { @@ -13268,6 +14190,24 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "node_modules/util.promisify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.2.tgz", + "integrity": "sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "object.getownpropertydescriptors": "^2.1.6", + "safe-array-concat": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -13462,6 +14402,18 @@ "node": ">= 0.10" } }, + "node_modules/voc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/voc/-/voc-1.2.0.tgz", + "integrity": "sha512-BOuDjFFYvJdZO6e/N65AlaDItXo2TgyLjeyRYcqgAPkXpp5yTJcvkL2n+syO1r9Qc5g96tfBD2tuiMhYDmaGcA==", + "dev": true, + "bin": { + "voc": "voc.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -13518,6 +14470,25 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", @@ -13549,6 +14520,143 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "node_modules/xlsjs": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/xlsjs/-/xlsjs-0.7.6.tgz", + "integrity": "sha512-IQtL2z+BVYaIVzEhknZ1YBr8ItUbqiS7kaQZ3O35/k1q+kSgjVxmzwno6r3EbBgEWhrVCad2mKbnFeMmEE5zdw==", + "deprecated": "xlsjs has been merged into xlsx", + "dev": true, + "dependencies": { + "cfb": "~0.11.0", + "codepage": "", + "commander": "", + "exit-on-epipe": "", + "ssf": "~0.8.1" + }, + "bin": { + "xls": "bin/xls.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx": { + "version": "0.11.19", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.11.19.tgz", + "integrity": "sha512-UTfD64o5Ka/E6QHL12fzcq5wnt9MCtuwgoUdYSTDxjjDkhNmZwSfPlJH/+Yh8vE6nU/0ax3MXNrc9AP4haAmIg==", + "dev": true, + "dependencies": { + "adler-32": "~1.2.0", + "cfb": "~1.0.2", + "codepage": "~1.12.0", + "commander": "~2.13.0", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "ssf": "~0.10.1" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx/node_modules/cfb": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.0.8.tgz", + "integrity": "sha512-oA7VomcgZRWTo8V20UYLlXu4ZOCFEAfwwrcxE8PcVzXW12WOhsi38PVnymb6Xoj8y7ghoZQOOOVRBMdLJ4jCjg==", + "dev": true, + "dependencies": { + "commander": "^2.14.1", + "printj": "~1.1.2" + }, + "bin": { + "cfb": "bin/cfb.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx/node_modules/cfb/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/xlsx/node_modules/codepage": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.12.2.tgz", + "integrity": "sha512-FAN+oPs/ocaPLFvIt4vEOHgWA6UJ6t+fVbbVBoXDpTpC+4JYasomYZEEjR/Miph3qQrVnIShRwwmwu4P35JW1w==", + "dev": true, + "dependencies": { + "commander": "~2.14.1", + "exit-on-epipe": "~1.0.1" + }, + "bin": { + "codepage": "bin/codepage.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx/node_modules/codepage/node_modules/commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + }, + "node_modules/xlsx/node_modules/commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "node_modules/xlsx/node_modules/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xlsx/node_modules/ssf": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.3.tgz", + "integrity": "sha512-pRuUdW0WwyB2doSqqjWyzwCD6PkfxpHAHdZp39K3dp/Hq7f+xfMwNAWIi16DyrRg4gg9c/RvLYkJTSawTPTm1w==", + "dev": true, + "dependencies": { + "frac": "~1.1.2" + }, + "bin": { + "ssf": "bin/ssf.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xml2js": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha512-1O7wk/NTQN0UEOItIYTxK4qP4sMUVU60MbF4Nj0a8jd6eebMXOicVI/KFOEsYKKH4uBpx6XG9ZGZctXK5rtO5Q==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "^4.1.0" + } + }, + "node_modules/xmlbuilder": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha512-oEePiEefhQhAeUnwRnIBLBWmk/fsWWbQ53EEWsRuzECbQ3m5o/Esmq6H47CYYwSLW+Ynt0rS9hd0pd2ogMAWjg==", + "dev": true, + "dependencies": { + "lodash": "^4.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -14131,6 +15239,16 @@ "negotiator": "0.6.2" } }, + "adler-32": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz", + "integrity": "sha512-/vUqU/UY4MVeFsg+SsK6c+/05RZXIHZMGJA+PX5JyWI0ZRcBpupnRuPLU/NXXoFwMYCPCoxIfElM2eS+DUXCqQ==", + "dev": true, + "requires": { + "exit-on-epipe": "~1.0.1", + "printj": "~1.1.0" + } + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -14192,6 +15310,44 @@ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "any-json": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/any-json/-/any-json-3.1.0.tgz", + "integrity": "sha512-p4sFflxj6pQzn7T1omWd63GI7bNRmoDgpqxQWJIWNEOWp2+Z8PYtUY/DTGu7QA3MnSBpf7E+cDT3ZNQmeg+WNg==", + "dev": true, + "requires": { + "cson": "^4.1.0", + "dashdash": "^1.14.1", + "fast-csv": "^2.4.0", + "format-unicorn": "^1.1.0", + "hjson": "^2.4.1", + "ini": "^1.3.4", + "js-yaml": "^3.7.0", + "json5": "^0.5.1", + "strip-json-comments": "^2.0.1", + "toml-j0.4": "^1.0.10", + "tomlify-j0.4": "^2.1.1", + "typescript": "^2.4.2", + "util.promisify": "^1.0.0", + "xlsjs": "^0.7.5", + "xlsx": "^0.11.3", + "xml2js": "0.4.17" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==", + "dev": true + }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + } + } + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -14364,6 +15520,16 @@ "sprintf-js": "~1.0.2" } }, + "arguments-extended": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/arguments-extended/-/arguments-extended-0.0.3.tgz", + "integrity": "sha512-MNYdPKgCiywbgHAmNsYr1tSNLtfbSdwE1akZV+33hU9A8RG0lO5HAK9oMnw7y7bjYUhc04dJpcIBMUaPPYYtXg==", + "dev": true, + "requires": { + "extended": "~0.0.3", + "is-extended": "~0.0.8" + } + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -14400,6 +15566,16 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -14412,6 +15588,17 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-extended": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/array-extended/-/array-extended-0.0.11.tgz", + "integrity": "sha512-Fe4Ti2YgM1onQgrcCD8dUhFuZgHQxzqylSl1C5IDJVVVqY5D07h8RghIXL9sZ6COZ0e+oTL5IusTv5eXABJ9Kw==", + "dev": true, + "requires": { + "arguments-extended": "~0.0.3", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -14494,12 +15681,46 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.reduce": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", + "integrity": "sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -14545,6 +15766,12 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "babel-plugin-styled-components": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz", @@ -14851,13 +16078,14 @@ } }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" } }, "call-me-maybe": { @@ -14909,6 +16137,15 @@ "tunnel-agent": "^0.4.0" } }, + "cfb": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-0.11.1.tgz", + "integrity": "sha512-1GEqpcO365hTRpP+GzHXNiUF5SB7qmY5aVYwrJm8ISx27HzHpaFlTQhnOCMNhqP0WPkHR0OGE9WDSqtksV4anw==", + "dev": true, + "requires": { + "commander": "" + } + }, "chalk": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", @@ -15238,6 +16475,18 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "dev": true + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, "collection-map": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", @@ -15280,6 +16529,12 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==", + "dev": true + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -15397,6 +16652,12 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true + }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -15416,6 +16677,28 @@ "which": "^1.2.9" } }, + "cson": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cson/-/cson-4.1.0.tgz", + "integrity": "sha512-WJE4sajPn19i2NVs7PUjODPoEcwE7NEmVDsXYxyYca7UOcWcGIZM7xPtI0VQeOWxNbCLI+uvuP0BetJJfsspxQ==", + "dev": true, + "requires": { + "coffee-script": "^1.12.4", + "cson-parser": "^1.3.4", + "extract-opts": "^3.3.1", + "requirefresh": "^2.1.0", + "safefs": "^4.1.0" + } + }, + "cson-parser": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cson-parser/-/cson-parser-1.3.5.tgz", + "integrity": "sha512-Pchz4dDkyafUL4V3xBuP9Os8Hu9VU96R+MxuTKh7NR+D866UiWrhBiSLbfuvwApEaJzpXhXTr3iPe4lFtXLzcQ==", + "dev": true, + "requires": { + "coffee-script": "^1.10.0" + } + }, "css-color-keywords": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", @@ -15454,6 +16737,26 @@ "type": "^1.0.1" } }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-extended": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/date-extended/-/date-extended-0.0.6.tgz", + "integrity": "sha512-v9a2QLTVn1GQGXf02TQaSvNfeXA/V1FL2Tr0OQYqjI5+L9T5jEtCpLYG01sxFk+m1OtwMxydkKa8NKcflANAoQ==", + "dev": true, + "requires": { + "array-extended": "~0.0.3", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "dateformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", @@ -15482,6 +16785,12 @@ "integrity": "sha1-/UPHNelnuAEzBohKVvvmZZlraBc=", "dev": true }, + "declare.js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/declare.js/-/declare.js-0.0.8.tgz", + "integrity": "sha512-O659hy1gcHef7JnwtqdQlrj2c5DAEgtxm8pgFXofW7eUE1L4FjsSLlziovWcrOJAOFlEPaOJshY+0hBWCG/AnA==", + "dev": true + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -15509,13 +16818,26 @@ "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", "dev": true }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "define-property": { @@ -15657,6 +16979,34 @@ } } }, + "eachr": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eachr/-/eachr-3.3.0.tgz", + "integrity": "sha512-yKWuGwOE283CTgbEuvqXXusLH4VBXnY2nZbDkeWev+cpAXY6zCIADSPLdvfkAROc0t8S4l07U1fateCdEDuuvg==", + "dev": true, + "requires": { + "editions": "^2.2.0", + "typechecker": "^4.9.0" + } + }, + "editions": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", + "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==", + "dev": true, + "requires": { + "errlop": "^2.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -15716,6 +17066,12 @@ "once": "^1.4.0" } }, + "errlop": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz", + "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==", + "dev": true + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -15726,31 +17082,67 @@ } }, "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", + "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" } }, "es-to-primitive": { @@ -15869,6 +17261,12 @@ "strip-eof": "^1.0.0" } }, + "exit-on-epipe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz", + "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==", + "dev": true + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -16079,6 +17477,24 @@ "is-extendable": "^1.0.1" } }, + "extended": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/extended/-/extended-0.0.6.tgz", + "integrity": "sha512-rvAV3BDGsV1SYGzUOu7aO0k82quhfl0QAyZudYhAcTeIr1rPbBnyOhOlkCLwLpDfP7HyKAWAPNSjRb9p7lE3rg==", + "dev": true, + "requires": { + "extender": "~0.0.5" + } + }, + "extender": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/extender/-/extender-0.0.10.tgz", + "integrity": "sha512-iPLUHZJaNW6RuOShQX33ZpewEUIlijFBcsXnKWyiYERKWPsFxfKgx8J0xRz29hKQWPFFPACgBW6cHM7Ke1pfaA==", + "dev": true, + "requires": { + "declare.js": "~0.0.4" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -16121,6 +17537,17 @@ } } }, + "extract-opts": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/extract-opts/-/extract-opts-3.4.0.tgz", + "integrity": "sha512-M7Y+1cJDkzOWqvGH5F/V2qgkD6+uitW3NV9rQGl+pLSVuXZ4IDDQgxxMeLPKcWUyfypBWczIILiroSuhXG7Ytg==", + "dev": true, + "requires": { + "eachr": "^3.2.0", + "editions": "^2.2.0", + "typechecker": "^4.9.0" + } + }, "faker": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", @@ -16139,6 +17566,19 @@ "time-stamp": "^1.0.0" } }, + "fast-csv": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/fast-csv/-/fast-csv-2.5.0.tgz", + "integrity": "sha512-M/9ezLU9/uDwvDZTt9sNFJa0iLDUsbhYJwPtnE0D9MjeuB6DY9wRCyUPZta9iI6cSz5wBWGaUPL61QH8h92cNA==", + "dev": true, + "requires": { + "extended": "0.0.6", + "is-extended": "0.0.10", + "object-extended": "0.0.7", + "safer-buffer": "^2.1.2", + "string-extended": "0.0.8" + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -16437,6 +17877,15 @@ "readable-stream": "^2.3.6" } }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -16458,6 +17907,12 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", "dev": true }, + "format-unicorn": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/format-unicorn/-/format-unicorn-1.1.1.tgz", + "integrity": "sha512-MEjmrLmOsxswQC+TLVgGRZTRw+QSwMTQ0aqnkWPMAw1jKcO710mET0GMwoxrm0GxN0nSSBSUVaxC4MNYyrDXHQ==", + "dev": true + }, "format-util": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz", @@ -16470,6 +17925,12 @@ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true }, + "frac": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/frac/-/frac-0.3.1.tgz", + "integrity": "sha512-1Lzf2jOjhIkRaa013KlxNOn2D9FemmQNeYUDpEIyPeFXmpLvbZXJOlaayMBT6JKXx+afQFgQ1QJ4kaF7Z07QFQ==", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -16513,9 +17974,27 @@ } }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, "get-caller-file": { @@ -16525,14 +18004,15 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-proxy": { @@ -16722,6 +18202,15 @@ "dev": true, "peer": true }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, "globby": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", @@ -16747,6 +18236,15 @@ "sparkles": "^1.0.0" } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", @@ -16989,9 +18487,9 @@ } }, "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true }, "has-color": { @@ -17015,10 +18513,25 @@ "sparkles": "^1.0.0" } }, + "has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.2" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true + }, "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true }, "has-tostringtag": { @@ -17082,6 +18595,21 @@ } } }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, + "hjson": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/hjson/-/hjson-2.4.3.tgz", + "integrity": "sha512-gpLABogUGlxNdW/PwdEYRBMsfU3Jvl96qkXx2D+GZIg0xllpNkuscV53Ibb1Wk4goyY6Hfm63yMRaNUExFe0hw==", + "dev": true + }, "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -17179,13 +18707,13 @@ } }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, @@ -17234,6 +18762,17 @@ } } }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -17275,9 +18814,9 @@ "dev": true }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true }, "is-core-module": { @@ -17354,6 +18893,15 @@ } } }, + "is-extended": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/is-extended/-/is-extended-0.0.10.tgz", + "integrity": "sha512-qp+HR+L9QXbgFurvqiVgD+JiGyUboRgICNzCXmbiLtZBFVSNFbxRsI4q7Be9mCWTO5PoO1IxoWp5sl+j5b83FA==", + "dev": true, + "requires": { + "extended": "~0.0.3" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -17403,9 +18951,9 @@ "dev": true }, "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "requires": { "has-tostringtag": "^1.0.0" @@ -17461,10 +19009,13 @@ } }, "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } }, "is-stream": { "version": "1.1.0", @@ -17490,6 +19041,15 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "requires": { + "which-typed-array": "^1.1.11" + } + }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -19193,10 +20753,21 @@ } } }, + "object-extended": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/object-extended/-/object-extended-0.0.7.tgz", + "integrity": "sha512-2LJYIacEXoZ1glGkAZuvA/4pfJM4Y1ShReAo9jWpBSuz89TiUCdiPqhGJJ6m97F3WjhCSRwrbgaxYEAm9dRYBw==", + "dev": true, + "requires": { + "array-extended": "~0.0.4", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true }, "object-keys": { @@ -19215,14 +20786,14 @@ } }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, @@ -19238,6 +20809,19 @@ "isobject": "^3.0.0" } }, + "object.getownpropertydescriptors": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz", + "integrity": "sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==", + "dev": true, + "requires": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "safe-array-concat": "^1.0.0" + } + }, "object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", @@ -19685,6 +21269,12 @@ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, + "printj": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", + "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==", + "dev": true + }, "prismjs": { "version": "1.25.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", @@ -22878,6 +24468,17 @@ "safe-regex": "^1.1.0" } }, + "regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + } + }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", @@ -22961,6 +24562,15 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, + "requirefresh": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/requirefresh/-/requirefresh-2.3.0.tgz", + "integrity": "sha512-oskKAg0pSlPnJAkFMrcqrHeCGzYunl4Hkl+N/NW3nnFWDHRg97yb475HtF5ax8LP9i8QvVkenVIhjNb+h+P7nA==", + "dev": true, + "requires": { + "editions": "^2.2.0" + } + }, "resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", @@ -23026,6 +24636,26 @@ "queue-microtask": "^1.2.2" } }, + "safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -23041,12 +24671,39 @@ "ret": "~0.1.10" } }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "safefs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/safefs/-/safefs-4.2.0.tgz", + "integrity": "sha512-1amPBO92jw/hWS+gH/u7z7EL7YxaJ8WecBQl49tMQ6Y6EQfndxNNKwlPqDOcwpUetdmK6nKLoVdjybVScRwq5A==", + "dev": true, + "requires": { + "editions": "^2.2.0", + "graceful-fs": "^4.2.3" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", + "dev": true + }, "scheduler": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", @@ -23177,6 +24834,29 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + } + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -23951,6 +25631,17 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "ssf": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.8.2.tgz", + "integrity": "sha512-+ZkFDAG+ImJ48DcZvabx6YTrZ67DKkM0kbyOOtH73mbUEvNhQWWgRZrHC8+k7GuGKWQnACYLi7bj0eCt1jmosQ==", + "dev": true, + "requires": { + "colors": "0.6.2", + "frac": "0.3.1", + "voc": "" + } + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -24062,6 +25753,18 @@ "safe-buffer": "~5.1.0" } }, + "string-extended": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/string-extended/-/string-extended-0.0.8.tgz", + "integrity": "sha512-CK46p3AxBvBhJbBi6WrF9bCcaWH20E4NwlLSzpooG2nXWvcP2gy2YR8VN6fSwZyrbcvL4S4zoNKbR0QG52X4rw==", + "dev": true, + "requires": { + "array-extended": "~0.0.5", + "date-extended": "~0.0.3", + "extended": "~0.0.3", + "is-extended": "~0.0.3" + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -24084,24 +25787,37 @@ "es-abstract": "^1.19.1" } }, + "string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "strip-ansi": { @@ -24324,6 +26040,18 @@ "through2": "^2.0.3" } }, + "toml-j0.4": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/toml-j0.4/-/toml-j0.4-1.1.1.tgz", + "integrity": "sha512-lYK5otg0+cto8YmsWcPEfeiTiC/VU6P6HA6ooaYI9K/KYT24Jg0BrYtRZK1K3cwakSMyh6nttfJL9RmQH0gyCg==", + "dev": true + }, + "tomlify-j0.4": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tomlify-j0.4/-/tomlify-j0.4-2.2.1.tgz", + "integrity": "sha512-0kCocYX8ujnbK6jQ9e+g9GLiCIfVkFaCB3DCTQDP7J79gPVZVmZgQZ/KUNe1a6hUfrmHHaErVGUjedfpaX5EZw==", + "dev": true + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -24372,6 +26100,62 @@ "mime-types": "~2.1.24" } }, + "typechecker": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-4.11.0.tgz", + "integrity": "sha512-lz39Mc/d1UBcF/uQFL5P8L+oWdIn/stvkUgHf0tPRW4aEwGGErewNXo2Nb6We2WslWifn00rhcHbbRWRcTGhuw==", + "dev": true, + "requires": { + "editions": "^2.2.0" + } + }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -24385,14 +26169,14 @@ "dev": true }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, @@ -24561,6 +26345,21 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.2.tgz", + "integrity": "sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "object.getownpropertydescriptors": "^2.1.6", + "safe-array-concat": "^1.0.0" + } + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -24728,6 +26527,12 @@ } } }, + "voc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/voc/-/voc-1.2.0.tgz", + "integrity": "sha512-BOuDjFFYvJdZO6e/N65AlaDItXo2TgyLjeyRYcqgAPkXpp5yTJcvkL2n+syO1r9Qc5g96tfBD2tuiMhYDmaGcA==", + "dev": true + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -24778,6 +26583,19 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", @@ -24800,6 +26618,112 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "xlsjs": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/xlsjs/-/xlsjs-0.7.6.tgz", + "integrity": "sha512-IQtL2z+BVYaIVzEhknZ1YBr8ItUbqiS7kaQZ3O35/k1q+kSgjVxmzwno6r3EbBgEWhrVCad2mKbnFeMmEE5zdw==", + "dev": true, + "requires": { + "cfb": "~0.11.0", + "codepage": "", + "commander": "", + "exit-on-epipe": "", + "ssf": "~0.8.1" + } + }, + "xlsx": { + "version": "0.11.19", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.11.19.tgz", + "integrity": "sha512-UTfD64o5Ka/E6QHL12fzcq5wnt9MCtuwgoUdYSTDxjjDkhNmZwSfPlJH/+Yh8vE6nU/0ax3MXNrc9AP4haAmIg==", + "dev": true, + "requires": { + "adler-32": "~1.2.0", + "cfb": "~1.0.2", + "codepage": "~1.12.0", + "commander": "~2.13.0", + "crc-32": "~1.2.0", + "exit-on-epipe": "~1.0.1", + "ssf": "~0.10.1" + }, + "dependencies": { + "cfb": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.0.8.tgz", + "integrity": "sha512-oA7VomcgZRWTo8V20UYLlXu4ZOCFEAfwwrcxE8PcVzXW12WOhsi38PVnymb6Xoj8y7ghoZQOOOVRBMdLJ4jCjg==", + "dev": true, + "requires": { + "commander": "^2.14.1", + "printj": "~1.1.2" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "codepage": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.12.2.tgz", + "integrity": "sha512-FAN+oPs/ocaPLFvIt4vEOHgWA6UJ6t+fVbbVBoXDpTpC+4JYasomYZEEjR/Miph3qQrVnIShRwwmwu4P35JW1w==", + "dev": true, + "requires": { + "commander": "~2.14.1", + "exit-on-epipe": "~1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", + "dev": true + } + } + }, + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "dev": true + }, + "ssf": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.10.3.tgz", + "integrity": "sha512-pRuUdW0WwyB2doSqqjWyzwCD6PkfxpHAHdZp39K3dp/Hq7f+xfMwNAWIi16DyrRg4gg9c/RvLYkJTSawTPTm1w==", + "dev": true, + "requires": { + "frac": "~1.1.2" + } + } + } + }, + "xml2js": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", + "integrity": "sha512-1O7wk/NTQN0UEOItIYTxK4qP4sMUVU60MbF4Nj0a8jd6eebMXOicVI/KFOEsYKKH4uBpx6XG9ZGZctXK5rtO5Q==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "^4.1.0" + } + }, + "xmlbuilder": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", + "integrity": "sha512-oEePiEefhQhAeUnwRnIBLBWmk/fsWWbQ53EEWsRuzECbQ3m5o/Esmq6H47CYYwSLW+Ynt0rS9hd0pd2ogMAWjg==", + "dev": true, + "requires": { + "lodash": "^4.0.0" + } + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/docs/package.json b/docs/package.json index 9812b2a804..b896479b62 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,7 +13,7 @@ "lint:openapi": "swagger-cli validate ./openapi.yaml", "generate:types": "ts-node ./scripts/generate-types.ts", "generate:schemas": "gulp && npm run generate:types", - "generate:git-info": "npm run generate:git-info --prefix .. && export API_VERSION=$(shx tail -n 1 ../.git-info) && speccy resolve --output .tmp/openapi.resolved.yaml openapi.yaml && shx sed -i 'STACKS_API_VERSION' ${API_VERSION:-1.0.0} .tmp/openapi.resolved.yaml > /dev/null", + "generate:git-info": "npm run generate:git-info --prefix .. && export API_VERSION=$(shx tail -n 1 ../.git-info) && speccy resolve --output .tmp/openapi.resolved.yaml openapi.yaml && shx sed -i 'STACKS_API_VERSION' ${API_VERSION:-1.0.0} .tmp/openapi.resolved.yaml > /dev/null && any-json convert .tmp/openapi.resolved.yaml .tmp/openapi.json", "generate:docs": "redoc-cli bundle --output .tmp/index.html .tmp/openapi.resolved.yaml", "generate:postman": "openapi2postmanv2 --spec .tmp/openapi.resolved.yaml --output .tmp/collection.json --options folderStrategy=Tags,requestParametersResolution=Example,exampleParametersResolution=Example,schemaFaker=false 2>/dev/null", "validate:schemas": "rimraf .tmp && gulp flattenSchemas --silent && ts-node ./scripts/validate-schemas.ts", @@ -40,6 +40,7 @@ "@types/json-schema-merge-allof": "0.6.0", "@types/node": "16.18.3", "ajv": "6.12.6", + "any-json": "^3.1.0", "chalk": "4.1.1", "del": "5.1.0", "glob": "7.1.6", From c2edd17379a467b7366531c1e22f50a225eed0b4 Mon Sep 17 00:00:00 2001 From: Charlie <2747302+CharlieC3@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:14:59 -0500 Subject: [PATCH 52/91] docs: trigger docs.hiro.so refresh on commits to master (#1787) --- .github/workflows/vercel.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/vercel.yml b/.github/workflows/vercel.yml index eec3a9cdc8..8902fa9276 100644 --- a/.github/workflows/vercel.yml +++ b/.github/workflows/vercel.yml @@ -59,6 +59,10 @@ jobs: id: deploy run: vercel ${{ github.ref_name == 'master' && '--prod' || 'deploy' }} --prebuilt --token=${{ secrets.VERCEL_TOKEN }} | awk '{print "deployment_url="$1}' >> $GITHUB_OUTPUT + - name: Trigger docs.hiro.so deployment + if: github.ref_name == 'master' + run: curl -X POST ${{ secrets.VERCEL_DOCS_DEPLOY_HOOK_URL }} + - name: Add comment with Vercel deployment URL if: ${{ github.event_name == 'pull_request' }} uses: thollander/actions-comment-pull-request@v2 From 02119326993891cc586274fab0e0fc3f5fd15ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Fri, 29 Dec 2023 12:52:17 -0600 Subject: [PATCH 53/91] fix: convert `chain_tip` materialized view into a table (#1789) * fix: convert `chain_tip` materialized view into a table (#1751) * feat: chain tip table * fix: handle reorgs * fix: lint --- migrations/1700071472495_chain-tip-table.js | 142 ++++++++++++++++++ src/api/controllers/cache-controller.ts | 6 +- src/api/routes/status.ts | 16 +- src/datastore/common.ts | 23 ++- src/datastore/pg-store.ts | 75 +++------ src/datastore/pg-write-store.ts | 110 +++++++------- src/event-stream/event-server.ts | 4 +- src/tests-event-replay/import-export-tests.ts | 38 ++--- .../poison-microblock-tests.ts | 9 +- src/tests/cache-control-tests.ts | 13 +- src/tests/datastore-tests.ts | 51 +++++-- src/tests/mempool-tests.ts | 2 +- src/tests/microblock-tests.ts | 26 ++-- 13 files changed, 313 insertions(+), 202 deletions(-) create mode 100644 migrations/1700071472495_chain-tip-table.js diff --git a/migrations/1700071472495_chain-tip-table.js b/migrations/1700071472495_chain-tip-table.js new file mode 100644 index 0000000000..dce518a530 --- /dev/null +++ b/migrations/1700071472495_chain-tip-table.js @@ -0,0 +1,142 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.dropMaterializedView('chain_tip'); + pgm.createTable('chain_tip', { + id: { + type: 'bool', + primaryKey: true, + default: true, + }, + block_height: { + type: 'integer', + notNull: true, + }, + block_count: { + type: 'integer', + notNull: true, + }, + block_hash: { + type: 'bytea', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + burn_block_height: { + type: 'integer', + notNull: true, + }, + microblock_hash: { + type: 'bytea', + }, + microblock_sequence: { + type: 'integer', + }, + microblock_count: { + type: 'integer', + notNull: true, + }, + tx_count: { + type: 'integer', + notNull: true, + }, + tx_count_unanchored: { + type: 'integer', + notNull: true, + }, + }); + pgm.addConstraint('chain_tip', 'chain_tip_one_row', 'CHECK(id)'); + pgm.sql(` + WITH block_tip AS ( + SELECT block_height, block_hash, index_block_hash, burn_block_height + FROM blocks + WHERE block_height = (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + microblock_tip AS ( + SELECT microblock_hash, microblock_sequence + FROM microblocks, block_tip + WHERE microblocks.parent_index_block_hash = block_tip.index_block_hash + AND microblock_canonical = true AND canonical = true + ORDER BY microblock_sequence DESC + LIMIT 1 + ), + microblock_count AS ( + SELECT COUNT(*)::INTEGER AS microblock_count + FROM microblocks + WHERE canonical = TRUE AND microblock_canonical = TRUE + ), + tx_count AS ( + SELECT COUNT(*)::INTEGER AS tx_count + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + AND block_height <= (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + tx_count_unanchored AS ( + SELECT COUNT(*)::INTEGER AS tx_count_unanchored + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + ) + INSERT INTO chain_tip (block_height, block_hash, index_block_hash, burn_block_height, + block_count, microblock_hash, microblock_sequence, microblock_count, tx_count, + tx_count_unanchored) + VALUES ( + COALESCE((SELECT block_height FROM block_tip), 0), + COALESCE((SELECT block_hash FROM block_tip), ''), + COALESCE((SELECT index_block_hash FROM block_tip), ''), + COALESCE((SELECT burn_block_height FROM block_tip), 0), + COALESCE((SELECT block_height FROM block_tip), 0), + (SELECT microblock_hash FROM microblock_tip), + (SELECT microblock_sequence FROM microblock_tip), + COALESCE((SELECT microblock_count FROM microblock_count), 0), + COALESCE((SELECT tx_count FROM tx_count), 0), + COALESCE((SELECT tx_count_unanchored FROM tx_count_unanchored), 0) + ) + `); +}; + +exports.down = pgm => { + pgm.dropTable('chain_tip'); + pgm.createMaterializedView('chain_tip', {}, ` + WITH block_tip AS ( + SELECT block_height, block_hash, index_block_hash, burn_block_height + FROM blocks + WHERE block_height = (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + microblock_tip AS ( + SELECT microblock_hash, microblock_sequence + FROM microblocks, block_tip + WHERE microblocks.parent_index_block_hash = block_tip.index_block_hash + AND microblock_canonical = true AND canonical = true + ORDER BY microblock_sequence DESC + LIMIT 1 + ), + microblock_count AS ( + SELECT COUNT(*)::INTEGER AS microblock_count + FROM microblocks + WHERE canonical = TRUE AND microblock_canonical = TRUE + ), + tx_count AS ( + SELECT COUNT(*)::INTEGER AS tx_count + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + AND block_height <= (SELECT MAX(block_height) FROM blocks WHERE canonical = TRUE) + ), + tx_count_unanchored AS ( + SELECT COUNT(*)::INTEGER AS tx_count_unanchored + FROM txs + WHERE canonical = TRUE AND microblock_canonical = TRUE + ) + SELECT *, block_tip.block_height AS block_count + FROM block_tip + LEFT JOIN microblock_tip ON TRUE + LEFT JOIN microblock_count ON TRUE + LEFT JOIN tx_count ON TRUE + LEFT JOIN tx_count_unanchored ON TRUE + LIMIT 1 + `); + pgm.createIndex('chain_tip', 'block_height', { unique: true }); +}; diff --git a/src/api/controllers/cache-controller.ts b/src/api/controllers/cache-controller.ts index b8d6e6d8df..648969d9d2 100644 --- a/src/api/controllers/cache-controller.ts +++ b/src/api/controllers/cache-controller.ts @@ -251,13 +251,13 @@ async function calculateETag( switch (etagType) { case ETagType.chainTip: try { - const chainTip = await db.getUnanchoredChainTip(); - if (!chainTip.found) { + const chainTip = await db.getChainTip(); + if (chainTip.block_height === 0) { // This should never happen unless the API is serving requests before it has synced any // blocks. return; } - return chainTip.result.microblockHash ?? chainTip.result.indexBlockHash; + return chainTip.microblock_hash ?? chainTip.index_block_hash; } catch (error) { logger.error(error, 'Unable to calculate chain_tip ETag'); return; diff --git a/src/api/routes/status.ts b/src/api/routes/status.ts index 3c8f7c415f..6d0d9abf52 100644 --- a/src/api/routes/status.ts +++ b/src/api/routes/status.ts @@ -18,15 +18,15 @@ export function createStatusRouter(db: PgStore): express.Router { response.pox_v1_unlock_height = poxForceUnlockHeights.result.pox1UnlockHeight as number; response.pox_v2_unlock_height = poxForceUnlockHeights.result.pox2UnlockHeight as number; } - const chainTip = await db.getUnanchoredChainTip(); - if (chainTip.found) { + const chainTip = await db.getChainTip(); + if (chainTip.block_height > 0) { response.chain_tip = { - block_height: chainTip.result.blockHeight, - block_hash: chainTip.result.blockHash, - index_block_hash: chainTip.result.indexBlockHash, - microblock_hash: chainTip.result.microblockHash, - microblock_sequence: chainTip.result.microblockSequence, - burn_block_height: chainTip.result.burnBlockHeight, + block_height: chainTip.block_height, + block_hash: chainTip.block_hash, + index_block_hash: chainTip.index_block_hash, + microblock_hash: chainTip.microblock_hash, + microblock_sequence: chainTip.microblock_sequence, + burn_block_height: chainTip.burn_block_height, }; } setETagCacheHeaders(res); diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 7cef586547..7378ac50f1 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -743,15 +743,6 @@ export type BlockIdentifier = | { burnBlockHash: string } | { burnBlockHeight: number }; -export interface DbChainTip { - blockHeight: number; - indexBlockHash: string; - blockHash: string; - microblockHash?: string; - microblockSequence?: number; - burnBlockHeight: number; -} - export interface BlockQueryResult { block_hash: string; index_block_hash: string; @@ -1455,8 +1446,14 @@ export interface SmartContractInsertValues { } export interface DbChainTip { - blockHeight: number; - blockHash: string; - indexBlockHash: string; - burnBlockHeight: number; + block_height: number; + block_count: number; + block_hash: string; + index_block_hash: string; + burn_block_height: number; + microblock_hash?: string; + microblock_sequence?: number; + microblock_count: number; + tx_count: number; + tx_count_unanchored: number; } diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 7bf9b9564a..e33acd8651 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -252,28 +252,20 @@ export class PgStore { }); } - async getChainTip( - sql: PgSqlClient - ): Promise<{ - blockHeight: number; - blockHash: string; - indexBlockHash: string; - burnBlockHeight: number; - }> { - const currentTipBlock = await sql< - { - block_height: number; - block_hash: string; - index_block_hash: string; - burn_block_height: number; - }[] - >`SELECT block_height, block_hash, index_block_hash, burn_block_height FROM chain_tip`; - const height = currentTipBlock[0]?.block_height ?? 0; + async getChainTip(): Promise { + const tipResult = await this.sql`SELECT * FROM chain_tip`; + const tip = tipResult[0]; return { - blockHeight: height, - blockHash: currentTipBlock[0]?.block_hash ?? '', - indexBlockHash: currentTipBlock[0]?.index_block_hash ?? '', - burnBlockHeight: currentTipBlock[0]?.burn_block_height ?? 0, + block_height: tip?.block_height ?? 0, + block_count: tip?.block_count ?? 0, + block_hash: tip?.block_hash ?? '', + index_block_hash: tip?.index_block_hash ?? '', + burn_block_height: tip?.burn_block_height ?? 0, + microblock_hash: tip?.microblock_hash ?? undefined, + microblock_sequence: tip?.microblock_sequence ?? undefined, + microblock_count: tip?.microblock_count ?? 0, + tx_count: tip?.tx_count ?? 0, + tx_count_unanchored: tip?.tx_count_unanchored ?? 0, }; } @@ -368,33 +360,6 @@ export class PgStore { return this.getPoxForcedUnlockHeightsInternal(this.sql); } - async getUnanchoredChainTip(): Promise> { - const result = await this.sql< - { - block_height: number; - index_block_hash: string; - block_hash: string; - microblock_hash: string | null; - microblock_sequence: number | null; - burn_block_height: number; - }[] - >`SELECT block_height, index_block_hash, block_hash, microblock_hash, microblock_sequence, burn_block_height - FROM chain_tip`; - if (result.length === 0) { - return { found: false } as const; - } - const row = result[0]; - const chainTipResult: DbChainTip = { - blockHeight: row.block_height, - indexBlockHash: row.index_block_hash, - blockHash: row.block_hash, - microblockHash: row.microblock_hash === null ? undefined : row.microblock_hash, - microblockSequence: row.microblock_sequence === null ? undefined : row.microblock_sequence, - burnBlockHeight: row.burn_block_height, - }; - return { found: true, result: chainTipResult }; - } - async getBlock(blockIdentifer: BlockIdentifier): Promise> { return this.getBlockInternal(this.sql, blockIdentifer); } @@ -678,8 +643,8 @@ export class PgStore { async getUnanchoredTxsInternal(sql: PgSqlClient): Promise<{ txs: DbTx[] }> { // Get transactions that have been streamed in microblocks but not yet accepted or rejected in an anchor block. - const { blockHeight } = await this.getChainTip(sql); - const unanchoredBlockHeight = blockHeight + 1; + const { block_height } = await this.getChainTip(); + const unanchoredBlockHeight = block_height + 1; const query = await sql` SELECT ${unsafeCols(sql, [...TX_COLUMNS, abiColumn()])} FROM txs @@ -1426,11 +1391,11 @@ export class PgStore { sql: PgSqlClient, { includeUnanchored }: { includeUnanchored: boolean } ): Promise { - const chainTip = await this.getChainTip(sql); + const chainTip = await this.getChainTip(); if (includeUnanchored) { - return chainTip.blockHeight + 1; + return chainTip.block_height + 1; } else { - return chainTip.blockHeight; + return chainTip.block_height; } } @@ -2213,9 +2178,9 @@ export class PgStore { async getStxBalanceAtBlock(stxAddress: string, blockHeight: number): Promise { return await this.sqlTransaction(async sql => { - const chainTip = await this.getChainTip(sql); + const chainTip = await this.getChainTip(); const blockHeightToQuery = - blockHeight > chainTip.blockHeight ? chainTip.blockHeight : blockHeight; + blockHeight > chainTip.block_height ? chainTip.block_height : blockHeight; const blockQuery = await this.getBlockByHeightInternal(sql, blockHeightToQuery); if (!blockQuery.found) { throw new Error(`Could not find block at height: ${blockHeight}`); diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 870d92f4c3..f2224c99c9 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -148,33 +148,6 @@ export class PgWriteStore extends PgStore { return super.sqlTransaction(callback, false); } - async getChainTip(sql: PgSqlClient, useMaterializedView = true): Promise { - if (!this.isEventReplay && useMaterializedView) { - return super.getChainTip(sql); - } - // The `chain_tip` materialized view is not available during event replay. - // Since `getChainTip()` is used heavily during event ingestion, we'll fall back to - // a classic query. - const currentTipBlock = await sql< - { - block_height: number; - block_hash: string; - index_block_hash: string; - burn_block_height: number; - }[] - >` - SELECT block_height, block_hash, index_block_hash, burn_block_height - FROM blocks - WHERE canonical = true AND block_height = (SELECT MAX(block_height) FROM blocks) - `; - return { - blockHeight: currentTipBlock[0]?.block_height ?? 0, - blockHash: currentTipBlock[0]?.block_hash ?? '', - indexBlockHash: currentTipBlock[0]?.index_block_hash ?? '', - burnBlockHeight: currentTipBlock[0]?.burn_block_height ?? 0, - }; - } - async storeRawEventRequest(eventPath: string, payload: PgJsonb): Promise { // To avoid depending on the DB more than once and to allow the query transaction to settle, // we'll take the complete insert result and move that to the output TSV file instead of taking @@ -205,10 +178,10 @@ export class PgWriteStore extends PgStore { const contractLogEvents: DbSmartContractEvent[] = []; await this.sqlWriteTransaction(async sql => { - const chainTip = await this.getChainTip(sql, false); - await this.handleReorg(sql, data.block, chainTip.blockHeight); + const chainTip = await this.getChainTip(); + await this.handleReorg(sql, data.block, chainTip.block_height); // If the incoming block is not of greater height than current chain tip, then store data as non-canonical. - const isCanonical = data.block.block_height > chainTip.blockHeight; + const isCanonical = data.block.block_height > chainTip.block_height; if (!isCanonical) { data.block = { ...data.block, canonical: false }; data.microblocks = data.microblocks.map(mb => ({ ...mb, canonical: false })); @@ -424,12 +397,27 @@ export class PgWriteStore extends PgStore { const mempoolStats = await this.getMempoolStatsInternal({ sql }); this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); } + if (isCanonical) + await sql` + WITH new_tx_count AS ( + SELECT tx_count + ${data.txs.length} AS tx_count FROM chain_tip + ) + UPDATE chain_tip SET + block_height = ${data.block.block_height}, + block_hash = ${data.block.block_hash}, + index_block_hash = ${data.block.index_block_hash}, + burn_block_height = ${data.block.burn_block_height}, + microblock_hash = NULL, + microblock_sequence = NULL, + block_count = ${data.block.block_height}, + tx_count = (SELECT tx_count FROM new_tx_count), + tx_count_unanchored = (SELECT tx_count FROM new_tx_count) + `; }); // Do we have an IBD height defined in ENV? If so, check if this block update reached it. const ibdHeight = getIbdBlockHeight(); this.isIbdBlockHeightReached = ibdHeight ? data.block.block_height > ibdHeight : true; - await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); // Skip sending `PgNotifier` updates altogether if we're in the genesis block since this block is the @@ -578,12 +566,12 @@ export class PgWriteStore extends PgStore { const contractLogEvents: DbSmartContractEvent[] = []; await this.sqlWriteTransaction(async sql => { - // Sanity check: ensure incoming microblocks have a `parent_index_block_hash` that matches the API's - // current known canonical chain tip. We assume this holds true so incoming microblock data is always - // treated as being built off the current canonical anchor block. - const chainTip = await this.getChainTip(sql, false); + // Sanity check: ensure incoming microblocks have a `parent_index_block_hash` that matches the + // API's current known canonical chain tip. We assume this holds true so incoming microblock + // data is always treated as being built off the current canonical anchor block. + const chainTip = await this.getChainTip(); const nonCanonicalMicroblock = data.microblocks.find( - mb => mb.parent_index_block_hash !== chainTip.indexBlockHash + mb => mb.parent_index_block_hash !== chainTip.index_block_hash ); // Note: the stacks-node event emitter can send old microblocks that have already been processed by a previous anchor block. // Log warning and return, nothing to do. @@ -591,13 +579,13 @@ export class PgWriteStore extends PgStore { logger.info( `Failure in microblock ingestion, microblock ${nonCanonicalMicroblock.microblock_hash} ` + `points to parent index block hash ${nonCanonicalMicroblock.parent_index_block_hash} rather ` + - `than the current canonical tip's index block hash ${chainTip.indexBlockHash}.` + `than the current canonical tip's index block hash ${chainTip.index_block_hash}.` ); return; } // The block height is just one after the current chain tip height - const blockHeight = chainTip.blockHeight + 1; + const blockHeight = chainTip.block_height + 1; dbMicroblocks = data.microblocks.map(mb => { const dbMicroBlock: DbMicroblock = { canonical: true, @@ -610,8 +598,8 @@ export class PgWriteStore extends PgStore { parent_burn_block_hash: mb.parent_burn_block_hash, parent_burn_block_time: mb.parent_burn_block_time, block_height: blockHeight, - parent_block_height: chainTip.blockHeight, - parent_block_hash: chainTip.blockHash, + parent_block_height: chainTip.block_height, + parent_block_hash: chainTip.block_hash, index_block_hash: '', // Empty until microblock is confirmed in an anchor block block_hash: '', // Empty until microblock is confirmed in an anchor block }; @@ -623,7 +611,7 @@ export class PgWriteStore extends PgStore { // block with that data doesn't yet exist. const dbTx: DbTxRaw = { ...entry.tx, - parent_block_hash: chainTip.blockHash, + parent_block_hash: chainTip.block_hash, block_height: blockHeight, }; @@ -703,9 +691,20 @@ export class PgWriteStore extends PgStore { const mempoolStats = await this.getMempoolStatsInternal({ sql }); this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); } + if (currentMicroblockTip.microblock_canonical) + await sql` + UPDATE chain_tip SET + microblock_hash = ${currentMicroblockTip.microblock_hash}, + microblock_sequence = ${currentMicroblockTip.microblock_sequence}, + microblock_count = microblock_count + ${data.microblocks.length}, + tx_count_unanchored = ${ + currentMicroblockTip.microblock_sequence === 0 + ? sql`tx_count + ${data.txs.length}` + : sql`tx_count_unanchored + ${data.txs.length}` + } + `; }); - await this.refreshMaterializedView('chain_tip'); await this.refreshMaterializedView('mempool_digest'); if (this.notifier) { @@ -1670,7 +1669,7 @@ export class PgWriteStore extends PgStore { anchor_mode: tx.anchor_mode, status: tx.status, receipt_time: tx.receipt_time, - receipt_block_height: chainTip.blockHeight, + receipt_block_height: chainTip.block_height, post_conditions: tx.post_conditions, nonce: tx.nonce, fee_rate: tx.fee_rate, @@ -1709,7 +1708,7 @@ export class PgWriteStore extends PgStore { async updateMempoolTxs({ mempoolTxs: txs }: { mempoolTxs: DbMempoolTxRaw[] }): Promise { const updatedTxIds: string[] = []; await this.sqlWriteTransaction(async sql => { - const chainTip = await this.getChainTip(sql, false); + const chainTip = await this.getChainTip(); for (const tx of txs) { const inserted = await this.insertDbMempoolTx(tx, chainTip, sql); if (inserted) { @@ -2187,6 +2186,12 @@ export class PgWriteStore extends PgStore { }); } + // Update unanchored tx count in `chain_tip` table + const txCountDelta = updatedMbTxs.length * (args.isMicroCanonical ? 1 : -1); + await sql` + UPDATE chain_tip SET tx_count_unanchored = tx_count_unanchored + ${txCountDelta} + `; + return { updatedTxs: updatedMbTxs }; } @@ -2802,6 +2807,14 @@ export class PgWriteStore extends PgStore { await this.restoreOrphanedChain(sql, parentResult[0].index_block_hash, updatedEntities); this.logReorgResultInfo(updatedEntities); } + // Reflect updated transaction totals in `chain_tip` table. + const txCountDelta = + updatedEntities.markedCanonical.txs - updatedEntities.markedNonCanonical.txs; + await sql` + UPDATE chain_tip SET + tx_count = tx_count + ${txCountDelta}, + tx_count_unanchored = tx_count_unanchored + ${txCountDelta} + `; } return updatedEntities; } @@ -2886,12 +2899,7 @@ export class PgWriteStore extends PgStore { * Called when a full event import is complete. */ async finishEventReplay() { - if (!this.isEventReplay) { - return; - } - await this.sqlWriteTransaction(async sql => { - await this.refreshMaterializedView('chain_tip', sql, false); - await this.refreshMaterializedView('mempool_digest', sql, false); - }); + if (!this.isEventReplay) return; + await this.refreshMaterializedView('mempool_digest', this.sql, false); } } diff --git a/src/event-stream/event-server.ts b/src/event-stream/event-server.ts index 7b45e1715e..5f6479ac01 100644 --- a/src/event-stream/event-server.ts +++ b/src/event-stream/event-server.ts @@ -848,8 +848,8 @@ export async function startEventServer(opts: { if (ibdHeight) { app.use(IBD_PRUNABLE_ROUTES, async (req, res, next) => { try { - const chainTip = await db.getChainTip(db.sql, false); - if (chainTip.blockHeight > ibdHeight) { + const chainTip = await db.getChainTip(); + if (chainTip.block_height > ibdHeight) { next(); } else { handleRawEventRequest(req, res, next); diff --git a/src/tests-event-replay/import-export-tests.ts b/src/tests-event-replay/import-export-tests.ts index ee6bd96e12..a43d5bd87d 100644 --- a/src/tests-event-replay/import-export-tests.ts +++ b/src/tests-event-replay/import-export-tests.ts @@ -30,13 +30,12 @@ describe('import/export tests', () => { test('event import and export cycle', async () => { // Import from mocknet TSV await importEventsFromTsv('src/tests-event-replay/tsv/mocknet.tsv', 'archival', true, true); - const chainTip = await db.getUnanchoredChainTip(); - expect(chainTip.found).toBe(true); - expect(chainTip.result?.blockHeight).toBe(28); - expect(chainTip.result?.indexBlockHash).toBe( + const chainTip = await db.getChainTip(); + expect(chainTip.block_height).toBe(28); + expect(chainTip.index_block_hash).toBe( '0x76cd67a65c0dfd5ea450bb9efe30da89fa125bfc077c953802f718353283a533' ); - expect(chainTip.result?.blockHash).toBe( + expect(chainTip.block_hash).toBe( '0x7682af212d3c1ef62613412f9b5a727269b4548f14eca2e3f941f7ad8b3c11b2' ); @@ -53,13 +52,12 @@ describe('import/export tests', () => { // Re-import with exported TSV and check that chain tip matches. try { await importEventsFromTsv(`${tmpDir}/export.tsv`, 'archival', true, true); - const newChainTip = await db.getUnanchoredChainTip(); - expect(newChainTip.found).toBe(true); - expect(newChainTip.result?.blockHeight).toBe(28); - expect(newChainTip.result?.indexBlockHash).toBe( + const newChainTip = await db.getChainTip(); + expect(newChainTip.block_height).toBe(28); + expect(newChainTip.index_block_hash).toBe( '0x76cd67a65c0dfd5ea450bb9efe30da89fa125bfc077c953802f718353283a533' ); - expect(newChainTip.result?.blockHash).toBe( + expect(newChainTip.block_hash).toBe( '0x7682af212d3c1ef62613412f9b5a727269b4548f14eca2e3f941f7ad8b3c11b2' ); } finally { @@ -200,30 +198,14 @@ describe('IBD', () => { process.env.IBD_MODE_UNTIL_BLOCK = '1000'; // TSV has 1 microblock message. await expect(getIbdInterceptCountFromTsvEvents()).resolves.toBe(1); - await expect(db.getChainTip(client, false)).resolves.toHaveProperty('blockHeight', 28); + await expect(db.getChainTip()).resolves.toHaveProperty('block_height', 28); }); test('IBD mode does NOT block certain API routes once the threshold number of blocks are ingested', async () => { process.env.IBD_MODE_UNTIL_BLOCK = '1'; // Microblock processed normally. await expect(getIbdInterceptCountFromTsvEvents()).resolves.toBe(0); - await expect(db.getChainTip(client, false)).resolves.toHaveProperty('blockHeight', 28); - }); - - test('IBD mode prevents refreshing materialized views', async () => { - process.env.IBD_MODE_UNTIL_BLOCK = '1000'; - await getIbdInterceptCountFromTsvEvents(); - await db.refreshMaterializedView('chain_tip', client); - const res = await db.sql<{ block_height: number }[]>`SELECT * FROM chain_tip`; - expect(res.count).toBe(0); - }); - - test('IBD mode allows refreshing materialized views after height has passed', async () => { - process.env.IBD_MODE_UNTIL_BLOCK = '10'; - await getIbdInterceptCountFromTsvEvents(); - await db.refreshMaterializedView('chain_tip', client); - const res = await db.sql<{ block_height: number }[]>`SELECT * FROM chain_tip`; - expect(res[0].block_height).toBe(28); + await expect(db.getChainTip()).resolves.toHaveProperty('block_height', 28); }); test('IBD mode covers prune mode', async () => { diff --git a/src/tests-event-replay/poison-microblock-tests.ts b/src/tests-event-replay/poison-microblock-tests.ts index 73a40cbefa..27cda9f3f0 100644 --- a/src/tests-event-replay/poison-microblock-tests.ts +++ b/src/tests-event-replay/poison-microblock-tests.ts @@ -26,22 +26,21 @@ describe('poison microblock for height 80743', () => { true ); const poisonTxId = '0x58ffe62029f94f7101b959536ea4953b9bce0ec3f6e2a06254c511bdd5cfa9e7'; - const chainTip = await db.getUnanchoredChainTip(); + const chainTip = await db.getChainTip(); // query the txs table and check the transaction type const searchResult = await db.searchHash({ hash: poisonTxId }); let entityData: any; if (searchResult.result?.entity_data) { entityData = searchResult.result?.entity_data; } - expect(chainTip.found).toBe(true); // check the transaction type to be contract call for this poison block expect(entityData.type_id).toBe(DbTxTypeId.ContractCall); expect(searchResult.found).toBe(true); - expect(chainTip.result?.blockHeight).toBe(1); - expect(chainTip.result?.indexBlockHash).toBe( + expect(chainTip.block_height).toBe(1); + expect(chainTip.index_block_hash).toBe( '0x05ca75b9949195da435e6e36d731dbaa10bb75fda576a52263e25164990bfdaa' ); - expect(chainTip.result?.blockHash).toBe( + expect(chainTip.block_hash).toBe( '0x6b83b44571365e6e530d679536578c71d6c376b07666f3671786b6fd8fac049c' ); }); diff --git a/src/tests/cache-control-tests.ts b/src/tests/cache-control-tests.ts index 76c32ad48d..0718f0574b 100644 --- a/src/tests/cache-control-tests.ts +++ b/src/tests/cache-control-tests.ts @@ -314,13 +314,12 @@ describe('cache-control tests', () => { ], }); - const chainTip2 = await db.getUnanchoredChainTip(); - expect(chainTip2.found).toBeTruthy(); - expect(chainTip2.result?.blockHash).toBe(block1.block_hash); - expect(chainTip2.result?.blockHeight).toBe(block1.block_height); - expect(chainTip2.result?.indexBlockHash).toBe(block1.index_block_hash); - expect(chainTip2.result?.microblockHash).toBe(mb1.microblock_hash); - expect(chainTip2.result?.microblockSequence).toBe(mb1.microblock_sequence); + const chainTip2 = await db.getChainTip(); + expect(chainTip2.block_hash).toBe(block1.block_hash); + expect(chainTip2.block_height).toBe(block1.block_height); + expect(chainTip2.index_block_hash).toBe(block1.index_block_hash); + expect(chainTip2.microblock_hash).toBe(mb1.microblock_hash); + expect(chainTip2.microblock_sequence).toBe(mb1.microblock_sequence); const expectedResp2 = { burn_block_time: 1594647996, diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index 116570da49..c54d1a9164 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -4010,6 +4010,7 @@ describe('postgres datastore', () => { contract_name: 'pox', }; + // Start canonical chain await db.update({ block: block1, microblocks: [], @@ -4230,6 +4231,7 @@ describe('postgres datastore', () => { abi: '{"thing":1}', }; + // Insert non-canonical block await db.update({ block: block2b, microblocks: [], @@ -4327,12 +4329,18 @@ describe('postgres datastore', () => { const blockQuery1 = await db.getBlock({ hash: block2b.block_hash }); expect(blockQuery1.result?.canonical).toBe(false); - const chainTip1 = await db.getChainTip(client); + const chainTip1 = await db.getChainTip(); expect(chainTip1).toEqual({ - blockHash: '0x33', - blockHeight: 3, - indexBlockHash: '0xcc', - burnBlockHeight: 123, + block_hash: '0x33', + block_height: 3, + index_block_hash: '0xcc', + burn_block_height: 123, + block_count: 3, + microblock_count: 0, + microblock_hash: undefined, + microblock_sequence: undefined, + tx_count: 2, // Tx from block 2b does not count + tx_count_unanchored: 2, }); const namespaces = await db.getNamespaceList({ includeUnanchored: false }); expect(namespaces.results.length).toBe(1); @@ -4386,12 +4394,19 @@ describe('postgres datastore', () => { await db.update({ block: block3b, microblocks: [], minerRewards: [], txs: [] }); const blockQuery2 = await db.getBlock({ hash: block3b.block_hash }); expect(blockQuery2.result?.canonical).toBe(false); - const chainTip2 = await db.getChainTip(client); + // Chain tip doesn't change yet. + const chainTip2 = await db.getChainTip(); expect(chainTip2).toEqual({ - blockHash: '0x33', - blockHeight: 3, - indexBlockHash: '0xcc', - burnBlockHeight: 123, + block_hash: '0x33', + block_height: 3, + index_block_hash: '0xcc', + burn_block_height: 123, + block_count: 3, + microblock_count: 0, + microblock_hash: undefined, + microblock_sequence: undefined, + tx_count: 2, + tx_count_unanchored: 2, }); const block4b: DbBlock = { @@ -4429,12 +4444,18 @@ describe('postgres datastore', () => { const blockQuery3 = await db.getBlock({ hash: block3b.block_hash }); expect(blockQuery3.result?.canonical).toBe(true); - const chainTip3 = await db.getChainTip(client); + const chainTip3 = await db.getChainTip(); expect(chainTip3).toEqual({ - blockHash: '0x44bb', - blockHeight: 4, - indexBlockHash: '0xddbb', - burnBlockHeight: 123, + block_count: 4, + block_hash: '0x44bb', + block_height: 4, + burn_block_height: 123, + index_block_hash: '0xddbb', + microblock_count: 0, + microblock_hash: undefined, + microblock_sequence: undefined, + tx_count: 2, // Tx from block 2b now counts, but compensates with tx from block 2 + tx_count_unanchored: 2, }); const b1 = await db.getBlock({ hash: block1.block_hash }); diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index eb189a729d..b31952e829 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1488,7 +1488,7 @@ describe('mempool tests', () => { // Simulate the bug with a txs being in the mempool at confirmed at the same time by // directly inserting the mempool-tx and mined-tx, bypassing the normal update functions. await db.updateBlock(db.sql, dbBlock1); - const chainTip = await db.getChainTip(db.sql); + const chainTip = await db.getChainTip(); await db.insertDbMempoolTx(mempoolTx, chainTip, db.sql); await db.updateTx(db.sql, dbTx1); diff --git a/src/tests/microblock-tests.ts b/src/tests/microblock-tests.ts index 2dde14047f..9775d71814 100644 --- a/src/tests/microblock-tests.ts +++ b/src/tests/microblock-tests.ts @@ -380,13 +380,12 @@ describe('microblock tests', () => { ], }); - const chainTip1 = await db.getUnanchoredChainTip(); - expect(chainTip1.found).toBeTruthy(); - expect(chainTip1.result?.blockHash).toBe(block1.block_hash); - expect(chainTip1.result?.blockHeight).toBe(block1.block_height); - expect(chainTip1.result?.indexBlockHash).toBe(block1.index_block_hash); - expect(chainTip1.result?.microblockHash).toBeUndefined(); - expect(chainTip1.result?.microblockSequence).toBeUndefined(); + const chainTip1 = await db.getChainTip(); + expect(chainTip1.block_hash).toBe(block1.block_hash); + expect(chainTip1.block_height).toBe(block1.block_height); + expect(chainTip1.index_block_hash).toBe(block1.index_block_hash); + expect(chainTip1.microblock_hash).toBeUndefined(); + expect(chainTip1.microblock_sequence).toBeUndefined(); const mb1: DbMicroblockPartial = { microblock_hash: '0xff01', @@ -542,13 +541,12 @@ describe('microblock tests', () => { ], }); - const chainTip2 = await db.getUnanchoredChainTip(); - expect(chainTip2.found).toBeTruthy(); - expect(chainTip2.result?.blockHash).toBe(block1.block_hash); - expect(chainTip2.result?.blockHeight).toBe(block1.block_height); - expect(chainTip2.result?.indexBlockHash).toBe(block1.index_block_hash); - expect(chainTip2.result?.microblockHash).toBe(mb1.microblock_hash); - expect(chainTip2.result?.microblockSequence).toBe(mb1.microblock_sequence); + const chainTip2 = await db.getChainTip(); + expect(chainTip2.block_hash).toBe(block1.block_hash); + expect(chainTip2.block_height).toBe(block1.block_height); + expect(chainTip2.index_block_hash).toBe(block1.index_block_hash); + expect(chainTip2.microblock_hash).toBe(mb1.microblock_hash); + expect(chainTip2.microblock_sequence).toBe(mb1.microblock_sequence); const txListResult1 = await supertest(api.server).get(`/extended/v1/tx`); const { body: txListBody1 }: { body: TransactionResults } = txListResult1; From 750817fbf015c0dd563e5cd35d01781689a3d036 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 29 Dec 2023 21:28:34 +0000 Subject: [PATCH 54/91] chore(release): 7.3.7-beta.1 [skip ci] ## [7.3.7-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.6...v7.3.7-beta.1) (2023-12-29) ### Bug Fixes * convert `chain_tip` materialized view into a table ([#1789](https://github.com/hirosystems/stacks-blockchain-api/issues/1789)) ([0211932](https://github.com/hirosystems/stacks-blockchain-api/commit/02119326993891cc586274fab0e0fc3f5fd15ef1)), closes [#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751) * release pino logger and mempool nonces ([16d3593](https://github.com/hirosystems/stacks-blockchain-api/commit/16d359370b413de36444d15a3a48cf479823367f)) --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cb240504b..635d4d6702 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [7.3.7-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.6...v7.3.7-beta.1) (2023-12-29) + + +### Bug Fixes + +* convert `chain_tip` materialized view into a table ([#1789](https://github.com/hirosystems/stacks-blockchain-api/issues/1789)) ([0211932](https://github.com/hirosystems/stacks-blockchain-api/commit/02119326993891cc586274fab0e0fc3f5fd15ef1)), closes [#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751) +* release pino logger and mempool nonces ([16d3593](https://github.com/hirosystems/stacks-blockchain-api/commit/16d359370b413de36444d15a3a48cf479823367f)) + ## [7.3.6](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.5...v7.3.6) (2023-12-11) From b5e8687e0002d509ce8ee6bb9aa16c56fd3b19a7 Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Fri, 29 Dec 2023 15:29:23 -0600 Subject: [PATCH 55/91] ci: upgrade github action versions --- .github/workflows/ci.yml | 102 +++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 474ce39bad..d3dc46e38e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,15 +18,15 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -57,17 +57,17 @@ jobs: run: working-directory: ./docs steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -104,15 +104,15 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -171,15 +171,15 @@ jobs: test-event-replay: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -227,15 +227,15 @@ jobs: test-rpc: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -286,15 +286,15 @@ jobs: test-btc-faucet: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -345,15 +345,15 @@ jobs: test-bns: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -404,15 +404,15 @@ jobs: test-subnets: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -463,15 +463,15 @@ jobs: test-bns-e2e: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -540,15 +540,15 @@ jobs: ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -599,15 +599,15 @@ jobs: test-rosetta: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -658,15 +658,15 @@ jobs: test-rosetta-construction: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -717,15 +717,15 @@ jobs: test-rosetta-cli-data: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -784,15 +784,15 @@ jobs: test-rosetta-cli-construction: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" - name: Cache node modules - uses: actions/cache@v2 + uses: actions/cache@v3 env: cache-name: cache-node-modules with: @@ -859,13 +859,13 @@ jobs: - test-rosetta - test-rosetta-cli-construction steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: token: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }} fetch-depth: 0 persist-credentials: false - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v4 with: node-version-file: ".nvmrc" @@ -887,11 +887,11 @@ jobs: conventional-changelog-conventionalcommits@6.1.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v3 - name: Docker Meta id: meta - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v5 with: images: | blockstack/${{ github.event.repository.name }} @@ -905,7 +905,7 @@ jobs: - name: Docker Standalone Meta id: meta_standalone - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v5 with: images: | blockstack/${{ github.event.repository.name }}-standalone @@ -918,13 +918,13 @@ jobs: type=raw,value=latest,enable={{is_default_branch}} - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Build/Tag/Push Image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: context: . tags: ${{ steps.meta.outputs.tags }} @@ -933,7 +933,7 @@ jobs: push: ${{ (github.ref != 'refs/heads/master' || steps.semantic.outputs.new_release_version != '') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} - name: Build/Tag/Push Standalone Image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v5 with: context: . build-args: | @@ -946,7 +946,7 @@ jobs: - name: API Discord notification if: steps.semantic.outputs.new_release_version != '' - uses: Ilshidur/action-discord@f1ed8844d9b33c17221fab0f36672cde39800eed + uses: Ilshidur/action-discord@master env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_API_WEBHOOK }} DISCORD_USERNAME: Hiro Team From aa287f8b6f6a4dbf872388a16c540ebf32085a52 Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Fri, 29 Dec 2023 15:36:35 -0600 Subject: [PATCH 56/91] ci: upgrade codecov github action --- .github/workflows/ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3dc46e38e..23bd5373ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,7 +157,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -213,7 +213,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -272,7 +272,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -331,7 +331,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -390,7 +390,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -449,7 +449,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -508,7 +508,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -585,7 +585,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -644,7 +644,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -703,7 +703,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -770,7 +770,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls @@ -837,7 +837,7 @@ jobs: if: always() - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: always() - name: Upload coverage to Coveralls From ce9b38f051216d149375d64b3dfb90a75ab50fcd Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Mon, 1 Jan 2024 14:39:25 +0100 Subject: [PATCH 57/91] fix: handle `Problematic` status in `/drop_mempool_tx` event (#1790) --- .../transaction-status.schema.json | 2 +- docs/generated.d.ts | 3 +- src/api/controllers/db-controller.ts | 2 + src/datastore/common.ts | 2 + src/datastore/helpers.ts | 2 + src/datastore/pg-store.ts | 1 + src/event-stream/core-node-message.ts | 3 +- src/tests/mempool-tests.ts | 42 ++++++++++++++++++- 8 files changed, 52 insertions(+), 5 deletions(-) diff --git a/docs/entities/mempool-transactions/transaction-status.schema.json b/docs/entities/mempool-transactions/transaction-status.schema.json index 660609ca3a..e19bfed18d 100644 --- a/docs/entities/mempool-transactions/transaction-status.schema.json +++ b/docs/entities/mempool-transactions/transaction-status.schema.json @@ -2,5 +2,5 @@ "title": "MempoolTransactionStatus", "description": "Status of the transaction", "type": "string", - "enum": ["pending", "dropped_replace_by_fee", "dropped_replace_across_fork", "dropped_too_expensive", "dropped_stale_garbage_collect"] + "enum": ["pending", "dropped_replace_by_fee", "dropped_replace_across_fork", "dropped_too_expensive", "dropped_stale_garbage_collect", "dropped_problematic"] } diff --git a/docs/generated.d.ts b/docs/generated.d.ts index 933fe0dc8d..9af2ccf670 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -569,7 +569,8 @@ export type MempoolTransactionStatus = | "dropped_replace_by_fee" | "dropped_replace_across_fork" | "dropped_too_expensive" - | "dropped_stale_garbage_collect"; + | "dropped_stale_garbage_collect" + | "dropped_problematic"; /** * Describes representation of a Type-1 Stacks 2.0 transaction. https://github.com/blockstack/stacks-blockchain/blob/master/sip/sip-005-blocks-and-transactions.md#type-1-instantiating-a-smart-contract */ diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index eecf271f89..8ca8da73a3 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -161,6 +161,8 @@ function getTxStatusString(txStatus: DbTxStatus): TransactionStatus | MempoolTra return 'dropped_replace_across_fork'; case DbTxStatus.DroppedTooExpensive: return 'dropped_too_expensive'; + case DbTxStatus.DroppedProblematic: + return 'dropped_problematic'; case DbTxStatus.DroppedStaleGarbageCollect: case DbTxStatus.DroppedApiGarbageCollect: return 'dropped_stale_garbage_collect'; diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 981fa6a7ef..da91913919 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -117,6 +117,8 @@ export enum DbTxStatus { DroppedStaleGarbageCollect = -13, /** Dropped by the API (even though the Stacks node hadn't dropped it) because it exceeded maximum mempool age */ DroppedApiGarbageCollect = -14, + /** Transaction is problematic (e.g. a DDoS vector) and should be dropped. */ + DroppedProblematic = -15, } export enum DbTxAnchorMode { diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index e35cabe9ee..db41e4865d 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -990,6 +990,8 @@ export function getTxDbStatus( return DbTxStatus.DroppedTooExpensive; case 'StaleGarbageCollect': return DbTxStatus.DroppedStaleGarbageCollect; + case 'Problematic': + return DbTxStatus.DroppedProblematic; default: throw new Error(`Unexpected tx status: ${txCoreStatus}`); } diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 22ed88617a..3adaf61d69 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -1247,6 +1247,7 @@ export class PgStore extends BasePgStore { DbTxStatus.DroppedTooExpensive, DbTxStatus.DroppedStaleGarbageCollect, DbTxStatus.DroppedApiGarbageCollect, + DbTxStatus.DroppedProblematic, ]; const resultQuery = await sql<(MempoolTxQueryResult & { count: number })[]>` SELECT ${unsafeCols(sql, [ diff --git a/src/event-stream/core-node-message.ts b/src/event-stream/core-node-message.ts index dd5927a0bf..7e0dea7a66 100644 --- a/src/event-stream/core-node-message.ts +++ b/src/event-stream/core-node-message.ts @@ -301,7 +301,8 @@ export type CoreNodeDropMempoolTxReasonType = | 'ReplaceByFee' | 'ReplaceAcrossFork' | 'TooExpensive' - | 'StaleGarbageCollect'; + | 'StaleGarbageCollect' + | 'Problematic'; export interface CoreNodeDropMempoolTxMessage { dropped_txids: string[]; diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index fd33072c2d..3948d9b689 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -323,9 +323,14 @@ describe('mempool tests', () => { tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005', receipt_time: 1594307705, }; + const mempoolTx6: DbMempoolTxRaw = { + ...mempoolTx1, + tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006', + receipt_time: 1594307706, + }; await db.updateMempoolTxs({ - mempoolTxs: [mempoolTx1, mempoolTx2, mempoolTx3, mempoolTx4, mempoolTx5], + mempoolTxs: [mempoolTx1, mempoolTx2, mempoolTx3, mempoolTx4, mempoolTx5, mempoolTx6], }); await db.dropMempoolTxs({ status: DbTxStatus.DroppedReplaceAcrossFork, @@ -450,6 +455,31 @@ describe('mempool tests', () => { }; expect(JSON.parse(searchResult5.text)).toEqual(expectedResp5); + await db.dropMempoolTxs({ + status: DbTxStatus.DroppedProblematic, + txIds: [mempoolTx6.tx_id], + }); + const searchResult6 = await supertest(api.server).get(`/extended/v1/tx/${mempoolTx6.tx_id}`); + expect(searchResult6.status).toBe(200); + expect(searchResult6.type).toBe('application/json'); + const expectedResp6 = { + tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006', + tx_status: 'dropped_problematic', + tx_type: 'coinbase', + fee_rate: '1234', + nonce: 0, + anchor_mode: 'any', + sender_address: 'sender-addr', + sponsor_address: 'sponsor-addr', + sponsored: true, + post_condition_mode: 'allow', + post_conditions: [], + receipt_time: 1594307706, + receipt_time_iso: '2020-07-09T15:15:06.000Z', + coinbase_payload: { data: '0x636f696e62617365206869', alt_recipient: null }, + }; + expect(JSON.parse(searchResult6.text)).toEqual(expectedResp6); + const mempoolDroppedResult1 = await supertest(api.server).get( '/extended/v1/tx/mempool/dropped' ); @@ -458,6 +488,10 @@ describe('mempool tests', () => { expect(mempoolDroppedResult1.body).toEqual( expect.objectContaining({ results: expect.arrayContaining([ + expect.objectContaining({ + tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006', + tx_status: 'dropped_problematic', + }), expect.objectContaining({ tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005', tx_status: 'dropped_stale_garbage_collect', @@ -549,10 +583,14 @@ describe('mempool tests', () => { ); expect(mempoolDroppedResult2.status).toBe(200); expect(mempoolDroppedResult2.type).toBe('application/json'); - expect(mempoolDroppedResult2.body.results).toHaveLength(4); + expect(mempoolDroppedResult2.body.results).toHaveLength(5); expect(mempoolDroppedResult2.body).toEqual( expect.objectContaining({ results: expect.arrayContaining([ + expect.objectContaining({ + tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006', + tx_status: 'dropped_problematic', + }), expect.objectContaining({ tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005', tx_status: 'dropped_stale_garbage_collect', From e8cccdd46d67e86f3ad36f226699bb59baa901ff Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 1 Jan 2024 13:45:29 +0000 Subject: [PATCH 58/91] chore(release): 7.4.0-nakamoto.10 [skip ci] ## [7.4.0-nakamoto.10](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.9...v7.4.0-nakamoto.10) (2024-01-01) ### Bug Fixes * handle `Problematic` status in `/drop_mempool_tx` event ([#1790](https://github.com/hirosystems/stacks-blockchain-api/issues/1790)) ([ce9b38f](https://github.com/hirosystems/stacks-blockchain-api/commit/ce9b38f051216d149375d64b3dfb90a75ab50fcd)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45fa95f37b..efe044a344 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-nakamoto.10](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.9...v7.4.0-nakamoto.10) (2024-01-01) + + +### Bug Fixes + +* handle `Problematic` status in `/drop_mempool_tx` event ([#1790](https://github.com/hirosystems/stacks-blockchain-api/issues/1790)) ([ce9b38f](https://github.com/hirosystems/stacks-blockchain-api/commit/ce9b38f051216d149375d64b3dfb90a75ab50fcd)) + ## [7.4.0-nakamoto.9](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.8...v7.4.0-nakamoto.9) (2023-12-26) From 3a02f5741f4109c1e662b4e7014189ae95430df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 2 Jan 2024 09:59:07 -0600 Subject: [PATCH 59/91] fix: optimize mempool transaction reads and writes (#1781) * fix: change mempool_digest into a table * fix: change digest to be last updated timestamp * fix: build * fix: update count on reconcile * test: mempool renconcile --- .../1703177555075_mempool-digest-table.js | 27 ++ src/datastore/pg-store.ts | 15 +- src/datastore/pg-write-store.ts | 288 +++++++++--------- src/event-replay/event-replay.ts | 1 - .../parquet-based/replay-controller.ts | 4 - src/tests/cache-control-tests.ts | 24 +- src/tests/mempool-tests.ts | 6 +- 7 files changed, 191 insertions(+), 174 deletions(-) create mode 100644 migrations/1703177555075_mempool-digest-table.js diff --git a/migrations/1703177555075_mempool-digest-table.js b/migrations/1703177555075_mempool-digest-table.js new file mode 100644 index 0000000000..af0185ac74 --- /dev/null +++ b/migrations/1703177555075_mempool-digest-table.js @@ -0,0 +1,27 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.addColumn('chain_tip', { + mempool_tx_count: { + type: 'int', + default: 0, + }, + mempool_updated_at: { + type: 'timestamptz', + default: pgm.func('(NOW())'), + }, + }); + pgm.sql(` + UPDATE chain_tip SET + mempool_tx_count = (SELECT COUNT(*)::int FROM mempool_txs WHERE pruned = FALSE), + mempool_updated_at = NOW() + `); + pgm.alterColumn('chain_tip', 'mempool_tx_count', { notNull: true }); + pgm.alterColumn('chain_tip', 'mempool_updated_at', { notNull: true }); +}; + +exports.down = pgm => { + pgm.dropColumn('chain_tip', ['mempool_tx_count', 'mempool_updated_at']); +}; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 3adaf61d69..369ce243fd 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -1474,12 +1474,13 @@ export class PgStore extends BasePgStore { const unanchoredTxs: string[] = !includeUnanchored ? (await this.getUnanchoredTxsInternal(sql)).txs.map(tx => tx.tx_id) : []; + // If caller is not filtering by any param, get the tx count from the `chain_tip` table. + const count = + senderAddress || recipientAddress || address + ? sql`(COUNT(*) OVER())::int AS count` + : sql`(SELECT mempool_tx_count FROM chain_tip) AS count`; const resultQuery = await sql<(MempoolTxQueryResult & { count: number })[]>` - SELECT ${unsafeCols(sql, [ - ...MEMPOOL_TX_COLUMNS, - abiColumn('mempool_txs'), - '(COUNT(*) OVER())::INTEGER AS count', - ])} + SELECT ${unsafeCols(sql, [...MEMPOOL_TX_COLUMNS, abiColumn('mempool_txs')])}, ${count} FROM mempool_txs WHERE ${ address @@ -1523,7 +1524,9 @@ export class PgStore extends BasePgStore { * @returns `FoundOrNot` object with a possible `digest` string. */ async getMempoolTxDigest(): Promise> { - const result = await this.sql<{ digest: string }[]>`SELECT digest FROM mempool_digest`; + const result = await this.sql<{ digest: string }[]>` + SELECT date_part('epoch', mempool_updated_at)::text AS digest FROM chain_tip + `; if (result.length === 0) { return { found: false } as const; } diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 1eac2ac2fc..ed8438076d 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -293,8 +293,6 @@ export class PgWriteStore extends PgStore { tx_count = (SELECT tx_count FROM new_tx_count), tx_count_unanchored = (SELECT tx_count FROM new_tx_count) `; - - await this.refreshMaterializedView('mempool_digest'); }); // Do we have an IBD height defined in ENV? If so, check if this block update reached it. const ibdHeight = getIbdBlockHeight(); @@ -686,8 +684,6 @@ export class PgWriteStore extends PgStore { `; }); - await this.refreshMaterializedView('mempool_digest'); - if (this.notifier) { for (const microblock of dbMicroblocks) { await this.notifier.sendMicroblock({ microblockHash: microblock.microblock_hash }); @@ -717,20 +713,28 @@ export class PgWriteStore extends PgStore { // NOTE: this is essentially a work-around for whatever bug is causing the underlying problem. async reconcileMempoolStatus(sql: PgSqlClient): Promise { const txsResult = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = true - FROM txs - WHERE - mempool_txs.tx_id = txs.tx_id AND - mempool_txs.pruned = false AND - txs.canonical = true AND - txs.microblock_canonical = true AND - txs.status IN ${sql([ - DbTxStatus.Success, - DbTxStatus.AbortByResponse, - DbTxStatus.AbortByPostCondition, - ])} - RETURNING mempool_txs.tx_id + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = true + FROM txs + WHERE + mempool_txs.tx_id = txs.tx_id AND + mempool_txs.pruned = false AND + txs.canonical = true AND + txs.microblock_canonical = true AND + txs.status IN ${sql([ + DbTxStatus.Success, + DbTxStatus.AbortByResponse, + DbTxStatus.AbortByPostCondition, + ])} + RETURNING mempool_txs.tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; if (txsResult.length > 0) { const txs = txsResult.map(tx => tx.tx_id); @@ -1630,99 +1634,106 @@ export class PgWriteStore extends PgStore { return result.count; } - async insertDbMempoolTx( - tx: DbMempoolTxRaw, + async insertDbMempoolTxs( + txs: DbMempoolTxRaw[], chainTip: DbChainTip, sql: PgSqlClient - ): Promise { - const values: MempoolTxInsertValues = { - pruned: tx.pruned, - tx_id: tx.tx_id, - raw_tx: tx.raw_tx, - type_id: tx.type_id, - anchor_mode: tx.anchor_mode, - status: tx.status, - receipt_time: tx.receipt_time, - receipt_block_height: chainTip.block_height, - post_conditions: tx.post_conditions, - nonce: tx.nonce, - fee_rate: tx.fee_rate, - sponsored: tx.sponsored, - sponsor_nonce: tx.sponsor_nonce ?? null, - sponsor_address: tx.sponsor_address ?? null, - sender_address: tx.sender_address, - origin_hash_mode: tx.origin_hash_mode, - token_transfer_recipient_address: tx.token_transfer_recipient_address ?? null, - token_transfer_amount: tx.token_transfer_amount ?? null, - token_transfer_memo: tx.token_transfer_memo ?? null, - smart_contract_clarity_version: tx.smart_contract_clarity_version ?? null, - smart_contract_contract_id: tx.smart_contract_contract_id ?? null, - smart_contract_source_code: tx.smart_contract_source_code ?? null, - contract_call_contract_id: tx.contract_call_contract_id ?? null, - contract_call_function_name: tx.contract_call_function_name ?? null, - contract_call_function_args: tx.contract_call_function_args ?? null, - poison_microblock_header_1: tx.poison_microblock_header_1 ?? null, - poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, - coinbase_payload: tx.coinbase_payload ?? null, - coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, - coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, - tenure_change_tenure_consensus_hash: tx.tenure_change_tenure_consensus_hash ?? null, - tenure_change_prev_tenure_consensus_hash: tx.tenure_change_prev_tenure_consensus_hash ?? null, - tenure_change_burn_view_consensus_hash: tx.tenure_change_burn_view_consensus_hash ?? null, - tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, - tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, - tenure_change_cause: tx.tenure_change_cause ?? null, - tenure_change_pubkey_hash: tx.tenure_change_pubkey_hash ?? null, - tenure_change_signature: tx.tenure_change_signature ?? null, - tenure_change_signers: tx.tenure_change_signers ?? null, - }; - const result = await sql` - INSERT INTO mempool_txs ${sql(values)} - ON CONFLICT ON CONSTRAINT unique_tx_id DO NOTHING - `; - if (result.count !== 1) { - const errMsg = `A duplicate transaction was attempted to be inserted into the mempool_txs table: ${tx.tx_id}`; - logger.warn(errMsg); - return false; - } else { - return true; + ): Promise { + const txIds: string[] = []; + for (const batch of batchIterate(txs, INSERT_BATCH_SIZE)) { + const values: MempoolTxInsertValues[] = batch.map(tx => ({ + pruned: tx.pruned, + tx_id: tx.tx_id, + raw_tx: tx.raw_tx, + type_id: tx.type_id, + anchor_mode: tx.anchor_mode, + status: tx.status, + receipt_time: tx.receipt_time, + receipt_block_height: chainTip.block_height, + post_conditions: tx.post_conditions, + nonce: tx.nonce, + fee_rate: tx.fee_rate, + sponsored: tx.sponsored, + sponsor_nonce: tx.sponsor_nonce ?? null, + sponsor_address: tx.sponsor_address ?? null, + sender_address: tx.sender_address, + origin_hash_mode: tx.origin_hash_mode, + token_transfer_recipient_address: tx.token_transfer_recipient_address ?? null, + token_transfer_amount: tx.token_transfer_amount ?? null, + token_transfer_memo: tx.token_transfer_memo ?? null, + smart_contract_clarity_version: tx.smart_contract_clarity_version ?? null, + smart_contract_contract_id: tx.smart_contract_contract_id ?? null, + smart_contract_source_code: tx.smart_contract_source_code ?? null, + contract_call_contract_id: tx.contract_call_contract_id ?? null, + contract_call_function_name: tx.contract_call_function_name ?? null, + contract_call_function_args: tx.contract_call_function_args ?? null, + poison_microblock_header_1: tx.poison_microblock_header_1 ?? null, + poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, + coinbase_payload: tx.coinbase_payload ?? null, + coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, + coinbase_vrf_proof: tx.coinbase_vrf_proof ?? null, + tenure_change_tenure_consensus_hash: tx.tenure_change_tenure_consensus_hash ?? null, + tenure_change_prev_tenure_consensus_hash: + tx.tenure_change_prev_tenure_consensus_hash ?? null, + tenure_change_burn_view_consensus_hash: tx.tenure_change_burn_view_consensus_hash ?? null, + tenure_change_previous_tenure_end: tx.tenure_change_previous_tenure_end ?? null, + tenure_change_previous_tenure_blocks: tx.tenure_change_previous_tenure_blocks ?? null, + tenure_change_cause: tx.tenure_change_cause ?? null, + tenure_change_pubkey_hash: tx.tenure_change_pubkey_hash ?? null, + tenure_change_signature: tx.tenure_change_signature ?? null, + tenure_change_signers: tx.tenure_change_signers ?? null, + })); + const result = await sql<{ tx_id: string }[]>` + WITH inserted AS ( + INSERT INTO mempool_txs ${sql(values)} + ON CONFLICT ON CONSTRAINT unique_tx_id DO NOTHING + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count + (SELECT COUNT(*) FROM inserted), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM inserted + `; + txIds.push(...result.map(r => r.tx_id)); } + return txIds; } async updateMempoolTxs({ mempoolTxs: txs }: { mempoolTxs: DbMempoolTxRaw[] }): Promise { const updatedTxIds: string[] = []; await this.sqlWriteTransaction(async sql => { const chainTip = await this.getChainTip(); - for (const tx of txs) { - const inserted = await this.insertDbMempoolTx(tx, chainTip, sql); - if (inserted) { - updatedTxIds.push(tx.tx_id); - } - } + updatedTxIds.push(...(await this.insertDbMempoolTxs(txs, chainTip, sql))); if (!this.isEventReplay) { await this.reconcileMempoolStatus(sql); - const mempoolStats = await this.getMempoolStatsInternal({ sql }); this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); } }); - await this.refreshMaterializedView('mempool_digest'); for (const txId of updatedTxIds) { - await this.notifier?.sendTx({ txId: txId }); + await this.notifier?.sendTx({ txId }); } } async dropMempoolTxs({ status, txIds }: { status: DbTxStatus; txIds: string[] }): Promise { - const updateResults = await this.sql` - UPDATE mempool_txs - SET pruned = true, status = ${status} - WHERE tx_id IN ${this.sql(txIds)} - RETURNING ${this.sql(MEMPOOL_TX_COLUMNS)} + const updateResults = await this.sql<{ tx_id: string }[]>` + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = TRUE, status = ${status} + WHERE tx_id IN ${this.sql(txIds)} AND pruned = FALSE + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; - const updatedTxs = updateResults.map(r => parseMempoolTxQueryResult(r)); - await this.refreshMaterializedView('mempool_digest'); - for (const tx of updatedTxs) { - await this.notifier?.sendTx({ txId: tx.tx_id }); + for (const txId of updateResults.map(r => r.tx_id)) { + await this.notifier?.sendTx({ txId }); } } @@ -2286,19 +2297,24 @@ export class PgWriteStore extends PgStore { * @param txIds - List of transactions to update in the mempool */ async restoreMempoolTxs(sql: PgSqlClient, txIds: string[]): Promise<{ restoredTxs: string[] }> { - if (txIds.length === 0) { - // Avoid an unnecessary query. - return { restoredTxs: [] }; - } + if (txIds.length === 0) return { restoredTxs: [] }; for (const txId of txIds) { logger.debug(`Restoring mempool tx: ${txId}`); } const updatedRows = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = false - WHERE tx_id IN ${sql(txIds)} - RETURNING tx_id + WITH restored AS ( + UPDATE mempool_txs + SET pruned = FALSE + WHERE tx_id IN ${sql(txIds)} AND pruned = TRUE + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count + (SELECT COUNT(*) FROM restored), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM restored `; const updatedTxs = updatedRows.map(r => r.tx_id); @@ -2350,13 +2366,20 @@ export class PgWriteStore extends PgStore { logger.debug(`Pruning mempool tx: ${txId}`); } const updateResults = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = true - WHERE tx_id IN ${sql(txIds)} - RETURNING tx_id + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = true + WHERE tx_id IN ${sql(txIds)} AND pruned = FALSE + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; - const removedTxs = updateResults.map(r => r.tx_id); - return { removedTxs: removedTxs }; + return { removedTxs: updateResults.map(r => r.tx_id) }; } /** @@ -2365,27 +2388,26 @@ export class PgWriteStore extends PgStore { * @returns List of deleted `tx_id`s */ async deleteGarbageCollectedMempoolTxs(sql: PgSqlClient): Promise<{ deletedTxs: string[] }> { - // Get threshold block. - const blockThreshold = process.env['STACKS_MEMPOOL_TX_GARBAGE_COLLECTION_THRESHOLD'] ?? 256; - const cutoffResults = await sql<{ block_height: number }[]>` - SELECT (MAX(block_height) - ${blockThreshold}) AS block_height - FROM blocks - WHERE canonical = TRUE - `; - if (cutoffResults.length != 1) { - return { deletedTxs: [] }; - } - const cutoffBlockHeight = cutoffResults[0].block_height; - // Delete every mempool tx that came before that block. + const blockThreshold = parseInt( + process.env['STACKS_MEMPOOL_TX_GARBAGE_COLLECTION_THRESHOLD'] ?? '256' + ); // TODO: Use DELETE instead of UPDATE once we implement a non-archival API replay mode. const deletedTxResults = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = TRUE, status = ${DbTxStatus.DroppedApiGarbageCollect} - WHERE pruned = FALSE AND receipt_block_height < ${cutoffBlockHeight} - RETURNING tx_id + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = TRUE, status = ${DbTxStatus.DroppedApiGarbageCollect} + WHERE pruned = FALSE + AND receipt_block_height <= (SELECT block_height - ${blockThreshold} FROM chain_tip) + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; - const deletedTxs = deletedTxResults.map(r => r.tx_id); - return { deletedTxs: deletedTxs }; + return { deletedTxs: deletedTxResults.map(r => r.tx_id) }; } async markEntitiesCanonical( @@ -2747,28 +2769,6 @@ export class PgWriteStore extends PgStore { return updatedEntities; } - /** - * Refreshes a Postgres materialized view. - * @param viewName - Materialized view name - * @param sql - Pg scoped client. Will use the default client if none specified - * @param skipDuringEventReplay - If we should skip refreshing during event replay - */ - async refreshMaterializedView(viewName: string, sql?: PgSqlClient, skipDuringEventReplay = true) { - sql = sql ?? this.sql; - if ((this.isEventReplay && skipDuringEventReplay) || !this.isIbdBlockHeightReached) { - return; - } - await sql`REFRESH MATERIALIZED VIEW ${isProdEnv ? sql`CONCURRENTLY` : sql``} ${sql(viewName)}`; - } - - /** - * Called when a full event import is complete. - */ - async finishEventReplay() { - if (!this.isEventReplay) return; - await this.refreshMaterializedView('mempool_digest', this.sql, false); - } - /** * batch operations (mainly for event-replay) */ diff --git a/src/event-replay/event-replay.ts b/src/event-replay/event-replay.ts index 4378d30243..e3f7b93bc6 100644 --- a/src/event-replay/event-replay.ts +++ b/src/event-replay/event-replay.ts @@ -171,7 +171,6 @@ export async function importEventsFromTsv( responses.push(response); } } - await db.finishEventReplay(); console.log(`Event import and playback successful.`); await eventServer.closeAsync(); await db.close(); diff --git a/src/event-replay/parquet-based/replay-controller.ts b/src/event-replay/parquet-based/replay-controller.ts index 945297fa4b..b9ec3136ef 100644 --- a/src/event-replay/parquet-based/replay-controller.ts +++ b/src/event-replay/parquet-based/replay-controller.ts @@ -264,10 +264,6 @@ export class ReplayController { // Remainder events to be replayed with regular HTTP POSTs await this.ingestRemainderEvents(); - // Refreshing materialized views - logger.info({ component: 'event-replay' }, `Refreshing materialized views`); - await this.db.finishEventReplay(); - // Close DB logger.info({ component: 'event-replay' }, 'Closing DB connection'); await this.db.close(); diff --git a/src/tests/cache-control-tests.ts b/src/tests/cache-control-tests.ts index 12cb6fb14c..4b1f5e3450 100644 --- a/src/tests/cache-control-tests.ts +++ b/src/tests/cache-control-tests.ts @@ -380,7 +380,7 @@ describe('cache-control tests', () => { const request1 = await supertest(api.server).get('/extended/v1/tx/mempool'); expect(request1.status).toBe(200); expect(request1.type).toBe('application/json'); - expect(request1.headers['etag']).toEqual('"0"'); + const etag0 = request1.headers['etag']; // Add mempool txs. const mempoolTx1 = testMempoolTx({ tx_id: '0x1101' }); @@ -393,6 +393,7 @@ describe('cache-control tests', () => { expect(request2.type).toBe('application/json'); expect(request2.headers['etag']).toBeTruthy(); const etag1 = request2.headers['etag']; + expect(etag1).not.toEqual(etag0); // Cache works with valid ETag. const request3 = await supertest(api.server) @@ -423,13 +424,12 @@ describe('cache-control tests', () => { .build(); await db.update(block2); - // Cache is now a miss and ETag is zero because mempool is empty. + // Cache is now a miss. const request5 = await supertest(api.server) .get('/extended/v1/tx/mempool') .set('If-None-Match', etag2); expect(request5.status).toBe(200); expect(request5.type).toBe('application/json'); - expect(request5.headers['etag']).toEqual('"0"'); const etag3 = request5.headers['etag']; // Restore a tx back into the mempool by making its anchor block non-canonical. @@ -456,7 +456,7 @@ describe('cache-control tests', () => { .set('If-None-Match', etag3); expect(request6.status).toBe(200); expect(request6.type).toBe('application/json'); - expect(request6.headers['etag']).toEqual(etag2); + expect(request6.headers['etag']).not.toEqual(etag3); const etag4 = request6.headers['etag']; // Garbage collect all txs. @@ -470,25 +470,13 @@ describe('cache-control tests', () => { .build(); await db.update(block4); - // ETag zero once again. + // ETag changes once again. const request7 = await supertest(api.server) .get('/extended/v1/tx/mempool') .set('If-None-Match', etag4); expect(request7.status).toBe(200); expect(request7.type).toBe('application/json'); - expect(request7.headers['etag']).toEqual('"0"'); - - // Simulate an incompatible pg version (without `bit_xor`). - await client.begin(async sql => { - await sql`DROP MATERIALIZED VIEW mempool_digest`; - await sql`CREATE MATERIALIZED VIEW mempool_digest AS (SELECT NULL AS digest)`; - }); - - // ETag is undefined as if mempool cache did not exist. - const request8 = await supertest(api.server).get('/extended/v1/tx/mempool'); - expect(request8.status).toBe(200); - expect(request8.type).toBe('application/json'); - expect(request8.headers['etag']).toBeUndefined(); + expect(request7.headers['etag']).not.toEqual(etag4); }); test('transaction cache control', async () => { diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index 3948d9b689..a426952741 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1584,7 +1584,7 @@ describe('mempool tests', () => { // directly inserting the mempool-tx and mined-tx, bypassing the normal update functions. await db.updateBlock(db.sql, dbBlock1); const chainTip = await db.getChainTip(); - await db.insertDbMempoolTx(mempoolTx, chainTip, db.sql); + await db.insertDbMempoolTxs([mempoolTx], chainTip, db.sql); await db.updateTx(db.sql, dbTx1); // Verify tx shows up in mempool (non-pruned) @@ -1592,6 +1592,8 @@ describe('mempool tests', () => { `/extended/v1/address/${mempoolTx.sender_address}/mempool` ); expect(mempoolResult1.body.results[0].tx_id).toBe(txId); + const mempoolCount1 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount1.body.total).toBe(1); const mempoolResult2 = await supertest(api.server).get( `/extended/v1/tx/mempool?sender_address=${senderAddress}` ); @@ -1614,6 +1616,8 @@ describe('mempool tests', () => { `/extended/v1/address/${mempoolTx.sender_address}/mempool` ); expect(mempoolResult3.body.results).toHaveLength(0); + const mempoolCount2 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount2.body.total).toBe(0); const mempoolResult4 = await supertest(api.server).get( `/extended/v1/tx/mempool?sender_address=${senderAddress}` ); From 2700642ed2225ce8598ee5fff833603007d5289f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 2 Jan 2024 11:14:30 -0600 Subject: [PATCH 60/91] fix: optimize mempool transaction reads and writes (#1781) (#1792) * fix: change mempool_digest into a table * fix: change digest to be last updated timestamp * fix: build * fix: update count on reconcile * test: mempool renconcile --- .../1703177555075_mempool-digest-table.js | 27 ++ src/datastore/pg-store.ts | 15 +- src/datastore/pg-write-store.ts | 243 ++++++++++-------- src/event-replay/event-replay.ts | 1 - src/tests/cache-control-tests.ts | 24 +- src/tests/mempool-tests.ts | 6 +- 6 files changed, 180 insertions(+), 136 deletions(-) create mode 100644 migrations/1703177555075_mempool-digest-table.js diff --git a/migrations/1703177555075_mempool-digest-table.js b/migrations/1703177555075_mempool-digest-table.js new file mode 100644 index 0000000000..af0185ac74 --- /dev/null +++ b/migrations/1703177555075_mempool-digest-table.js @@ -0,0 +1,27 @@ +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + pgm.addColumn('chain_tip', { + mempool_tx_count: { + type: 'int', + default: 0, + }, + mempool_updated_at: { + type: 'timestamptz', + default: pgm.func('(NOW())'), + }, + }); + pgm.sql(` + UPDATE chain_tip SET + mempool_tx_count = (SELECT COUNT(*)::int FROM mempool_txs WHERE pruned = FALSE), + mempool_updated_at = NOW() + `); + pgm.alterColumn('chain_tip', 'mempool_tx_count', { notNull: true }); + pgm.alterColumn('chain_tip', 'mempool_updated_at', { notNull: true }); +}; + +exports.down = pgm => { + pgm.dropColumn('chain_tip', ['mempool_tx_count', 'mempool_updated_at']); +}; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index e33acd8651..88d1776816 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -1306,12 +1306,13 @@ export class PgStore { const unanchoredTxs: string[] = !includeUnanchored ? (await this.getUnanchoredTxsInternal(sql)).txs.map(tx => tx.tx_id) : []; + // If caller is not filtering by any param, get the tx count from the `chain_tip` table. + const count = + senderAddress || recipientAddress || address + ? sql`(COUNT(*) OVER())::int AS count` + : sql`(SELECT mempool_tx_count FROM chain_tip) AS count`; const resultQuery = await sql<(MempoolTxQueryResult & { count: number })[]>` - SELECT ${unsafeCols(sql, [ - ...MEMPOOL_TX_COLUMNS, - abiColumn('mempool_txs'), - '(COUNT(*) OVER())::INTEGER AS count', - ])} + SELECT ${unsafeCols(sql, [...MEMPOOL_TX_COLUMNS, abiColumn('mempool_txs')])}, ${count} FROM mempool_txs WHERE ${ address @@ -1355,7 +1356,9 @@ export class PgStore { * @returns `FoundOrNot` object with a possible `digest` string. */ async getMempoolTxDigest(): Promise> { - const result = await this.sql<{ digest: string }[]>`SELECT digest FROM mempool_digest`; + const result = await this.sql<{ digest: string }[]>` + SELECT date_part('epoch', mempool_updated_at)::text AS digest FROM chain_tip + `; if (result.length === 0) { return { found: false } as const; } diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index f2224c99c9..55e9ca48a5 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -705,8 +705,6 @@ export class PgWriteStore extends PgStore { `; }); - await this.refreshMaterializedView('mempool_digest'); - if (this.notifier) { for (const microblock of dbMicroblocks) { await this.notifier.sendMicroblock({ microblockHash: microblock.microblock_hash }); @@ -736,20 +734,28 @@ export class PgWriteStore extends PgStore { // NOTE: this is essentially a work-around for whatever bug is causing the underlying problem. async reconcileMempoolStatus(sql: PgSqlClient): Promise { const txsResult = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = true - FROM txs - WHERE - mempool_txs.tx_id = txs.tx_id AND - mempool_txs.pruned = false AND - txs.canonical = true AND - txs.microblock_canonical = true AND - txs.status IN ${sql([ - DbTxStatus.Success, - DbTxStatus.AbortByResponse, - DbTxStatus.AbortByPostCondition, - ])} - RETURNING mempool_txs.tx_id + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = true + FROM txs + WHERE + mempool_txs.tx_id = txs.tx_id AND + mempool_txs.pruned = false AND + txs.canonical = true AND + txs.microblock_canonical = true AND + txs.status IN ${sql([ + DbTxStatus.Success, + DbTxStatus.AbortByResponse, + DbTxStatus.AbortByPostCondition, + ])} + RETURNING mempool_txs.tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; if (txsResult.length > 0) { const txs = txsResult.map(tx => tx.tx_id); @@ -1656,89 +1662,95 @@ export class PgWriteStore extends PgStore { return result.count; } - async insertDbMempoolTx( - tx: DbMempoolTxRaw, + async insertDbMempoolTxs( + txs: DbMempoolTxRaw[], chainTip: DbChainTip, sql: PgSqlClient - ): Promise { - const values: MempoolTxInsertValues = { - pruned: tx.pruned, - tx_id: tx.tx_id, - raw_tx: tx.raw_tx, - type_id: tx.type_id, - anchor_mode: tx.anchor_mode, - status: tx.status, - receipt_time: tx.receipt_time, - receipt_block_height: chainTip.block_height, - post_conditions: tx.post_conditions, - nonce: tx.nonce, - fee_rate: tx.fee_rate, - sponsored: tx.sponsored, - sponsor_nonce: tx.sponsor_nonce ?? null, - sponsor_address: tx.sponsor_address ?? null, - sender_address: tx.sender_address, - origin_hash_mode: tx.origin_hash_mode, - token_transfer_recipient_address: tx.token_transfer_recipient_address ?? null, - token_transfer_amount: tx.token_transfer_amount ?? null, - token_transfer_memo: tx.token_transfer_memo ?? null, - smart_contract_clarity_version: tx.smart_contract_clarity_version ?? null, - smart_contract_contract_id: tx.smart_contract_contract_id ?? null, - smart_contract_source_code: tx.smart_contract_source_code ?? null, - contract_call_contract_id: tx.contract_call_contract_id ?? null, - contract_call_function_name: tx.contract_call_function_name ?? null, - contract_call_function_args: tx.contract_call_function_args ?? null, - poison_microblock_header_1: tx.poison_microblock_header_1 ?? null, - poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, - coinbase_payload: tx.coinbase_payload ?? null, - coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, - }; - const result = await sql` - INSERT INTO mempool_txs ${sql(values)} - ON CONFLICT ON CONSTRAINT unique_tx_id DO NOTHING - `; - if (result.count !== 1) { - const errMsg = `A duplicate transaction was attempted to be inserted into the mempool_txs table: ${tx.tx_id}`; - logger.warn(errMsg); - return false; - } else { - return true; + ): Promise { + const txIds: string[] = []; + for (const batch of batchIterate(txs, 500)) { + const values: MempoolTxInsertValues[] = batch.map(tx => ({ + pruned: tx.pruned, + tx_id: tx.tx_id, + raw_tx: tx.raw_tx, + type_id: tx.type_id, + anchor_mode: tx.anchor_mode, + status: tx.status, + receipt_time: tx.receipt_time, + receipt_block_height: chainTip.block_height, + post_conditions: tx.post_conditions, + nonce: tx.nonce, + fee_rate: tx.fee_rate, + sponsored: tx.sponsored, + sponsor_nonce: tx.sponsor_nonce ?? null, + sponsor_address: tx.sponsor_address ?? null, + sender_address: tx.sender_address, + origin_hash_mode: tx.origin_hash_mode, + token_transfer_recipient_address: tx.token_transfer_recipient_address ?? null, + token_transfer_amount: tx.token_transfer_amount ?? null, + token_transfer_memo: tx.token_transfer_memo ?? null, + smart_contract_clarity_version: tx.smart_contract_clarity_version ?? null, + smart_contract_contract_id: tx.smart_contract_contract_id ?? null, + smart_contract_source_code: tx.smart_contract_source_code ?? null, + contract_call_contract_id: tx.contract_call_contract_id ?? null, + contract_call_function_name: tx.contract_call_function_name ?? null, + contract_call_function_args: tx.contract_call_function_args ?? null, + poison_microblock_header_1: tx.poison_microblock_header_1 ?? null, + poison_microblock_header_2: tx.poison_microblock_header_2 ?? null, + coinbase_payload: tx.coinbase_payload ?? null, + coinbase_alt_recipient: tx.coinbase_alt_recipient ?? null, + })); + const result = await sql<{ tx_id: string }[]>` + WITH inserted AS ( + INSERT INTO mempool_txs ${sql(values)} + ON CONFLICT ON CONSTRAINT unique_tx_id DO NOTHING + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count + (SELECT COUNT(*) FROM inserted), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM inserted + `; + txIds.push(...result.map(r => r.tx_id)); } + return txIds; } async updateMempoolTxs({ mempoolTxs: txs }: { mempoolTxs: DbMempoolTxRaw[] }): Promise { const updatedTxIds: string[] = []; await this.sqlWriteTransaction(async sql => { const chainTip = await this.getChainTip(); - for (const tx of txs) { - const inserted = await this.insertDbMempoolTx(tx, chainTip, sql); - if (inserted) { - updatedTxIds.push(tx.tx_id); - } - } + updatedTxIds.push(...(await this.insertDbMempoolTxs(txs, chainTip, sql))); if (!this.isEventReplay) { await this.reconcileMempoolStatus(sql); - const mempoolStats = await this.getMempoolStatsInternal({ sql }); this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); } }); - await this.refreshMaterializedView('mempool_digest'); for (const txId of updatedTxIds) { - await this.notifier?.sendTx({ txId: txId }); + await this.notifier?.sendTx({ txId }); } } async dropMempoolTxs({ status, txIds }: { status: DbTxStatus; txIds: string[] }): Promise { - const updateResults = await this.sql` - UPDATE mempool_txs - SET pruned = true, status = ${status} - WHERE tx_id IN ${this.sql(txIds)} - RETURNING ${this.sql(MEMPOOL_TX_COLUMNS)} + const updateResults = await this.sql<{ tx_id: string }[]>` + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = TRUE, status = ${status} + WHERE tx_id IN ${this.sql(txIds)} AND pruned = FALSE + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; - const updatedTxs = updateResults.map(r => parseMempoolTxQueryResult(r)); - await this.refreshMaterializedView('mempool_digest'); - for (const tx of updatedTxs) { - await this.notifier?.sendTx({ txId: tx.tx_id }); + for (const txId of updateResults.map(r => r.tx_id)) { + await this.notifier?.sendTx({ txId }); } } @@ -2326,19 +2338,24 @@ export class PgWriteStore extends PgStore { * @param txIds - List of transactions to update in the mempool */ async restoreMempoolTxs(sql: PgSqlClient, txIds: string[]): Promise<{ restoredTxs: string[] }> { - if (txIds.length === 0) { - // Avoid an unnecessary query. - return { restoredTxs: [] }; - } + if (txIds.length === 0) return { restoredTxs: [] }; for (const txId of txIds) { logger.debug(`Restoring mempool tx: ${txId}`); } const updatedRows = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = false - WHERE tx_id IN ${sql(txIds)} - RETURNING tx_id + WITH restored AS ( + UPDATE mempool_txs + SET pruned = FALSE + WHERE tx_id IN ${sql(txIds)} AND pruned = TRUE + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count + (SELECT COUNT(*) FROM restored), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM restored `; const updatedTxs = updatedRows.map(r => r.tx_id); @@ -2393,13 +2410,20 @@ export class PgWriteStore extends PgStore { logger.debug(`Pruning mempool tx: ${txId}`); } const updateResults = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = true - WHERE tx_id IN ${sql(txIds)} - RETURNING tx_id + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = true + WHERE tx_id IN ${sql(txIds)} AND pruned = FALSE + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; - const removedTxs = updateResults.map(r => r.tx_id); - return { removedTxs: removedTxs }; + return { removedTxs: updateResults.map(r => r.tx_id) }; } /** @@ -2408,27 +2432,26 @@ export class PgWriteStore extends PgStore { * @returns List of deleted `tx_id`s */ async deleteGarbageCollectedMempoolTxs(sql: PgSqlClient): Promise<{ deletedTxs: string[] }> { - // Get threshold block. - const blockThreshold = process.env['STACKS_MEMPOOL_TX_GARBAGE_COLLECTION_THRESHOLD'] ?? 256; - const cutoffResults = await sql<{ block_height: number }[]>` - SELECT (MAX(block_height) - ${blockThreshold}) AS block_height - FROM blocks - WHERE canonical = TRUE - `; - if (cutoffResults.length != 1) { - return { deletedTxs: [] }; - } - const cutoffBlockHeight = cutoffResults[0].block_height; - // Delete every mempool tx that came before that block. + const blockThreshold = parseInt( + process.env['STACKS_MEMPOOL_TX_GARBAGE_COLLECTION_THRESHOLD'] ?? '256' + ); // TODO: Use DELETE instead of UPDATE once we implement a non-archival API replay mode. const deletedTxResults = await sql<{ tx_id: string }[]>` - UPDATE mempool_txs - SET pruned = TRUE, status = ${DbTxStatus.DroppedApiGarbageCollect} - WHERE pruned = FALSE AND receipt_block_height < ${cutoffBlockHeight} - RETURNING tx_id + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = TRUE, status = ${DbTxStatus.DroppedApiGarbageCollect} + WHERE pruned = FALSE + AND receipt_block_height <= (SELECT block_height - ${blockThreshold} FROM chain_tip) + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned `; - const deletedTxs = deletedTxResults.map(r => r.tx_id); - return { deletedTxs: deletedTxs }; + return { deletedTxs: deletedTxResults.map(r => r.tx_id) }; } async markEntitiesCanonical( diff --git a/src/event-replay/event-replay.ts b/src/event-replay/event-replay.ts index 53cb077509..172c13e5d1 100644 --- a/src/event-replay/event-replay.ts +++ b/src/event-replay/event-replay.ts @@ -167,7 +167,6 @@ export async function importEventsFromTsv( responses.push(response); } } - await db.finishEventReplay(); console.log(`Event import and playback successful.`); await eventServer.closeAsync(); await db.close(); diff --git a/src/tests/cache-control-tests.ts b/src/tests/cache-control-tests.ts index 0718f0574b..a2d88c960d 100644 --- a/src/tests/cache-control-tests.ts +++ b/src/tests/cache-control-tests.ts @@ -373,7 +373,7 @@ describe('cache-control tests', () => { const request1 = await supertest(api.server).get('/extended/v1/tx/mempool'); expect(request1.status).toBe(200); expect(request1.type).toBe('application/json'); - expect(request1.headers['etag']).toEqual('"0"'); + const etag0 = request1.headers['etag']; // Add mempool txs. const mempoolTx1 = testMempoolTx({ tx_id: '0x1101' }); @@ -386,6 +386,7 @@ describe('cache-control tests', () => { expect(request2.type).toBe('application/json'); expect(request2.headers['etag']).toBeTruthy(); const etag1 = request2.headers['etag']; + expect(etag1).not.toEqual(etag0); // Cache works with valid ETag. const request3 = await supertest(api.server) @@ -416,13 +417,12 @@ describe('cache-control tests', () => { .build(); await db.update(block2); - // Cache is now a miss and ETag is zero because mempool is empty. + // Cache is now a miss. const request5 = await supertest(api.server) .get('/extended/v1/tx/mempool') .set('If-None-Match', etag2); expect(request5.status).toBe(200); expect(request5.type).toBe('application/json'); - expect(request5.headers['etag']).toEqual('"0"'); const etag3 = request5.headers['etag']; // Restore a tx back into the mempool by making its anchor block non-canonical. @@ -449,7 +449,7 @@ describe('cache-control tests', () => { .set('If-None-Match', etag3); expect(request6.status).toBe(200); expect(request6.type).toBe('application/json'); - expect(request6.headers['etag']).toEqual(etag2); + expect(request6.headers['etag']).not.toEqual(etag3); const etag4 = request6.headers['etag']; // Garbage collect all txs. @@ -463,25 +463,13 @@ describe('cache-control tests', () => { .build(); await db.update(block4); - // ETag zero once again. + // ETag changes once again. const request7 = await supertest(api.server) .get('/extended/v1/tx/mempool') .set('If-None-Match', etag4); expect(request7.status).toBe(200); expect(request7.type).toBe('application/json'); - expect(request7.headers['etag']).toEqual('"0"'); - - // Simulate an incompatible pg version (without `bit_xor`). - await client.begin(async sql => { - await sql`DROP MATERIALIZED VIEW mempool_digest`; - await sql`CREATE MATERIALIZED VIEW mempool_digest AS (SELECT NULL AS digest)`; - }); - - // ETag is undefined as if mempool cache did not exist. - const request8 = await supertest(api.server).get('/extended/v1/tx/mempool'); - expect(request8.status).toBe(200); - expect(request8.type).toBe('application/json'); - expect(request8.headers['etag']).toBeUndefined(); + expect(request7.headers['etag']).not.toEqual(etag4); }); test('transaction cache control', async () => { diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index b31952e829..b44440fae4 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1489,7 +1489,7 @@ describe('mempool tests', () => { // directly inserting the mempool-tx and mined-tx, bypassing the normal update functions. await db.updateBlock(db.sql, dbBlock1); const chainTip = await db.getChainTip(); - await db.insertDbMempoolTx(mempoolTx, chainTip, db.sql); + await db.insertDbMempoolTxs([mempoolTx], chainTip, db.sql); await db.updateTx(db.sql, dbTx1); // Verify tx shows up in mempool (non-pruned) @@ -1497,6 +1497,8 @@ describe('mempool tests', () => { `/extended/v1/address/${mempoolTx.sender_address}/mempool` ); expect(mempoolResult1.body.results[0].tx_id).toBe(txId); + const mempoolCount1 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount1.body.total).toBe(1); const mempoolResult2 = await supertest(api.server).get( `/extended/v1/tx/mempool?sender_address=${senderAddress}` ); @@ -1519,6 +1521,8 @@ describe('mempool tests', () => { `/extended/v1/address/${mempoolTx.sender_address}/mempool` ); expect(mempoolResult3.body.results).toHaveLength(0); + const mempoolCount2 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount2.body.total).toBe(0); const mempoolResult4 = await supertest(api.server).get( `/extended/v1/tx/mempool?sender_address=${senderAddress}` ); From 20466a16573bff1634bc9b6ff1180bb8e0f620a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Wed, 3 Jan 2024 09:19:56 -0600 Subject: [PATCH 61/91] feat: create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint (#1782) * chore: move to v2 pg submodule * fix: move blocks per burn block endpoint * docs: openapi * docs: endpoint name --- docs/openapi.yaml | 143 +++++++--------- src/api/controllers/db-controller.ts | 1 - src/api/routes/v2/blocks.ts | 14 +- src/api/routes/v2/burn-blocks.ts | 47 +++++- src/api/routes/v2/schemas.ts | 24 --- src/datastore/pg-store-v2.ts | 233 +++++++++++++++++++++++++++ src/datastore/pg-store.ts | 214 +----------------------- src/tests/block-tests.ts | 19 +-- 8 files changed, 348 insertions(+), 347 deletions(-) create mode 100644 src/datastore/pg-store-v2.ts diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 1a2fadfdb8..5b1a4fe544 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -21,6 +21,8 @@ tags: url: https://docs.stacks.co/understand-stacks/accounts - name: Blocks description: Read-only endpoints to obtain Stacks block details + - name: Burn Blocks + description: Read-only endpoints to obtain burn block details - name: Faucets description: Endpoints to request STX or BTC tokens (not possible on Mainnet) - name: Fees @@ -613,7 +615,7 @@ paths: description: | Retrieves a list of recent burn blocks tags: - - Blocks + - Burn Blocks operationId: get_burn_blocks parameters: - name: limit @@ -646,7 +648,7 @@ paths: summary: Get burn block description: Retrieves a single burn block tags: - - Blocks + - Burn Blocks operationId: get_burn_block parameters: - name: height_or_hash @@ -668,16 +670,26 @@ paths: $ref: ./entities/blocks/burn-block.schema.json example: $ref: ./entities/blocks/burn-block.example.json - - /extended/v2/blocks: + + /extended/v2/burn-blocks/{height_or_hash}/blocks: get: - summary: Get blocks + summary: Get blocks by burn block description: | - Retrieves a list of recently mined blocks + Retrieves a list of blocks confirmed by a specific burn block tags: - Blocks - operationId: get_blocks + operationId: get_blocks_by_burn_block parameters: + - name: height_or_hash + in: path + description: filter by burn block height, hash, or the constant `latest` to filter for the most recent burn block + required: true + schema: + oneOf: + - type: integer + example: 42000 + - type: string + example: "0x4839a8b01cfb39ffcc0d07d3db31e848d5adf5279d529ed5062300b9f353ff79" - name: limit in: query description: max number of blocks to fetch @@ -692,20 +704,39 @@ paths: schema: type: integer example: 0 - - name: burn_block_hash + responses: + 200: + description: List of blocks + content: + application/json: + schema: + $ref: ./api/blocks/get-nakamoto-blocks.schema.json + example: + $ref: ./api/blocks/get-nakamoto-blocks.example.json + + /extended/v2/blocks: + get: + summary: Get blocks + description: | + Retrieves a list of recently mined blocks + tags: + - Blocks + operationId: get_blocks + parameters: + - name: limit in: query - description: filter blocks by burn block hash + description: max number of blocks to fetch required: false schema: - type: string - example: "0xb154c008df2101023a6d0d54986b3964cee58119eed14f5bed98e15678e18fe2" - - name: burn_block_height + type: integer + example: 20 + - name: offset in: query - description: filter blocks by burn block height + description: index of first burn block to fetch required: false schema: type: integer - example: 810344 + example: 0 responses: 200: description: List of blocks @@ -747,12 +778,12 @@ paths: /extended/v2/blocks/{height_or_hash}/transactions: get: - summary: Get block transactions + summary: Get transactions by block description: | Retrieves transactions confirmed in a single block tags: - - Blocks - operationId: get_block_transactions + - Transactions + operationId: get_transactions_by_block parameters: - name: height_or_hash in: path @@ -2913,77 +2944,15 @@ paths: example: $ref: ./api/bns/errors/bns-unsupported-blockchain.example.json -# /v1/subdomains: -# get: -# summary: Get All Subdomains -# description: Retrieves a list of all subdomains known to the node. -# tags: -# - Names -# operationId: get_all_subdomains -# parameters: -# - name: page -# in: query -# description: names are returned in pages of size 100, so specify the page number. -# required: true -# example: 3 -# schema: -# type: integer -# responses: -# 200: -# description: Success -# content: -# application/json: -# schema: -# $ref: ./api/bns/name-querying/bns-get-all-subdomains-response.schema.json -# example: -# $ref: ./api/bns/name-querying/bns-get-all-subdomains-response.example.json -# 400: -# description: Error -# content: -# application/json: -# schema: -# $ref: ./api/bns/errors/bns-error.schema.json -# example: -# $ref: ./api/bns/errors/bns-invalid-page.example.json -# -# /v1/subdomains/{txid}: -# get: -# summary: Get Subdomain at Transaction -# description: Retrieves the list of subdomain operations processed by a given transaction. The returned array includes subdomain operations that have not yet been accepted as part of any subdomain’s history (checkable via the accepted field). If the given transaction ID does not correspond to a Stacks transaction that introduced new subdomain operations, and empty array will be returned. -# tags: -# - Names -# operationId: get_subdomain_at_transaction -# parameters: -# - name: txid -# in: path -# description: transaction id -# required: true -# schema: -# type: string -# example: "d04d708472ea3c147f50e43264efdb1535f71974053126dc4db67b3ac19d41fe" -# responses: -# 200: -# description: Success -# content: -# application/json: -# schema: -# $ref: ./api/bns/name-querying/bns-get-subdomain-at-tx-response.schema.json -# example: -# $ref: ./api/bns/name-querying/bns-get-subdomain-at-tx-response.example.json -# 400: -# description: Error -# content: -# application/json: -# schema: -# $ref: ./api/bns/errors/bns-error.schema.json -# example: -# $ref: ./api/bns/errors/bns-invalid-tx-id.example.json - /extended/v1/tx/block/{block_hash}: get: + deprecated: true operationId: get_transactions_by_block_hash summary: Transactions by block hash - description: Retrieves a list of all transactions within a block for a given block hash. + description: | + **NOTE:** This endpoint is deprecated in favor of [Get transactions by block](#operation/get_transactions_by_block). + + Retrieves a list of all transactions within a block for a given block hash. tags: - Transactions parameters: @@ -3020,9 +2989,13 @@ paths: /extended/v1/tx/block_height/{height}: get: + deprecated: true operationId: get_transactions_by_block_height summary: Transactions by block height - description: Retrieves all transactions within a block at a given height + description: | + **NOTE:** This endpoint is deprecated in favor of [Get transactions by block](#operation/get_transactions_by_block). + + Retrieves all transactions within a block at a given height tags: - Transactions parameters: diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 8ca8da73a3..9a8e284099 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -68,7 +68,6 @@ import { getOperations, parseTransactionMemo } from '../../rosetta/rosetta-helpe import { PgStore } from '../../datastore/pg-store'; import { SyntheticPoxEventName } from '../../pox-helpers'; import { logger } from '../../logger'; -import { BlocksQueryParams } from '../routes/v2/schemas'; export function parseTxTypeStrings(values: string[]): TransactionType[] { return values.map(v => { diff --git a/src/api/routes/v2/blocks.ts b/src/api/routes/v2/blocks.ts index 9a78c302e0..666f5e0871 100644 --- a/src/api/routes/v2/blocks.ts +++ b/src/api/routes/v2/blocks.ts @@ -7,14 +7,14 @@ import { import { asyncHandler } from '../../async-handler'; import { NakamotoBlockListResponse, TransactionResults } from 'docs/generated'; import { - BlocksQueryParams, BlockParams, - CompiledBlocksQueryParams, CompiledBlockParams, CompiledTransactionPaginationQueryParams, TransactionPaginationQueryParams, validRequestQuery, validRequestParams, + CompiledBlockPaginationQueryParams, + BlockPaginationQueryParams, } from './schemas'; import { parseDbNakamotoBlock } from './helpers'; import { InvalidRequestError } from '../../../errors'; @@ -28,10 +28,10 @@ export function createV2BlocksRouter(db: PgStore): express.Router { '/', cacheHandler, asyncHandler(async (req, res) => { - if (!validRequestQuery(req, res, CompiledBlocksQueryParams)) return; - const query = req.query as BlocksQueryParams; + if (!validRequestQuery(req, res, CompiledBlockPaginationQueryParams)) return; + const query = req.query as BlockPaginationQueryParams; - const { limit, offset, results, total } = await db.getV2Blocks(query); + const { limit, offset, results, total } = await db.v2.getBlocks(query); const response: NakamotoBlockListResponse = { limit, offset, @@ -50,7 +50,7 @@ export function createV2BlocksRouter(db: PgStore): express.Router { if (!validRequestParams(req, res, CompiledBlockParams)) return; const params = req.params as BlockParams; - const block = await db.getV2Block(params); + const block = await db.v2.getBlock(params); if (!block) { res.status(404).json({ errors: 'Not found' }); return; @@ -73,7 +73,7 @@ export function createV2BlocksRouter(db: PgStore): express.Router { const query = req.query as TransactionPaginationQueryParams; try { - const { limit, offset, results, total } = await db.getV2BlockTransactions({ + const { limit, offset, results, total } = await db.v2.getBlockTransactions({ ...params, ...query, }); diff --git a/src/api/routes/v2/burn-blocks.ts b/src/api/routes/v2/burn-blocks.ts index 1f2d5c323e..72b51e9eac 100644 --- a/src/api/routes/v2/burn-blocks.ts +++ b/src/api/routes/v2/burn-blocks.ts @@ -1,9 +1,12 @@ import * as express from 'express'; -import { BurnBlockListResponse } from '@stacks/stacks-blockchain-api-types'; +import { + BurnBlockListResponse, + NakamotoBlockListResponse, +} from '@stacks/stacks-blockchain-api-types'; import { getETagCacheHandler, setETagCacheHeaders } from '../../controllers/cache-controller'; import { asyncHandler } from '../../async-handler'; import { PgStore } from '../../../datastore/pg-store'; -import { parseDbBurnBlock } from './helpers'; +import { parseDbBurnBlock, parseDbNakamotoBlock } from './helpers'; import { BlockPaginationQueryParams, BlockParams, @@ -12,6 +15,7 @@ import { validRequestParams, validRequestQuery, } from './schemas'; +import { InvalidRequestError } from '../../../errors'; export function createV2BurnBlocksRouter(db: PgStore): express.Router { const router = express.Router(); @@ -24,7 +28,7 @@ export function createV2BurnBlocksRouter(db: PgStore): express.Router { if (!validRequestQuery(req, res, CompiledBlockPaginationQueryParams)) return; const query = req.query as BlockPaginationQueryParams; - const { limit, offset, results, total } = await db.getBurnBlocks(query); + const { limit, offset, results, total } = await db.v2.getBurnBlocks(query); const response: BurnBlockListResponse = { limit, offset, @@ -43,7 +47,7 @@ export function createV2BurnBlocksRouter(db: PgStore): express.Router { if (!validRequestParams(req, res, CompiledBlockParams)) return; const params = req.params as BlockParams; - const block = await db.getBurnBlock(params); + const block = await db.v2.getBurnBlock(params); if (!block) { res.status(404).json({ errors: 'Not found' }); return; @@ -53,5 +57,40 @@ export function createV2BurnBlocksRouter(db: PgStore): express.Router { }) ); + router.get( + '/:height_or_hash/blocks', + cacheHandler, + asyncHandler(async (req, res) => { + if ( + !validRequestParams(req, res, CompiledBlockParams) || + !validRequestQuery(req, res, CompiledBlockPaginationQueryParams) + ) + return; + const params = req.params as BlockParams; + const query = req.query as BlockPaginationQueryParams; + + try { + const { limit, offset, results, total } = await db.v2.getBlocksByBurnBlock({ + ...params, + ...query, + }); + const response: NakamotoBlockListResponse = { + limit, + offset, + total, + results: results.map(r => parseDbNakamotoBlock(r)), + }; + setETagCacheHeaders(res); + res.json(response); + } catch (error) { + if (error instanceof InvalidRequestError) { + res.status(404).json({ errors: error.message }); + return; + } + throw error; + } + }) + ); + return router; } diff --git a/src/api/routes/v2/schemas.ts b/src/api/routes/v2/schemas.ts index 50d3f12d69..5be6a3b7e5 100644 --- a/src/api/routes/v2/schemas.ts +++ b/src/api/routes/v2/schemas.ts @@ -113,30 +113,6 @@ export const CompiledTransactionPaginationQueryParams = ajv.compile( TransactionPaginationQueryParamsSchema ); -const BlocksQueryParamsSchema = Type.Union([ - BlockPaginationQueryParamsSchema, - Type.Composite( - [ - Type.Object({ - burn_block_hash: Type.Union([Type.Literal('latest'), BurnBlockHashParamSchema]), - }), - BlockPaginationQueryParamsSchema, - ], - { additionalProperties: false } - ), - Type.Composite( - [ - Type.Object({ - burn_block_height: Type.Union([Type.Literal('latest'), BurnBlockHeightParamSchema]), - }), - BlockPaginationQueryParamsSchema, - ], - { additionalProperties: false } - ), -]); -export type BlocksQueryParams = Static; -export const CompiledBlocksQueryParams = ajv.compile(BlocksQueryParamsSchema); - const BlockParamsSchema = Type.Object( { height_or_hash: Type.Union([ diff --git a/src/datastore/pg-store-v2.ts b/src/datastore/pg-store-v2.ts new file mode 100644 index 0000000000..53b63f4aca --- /dev/null +++ b/src/datastore/pg-store-v2.ts @@ -0,0 +1,233 @@ +import { BasePgStoreModule } from '@hirosystems/api-toolkit'; +import { + BlockLimitParamSchema, + CompiledBurnBlockHashParam, + TransactionPaginationQueryParams, + TransactionLimitParamSchema, + BlockParams, + BlockPaginationQueryParams, +} from '../api/routes/v2/schemas'; +import { InvalidRequestError, InvalidRequestErrorType } from '../errors'; +import { normalizeHashString } from '../helpers'; +import { + DbPaginatedResult, + DbBlock, + BlockQueryResult, + DbTx, + TxQueryResult, + DbBurnBlock, +} from './common'; +import { BLOCK_COLUMNS, parseBlockQueryResult, TX_COLUMNS, parseTxQueryResult } from './helpers'; + +export class PgStoreV2 extends BasePgStoreModule { + async getBlocks(args: BlockPaginationQueryParams): Promise> { + return await this.sqlTransaction(async sql => { + const limit = args.limit ?? BlockLimitParamSchema.default; + const offset = args.offset ?? 0; + const blocksQuery = await sql<(BlockQueryResult & { total: number })[]>` + WITH block_count AS ( + SELECT block_count AS count FROM chain_tip + ) + SELECT + ${sql(BLOCK_COLUMNS)}, + (SELECT count FROM block_count)::int AS total + FROM blocks + WHERE canonical = true + ORDER BY block_height DESC + LIMIT ${limit} + OFFSET ${offset} + `; + if (blocksQuery.count === 0) + return { + limit, + offset, + results: [], + total: 0, + }; + const blocks = blocksQuery.map(b => parseBlockQueryResult(b)); + return { + limit, + offset, + results: blocks, + total: blocksQuery[0].total, + }; + }); + } + + async getBlocksByBurnBlock( + args: BlockParams & BlockPaginationQueryParams + ): Promise> { + return await this.sqlTransaction(async sql => { + const limit = args.limit ?? BlockLimitParamSchema.default; + const offset = args.offset ?? 0; + const filter = + args.height_or_hash === 'latest' + ? sql`burn_block_hash = (SELECT burn_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : CompiledBurnBlockHashParam(args.height_or_hash) + ? sql`burn_block_hash = ${normalizeHashString(args.height_or_hash)}` + : sql`burn_block_height = ${args.height_or_hash}`; + const blockCheck = await sql`SELECT burn_block_hash FROM blocks WHERE ${filter} LIMIT 1`; + if (blockCheck.count === 0) + throw new InvalidRequestError( + `Burn block not found`, + InvalidRequestErrorType.invalid_param + ); + + const blocksQuery = await sql<(BlockQueryResult & { total: number })[]>` + WITH block_count AS ( + SELECT COUNT(*) AS count FROM blocks WHERE canonical = TRUE AND ${filter} + ) + SELECT + ${sql(BLOCK_COLUMNS)}, + (SELECT count FROM block_count)::int AS total + FROM blocks + WHERE canonical = true AND ${filter} + ORDER BY block_height DESC + LIMIT ${limit} + OFFSET ${offset} + `; + if (blocksQuery.count === 0) + return { + limit, + offset, + results: [], + total: 0, + }; + const blocks = blocksQuery.map(b => parseBlockQueryResult(b)); + return { + limit, + offset, + results: blocks, + total: blocksQuery[0].total, + }; + }); + } + + async getBlock(args: BlockParams): Promise { + return await this.sqlTransaction(async sql => { + const filter = + args.height_or_hash === 'latest' + ? sql`index_block_hash = (SELECT index_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : CompiledBurnBlockHashParam(args.height_or_hash) + ? sql`( + block_hash = ${normalizeHashString(args.height_or_hash)} + OR index_block_hash = ${normalizeHashString(args.height_or_hash)} + )` + : sql`block_height = ${args.height_or_hash}`; + const blockQuery = await sql` + SELECT ${sql(BLOCK_COLUMNS)} + FROM blocks + WHERE canonical = true AND ${filter} + LIMIT 1 + `; + if (blockQuery.count > 0) return parseBlockQueryResult(blockQuery[0]); + }); + } + + async getBlockTransactions( + args: BlockParams & TransactionPaginationQueryParams + ): Promise> { + return await this.sqlTransaction(async sql => { + const limit = args.limit ?? TransactionLimitParamSchema.default; + const offset = args.offset ?? 0; + const filter = + args.height_or_hash === 'latest' + ? sql`index_block_hash = (SELECT index_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : CompiledBurnBlockHashParam(args.height_or_hash) + ? sql`( + block_hash = ${normalizeHashString(args.height_or_hash)} + OR index_block_hash = ${normalizeHashString(args.height_or_hash)} + )` + : sql`block_height = ${args.height_or_hash}`; + const blockCheck = await sql`SELECT index_block_hash FROM blocks WHERE ${filter} LIMIT 1`; + if (blockCheck.count === 0) + throw new InvalidRequestError(`Block not found`, InvalidRequestErrorType.invalid_param); + const txsQuery = await sql<(TxQueryResult & { total: number })[]>` + WITH tx_count AS ( + SELECT tx_count AS total FROM blocks WHERE canonical = TRUE AND ${filter} + ) + SELECT ${sql(TX_COLUMNS)}, (SELECT total FROM tx_count)::int AS total + FROM txs + WHERE canonical = true + AND microblock_canonical = true + AND ${filter} + ORDER BY microblock_sequence ASC, tx_index ASC + LIMIT ${limit} + OFFSET ${offset} + `; + if (txsQuery.count === 0) + return { + limit, + offset, + results: [], + total: 0, + }; + return { + limit, + offset, + results: txsQuery.map(t => parseTxQueryResult(t)), + total: txsQuery[0].total, + }; + }); + } + + async getBurnBlocks(args: BlockPaginationQueryParams): Promise> { + return await this.sqlTransaction(async sql => { + const limit = args.limit ?? BlockLimitParamSchema.default; + const offset = args.offset ?? 0; + const blocksQuery = await sql<(DbBurnBlock & { total: number })[]>` + WITH block_count AS ( + SELECT burn_block_height, block_count AS count FROM chain_tip + ) + SELECT DISTINCT ON (burn_block_height) + burn_block_time, + burn_block_hash, + burn_block_height, + ARRAY_AGG(block_hash) OVER ( + PARTITION BY burn_block_height + ORDER BY block_height DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS stacks_blocks, + (SELECT count FROM block_count)::int AS total + FROM blocks + WHERE canonical = true + ORDER BY burn_block_height DESC, block_height DESC + LIMIT ${limit} + OFFSET ${offset} + `; + const blocks = blocksQuery.map(r => r); + return { + limit, + offset, + results: blocks, + total: blocks[0].total, + }; + }); + } + + async getBurnBlock(args: BlockParams): Promise { + return await this.sqlTransaction(async sql => { + const filter = + args.height_or_hash === 'latest' + ? sql`burn_block_hash = (SELECT burn_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` + : CompiledBurnBlockHashParam(args.height_or_hash) + ? sql`burn_block_hash = ${args.height_or_hash}` + : sql`burn_block_height = ${args.height_or_hash}`; + const blockQuery = await sql` + SELECT DISTINCT ON (burn_block_height) + burn_block_time, + burn_block_hash, + burn_block_height, + ARRAY_AGG(block_hash) OVER ( + PARTITION BY burn_block_height + ORDER BY block_height DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) AS stacks_blocks + FROM blocks + WHERE canonical = true AND ${filter} + LIMIT 1 + `; + if (blockQuery.count > 0) return blockQuery[0]; + }); + } +} diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 369ce243fd..edcb61c4fa 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -15,7 +15,6 @@ import { bnsNameFromSubdomain, ChainID, REPO_DIR, - normalizeHashString, } from '../helpers'; import { PgStoreEventEmitter } from './pg-store-event-emitter'; import { @@ -29,7 +28,6 @@ import { DbBnsNamespace, DbBnsSubdomain, DbBnsZoneFile, - DbBurnBlock, DbBurnchainReward, DbChainTip, DbEvent, @@ -44,7 +42,6 @@ import { DbMicroblock, DbMinerReward, DbNftEvent, - DbPaginatedResult, DbRewardSlotHolder, DbSearchResult, DbSmartContract, @@ -71,7 +68,6 @@ import { PoxSyntheticEventTable, DbPoxStacker, DbPoxSyntheticEvent, - TxQueryResult, } from './common'; import { abiColumn, @@ -103,16 +99,7 @@ import { getPgConnectionEnvValue, } from './connection'; import * as path from 'path'; -import { - BlockLimitParamSchema, - BlockPaginationQueryParams, - BlocksQueryParams, - BlockParams, - TransactionPaginationQueryParams, - TransactionLimitParamSchema, - CompiledBurnBlockHashParam, -} from '../api/routes/v2/schemas'; -import { InvalidRequestError, InvalidRequestErrorType } from '../errors'; +import { PgStoreV2 } from './pg-store-v2'; export const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); @@ -123,6 +110,7 @@ export const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); * happened in the `PgServer.primary` server (see `.env`). */ export class PgStore extends BasePgStore { + readonly v2: PgStoreV2; readonly eventEmitter: PgStoreEventEmitter; readonly notifier?: PgNotifier; @@ -130,6 +118,7 @@ export class PgStore extends BasePgStore { super(sql); this.notifier = notifier; this.eventEmitter = new PgStoreEventEmitter(); + this.v2 = new PgStoreV2(this); } static async connect({ @@ -404,66 +393,6 @@ export class PgStore extends BasePgStore { return { found: true, result: block } as const; } - async getBurnBlocks(args: BlockPaginationQueryParams): Promise> { - return await this.sqlTransaction(async sql => { - const limit = args.limit ?? BlockLimitParamSchema.default; - const offset = args.offset ?? 0; - const blocksQuery = await sql<(DbBurnBlock & { total: number })[]>` - WITH block_count AS ( - SELECT burn_block_height, block_count AS count FROM chain_tip - ) - SELECT DISTINCT ON (burn_block_height) - burn_block_time, - burn_block_hash, - burn_block_height, - ARRAY_AGG(block_hash) OVER ( - PARTITION BY burn_block_height - ORDER BY block_height DESC - ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING - ) AS stacks_blocks, - (SELECT count FROM block_count)::int AS total - FROM blocks - WHERE canonical = true - ORDER BY burn_block_height DESC, block_height DESC - LIMIT ${limit} - OFFSET ${offset} - `; - const blocks = blocksQuery.map(r => r); - return { - limit, - offset, - results: blocks, - total: blocks[0].total, - }; - }); - } - - async getBurnBlock(args: BlockParams): Promise { - return await this.sqlTransaction(async sql => { - const filter = - args.height_or_hash === 'latest' - ? sql`burn_block_hash = (SELECT burn_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` - : CompiledBurnBlockHashParam(args.height_or_hash) - ? sql`burn_block_hash = ${args.height_or_hash}` - : sql`burn_block_height = ${args.height_or_hash}`; - const blockQuery = await sql` - SELECT DISTINCT ON (burn_block_height) - burn_block_time, - burn_block_hash, - burn_block_height, - ARRAY_AGG(block_hash) OVER ( - PARTITION BY burn_block_height - ORDER BY block_height DESC - ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING - ) AS stacks_blocks - FROM blocks - WHERE canonical = true AND ${filter} - LIMIT 1 - `; - if (blockQuery.count > 0) return blockQuery[0]; - }); - } - /** * Returns Block information with metadata, including accepted and streamed microblocks hash * @returns `BlocksWithMetadata` object including list of Blocks with metadata and total count. @@ -573,143 +502,6 @@ export class PgStore extends BasePgStore { }); } - /** - * Returns Block information with transaction IDs - * @returns Paginated `DbBlock` array - */ - async getV2Blocks(args: BlocksQueryParams): Promise> { - return await this.sqlTransaction(async sql => { - const limit = args.limit ?? BlockLimitParamSchema.default; - const offset = args.offset ?? 0; - const burnBlockHashCond = - 'burn_block_hash' in args - ? sql`burn_block_hash = ${ - args.burn_block_hash === 'latest' - ? sql`(SELECT burn_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` - : sql`${normalizeHashString(args.burn_block_hash)}` - }` - : undefined; - const burnBlockHeightCond = - 'burn_block_height' in args - ? sql`burn_block_height = ${ - args.burn_block_height === 'latest' - ? sql`(SELECT burn_block_height FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` - : sql`${args.burn_block_height}` - }` - : undefined; - - // Obtain blocks and transaction counts in the same query. - const blocksQuery = await sql<(BlockQueryResult & { total: number })[]>` - WITH block_count AS ( - ${ - 'burn_block_hash' in args - ? sql`SELECT COUNT(*) AS count FROM blocks WHERE canonical = TRUE AND ${burnBlockHashCond}` - : 'burn_block_height' in args - ? sql`SELECT COUNT(*) AS count FROM blocks WHERE canonical = TRUE AND ${burnBlockHeightCond}` - : sql`SELECT block_count AS count FROM chain_tip` - } - ) - SELECT - ${sql(BLOCK_COLUMNS)}, - (SELECT count FROM block_count)::int AS total - FROM blocks - WHERE canonical = true - AND ${ - 'burn_block_hash' in args - ? burnBlockHashCond - : 'burn_block_height' in args - ? burnBlockHeightCond - : sql`TRUE` - } - ORDER BY block_height DESC - LIMIT ${limit} - OFFSET ${offset} - `; - if (blocksQuery.count === 0) - return { - limit, - offset, - results: [], - total: 0, - }; - const blocks = blocksQuery.map(b => parseBlockQueryResult(b)); - return { - limit, - offset, - results: blocks, - total: blocksQuery[0].total, - }; - }); - } - - async getV2Block(args: BlockParams): Promise { - return await this.sqlTransaction(async sql => { - const filter = - args.height_or_hash === 'latest' - ? sql`index_block_hash = (SELECT index_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` - : CompiledBurnBlockHashParam(args.height_or_hash) - ? sql`( - block_hash = ${normalizeHashString(args.height_or_hash)} - OR index_block_hash = ${normalizeHashString(args.height_or_hash)} - )` - : sql`block_height = ${args.height_or_hash}`; - const blockQuery = await sql` - SELECT ${sql(BLOCK_COLUMNS)} - FROM blocks - WHERE canonical = true AND ${filter} - LIMIT 1 - `; - if (blockQuery.count > 0) return parseBlockQueryResult(blockQuery[0]); - }); - } - - async getV2BlockTransactions( - args: BlockParams & TransactionPaginationQueryParams - ): Promise> { - return await this.sqlTransaction(async sql => { - const limit = args.limit ?? TransactionLimitParamSchema.default; - const offset = args.offset ?? 0; - const filter = - args.height_or_hash === 'latest' - ? sql`index_block_hash = (SELECT index_block_hash FROM blocks WHERE canonical = TRUE ORDER BY block_height DESC LIMIT 1)` - : CompiledBurnBlockHashParam(args.height_or_hash) - ? sql`( - block_hash = ${normalizeHashString(args.height_or_hash)} - OR index_block_hash = ${normalizeHashString(args.height_or_hash)} - )` - : sql`block_height = ${args.height_or_hash}`; - const blockCheck = await sql`SELECT index_block_hash FROM blocks WHERE ${filter} LIMIT 1`; - if (blockCheck.count === 0) - throw new InvalidRequestError(`Block not found`, InvalidRequestErrorType.invalid_param); - const txsQuery = await sql<(TxQueryResult & { total: number })[]>` - WITH tx_count AS ( - SELECT tx_count AS total FROM blocks WHERE canonical = TRUE AND ${filter} - ) - SELECT ${sql(TX_COLUMNS)}, (SELECT total FROM tx_count)::int AS total - FROM txs - WHERE canonical = true - AND microblock_canonical = true - AND ${filter} - ORDER BY microblock_sequence ASC, tx_index ASC - LIMIT ${limit} - OFFSET ${offset} - `; - if (txsQuery.count === 0) - return { - limit, - offset, - results: [], - total: 0, - }; - return { - limit, - offset, - results: txsQuery.map(t => parseTxQueryResult(t)), - total: txsQuery[0].total, - }; - }); - } - /** * @deprecated Only used in tests */ diff --git a/src/tests/block-tests.ts b/src/tests/block-tests.ts index 44616f58d8..1517961d2f 100644 --- a/src/tests/block-tests.ts +++ b/src/tests/block-tests.ts @@ -678,7 +678,7 @@ describe('block tests', () => { tx_count: 1, }; let fetch = await supertest(api.server).get( - `/extended/v2/blocks?burn_block_hash=00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8` + `/extended/v2/burn-blocks/00000000000000000001e2ee7f0c6bd5361b5e7afd76156ca7d6f524ee5ca3d8/blocks` ); let json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); @@ -686,7 +686,7 @@ describe('block tests', () => { expect(json.results[0]).toStrictEqual(block5); // Filter by burn height - fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_height=700000`); + fetch = await supertest(api.server).get(`/extended/v2/burn-blocks/700000/blocks`); json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); expect(json.total).toEqual(5); @@ -712,25 +712,14 @@ describe('block tests', () => { parent_index_block_hash: '0x0007', tx_count: 1, }; - fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_hash=latest`); + fetch = await supertest(api.server).get(`/extended/v2/burn-blocks/latest/blocks`); json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); expect(json.total).toEqual(3); expect(json.results[0]).toStrictEqual(block8); - fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_height=latest`); - json = JSON.parse(fetch.text); - expect(fetch.status).toBe(200); - expect(json.total).toEqual(3); - expect(json.results[0]).toStrictEqual(block8); - - // Can't filter by both params - fetch = await supertest(api.server).get( - `/extended/v2/blocks?burn_block_hash=latest&burn_block_height=latest` - ); - expect(fetch.status).toBe(400); // Block hashes are validated - fetch = await supertest(api.server).get(`/extended/v2/blocks?burn_block_hash=testvalue`); + fetch = await supertest(api.server).get(`/extended/v2/burn-blocks/testvalue/blocks`); expect(fetch.status).toBe(400); }); From d7354ffe7bff9e2153bc530814040507a9d70280 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 3 Jan 2024 15:25:56 +0000 Subject: [PATCH 62/91] chore(release): 7.4.0-nakamoto.11 [skip ci] ## [7.4.0-nakamoto.11](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.10...v7.4.0-nakamoto.11) (2024-01-03) ### Features * create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint ([#1782](https://github.com/hirosystems/stacks-blockchain-api/issues/1782)) ([20466a1](https://github.com/hirosystems/stacks-blockchain-api/commit/20466a16573bff1634bc9b6ff1180bb8e0f620a0)) ### Bug Fixes * optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([3a02f57](https://github.com/hirosystems/stacks-blockchain-api/commit/3a02f5741f4109c1e662b4e7014189ae95430df8)) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index efe044a344..6a6c9f6680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [7.4.0-nakamoto.11](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.10...v7.4.0-nakamoto.11) (2024-01-03) + + +### Features + +* create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint ([#1782](https://github.com/hirosystems/stacks-blockchain-api/issues/1782)) ([20466a1](https://github.com/hirosystems/stacks-blockchain-api/commit/20466a16573bff1634bc9b6ff1180bb8e0f620a0)) + + +### Bug Fixes + +* optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([3a02f57](https://github.com/hirosystems/stacks-blockchain-api/commit/3a02f5741f4109c1e662b4e7014189ae95430df8)) + ## [7.4.0-nakamoto.10](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.9...v7.4.0-nakamoto.10) (2024-01-01) From ea9c3783e62715747db06eea5dd837297271c21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Wed, 3 Jan 2024 14:53:21 -0600 Subject: [PATCH 63/91] feat: add `/extended/v2/mempool/fees` endpoint (#1795) * docs: endpoints * feat: fees endpoint * test: strict eq --- .../mempool/get-fee-priorities.example.json | 26 +++++ .../mempool/get-fee-priorities.schema.json | 107 ++++++++++++++++++ docs/generated.d.ts | 30 +++++ docs/openapi.yaml | 20 ++++ src/api/init.ts | 16 +++ src/api/v2/mempool.ts | 55 +++++++++ src/datastore/common.ts | 8 ++ src/datastore/pg-store.ts | 39 +++++++ src/test-utils/test-builders.ts | 7 +- src/tests/mempool-tests.ts | 98 ++++++++++++++++ 10 files changed, 403 insertions(+), 3 deletions(-) create mode 100644 docs/api/mempool/get-fee-priorities.example.json create mode 100644 docs/api/mempool/get-fee-priorities.schema.json create mode 100644 src/api/v2/mempool.ts diff --git a/docs/api/mempool/get-fee-priorities.example.json b/docs/api/mempool/get-fee-priorities.example.json new file mode 100644 index 0000000000..0dd1ac80c1 --- /dev/null +++ b/docs/api/mempool/get-fee-priorities.example.json @@ -0,0 +1,26 @@ +{ + "all": { + "no_priority": 3000, + "low_priority": 3000, + "medium_priority": 6000, + "high_priority": 401199 + }, + "token_transfer": { + "no_priority": 3000, + "low_priority": 3000, + "medium_priority": 6000, + "high_priority": 401199 + }, + "smart_contract": { + "no_priority": 837500, + "low_priority": 925000, + "medium_priority": 1012500, + "high_priority": 1082500 + }, + "contract_call": { + "no_priority": 3000, + "low_priority": 10368, + "medium_priority": 100000, + "high_priority": 1000000 + } +} diff --git a/docs/api/mempool/get-fee-priorities.schema.json b/docs/api/mempool/get-fee-priorities.schema.json new file mode 100644 index 0000000000..3a2c804527 --- /dev/null +++ b/docs/api/mempool/get-fee-priorities.schema.json @@ -0,0 +1,107 @@ +{ + "description": "GET request that returns fee priorities from mempool transactions", + "title": "MempoolFeePriorities", + "type": "object", + "additionalProperties": false, + "required": [ + "all" + ], + "properties": { + "all": { + "type": "object", + "additionalProperties": false, + "required": [ + "no_priority", + "low_priority", + "medium_priority", + "high_priority" + ], + "properties": { + "no_priority": { + "type": "integer" + }, + "low_priority": { + "type": "integer" + }, + "medium_priority": { + "type": "integer" + }, + "high_priority": { + "type": "integer" + } + } + }, + "token_transfer": { + "type": "object", + "additionalProperties": false, + "required": [ + "no_priority", + "low_priority", + "medium_priority", + "high_priority" + ], + "properties": { + "no_priority": { + "type": "integer" + }, + "low_priority": { + "type": "integer" + }, + "medium_priority": { + "type": "integer" + }, + "high_priority": { + "type": "integer" + } + } + }, + "smart_contract": { + "type": "object", + "additionalProperties": false, + "required": [ + "no_priority", + "low_priority", + "medium_priority", + "high_priority" + ], + "properties": { + "no_priority": { + "type": "integer" + }, + "low_priority": { + "type": "integer" + }, + "medium_priority": { + "type": "integer" + }, + "high_priority": { + "type": "integer" + } + } + }, + "contract_call": { + "type": "object", + "additionalProperties": false, + "required": [ + "no_priority", + "low_priority", + "medium_priority", + "high_priority" + ], + "properties": { + "no_priority": { + "type": "integer" + }, + "low_priority": { + "type": "integer" + }, + "medium_priority": { + "type": "integer" + }, + "high_priority": { + "type": "integer" + } + } + } + } +} diff --git a/docs/generated.d.ts b/docs/generated.d.ts index 450d834b3e..53220d028e 100644 --- a/docs/generated.d.ts +++ b/docs/generated.d.ts @@ -49,6 +49,7 @@ export type SchemaMergeRootStub = | GetStxSupplyLegacyFormatResponse | GetStxTotalSupplyPlainResponse | GetStxSupplyResponse + | MempoolFeePriorities | MicroblockListResponse | UnanchoredTransactionListResponse | RosettaAccountBalanceRequest @@ -1694,6 +1695,35 @@ export interface GetStxSupplyResponse { */ block_height: number; } +/** + * GET request that returns fee priorities from mempool transactions + */ +export interface MempoolFeePriorities { + all: { + no_priority: number; + low_priority: number; + medium_priority: number; + high_priority: number; + }; + token_transfer?: { + no_priority: number; + low_priority: number; + medium_priority: number; + high_priority: number; + }; + smart_contract?: { + no_priority: number; + low_priority: number; + medium_priority: number; + high_priority: number; + }; + contract_call?: { + no_priority: number; + low_priority: number; + medium_priority: number; + high_priority: number; + }; +} /** * GET request that returns microblocks */ diff --git a/docs/openapi.yaml b/docs/openapi.yaml index ecc7f74b8c..7e3394ed43 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -69,6 +69,8 @@ tags: externalDocs: description: Hiro Documentation - Transactions url: https://docs.hiro.so/get-started/transactions + - name: Mempool + description: Endpoints to obtain Mempool information paths: /extended/v1/faucets/stx: @@ -296,6 +298,24 @@ paths: example: $ref: ./api/transaction/get-mempool-transactions.example.json + /extended/v2/mempool/fees: + get: + summary: Get mempool transaction fee priorities + tags: + - Mempool + operationId: get_mempool_fee_priorities + description: | + Returns estimated fee priorities (in micro-STX) for all transactions that are currently in the mempool. Also returns priorities separated by transaction type. + responses: + 200: + description: Mempool fee priorities + content: + application/json: + schema: + $ref: ./api/transaction/get-mempool-transactions.schema.json + example: + $ref: ./api/transaction/get-mempool-transactions.example.json + /extended/v1/tx/mempool/dropped: get: summary: Get dropped mempool transactions diff --git a/src/api/init.ts b/src/api/init.ts index 546c2d4086..57589b2fa7 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -45,6 +45,7 @@ import { createPox3EventsRouter } from './routes/pox3'; import { isPgConnectionError } from '../datastore/helpers'; import { createStackingRouter } from './routes/stacking'; import { logger, loggerMiddleware } from '../logger'; +import { createMempoolRouter } from './v2/mempool'; export interface ApiServer { expressApp: express.Express; @@ -220,6 +221,21 @@ export async function startApiServer(opts: { })() ); + app.use( + '/extended/v2', + (() => { + const router = express.Router(); + router.use(cors()); + router.use((req, res, next) => { + // Set caching on all routes to be disabled by default, individual routes can override + res.set('Cache-Control', 'no-store'); + next(); + }); + router.use('/mempool', createMempoolRouter(datastore)); + return router; + })() + ); + app.use( '/extended/beta', (() => { diff --git a/src/api/v2/mempool.ts b/src/api/v2/mempool.ts new file mode 100644 index 0000000000..c106b06711 --- /dev/null +++ b/src/api/v2/mempool.ts @@ -0,0 +1,55 @@ +import * as express from 'express'; +import { asyncHandler } from '../async-handler'; +import { + ETagType, + getETagCacheHandler, + setETagCacheHeaders, +} from '../controllers/cache-controller'; +import { PgStore } from '../../datastore/pg-store'; +import { DbMempoolFeePriority, DbTxTypeId } from '../../datastore/common'; +import { MempoolFeePriorities } from '../../../docs/generated'; + +function parseMempoolFeePriority(fees: DbMempoolFeePriority[]): MempoolFeePriorities { + const out: MempoolFeePriorities = { + all: { no_priority: 0, low_priority: 0, medium_priority: 0, high_priority: 0 }, + }; + for (const fee of fees) { + const value = { + no_priority: fee.no_priority, + low_priority: fee.low_priority, + medium_priority: fee.medium_priority, + high_priority: fee.high_priority, + }; + if (fee.type_id == null) out.all = value; + else + switch (fee.type_id) { + case DbTxTypeId.TokenTransfer: + out.token_transfer = value; + break; + case DbTxTypeId.ContractCall: + out.contract_call = value; + break; + case DbTxTypeId.SmartContract: + case DbTxTypeId.VersionedSmartContract: + out.smart_contract = value; + break; + } + } + return out; +} + +export function createMempoolRouter(db: PgStore): express.Router { + const router = express.Router(); + const mempoolCacheHandler = getETagCacheHandler(db, ETagType.mempool); + + router.get( + '/fees', + mempoolCacheHandler, + asyncHandler(async (req, res, next) => { + setETagCacheHeaders(res); + res.status(200).json(parseMempoolFeePriority(await db.getMempoolFeePriority())); + }) + ); + + return router; +} diff --git a/src/datastore/common.ts b/src/datastore/common.ts index 7378ac50f1..41f2cf7b9b 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -235,6 +235,14 @@ export interface DbMempoolStats { >; } +export interface DbMempoolFeePriority { + type_id: DbTxTypeId | null; + high_priority: number; + medium_priority: number; + low_priority: number; + no_priority: number; +} + export interface DbMempoolTx extends BaseTx { pruned: boolean; diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index 88d1776816..6e88170d53 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -38,6 +38,7 @@ import { DbGetBlockWithMetadataOpts, DbGetBlockWithMetadataResponse, DbInboundStxTransfer, + DbMempoolFeePriority, DbMempoolStats, DbMempoolTx, DbMicroblock, @@ -1286,6 +1287,44 @@ export class PgStore { }; } + async getMempoolFeePriority(): Promise { + const txFeesQuery = await this.sql` + WITH fees AS ( + ( + SELECT + NULL AS type_id, + ROUND(PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY fee_rate ASC)) AS high_priority, + ROUND(PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY fee_rate ASC)) AS medium_priority, + ROUND(PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY fee_rate ASC)) AS low_priority, + ROUND(PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY fee_rate ASC)) AS no_priority + FROM mempool_txs + WHERE pruned = FALSE + ) + UNION + ( + WITH txs_grouped AS ( + SELECT + (CASE type_id WHEN 6 THEN 1 ELSE type_id END) AS type_id, + fee_rate + FROM mempool_txs + WHERE pruned = FALSE + AND type_id NOT IN (4, 5) + ) + SELECT + type_id, + ROUND(PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY fee_rate ASC)) AS high_priority, + ROUND(PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY fee_rate ASC)) AS medium_priority, + ROUND(PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY fee_rate ASC)) AS low_priority, + ROUND(PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY fee_rate ASC)) AS no_priority + FROM txs_grouped + GROUP BY type_id + ) + ) + SELECT * FROM fees ORDER BY type_id ASC NULLS FIRST + `; + return txFeesQuery; + } + async getMempoolTxList({ limit, offset, diff --git a/src/test-utils/test-builders.ts b/src/test-utils/test-builders.ts index 700dbe790f..8146396528 100644 --- a/src/test-utils/test-builders.ts +++ b/src/test-utils/test-builders.ts @@ -16,7 +16,6 @@ import { DbBnsNamespace, DbEventTypeId, DbFtEvent, - DbMempoolTx, DbMempoolTxRaw, DbMicroblockPartial, DbMinerReward, @@ -259,6 +258,8 @@ interface TestMempoolTxArgs { smart_contract_contract_id?: string; status?: DbTxStatus; token_transfer_recipient_address?: string; + token_transfer_amount?: bigint; + token_transfer_memo?: string; tx_id?: string; type_id?: DbTxTypeId; nonce?: number; @@ -287,8 +288,8 @@ export function testMempoolTx(args?: TestMempoolTxArgs): DbMempoolTxRaw { sponsor_address: undefined, origin_hash_mode: 1, sender_address: args?.sender_address ?? SENDER_ADDRESS, - token_transfer_amount: 1234n, - token_transfer_memo: '', + token_transfer_amount: args?.token_transfer_amount ?? 1234n, + token_transfer_memo: args?.token_transfer_memo ?? '', token_transfer_recipient_address: args?.token_transfer_recipient_address ?? RECIPIENT_ADDRESS, smart_contract_clarity_version: args?.smart_contract_clarity_version, smart_contract_contract_id: args?.smart_contract_contract_id ?? CONTRACT_ID, diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index b44440fae4..f84bd13b20 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1532,4 +1532,102 @@ describe('mempool tests', () => { const txResult2 = await supertest(api.server).get(`/extended/v1/tx/${txId}`); expect(txResult2.body.tx_status).toBe('success'); }); + + test('returns fee priorities for mempool transactions', async () => { + const mempoolTxs: DbMempoolTxRaw[] = []; + for (let i = 0; i < 10; i++) { + const sender_address = 'SP25YGP221F01S9SSCGN114MKDAK9VRK8P3KXGEMB'; + const tx_id = `0x00000${i}`; + const fee_rate = BigInt(100000 * i); + const nonce = i; + if (i < 3) { + mempoolTxs.push({ + tx_id, + nonce, + fee_rate, + type_id: DbTxTypeId.ContractCall, + anchor_mode: 3, + raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + status: 1, + post_conditions: '0x01f5', + sponsored: false, + sponsor_address: undefined, + contract_call_contract_id: 'SP32AEEF6WW5Y0NMJ1S8SBSZDAY8R5J32NBZFPKKZ.free-punks-v0', + contract_call_function_name: 'test-func', + contract_call_function_args: '0x00', + sender_address, + origin_hash_mode: 1, + pruned: false, + receipt_time: 1616063078, + }); + } else if (i < 6) { + mempoolTxs.push({ + tx_id, + nonce, + type_id: DbTxTypeId.SmartContract, + fee_rate, + anchor_mode: 3, + raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + status: 1, + post_conditions: '0x01f5', + sponsored: false, + sponsor_address: undefined, + sender_address, + origin_hash_mode: 1, + pruned: false, + smart_contract_contract_id: 'some-versioned-smart-contract', + smart_contract_source_code: '(some-versioned-contract-src)', + receipt_time: 1616063078, + }); + } else { + mempoolTxs.push({ + tx_id, + nonce, + type_id: DbTxTypeId.TokenTransfer, + fee_rate, + anchor_mode: 3, + raw_tx: bufferToHexPrefixString(Buffer.from('test-raw-mempool-tx')), + status: 1, + post_conditions: '0x01f5', + sponsored: false, + sponsor_address: undefined, + sender_address, + token_transfer_amount: 100n, + token_transfer_memo: '0x010101', + token_transfer_recipient_address: 'STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6', + origin_hash_mode: 1, + pruned: false, + receipt_time: 1616063078, + }); + } + } + await db.updateMempoolTxs({ mempoolTxs }); + const result = await supertest(api.server).get(`/extended/v2/mempool/fees`); + expect(result.body).toStrictEqual({ + all: { + high_priority: 855000, + low_priority: 450000, + medium_priority: 675000, + no_priority: 225000, + }, + contract_call: { + high_priority: 190000, + low_priority: 100000, + medium_priority: 150000, + no_priority: 50000, + }, + smart_contract: { + high_priority: 490000, + low_priority: 400000, + medium_priority: 450000, + no_priority: 350000, + }, + token_transfer: { + high_priority: 885000, + low_priority: 750000, + medium_priority: 825000, + no_priority: 675000, + }, + }); + }); }); From f492251223176ff13802ae8d74b8f59b01fb0909 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 3 Jan 2024 20:59:47 +0000 Subject: [PATCH 64/91] chore(release): 7.4.0-beta.1 [skip ci] ## [7.4.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.7-beta.1...v7.4.0-beta.1) (2024-01-03) ### Features * add `/extended/v2/mempool/fees` endpoint ([#1795](https://github.com/hirosystems/stacks-blockchain-api/issues/1795)) ([ea9c378](https://github.com/hirosystems/stacks-blockchain-api/commit/ea9c3783e62715747db06eea5dd837297271c21e)) ### Bug Fixes * optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([#1792](https://github.com/hirosystems/stacks-blockchain-api/issues/1792)) ([2700642](https://github.com/hirosystems/stacks-blockchain-api/commit/2700642ed2225ce8598ee5fff833603007d5289f)) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 635d4d6702..bf11711912 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [7.4.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.7-beta.1...v7.4.0-beta.1) (2024-01-03) + + +### Features + +* add `/extended/v2/mempool/fees` endpoint ([#1795](https://github.com/hirosystems/stacks-blockchain-api/issues/1795)) ([ea9c378](https://github.com/hirosystems/stacks-blockchain-api/commit/ea9c3783e62715747db06eea5dd837297271c21e)) + + +### Bug Fixes + +* optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([#1792](https://github.com/hirosystems/stacks-blockchain-api/issues/1792)) ([2700642](https://github.com/hirosystems/stacks-blockchain-api/commit/2700642ed2225ce8598ee5fff833603007d5289f)) + ## [7.3.7-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.6...v7.3.7-beta.1) (2023-12-29) From 9853e29d89b2846454197438c7d1b4b636384d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Thu, 4 Jan 2024 10:58:42 -0600 Subject: [PATCH 65/91] fix: update client code, fix mempool fee return type (#1797) --- client/src/generated/.openapi-generator/FILES | 172 +++++ client/src/generated/apis/AccountsApi.ts | 550 +++++++++++++-- client/src/generated/apis/BlocksApi.ts | 214 +++++- client/src/generated/apis/BurnchainApi.ts | 214 ------ client/src/generated/apis/FaucetsApi.ts | 83 ++- client/src/generated/apis/FeesApi.ts | 148 +++- .../src/generated/apis/FungibleTokensApi.ts | 150 ++++ client/src/generated/apis/InfoApi.ts | 330 +++++++-- client/src/generated/apis/MempoolApi.ts | 80 +++ client/src/generated/apis/MicroblocksApi.ts | 196 ++++++ client/src/generated/apis/NamesApi.ts | 581 ++++++++++++++++ .../generated/apis/NonFungibleTokensApi.ts | 415 +++++++++++ client/src/generated/apis/RosettaApi.ts | 339 ++++----- client/src/generated/apis/SearchApi.ts | 26 +- .../src/generated/apis/SmartContractsApi.ts | 218 ++++-- client/src/generated/apis/StackingApi.ts | 113 +++ .../src/generated/apis/StackingRewardsApi.ts | 339 +++++++++ client/src/generated/apis/TransactionsApi.ts | 645 ++++++++++++++++-- client/src/generated/apis/index.ts | 10 +- client/src/generated/index.ts | 2 + .../generated/models/AccountDataResponse.ts | 7 +- .../models/AddressAssetsListResponse.ts | 7 +- .../models/AddressBalanceResponse.ts | 43 +- .../models/AddressNftListResponse.ts | 87 +++ .../models/AddressNftListResponseValue.ts | 64 ++ client/src/generated/models/AddressNonces.ts | 88 +++ .../models/AddressStxBalanceResponse.ts | 129 ---- .../models/AddressStxInboundListResponse.ts | 87 +++ .../models/AddressTokenOfferingLocked.ts | 79 +++ .../models/AddressTransactionWithTransfers.ts | 111 +++ ...ressTransactionWithTransfersFtTransfers.ts | 80 +++ ...essTransactionWithTransfersNftTransfers.ts | 87 +++ ...essTransactionWithTransfersStxTransfers.ts | 72 ++ .../AddressTransactionWithTransfersValue.ts | 64 ++ .../models/AddressTransactionsListResponse.ts | 7 +- ...ssTransactionsWithTransfersListResponse.ts | 87 +++ .../generated/models/AddressUnlockSchedule.ts | 64 ++ client/src/generated/models/Block.ts | 95 ++- .../src/generated/models/BlockListResponse.ts | 7 +- client/src/generated/models/BnsError.ts | 56 ++ .../models/BnsGetAllNamespacesResponse.ts | 56 ++ .../models/BnsGetNameInfoResponse.ts | 120 ++++ .../models/BnsGetNamePriceResponse.ts | 64 ++ .../models/BnsGetNamespacePriceResponse.ts | 64 ++ .../models/BnsNamesOwnByAddressResponse.ts | 56 ++ .../src/generated/models/BurnchainReward.ts | 7 +- .../models/BurnchainRewardListResponse.ts | 7 +- .../models/BurnchainRewardSlotHolder.ts | 88 +++ .../BurnchainRewardSlotHolderListResponse.ts | 87 +++ .../generated/models/BurnchainRewardsTotal.ts | 7 +- client/src/generated/models/ChainTip.ts | 96 +++ .../models/ContractInterfaceResponse.ts | 7 +- .../generated/models/ContractListResponse.ts | 79 +++ .../models/ContractSourceResponse.ts | 7 +- .../generated/models/CoreNodeInfoResponse.ts | 7 +- .../generated/models/CoreNodePoxResponse.ts | 7 +- client/src/generated/models/FeeRate.ts | 56 ++ client/src/generated/models/FeeRateRequest.ts | 56 ++ .../generated/models/FungibleTokenMetadata.ts | 120 ++++ .../models/FungibleTokensMetadataList.ts | 87 +++ .../models/GetRawTransactionResult.ts | 56 ++ .../GetStxSupplyLegacyFormatResponse.ts | 96 +++ .../generated/models/GetStxSupplyResponse.ts | 80 +++ .../generated/models/InboundStxTransfer.ts | 114 ++++ client/src/generated/models/InlineObject.ts | 56 ++ .../src/generated/models/InlineResponse403.ts | 64 ++ .../src/generated/models/MapEntryResponse.ts | 7 +- .../generated/models/MempoolFeePriorities.ts | 87 +++ .../models/MempoolFeePrioritiesAll.ts | 80 +++ .../models/MempoolTransactionListResponse.ts | 7 +- .../models/MempoolTransactionStatsResponse.ts | 99 +++ .../MempoolTransactionStatsResponseTxAges.ts | 87 +++ ...poolTransactionStatsResponseTxByteSizes.ts | 87 +++ ...sactionStatsResponseTxSimpleFeeAverages.ts | 87 +++ ...esponseTxSimpleFeeAveragesTokenTransfer.ts | 80 +++ ...oolTransactionStatsResponseTxTypeCounts.ts | 80 +++ client/src/generated/models/Microblock.ts | 160 +++++ .../models/MicroblockListResponse.ts | 87 +++ .../models/NetworkBlockTimeResponse.ts | 7 +- .../models/NetworkBlockTimesResponse.ts | 31 +- .../NetworkBlockTimesResponseMainnet.ts | 57 -- .../src/generated/models/NetworkIdentifier.ts | 7 +- client/src/generated/models/NftEvent.ts | 127 ++++ .../NonFungibleTokenHistoryEventList.ts | 80 +++ .../models/NonFungibleTokenHoldingsList.ts | 80 +++ .../models/NonFungibleTokenMetadata.ts | 104 +++ .../models/NonFungibleTokenMintList.ts | 80 +++ .../models/NonFungibleTokensMetadataList.ts | 87 +++ .../models/OtherTransactionIdentifier.ts | 56 ++ client/src/generated/models/PoolDelegation.ts | 96 +++ .../models/PoolDelegationsResponse.ts | 87 +++ .../models/PostCoreNodeTransactionsError.ts | 7 +- .../generated/models/ReadOnlyFunctionArgs.ts | 7 +- .../models/ReadOnlyFunctionSuccessResponse.ts | 7 +- client/src/generated/models/RosettaAccount.ts | 7 +- .../models/RosettaAccountBalanceRequest.ts | 7 +- .../models/RosettaAccountBalanceResponse.ts | 9 +- ...ttaAccountBalanceResponseCoinIdentifier.ts | 7 +- .../RosettaAccountBalanceResponseMetadata.ts | 7 +- .../models/RosettaAccountIdentifier.ts | 79 +++ client/src/generated/models/RosettaAmount.ts | 7 +- client/src/generated/models/RosettaBlock.ts | 25 +- .../generated/models/RosettaBlockMetadata.ts | 35 +- .../generated/models/RosettaBlockMetadata1.ts | 29 +- .../generated/models/RosettaBlockMetadata2.ts | 65 -- .../generated/models/RosettaBlockRequest.ts | 11 +- .../generated/models/RosettaBlockResponse.ts | 23 +- .../models/RosettaBlockTransactionRequest.ts | 9 +- .../models/RosettaBlockTransactionResponse.ts | 7 +- client/src/generated/models/RosettaCoin.ts | 7 +- .../src/generated/models/RosettaCoinChange.ts | 25 +- .../RosettaConstructionCombineRequest.ts | 7 +- .../RosettaConstructionCombineResponse.ts | 7 +- .../RosettaConstructionDeriveRequest.ts | 7 +- .../RosettaConstructionDeriveResponse.ts | 28 +- .../models/RosettaConstructionHashRequest.ts | 7 +- .../models/RosettaConstructionHashResponse.ts | 7 +- .../RosettaConstructionMetadataRequest.ts | 7 +- .../RosettaConstructionMetadataResponse.ts | 15 +- ...ttaConstructionMetadataResponseMetadata.ts | 7 +- .../models/RosettaConstructionParseRequest.ts | 7 +- .../RosettaConstructionParseResponse.ts | 31 +- .../RosettaConstructionPayloadResponse.ts | 7 +- .../RosettaConstructionPayloadsRequest.ts | 19 +- .../RosettaConstructionPreprocessRequest.ts | 23 +- .../RosettaConstructionPreprocessResponse.ts | 7 +- .../RosettaConstructionSubmitRequest.ts | 7 +- .../RosettaConstructionSubmitResponse.ts | 7 +- .../src/generated/models/RosettaCurrency.ts | 7 +- client/src/generated/models/RosettaError.ts | 7 +- .../generated/models/RosettaErrorDetails.ts | 7 +- .../generated/models/RosettaErrorNoDetails.ts | 72 ++ .../models/RosettaGenesisBlockIdentifier.ts | 64 ++ .../generated/models/RosettaMaxFeeAmount.ts | 79 +++ .../generated/models/RosettaMempoolRequest.ts | 7 +- .../models/RosettaMempoolResponse.ts | 7 +- .../RosettaMempoolTransactionRequest.ts | 7 +- .../RosettaMempoolTransactionResponse.ts | 7 +- .../models/RosettaNetworkListResponse.ts | 7 +- ...NetworkListResponseSubNetworkIdentifier.ts | 9 +- ...istResponseSubNetworkIdentifierMetadata.ts | 7 +- .../models/RosettaNetworkOptionsResponse.ts | 7 +- .../RosettaNetworkOptionsResponseAllow.ts | 23 +- .../RosettaNetworkOptionsResponseVersion.ts | 7 +- .../models/RosettaNetworkStatusResponse.ts | 115 ++++ .../models/RosettaOldestBlockIdentifier.ts | 64 ++ .../src/generated/models/RosettaOperation.ts | 25 +- .../models/RosettaOperationIdentifier.ts | 7 +- .../models/RosettaOperationStatus.ts | 7 +- client/src/generated/models/RosettaOptions.ts | 73 +- .../generated/models/RosettaOptionsRequest.ts | 7 +- .../models/RosettaParentBlockIdentifier.ts | 7 +- client/src/generated/models/RosettaPeers.ts | 64 ++ .../src/generated/models/RosettaPublicKey.ts | 25 +- .../models/RosettaRelatedOperation.ts | 28 +- .../src/generated/models/RosettaSignature.ts | 31 +- .../generated/models/RosettaStatusRequest.ts | 7 +- .../src/generated/models/RosettaSubAccount.ts | 7 +- .../src/generated/models/RosettaSyncStatus.ts | 80 +++ .../generated/models/RosettaTransaction.ts | 23 +- .../src/generated/models/RunFaucetResponse.ts | 9 +- .../generated/models/ServerStatusResponse.ts | 95 +++ client/src/generated/models/SigningPayload.ts | 33 +- client/src/generated/models/SmartContract.ts | 96 +++ ...essBalanceResponseStx.ts => StxBalance.ts} | 41 +- .../src/generated/models/TargetBlockTime.ts | 56 ++ .../models/TransactionEventsResponse.ts | 72 ++ .../models/TransactionFeeEstimateRequest.ts | 64 ++ .../models/TransactionFeeEstimateResponse.ts | 91 +++ ...sactionFeeEstimateResponseEstimatedCost.ts | 88 +++ ...ansactionFeeEstimateResponseEstimations.ts | 64 ++ .../generated/models/TransactionIdentifier.ts | 7 +- .../generated/models/TransactionResults.ts | 7 +- .../UnanchoredTransactionListResponse.ts | 64 ++ client/src/generated/models/index.ts | 75 +- client/src/generated/runtime.ts | 40 +- docs/openapi.yaml | 4 +- 177 files changed, 10412 insertions(+), 1505 deletions(-) create mode 100644 client/src/generated/.openapi-generator/FILES delete mode 100644 client/src/generated/apis/BurnchainApi.ts create mode 100644 client/src/generated/apis/FungibleTokensApi.ts create mode 100644 client/src/generated/apis/MempoolApi.ts create mode 100644 client/src/generated/apis/MicroblocksApi.ts create mode 100644 client/src/generated/apis/NamesApi.ts create mode 100644 client/src/generated/apis/NonFungibleTokensApi.ts create mode 100644 client/src/generated/apis/StackingApi.ts create mode 100644 client/src/generated/apis/StackingRewardsApi.ts create mode 100644 client/src/generated/models/AddressNftListResponse.ts create mode 100644 client/src/generated/models/AddressNftListResponseValue.ts create mode 100644 client/src/generated/models/AddressNonces.ts delete mode 100644 client/src/generated/models/AddressStxBalanceResponse.ts create mode 100644 client/src/generated/models/AddressStxInboundListResponse.ts create mode 100644 client/src/generated/models/AddressTokenOfferingLocked.ts create mode 100644 client/src/generated/models/AddressTransactionWithTransfers.ts create mode 100644 client/src/generated/models/AddressTransactionWithTransfersFtTransfers.ts create mode 100644 client/src/generated/models/AddressTransactionWithTransfersNftTransfers.ts create mode 100644 client/src/generated/models/AddressTransactionWithTransfersStxTransfers.ts create mode 100644 client/src/generated/models/AddressTransactionWithTransfersValue.ts create mode 100644 client/src/generated/models/AddressTransactionsWithTransfersListResponse.ts create mode 100644 client/src/generated/models/AddressUnlockSchedule.ts create mode 100644 client/src/generated/models/BnsError.ts create mode 100644 client/src/generated/models/BnsGetAllNamespacesResponse.ts create mode 100644 client/src/generated/models/BnsGetNameInfoResponse.ts create mode 100644 client/src/generated/models/BnsGetNamePriceResponse.ts create mode 100644 client/src/generated/models/BnsGetNamespacePriceResponse.ts create mode 100644 client/src/generated/models/BnsNamesOwnByAddressResponse.ts create mode 100644 client/src/generated/models/BurnchainRewardSlotHolder.ts create mode 100644 client/src/generated/models/BurnchainRewardSlotHolderListResponse.ts create mode 100644 client/src/generated/models/ChainTip.ts create mode 100644 client/src/generated/models/ContractListResponse.ts create mode 100644 client/src/generated/models/FeeRate.ts create mode 100644 client/src/generated/models/FeeRateRequest.ts create mode 100644 client/src/generated/models/FungibleTokenMetadata.ts create mode 100644 client/src/generated/models/FungibleTokensMetadataList.ts create mode 100644 client/src/generated/models/GetRawTransactionResult.ts create mode 100644 client/src/generated/models/GetStxSupplyLegacyFormatResponse.ts create mode 100644 client/src/generated/models/GetStxSupplyResponse.ts create mode 100644 client/src/generated/models/InboundStxTransfer.ts create mode 100644 client/src/generated/models/InlineObject.ts create mode 100644 client/src/generated/models/InlineResponse403.ts create mode 100644 client/src/generated/models/MempoolFeePriorities.ts create mode 100644 client/src/generated/models/MempoolFeePrioritiesAll.ts create mode 100644 client/src/generated/models/MempoolTransactionStatsResponse.ts create mode 100644 client/src/generated/models/MempoolTransactionStatsResponseTxAges.ts create mode 100644 client/src/generated/models/MempoolTransactionStatsResponseTxByteSizes.ts create mode 100644 client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAverages.ts create mode 100644 client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer.ts create mode 100644 client/src/generated/models/MempoolTransactionStatsResponseTxTypeCounts.ts create mode 100644 client/src/generated/models/Microblock.ts create mode 100644 client/src/generated/models/MicroblockListResponse.ts delete mode 100644 client/src/generated/models/NetworkBlockTimesResponseMainnet.ts create mode 100644 client/src/generated/models/NftEvent.ts create mode 100644 client/src/generated/models/NonFungibleTokenHistoryEventList.ts create mode 100644 client/src/generated/models/NonFungibleTokenHoldingsList.ts create mode 100644 client/src/generated/models/NonFungibleTokenMetadata.ts create mode 100644 client/src/generated/models/NonFungibleTokenMintList.ts create mode 100644 client/src/generated/models/NonFungibleTokensMetadataList.ts create mode 100644 client/src/generated/models/OtherTransactionIdentifier.ts create mode 100644 client/src/generated/models/PoolDelegation.ts create mode 100644 client/src/generated/models/PoolDelegationsResponse.ts create mode 100644 client/src/generated/models/RosettaAccountIdentifier.ts delete mode 100644 client/src/generated/models/RosettaBlockMetadata2.ts create mode 100644 client/src/generated/models/RosettaErrorNoDetails.ts create mode 100644 client/src/generated/models/RosettaGenesisBlockIdentifier.ts create mode 100644 client/src/generated/models/RosettaMaxFeeAmount.ts create mode 100644 client/src/generated/models/RosettaNetworkStatusResponse.ts create mode 100644 client/src/generated/models/RosettaOldestBlockIdentifier.ts create mode 100644 client/src/generated/models/RosettaPeers.ts create mode 100644 client/src/generated/models/RosettaSyncStatus.ts create mode 100644 client/src/generated/models/ServerStatusResponse.ts create mode 100644 client/src/generated/models/SmartContract.ts rename client/src/generated/models/{AddressBalanceResponseStx.ts => StxBalance.ts} (53%) create mode 100644 client/src/generated/models/TargetBlockTime.ts create mode 100644 client/src/generated/models/TransactionEventsResponse.ts create mode 100644 client/src/generated/models/TransactionFeeEstimateRequest.ts create mode 100644 client/src/generated/models/TransactionFeeEstimateResponse.ts create mode 100644 client/src/generated/models/TransactionFeeEstimateResponseEstimatedCost.ts create mode 100644 client/src/generated/models/TransactionFeeEstimateResponseEstimations.ts create mode 100644 client/src/generated/models/UnanchoredTransactionListResponse.ts diff --git a/client/src/generated/.openapi-generator/FILES b/client/src/generated/.openapi-generator/FILES new file mode 100644 index 0000000000..698b84bca8 --- /dev/null +++ b/client/src/generated/.openapi-generator/FILES @@ -0,0 +1,172 @@ +.openapi-generator-ignore +apis/AccountsApi.ts +apis/BlocksApi.ts +apis/FaucetsApi.ts +apis/FeesApi.ts +apis/FungibleTokensApi.ts +apis/InfoApi.ts +apis/MempoolApi.ts +apis/MicroblocksApi.ts +apis/NamesApi.ts +apis/NonFungibleTokensApi.ts +apis/RosettaApi.ts +apis/SearchApi.ts +apis/SmartContractsApi.ts +apis/StackingApi.ts +apis/StackingRewardsApi.ts +apis/TransactionsApi.ts +apis/index.ts +index.ts +models/AccountDataResponse.ts +models/AddressAssetsListResponse.ts +models/AddressBalanceResponse.ts +models/AddressNftListResponse.ts +models/AddressNftListResponseValue.ts +models/AddressNonces.ts +models/AddressStxInboundListResponse.ts +models/AddressTokenOfferingLocked.ts +models/AddressTransactionWithTransfers.ts +models/AddressTransactionWithTransfersFtTransfers.ts +models/AddressTransactionWithTransfersNftTransfers.ts +models/AddressTransactionWithTransfersStxTransfers.ts +models/AddressTransactionWithTransfersValue.ts +models/AddressTransactionsListResponse.ts +models/AddressTransactionsWithTransfersListResponse.ts +models/AddressUnlockSchedule.ts +models/Block.ts +models/BlockListResponse.ts +models/BnsError.ts +models/BnsGetAllNamespacesResponse.ts +models/BnsGetNameInfoResponse.ts +models/BnsGetNamePriceResponse.ts +models/BnsGetNamespacePriceResponse.ts +models/BnsNamesOwnByAddressResponse.ts +models/BurnchainReward.ts +models/BurnchainRewardListResponse.ts +models/BurnchainRewardSlotHolder.ts +models/BurnchainRewardSlotHolderListResponse.ts +models/BurnchainRewardsTotal.ts +models/ChainTip.ts +models/ContractInterfaceResponse.ts +models/ContractListResponse.ts +models/ContractSourceResponse.ts +models/CoreNodeInfoResponse.ts +models/CoreNodePoxResponse.ts +models/FeeRate.ts +models/FeeRateRequest.ts +models/FungibleTokenMetadata.ts +models/FungibleTokensMetadataList.ts +models/GetRawTransactionResult.ts +models/GetStxSupplyLegacyFormatResponse.ts +models/GetStxSupplyResponse.ts +models/InboundStxTransfer.ts +models/InlineObject.ts +models/InlineResponse403.ts +models/MapEntryResponse.ts +models/MempoolFeePriorities.ts +models/MempoolFeePrioritiesAll.ts +models/MempoolTransactionListResponse.ts +models/MempoolTransactionStatsResponse.ts +models/MempoolTransactionStatsResponseTxAges.ts +models/MempoolTransactionStatsResponseTxByteSizes.ts +models/MempoolTransactionStatsResponseTxSimpleFeeAverages.ts +models/MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer.ts +models/MempoolTransactionStatsResponseTxTypeCounts.ts +models/Microblock.ts +models/MicroblockListResponse.ts +models/NetworkBlockTimeResponse.ts +models/NetworkBlockTimesResponse.ts +models/NetworkIdentifier.ts +models/NftEvent.ts +models/NonFungibleTokenHistoryEventList.ts +models/NonFungibleTokenHoldingsList.ts +models/NonFungibleTokenMetadata.ts +models/NonFungibleTokenMintList.ts +models/NonFungibleTokensMetadataList.ts +models/OtherTransactionIdentifier.ts +models/PoolDelegation.ts +models/PoolDelegationsResponse.ts +models/PostCoreNodeTransactionsError.ts +models/ReadOnlyFunctionArgs.ts +models/ReadOnlyFunctionSuccessResponse.ts +models/RosettaAccount.ts +models/RosettaAccountBalanceRequest.ts +models/RosettaAccountBalanceResponse.ts +models/RosettaAccountBalanceResponseCoinIdentifier.ts +models/RosettaAccountBalanceResponseMetadata.ts +models/RosettaAccountIdentifier.ts +models/RosettaAmount.ts +models/RosettaBlock.ts +models/RosettaBlockMetadata.ts +models/RosettaBlockMetadata1.ts +models/RosettaBlockRequest.ts +models/RosettaBlockResponse.ts +models/RosettaBlockTransactionRequest.ts +models/RosettaBlockTransactionResponse.ts +models/RosettaCoin.ts +models/RosettaCoinChange.ts +models/RosettaConstructionCombineRequest.ts +models/RosettaConstructionCombineResponse.ts +models/RosettaConstructionDeriveRequest.ts +models/RosettaConstructionDeriveResponse.ts +models/RosettaConstructionHashRequest.ts +models/RosettaConstructionHashResponse.ts +models/RosettaConstructionMetadataRequest.ts +models/RosettaConstructionMetadataResponse.ts +models/RosettaConstructionMetadataResponseMetadata.ts +models/RosettaConstructionParseRequest.ts +models/RosettaConstructionParseResponse.ts +models/RosettaConstructionPayloadResponse.ts +models/RosettaConstructionPayloadsRequest.ts +models/RosettaConstructionPreprocessRequest.ts +models/RosettaConstructionPreprocessResponse.ts +models/RosettaConstructionSubmitRequest.ts +models/RosettaConstructionSubmitResponse.ts +models/RosettaCurrency.ts +models/RosettaError.ts +models/RosettaErrorDetails.ts +models/RosettaErrorNoDetails.ts +models/RosettaGenesisBlockIdentifier.ts +models/RosettaMaxFeeAmount.ts +models/RosettaMempoolRequest.ts +models/RosettaMempoolResponse.ts +models/RosettaMempoolTransactionRequest.ts +models/RosettaMempoolTransactionResponse.ts +models/RosettaNetworkListResponse.ts +models/RosettaNetworkListResponseSubNetworkIdentifier.ts +models/RosettaNetworkListResponseSubNetworkIdentifierMetadata.ts +models/RosettaNetworkOptionsResponse.ts +models/RosettaNetworkOptionsResponseAllow.ts +models/RosettaNetworkOptionsResponseVersion.ts +models/RosettaNetworkStatusResponse.ts +models/RosettaOldestBlockIdentifier.ts +models/RosettaOperation.ts +models/RosettaOperationIdentifier.ts +models/RosettaOperationStatus.ts +models/RosettaOptions.ts +models/RosettaOptionsRequest.ts +models/RosettaParentBlockIdentifier.ts +models/RosettaPeers.ts +models/RosettaPublicKey.ts +models/RosettaRelatedOperation.ts +models/RosettaSignature.ts +models/RosettaStatusRequest.ts +models/RosettaSubAccount.ts +models/RosettaSyncStatus.ts +models/RosettaTransaction.ts +models/RunFaucetResponse.ts +models/ServerStatusResponse.ts +models/SigningPayload.ts +models/SmartContract.ts +models/StxBalance.ts +models/TargetBlockTime.ts +models/TransactionEventsResponse.ts +models/TransactionFeeEstimateRequest.ts +models/TransactionFeeEstimateResponse.ts +models/TransactionFeeEstimateResponseEstimatedCost.ts +models/TransactionFeeEstimateResponseEstimations.ts +models/TransactionIdentifier.ts +models/TransactionResults.ts +models/UnanchoredTransactionListResponse.ts +models/index.ts +runtime.ts diff --git a/client/src/generated/apis/AccountsApi.ts b/client/src/generated/apis/AccountsApi.ts index 9ea7abf259..e1120dc74a 100644 --- a/client/src/generated/apis/AccountsApi.ts +++ b/client/src/generated/apis/AccountsApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -24,22 +24,47 @@ import { AddressBalanceResponse, AddressBalanceResponseFromJSON, AddressBalanceResponseToJSON, - AddressStxBalanceResponse, - AddressStxBalanceResponseFromJSON, - AddressStxBalanceResponseToJSON, + AddressNftListResponse, + AddressNftListResponseFromJSON, + AddressNftListResponseToJSON, + AddressNonces, + AddressNoncesFromJSON, + AddressNoncesToJSON, + AddressStxInboundListResponse, + AddressStxInboundListResponseFromJSON, + AddressStxInboundListResponseToJSON, + AddressTransactionWithTransfers, + AddressTransactionWithTransfersFromJSON, + AddressTransactionWithTransfersToJSON, AddressTransactionsListResponse, AddressTransactionsListResponseFromJSON, AddressTransactionsListResponseToJSON, + AddressTransactionsWithTransfersListResponse, + AddressTransactionsWithTransfersListResponseFromJSON, + AddressTransactionsWithTransfersListResponseToJSON, } from '../models'; export interface GetAccountAssetsRequest { principal: string; limit?: number; offset?: number; + unanchored?: boolean; + untilBlock?: string; } export interface GetAccountBalanceRequest { principal: string; + unanchored?: boolean; + untilBlock?: string; +} + +export interface GetAccountInboundRequest { + principal: string; + limit?: number; + offset?: number; + height?: number; + unanchored?: boolean; + untilBlock?: string; } export interface GetAccountInfoRequest { @@ -48,14 +73,47 @@ export interface GetAccountInfoRequest { tip?: string; } +export interface GetAccountNftRequest { + principal: string; + limit?: number; + offset?: number; + unanchored?: boolean; + untilBlock?: string; +} + +export interface GetAccountNoncesRequest { + principal: string; + blockHeight?: number; + blockHash?: string; +} + export interface GetAccountStxBalanceRequest { principal: string; + unanchored?: boolean; + untilBlock?: string; } export interface GetAccountTransactionsRequest { principal: string; limit?: number; offset?: number; + height?: number; + unanchored?: boolean; + untilBlock?: string; +} + +export interface GetAccountTransactionsWithTransfersRequest { + principal: string; + limit?: number; + offset?: number; + height?: number; + unanchored?: boolean; + untilBlock?: string; +} + +export interface GetSingleTransactionWithTransfersRequest { + principal: string; + txId: string; } /** @@ -66,86 +124,196 @@ export interface GetAccountTransactionsRequest { */ export interface AccountsApiInterface { /** - * + * Retrieves a list of all assets events associated with an account or a Contract Identifier. This includes Transfers, Mints. * @summary Get account assets - * @param {string} principal Stacks address or a Contract identifier (e.g. `SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0.get-info`) + * @param {string} principal Stacks address or a Contract identifier * @param {number} [limit] max number of account assets to fetch * @param {number} [offset] index of first account assets to fetch + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {string} [untilBlock] returned data representing the state at that point in time, rather than the current block. Note - Use either of the query parameters but not both at a time. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountsApiInterface */ - getAccountAssetsRaw(requestParameters: GetAccountAssetsRequest): Promise>; + getAccountAssetsRaw(requestParameters: GetAccountAssetsRequest, initOverrides?: RequestInit): Promise>; /** + * Retrieves a list of all assets events associated with an account or a Contract Identifier. This includes Transfers, Mints. * Get account assets */ - getAccountAssets(requestParameters: GetAccountAssetsRequest): Promise; + getAccountAssets(requestParameters: GetAccountAssetsRequest, initOverrides?: RequestInit): Promise; /** - * + * Retrieves total account balance information for a given Address or Contract Identifier. This includes the balances of STX Tokens, Fungible Tokens and Non-Fungible Tokens for the account. * @summary Get account balances - * @param {string} principal Stacks address or a Contract identifier (e.g. `SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0.get-info`) + * @param {string} principal Stacks address or a Contract identifier + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {string} [untilBlock] returned data representing the state up until that point in time, rather than the current block. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountsApiInterface */ - getAccountBalanceRaw(requestParameters: GetAccountBalanceRequest): Promise>; + getAccountBalanceRaw(requestParameters: GetAccountBalanceRequest, initOverrides?: RequestInit): Promise>; /** + * Retrieves total account balance information for a given Address or Contract Identifier. This includes the balances of STX Tokens, Fungible Tokens and Non-Fungible Tokens for the account. * Get account balances */ - getAccountBalance(requestParameters: GetAccountBalanceRequest): Promise; + getAccountBalance(requestParameters: GetAccountBalanceRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of STX transfers with memos to the given principal. This includes regular transfers from a stx-transfer transaction type, and transfers from contract-call transactions a the `send-many-memo` bulk sending contract. + * @summary Get inbound STX transfers + * @param {string} principal Stacks address or a Contract identifier + * @param {number} [limit] number of items to return + * @param {number} [offset] number of items to skip + * @param {number} [height] Filter for transfers only at this given block height + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {string} [untilBlock] returned data representing the state up until that point in time, rather than the current block. Note - Use either of the query parameters but not both at a time. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApiInterface + */ + getAccountInboundRaw(requestParameters: GetAccountInboundRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of STX transfers with memos to the given principal. This includes regular transfers from a stx-transfer transaction type, and transfers from contract-call transactions a the `send-many-memo` bulk sending contract. + * Get inbound STX transfers + */ + getAccountInbound(requestParameters: GetAccountInboundRequest, initOverrides?: RequestInit): Promise; /** - * Get the account data for the provided principal Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is a unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not 404, rather it returns an object with balance and nonce of 0. + * Retrieves the account data for a given Account or a Contract Identifier Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is an unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not return a 404 error, rather it returns an object with balance and nonce of 0. * @summary Get account info - * @param {string} principal Stacks address or a Contract identifier (e.g. `SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0.get-info`) + * @param {string} principal Stacks address or a Contract identifier * @param {number} [proof] Returns object without the proof field if set to 0 * @param {string} [tip] The Stacks chain tip to query from * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountsApiInterface */ - getAccountInfoRaw(requestParameters: GetAccountInfoRequest): Promise>; + getAccountInfoRaw(requestParameters: GetAccountInfoRequest, initOverrides?: RequestInit): Promise>; /** - * Get the account data for the provided principal Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is a unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not 404, rather it returns an object with balance and nonce of 0. + * Retrieves the account data for a given Account or a Contract Identifier Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is an unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not return a 404 error, rather it returns an object with balance and nonce of 0. * Get account info */ - getAccountInfo(requestParameters: GetAccountInfoRequest): Promise; + getAccountInfo(requestParameters: GetAccountInfoRequest, initOverrides?: RequestInit): Promise; + + /** + * **NOTE:** This endpoint is deprecated in favor of [Non-Fungible Token holdings](#operation/get_nft_holdings). Retrieves a list of all nfts owned by an address, contains the clarity value of the identifier of the nft. + * @summary Get nft events + * @param {string} principal Stacks address or a Contract identifier + * @param {number} [limit] number of items to return + * @param {number} [offset] number of items to skip + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {string} [untilBlock] returned data representing the state up until that point in time, rather than the current block. Note - Use either of the query parameters but not both at a time. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApiInterface + */ + getAccountNftRaw(requestParameters: GetAccountNftRequest, initOverrides?: RequestInit): Promise>; /** - * + * **NOTE:** This endpoint is deprecated in favor of [Non-Fungible Token holdings](#operation/get_nft_holdings). Retrieves a list of all nfts owned by an address, contains the clarity value of the identifier of the nft. + * Get nft events + */ + getAccountNft(requestParameters: GetAccountNftRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves the latest nonce values used by an account by inspecting the mempool, microblock transactions, and anchored transactions. + * @summary Get the latest nonce used by an account + * @param {string} principal Stacks address + * @param {number} [blockHeight] Optionally get the nonce at a given block height. + * @param {string} [blockHash] Optionally get the nonce at a given block hash. Note - Use either of the query parameters but not both at a time. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApiInterface + */ + getAccountNoncesRaw(requestParameters: GetAccountNoncesRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the latest nonce values used by an account by inspecting the mempool, microblock transactions, and anchored transactions. + * Get the latest nonce used by an account + */ + getAccountNonces(requestParameters: GetAccountNoncesRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves STX token balance for a given Address or Contract Identifier. * @summary Get account STX balance - * @param {string} principal Stacks address or a Contract identifier (e.g. `SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0.get-info`) + * @param {string} principal Stacks address or a Contract identifier. + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks. + * @param {string} [untilBlock] returned data representing the state up until that point in time, rather than the current block. Note - Use either of the query parameters but not both at a time. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountsApiInterface */ - getAccountStxBalanceRaw(requestParameters: GetAccountStxBalanceRequest): Promise>; + getAccountStxBalanceRaw(requestParameters: GetAccountStxBalanceRequest, initOverrides?: RequestInit): Promise>; /** + * Retrieves STX token balance for a given Address or Contract Identifier. * Get account STX balance */ - getAccountStxBalance(requestParameters: GetAccountStxBalanceRequest): Promise; + getAccountStxBalance(requestParameters: GetAccountStxBalanceRequest, initOverrides?: RequestInit): Promise; /** - * + * Retrieves a list of all Transactions for a given Address or Contract Identifier. More information on Transaction types can be found [here](https://docs.stacks.co/understand-stacks/transactions#types). If you need to actively monitor new transactions for an address or contract id, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * @summary Get account transactions - * @param {string} principal Stacks address or a Contract identifier (e.g. `SP31DA6FTSJX2WGTZ69SFY11BH51NZMB0ZW97B5P0.get-info`) + * @param {string} principal Stacks address or a Contract identifier * @param {number} [limit] max number of account transactions to fetch * @param {number} [offset] index of first account transaction to fetch + * @param {number} [height] Filter for transactions only at this given block height + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {string} [untilBlock] returned data representing the state up until that point in time, rather than the current block. Note - Use either of the query parameters but not both at a time. * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof AccountsApiInterface */ - getAccountTransactionsRaw(requestParameters: GetAccountTransactionsRequest): Promise>; + getAccountTransactionsRaw(requestParameters: GetAccountTransactionsRequest, initOverrides?: RequestInit): Promise>; /** + * Retrieves a list of all Transactions for a given Address or Contract Identifier. More information on Transaction types can be found [here](https://docs.stacks.co/understand-stacks/transactions#types). If you need to actively monitor new transactions for an address or contract id, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get account transactions */ - getAccountTransactions(requestParameters: GetAccountTransactionsRequest): Promise; + getAccountTransactions(requestParameters: GetAccountTransactionsRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieve all transactions for an account or contract identifier including STX transfers for each transaction. + * @summary Get account transactions including STX transfers for each transaction. + * @param {string} principal Stacks address or a Contract identifier + * @param {number} [limit] max number of account transactions to fetch + * @param {number} [offset] index of first account transaction to fetch + * @param {number} [height] Filter for transactions only at this given block height + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {string} [untilBlock] returned data representing the state up until that point in time, rather than the current block. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApiInterface + */ + getAccountTransactionsWithTransfersRaw(requestParameters: GetAccountTransactionsWithTransfersRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieve all transactions for an account or contract identifier including STX transfers for each transaction. + * Get account transactions including STX transfers for each transaction. + */ + getAccountTransactionsWithTransfers(requestParameters: GetAccountTransactionsWithTransfersRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves transaction details for a given Transaction Id `tx_id`, for a given account or contract Identifier. + * @summary Get account transaction information for specific transaction + * @param {string} principal Stacks address or a contract identifier + * @param {string} txId Transaction id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApiInterface + */ + getSingleTransactionWithTransfersRaw(requestParameters: GetSingleTransactionWithTransfersRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves transaction details for a given Transaction Id `tx_id`, for a given account or contract Identifier. + * Get account transaction information for specific transaction + */ + getSingleTransactionWithTransfers(requestParameters: GetSingleTransactionWithTransfersRequest, initOverrides?: RequestInit): Promise; } @@ -155,14 +323,15 @@ export interface AccountsApiInterface { export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface { /** + * Retrieves a list of all assets events associated with an account or a Contract Identifier. This includes Transfers, Mints. * Get account assets */ - async getAccountAssetsRaw(requestParameters: GetAccountAssetsRequest): Promise> { + async getAccountAssetsRaw(requestParameters: GetAccountAssetsRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.principal === null || requestParameters.principal === undefined) { throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountAssets.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.limit !== undefined) { queryParameters['limit'] = requestParameters.limit; @@ -172,6 +341,14 @@ export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface queryParameters['offset'] = requestParameters.offset; } + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.untilBlock !== undefined) { + queryParameters['until_block'] = requestParameters.untilBlock; + } + const headerParameters: runtime.HTTPHeaders = {}; const response = await this.request({ @@ -179,28 +356,38 @@ export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => AddressAssetsListResponseFromJSON(jsonValue)); } /** + * Retrieves a list of all assets events associated with an account or a Contract Identifier. This includes Transfers, Mints. * Get account assets */ - async getAccountAssets(requestParameters: GetAccountAssetsRequest): Promise { - const response = await this.getAccountAssetsRaw(requestParameters); + async getAccountAssets(requestParameters: GetAccountAssetsRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountAssetsRaw(requestParameters, initOverrides); return await response.value(); } /** + * Retrieves total account balance information for a given Address or Contract Identifier. This includes the balances of STX Tokens, Fungible Tokens and Non-Fungible Tokens for the account. * Get account balances */ - async getAccountBalanceRaw(requestParameters: GetAccountBalanceRequest): Promise> { + async getAccountBalanceRaw(requestParameters: GetAccountBalanceRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.principal === null || requestParameters.principal === undefined) { throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountBalance.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.untilBlock !== undefined) { + queryParameters['until_block'] = requestParameters.untilBlock; + } const headerParameters: runtime.HTTPHeaders = {}; @@ -209,29 +396,82 @@ export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => AddressBalanceResponseFromJSON(jsonValue)); } /** + * Retrieves total account balance information for a given Address or Contract Identifier. This includes the balances of STX Tokens, Fungible Tokens and Non-Fungible Tokens for the account. * Get account balances */ - async getAccountBalance(requestParameters: GetAccountBalanceRequest): Promise { - const response = await this.getAccountBalanceRaw(requestParameters); + async getAccountBalance(requestParameters: GetAccountBalanceRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountBalanceRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of STX transfers with memos to the given principal. This includes regular transfers from a stx-transfer transaction type, and transfers from contract-call transactions a the `send-many-memo` bulk sending contract. + * Get inbound STX transfers + */ + async getAccountInboundRaw(requestParameters: GetAccountInboundRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.principal === null || requestParameters.principal === undefined) { + throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountInbound.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.height !== undefined) { + queryParameters['height'] = requestParameters.height; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.untilBlock !== undefined) { + queryParameters['until_block'] = requestParameters.untilBlock; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/address/{principal}/stx_inbound`.replace(`{${"principal"}}`, encodeURIComponent(String(requestParameters.principal))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => AddressStxInboundListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of STX transfers with memos to the given principal. This includes regular transfers from a stx-transfer transaction type, and transfers from contract-call transactions a the `send-many-memo` bulk sending contract. + * Get inbound STX transfers + */ + async getAccountInbound(requestParameters: GetAccountInboundRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountInboundRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get the account data for the provided principal Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is a unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not 404, rather it returns an object with balance and nonce of 0. + * Retrieves the account data for a given Account or a Contract Identifier Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is an unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not return a 404 error, rather it returns an object with balance and nonce of 0. * Get account info */ - async getAccountInfoRaw(requestParameters: GetAccountInfoRequest): Promise> { + async getAccountInfoRaw(requestParameters: GetAccountInfoRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.principal === null || requestParameters.principal === undefined) { throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountInfo.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.proof !== undefined) { queryParameters['proof'] = requestParameters.proof; @@ -248,29 +488,126 @@ export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => AccountDataResponseFromJSON(jsonValue)); } /** - * Get the account data for the provided principal Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is a unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not 404, rather it returns an object with balance and nonce of 0. + * Retrieves the account data for a given Account or a Contract Identifier Where balance is the hex encoding of a unsigned 128-bit integer (big-endian), nonce is an unsigned 64-bit integer, and the proofs are provided as hex strings. For non-existent accounts, this does not return a 404 error, rather it returns an object with balance and nonce of 0. * Get account info */ - async getAccountInfo(requestParameters: GetAccountInfoRequest): Promise { - const response = await this.getAccountInfoRaw(requestParameters); + async getAccountInfo(requestParameters: GetAccountInfoRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountInfoRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of [Non-Fungible Token holdings](#operation/get_nft_holdings). Retrieves a list of all nfts owned by an address, contains the clarity value of the identifier of the nft. + * Get nft events + */ + async getAccountNftRaw(requestParameters: GetAccountNftRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.principal === null || requestParameters.principal === undefined) { + throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountNft.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.untilBlock !== undefined) { + queryParameters['until_block'] = requestParameters.untilBlock; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/address/{principal}/nft_events`.replace(`{${"principal"}}`, encodeURIComponent(String(requestParameters.principal))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => AddressNftListResponseFromJSON(jsonValue)); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of [Non-Fungible Token holdings](#operation/get_nft_holdings). Retrieves a list of all nfts owned by an address, contains the clarity value of the identifier of the nft. + * Get nft events + */ + async getAccountNft(requestParameters: GetAccountNftRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountNftRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves the latest nonce values used by an account by inspecting the mempool, microblock transactions, and anchored transactions. + * Get the latest nonce used by an account + */ + async getAccountNoncesRaw(requestParameters: GetAccountNoncesRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.principal === null || requestParameters.principal === undefined) { + throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountNonces.'); + } + + const queryParameters: any = {}; + + if (requestParameters.blockHeight !== undefined) { + queryParameters['block_height'] = requestParameters.blockHeight; + } + + if (requestParameters.blockHash !== undefined) { + queryParameters['block_hash'] = requestParameters.blockHash; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/address/{principal}/nonces`.replace(`{${"principal"}}`, encodeURIComponent(String(requestParameters.principal))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => AddressNoncesFromJSON(jsonValue)); + } + + /** + * Retrieves the latest nonce values used by an account by inspecting the mempool, microblock transactions, and anchored transactions. + * Get the latest nonce used by an account + */ + async getAccountNonces(requestParameters: GetAccountNoncesRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountNoncesRaw(requestParameters, initOverrides); return await response.value(); } /** + * Retrieves STX token balance for a given Address or Contract Identifier. * Get account STX balance */ - async getAccountStxBalanceRaw(requestParameters: GetAccountStxBalanceRequest): Promise> { + async getAccountStxBalanceRaw(requestParameters: GetAccountStxBalanceRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.principal === null || requestParameters.principal === undefined) { throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountStxBalance.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.untilBlock !== undefined) { + queryParameters['until_block'] = requestParameters.untilBlock; + } const headerParameters: runtime.HTTPHeaders = {}; @@ -279,28 +616,30 @@ export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); - return new runtime.JSONApiResponse(response, (jsonValue) => AddressStxBalanceResponseFromJSON(jsonValue)); + return new runtime.JSONApiResponse(response); } /** + * Retrieves STX token balance for a given Address or Contract Identifier. * Get account STX balance */ - async getAccountStxBalance(requestParameters: GetAccountStxBalanceRequest): Promise { - const response = await this.getAccountStxBalanceRaw(requestParameters); + async getAccountStxBalance(requestParameters: GetAccountStxBalanceRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountStxBalanceRaw(requestParameters, initOverrides); return await response.value(); } /** + * Retrieves a list of all Transactions for a given Address or Contract Identifier. More information on Transaction types can be found [here](https://docs.stacks.co/understand-stacks/transactions#types). If you need to actively monitor new transactions for an address or contract id, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get account transactions */ - async getAccountTransactionsRaw(requestParameters: GetAccountTransactionsRequest): Promise> { + async getAccountTransactionsRaw(requestParameters: GetAccountTransactionsRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.principal === null || requestParameters.principal === undefined) { throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountTransactions.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.limit !== undefined) { queryParameters['limit'] = requestParameters.limit; @@ -310,6 +649,18 @@ export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface queryParameters['offset'] = requestParameters.offset; } + if (requestParameters.height !== undefined) { + queryParameters['height'] = requestParameters.height; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.untilBlock !== undefined) { + queryParameters['until_block'] = requestParameters.untilBlock; + } + const headerParameters: runtime.HTTPHeaders = {}; const response = await this.request({ @@ -317,16 +668,105 @@ export class AccountsApi extends runtime.BaseAPI implements AccountsApiInterface method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => AddressTransactionsListResponseFromJSON(jsonValue)); } /** + * Retrieves a list of all Transactions for a given Address or Contract Identifier. More information on Transaction types can be found [here](https://docs.stacks.co/understand-stacks/transactions#types). If you need to actively monitor new transactions for an address or contract id, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get account transactions */ - async getAccountTransactions(requestParameters: GetAccountTransactionsRequest): Promise { - const response = await this.getAccountTransactionsRaw(requestParameters); + async getAccountTransactions(requestParameters: GetAccountTransactionsRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountTransactionsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieve all transactions for an account or contract identifier including STX transfers for each transaction. + * Get account transactions including STX transfers for each transaction. + */ + async getAccountTransactionsWithTransfersRaw(requestParameters: GetAccountTransactionsWithTransfersRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.principal === null || requestParameters.principal === undefined) { + throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getAccountTransactionsWithTransfers.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.height !== undefined) { + queryParameters['height'] = requestParameters.height; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.untilBlock !== undefined) { + queryParameters['until_block'] = requestParameters.untilBlock; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/address/{principal}/transactions_with_transfers`.replace(`{${"principal"}}`, encodeURIComponent(String(requestParameters.principal))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => AddressTransactionsWithTransfersListResponseFromJSON(jsonValue)); + } + + /** + * Retrieve all transactions for an account or contract identifier including STX transfers for each transaction. + * Get account transactions including STX transfers for each transaction. + */ + async getAccountTransactionsWithTransfers(requestParameters: GetAccountTransactionsWithTransfersRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAccountTransactionsWithTransfersRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves transaction details for a given Transaction Id `tx_id`, for a given account or contract Identifier. + * Get account transaction information for specific transaction + */ + async getSingleTransactionWithTransfersRaw(requestParameters: GetSingleTransactionWithTransfersRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.principal === null || requestParameters.principal === undefined) { + throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getSingleTransactionWithTransfers.'); + } + + if (requestParameters.txId === null || requestParameters.txId === undefined) { + throw new runtime.RequiredError('txId','Required parameter requestParameters.txId was null or undefined when calling getSingleTransactionWithTransfers.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/address/{principal}/{tx_id}/with_transfers`.replace(`{${"principal"}}`, encodeURIComponent(String(requestParameters.principal))).replace(`{${"tx_id"}}`, encodeURIComponent(String(requestParameters.txId))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => AddressTransactionWithTransfersFromJSON(jsonValue)); + } + + /** + * Retrieves transaction details for a given Transaction Id `tx_id`, for a given account or contract Identifier. + * Get account transaction information for specific transaction + */ + async getSingleTransactionWithTransfers(requestParameters: GetSingleTransactionWithTransfersRequest, initOverrides?: RequestInit): Promise { + const response = await this.getSingleTransactionWithTransfersRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/client/src/generated/apis/BlocksApi.ts b/client/src/generated/apis/BlocksApi.ts index 535b30d494..d51aa87cc3 100644 --- a/client/src/generated/apis/BlocksApi.ts +++ b/client/src/generated/apis/BlocksApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -23,10 +23,22 @@ import { BlockListResponseToJSON, } from '../models'; +export interface GetBlockByBurnBlockHashRequest { + burnBlockHash: string; +} + +export interface GetBlockByBurnBlockHeightRequest { + burnBlockHeight: number; +} + export interface GetBlockByHashRequest { hash: string; } +export interface GetBlockByHeightRequest { + height: number; +} + export interface GetBlockListRequest { limit?: number; offset?: number; @@ -40,23 +52,71 @@ export interface GetBlockListRequest { */ export interface BlocksApiInterface { /** - * Get a specific block by hash - * @summary Get block + * Retrieves block details of a specific block for a given burnchain block hash + * @summary Get block by burnchain block hash + * @param {string} burnBlockHash Hash of the burnchain block + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof BlocksApiInterface + */ + getBlockByBurnBlockHashRaw(requestParameters: GetBlockByBurnBlockHashRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves block details of a specific block for a given burnchain block hash + * Get block by burnchain block hash + */ + getBlockByBurnBlockHash(requestParameters: GetBlockByBurnBlockHashRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves block details of a specific block for a given burn chain height + * @summary Get block by burnchain height + * @param {number} burnBlockHeight Height of the burn chain block + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof BlocksApiInterface + */ + getBlockByBurnBlockHeightRaw(requestParameters: GetBlockByBurnBlockHeightRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves block details of a specific block for a given burn chain height + * Get block by burnchain height + */ + getBlockByBurnBlockHeight(requestParameters: GetBlockByBurnBlockHeightRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves block details of a specific block for a given chain height. You can use the hash from your latest block (\'get_block_list\' API) to get your block details. + * @summary Get block by hash * @param {string} hash Hash of the block * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof BlocksApiInterface */ - getBlockByHashRaw(requestParameters: GetBlockByHashRequest): Promise>; + getBlockByHashRaw(requestParameters: GetBlockByHashRequest, initOverrides?: RequestInit): Promise>; /** - * Get a specific block by hash - * Get block + * Retrieves block details of a specific block for a given chain height. You can use the hash from your latest block (\'get_block_list\' API) to get your block details. + * Get block by hash */ - getBlockByHash(requestParameters: GetBlockByHashRequest): Promise; + getBlockByHash(requestParameters: GetBlockByHashRequest, initOverrides?: RequestInit): Promise; /** - * Get all recently mined blocks + * Retrieves block details of a specific block at a given block height + * @summary Get block by height + * @param {number} height Height of the block + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof BlocksApiInterface + */ + getBlockByHeightRaw(requestParameters: GetBlockByHeightRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves block details of a specific block at a given block height + * Get block by height + */ + getBlockByHeight(requestParameters: GetBlockByHeightRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of recently mined blocks If you need to actively monitor new blocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * @summary Get recent blocks * @param {number} [limit] max number of blocks to fetch * @param {number} [offset] index of first block to fetch @@ -64,13 +124,13 @@ export interface BlocksApiInterface { * @throws {RequiredError} * @memberof BlocksApiInterface */ - getBlockListRaw(requestParameters: GetBlockListRequest): Promise>; + getBlockListRaw(requestParameters: GetBlockListRequest, initOverrides?: RequestInit): Promise>; /** - * Get all recently mined blocks + * Retrieves a list of recently mined blocks If you need to actively monitor new blocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get recent blocks */ - getBlockList(requestParameters: GetBlockListRequest): Promise; + getBlockList(requestParameters: GetBlockListRequest, initOverrides?: RequestInit): Promise; } @@ -80,15 +140,79 @@ export interface BlocksApiInterface { export class BlocksApi extends runtime.BaseAPI implements BlocksApiInterface { /** - * Get a specific block by hash - * Get block + * Retrieves block details of a specific block for a given burnchain block hash + * Get block by burnchain block hash */ - async getBlockByHashRaw(requestParameters: GetBlockByHashRequest): Promise> { + async getBlockByBurnBlockHashRaw(requestParameters: GetBlockByBurnBlockHashRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.burnBlockHash === null || requestParameters.burnBlockHash === undefined) { + throw new runtime.RequiredError('burnBlockHash','Required parameter requestParameters.burnBlockHash was null or undefined when calling getBlockByBurnBlockHash.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/block/by_burn_block_hash/{burn_block_hash}`.replace(`{${"burn_block_hash"}}`, encodeURIComponent(String(requestParameters.burnBlockHash))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BlockFromJSON(jsonValue)); + } + + /** + * Retrieves block details of a specific block for a given burnchain block hash + * Get block by burnchain block hash + */ + async getBlockByBurnBlockHash(requestParameters: GetBlockByBurnBlockHashRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBlockByBurnBlockHashRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves block details of a specific block for a given burn chain height + * Get block by burnchain height + */ + async getBlockByBurnBlockHeightRaw(requestParameters: GetBlockByBurnBlockHeightRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.burnBlockHeight === null || requestParameters.burnBlockHeight === undefined) { + throw new runtime.RequiredError('burnBlockHeight','Required parameter requestParameters.burnBlockHeight was null or undefined when calling getBlockByBurnBlockHeight.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/block/by_burn_block_height/{burn_block_height}`.replace(`{${"burn_block_height"}}`, encodeURIComponent(String(requestParameters.burnBlockHeight))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BlockFromJSON(jsonValue)); + } + + /** + * Retrieves block details of a specific block for a given burn chain height + * Get block by burnchain height + */ + async getBlockByBurnBlockHeight(requestParameters: GetBlockByBurnBlockHeightRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBlockByBurnBlockHeightRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves block details of a specific block for a given chain height. You can use the hash from your latest block (\'get_block_list\' API) to get your block details. + * Get block by hash + */ + async getBlockByHashRaw(requestParameters: GetBlockByHashRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.hash === null || requestParameters.hash === undefined) { throw new runtime.RequiredError('hash','Required parameter requestParameters.hash was null or undefined when calling getBlockByHash.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -97,26 +221,58 @@ export class BlocksApi extends runtime.BaseAPI implements BlocksApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BlockFromJSON(jsonValue)); + } + + /** + * Retrieves block details of a specific block for a given chain height. You can use the hash from your latest block (\'get_block_list\' API) to get your block details. + * Get block by hash + */ + async getBlockByHash(requestParameters: GetBlockByHashRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBlockByHashRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves block details of a specific block at a given block height + * Get block by height + */ + async getBlockByHeightRaw(requestParameters: GetBlockByHeightRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.height === null || requestParameters.height === undefined) { + throw new runtime.RequiredError('height','Required parameter requestParameters.height was null or undefined when calling getBlockByHeight.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/block/by_height/{height}`.replace(`{${"height"}}`, encodeURIComponent(String(requestParameters.height))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => BlockFromJSON(jsonValue)); } /** - * Get a specific block by hash - * Get block + * Retrieves block details of a specific block at a given block height + * Get block by height */ - async getBlockByHash(requestParameters: GetBlockByHashRequest): Promise { - const response = await this.getBlockByHashRaw(requestParameters); + async getBlockByHeight(requestParameters: GetBlockByHeightRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBlockByHeightRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get all recently mined blocks + * Retrieves a list of recently mined blocks If you need to actively monitor new blocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get recent blocks */ - async getBlockListRaw(requestParameters: GetBlockListRequest): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getBlockListRaw(requestParameters: GetBlockListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; if (requestParameters.limit !== undefined) { queryParameters['limit'] = requestParameters.limit; @@ -133,17 +289,17 @@ export class BlocksApi extends runtime.BaseAPI implements BlocksApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => BlockListResponseFromJSON(jsonValue)); } /** - * Get all recently mined blocks + * Retrieves a list of recently mined blocks If you need to actively monitor new blocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get recent blocks */ - async getBlockList(requestParameters: GetBlockListRequest): Promise { - const response = await this.getBlockListRaw(requestParameters); + async getBlockList(requestParameters: GetBlockListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBlockListRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/client/src/generated/apis/BurnchainApi.ts b/client/src/generated/apis/BurnchainApi.ts deleted file mode 100644 index 3dfd4f987f..0000000000 --- a/client/src/generated/apis/BurnchainApi.ts +++ /dev/null @@ -1,214 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) - * - * The version of the OpenAPI document: 1.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -import * as runtime from '../runtime'; -import { - BurnchainRewardListResponse, - BurnchainRewardListResponseFromJSON, - BurnchainRewardListResponseToJSON, - BurnchainRewardsTotal, - BurnchainRewardsTotalFromJSON, - BurnchainRewardsTotalToJSON, -} from '../models'; - -export interface GetBurnchainRewardListRequest { - limit?: number; - offset?: number; -} - -export interface GetBurnchainRewardListByAddressRequest { - address: string; - limit?: number; - offset?: number; -} - -export interface GetBurnchainRewardsTotalByAddressRequest { - address: string; -} - -/** - * BurnchainApi - interface - * - * @export - * @interface BurnchainApiInterface - */ -export interface BurnchainApiInterface { - /** - * Get a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info - * @summary Get recent burnchain reward recipients - * @param {number} [limit] max number of rewards to fetch - * @param {number} [offset] index of first rewards to fetch - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BurnchainApiInterface - */ - getBurnchainRewardListRaw(requestParameters: GetBurnchainRewardListRequest): Promise>; - - /** - * Get a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info - * Get recent burnchain reward recipients - */ - getBurnchainRewardList(requestParameters: GetBurnchainRewardListRequest): Promise; - - /** - * Get a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info - * @summary Get recent burnchain reward for the given recipient - * @param {string} address Reward recipient address. Should either be in the native burnchain\'s format (e.g. B58 for Bitcoin), or if a STX principal address is provided it will be encoded as into the equivalent burnchain format - * @param {number} [limit] max number of rewards to fetch - * @param {number} [offset] index of first rewards to fetch - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BurnchainApiInterface - */ - getBurnchainRewardListByAddressRaw(requestParameters: GetBurnchainRewardListByAddressRequest): Promise>; - - /** - * Get a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info - * Get recent burnchain reward for the given recipient - */ - getBurnchainRewardListByAddress(requestParameters: GetBurnchainRewardListByAddressRequest): Promise; - - /** - * Get the total burnchain (e.g. Bitcoin) rewards for the given recipient - * @summary Get total burnchain rewards for the given recipient - * @param {string} address Reward recipient address. Should either be in the native burnchain\'s format (e.g. B58 for Bitcoin), or if a STX principal address is provided it will be encoded as into the equivalent burnchain format - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof BurnchainApiInterface - */ - getBurnchainRewardsTotalByAddressRaw(requestParameters: GetBurnchainRewardsTotalByAddressRequest): Promise>; - - /** - * Get the total burnchain (e.g. Bitcoin) rewards for the given recipient - * Get total burnchain rewards for the given recipient - */ - getBurnchainRewardsTotalByAddress(requestParameters: GetBurnchainRewardsTotalByAddressRequest): Promise; - -} - -/** - * - */ -export class BurnchainApi extends runtime.BaseAPI implements BurnchainApiInterface { - - /** - * Get a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info - * Get recent burnchain reward recipients - */ - async getBurnchainRewardListRaw(requestParameters: GetBurnchainRewardListRequest): Promise> { - const queryParameters: runtime.HTTPQuery = {}; - - if (requestParameters.limit !== undefined) { - queryParameters['limit'] = requestParameters.limit; - } - - if (requestParameters.offset !== undefined) { - queryParameters['offset'] = requestParameters.offset; - } - - const headerParameters: runtime.HTTPHeaders = {}; - - const response = await this.request({ - path: `/extended/v1/burnchain/rewards`, - method: 'GET', - headers: headerParameters, - query: queryParameters, - }); - - return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardListResponseFromJSON(jsonValue)); - } - - /** - * Get a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info - * Get recent burnchain reward recipients - */ - async getBurnchainRewardList(requestParameters: GetBurnchainRewardListRequest): Promise { - const response = await this.getBurnchainRewardListRaw(requestParameters); - return await response.value(); - } - - /** - * Get a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info - * Get recent burnchain reward for the given recipient - */ - async getBurnchainRewardListByAddressRaw(requestParameters: GetBurnchainRewardListByAddressRequest): Promise> { - if (requestParameters.address === null || requestParameters.address === undefined) { - throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling getBurnchainRewardListByAddress.'); - } - - const queryParameters: runtime.HTTPQuery = {}; - - if (requestParameters.limit !== undefined) { - queryParameters['limit'] = requestParameters.limit; - } - - if (requestParameters.offset !== undefined) { - queryParameters['offset'] = requestParameters.offset; - } - - const headerParameters: runtime.HTTPHeaders = {}; - - const response = await this.request({ - path: `/extended/v1/burnchain/rewards/{address}`.replace(`{${"address"}}`, encodeURIComponent(String(requestParameters.address))), - method: 'GET', - headers: headerParameters, - query: queryParameters, - }); - - return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardListResponseFromJSON(jsonValue)); - } - - /** - * Get a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info - * Get recent burnchain reward for the given recipient - */ - async getBurnchainRewardListByAddress(requestParameters: GetBurnchainRewardListByAddressRequest): Promise { - const response = await this.getBurnchainRewardListByAddressRaw(requestParameters); - return await response.value(); - } - - /** - * Get the total burnchain (e.g. Bitcoin) rewards for the given recipient - * Get total burnchain rewards for the given recipient - */ - async getBurnchainRewardsTotalByAddressRaw(requestParameters: GetBurnchainRewardsTotalByAddressRequest): Promise> { - if (requestParameters.address === null || requestParameters.address === undefined) { - throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling getBurnchainRewardsTotalByAddress.'); - } - - const queryParameters: runtime.HTTPQuery = {}; - - const headerParameters: runtime.HTTPHeaders = {}; - - const response = await this.request({ - path: `/extended/v1/burnchain/rewards/{address}/total`.replace(`{${"address"}}`, encodeURIComponent(String(requestParameters.address))), - method: 'GET', - headers: headerParameters, - query: queryParameters, - }); - - return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardsTotalFromJSON(jsonValue)); - } - - /** - * Get the total burnchain (e.g. Bitcoin) rewards for the given recipient - * Get total burnchain rewards for the given recipient - */ - async getBurnchainRewardsTotalByAddress(requestParameters: GetBurnchainRewardsTotalByAddressRequest): Promise { - const response = await this.getBurnchainRewardsTotalByAddressRaw(requestParameters); - return await response.value(); - } - -} diff --git a/client/src/generated/apis/FaucetsApi.ts b/client/src/generated/apis/FaucetsApi.ts index 4fe27b8ffb..2f7d512afa 100644 --- a/client/src/generated/apis/FaucetsApi.ts +++ b/client/src/generated/apis/FaucetsApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -15,6 +15,12 @@ import * as runtime from '../runtime'; import { + InlineObject, + InlineObjectFromJSON, + InlineObjectToJSON, + InlineResponse403, + InlineResponse403FromJSON, + InlineResponse403ToJSON, RunFaucetResponse, RunFaucetResponseFromJSON, RunFaucetResponseToJSON, @@ -22,6 +28,7 @@ import { export interface RunFaucetBtcRequest { address: string; + inlineObject?: InlineObject; } export interface RunFaucetStxRequest { @@ -37,37 +44,38 @@ export interface RunFaucetStxRequest { */ export interface FaucetsApiInterface { /** - * Get BTC tokens for the testnet - * @summary Get BTC tokens - * @param {string} address BTC address + * Add 1 BTC token to the specified testnet BTC address. The endpoint returns the transaction ID, which you can use to view the transaction in a testnet Bitcoin block explorer. The tokens are delivered once the transaction has been included in a block. **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * @summary Add testnet BTC tokens to address + * @param {string} address A valid testnet BTC address + * @param {InlineObject} [inlineObject] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof FaucetsApiInterface */ - runFaucetBtcRaw(requestParameters: RunFaucetBtcRequest): Promise>; + runFaucetBtcRaw(requestParameters: RunFaucetBtcRequest, initOverrides?: RequestInit): Promise>; /** - * Get BTC tokens for the testnet - * Get BTC tokens + * Add 1 BTC token to the specified testnet BTC address. The endpoint returns the transaction ID, which you can use to view the transaction in a testnet Bitcoin block explorer. The tokens are delivered once the transaction has been included in a block. **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * Add testnet BTC tokens to address */ - runFaucetBtc(requestParameters: RunFaucetBtcRequest): Promise; + runFaucetBtc(requestParameters: RunFaucetBtcRequest, initOverrides?: RequestInit): Promise; /** - * Get STX tokens for the testnet - * @summary Get STX tokens - * @param {string} address STX address - * @param {boolean} [stacking] Request the amount of STX needed for stacking + * Add 500 STX tokens to the specified testnet address. Testnet STX addresses begin with `ST`. If the `stacking` parameter is set to `true`, the faucet will add the required number of tokens for individual stacking to the specified testnet address. The endpoint returns the transaction ID, which you can use to view the transaction in the [Stacks Explorer](https://explorer.hiro.so/?chain=testnet). The tokens are delivered once the transaction has been included in an anchor block. A common reason for failed faucet transactions is that the faucet has run out of tokens. If you are experiencing failed faucet transactions to a testnet address, you can get help in [Discord](https://stacks.chat). **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * @summary Get STX testnet tokens + * @param {string} address A valid testnet STX address + * @param {boolean} [stacking] Request the amount of STX tokens needed for individual address stacking * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof FaucetsApiInterface */ - runFaucetStxRaw(requestParameters: RunFaucetStxRequest): Promise>; + runFaucetStxRaw(requestParameters: RunFaucetStxRequest, initOverrides?: RequestInit): Promise>; /** - * Get STX tokens for the testnet - * Get STX tokens + * Add 500 STX tokens to the specified testnet address. Testnet STX addresses begin with `ST`. If the `stacking` parameter is set to `true`, the faucet will add the required number of tokens for individual stacking to the specified testnet address. The endpoint returns the transaction ID, which you can use to view the transaction in the [Stacks Explorer](https://explorer.hiro.so/?chain=testnet). The tokens are delivered once the transaction has been included in an anchor block. A common reason for failed faucet transactions is that the faucet has run out of tokens. If you are experiencing failed faucet transactions to a testnet address, you can get help in [Discord](https://stacks.chat). **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * Get STX testnet tokens */ - runFaucetStx(requestParameters: RunFaucetStxRequest): Promise; + runFaucetStx(requestParameters: RunFaucetStxRequest, initOverrides?: RequestInit): Promise; } @@ -77,15 +85,15 @@ export interface FaucetsApiInterface { export class FaucetsApi extends runtime.BaseAPI implements FaucetsApiInterface { /** - * Get BTC tokens for the testnet - * Get BTC tokens + * Add 1 BTC token to the specified testnet BTC address. The endpoint returns the transaction ID, which you can use to view the transaction in a testnet Bitcoin block explorer. The tokens are delivered once the transaction has been included in a block. **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * Add testnet BTC tokens to address */ - async runFaucetBtcRaw(requestParameters: RunFaucetBtcRequest): Promise> { + async runFaucetBtcRaw(requestParameters: RunFaucetBtcRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.address === null || requestParameters.address === undefined) { throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling runFaucetBtc.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.address !== undefined) { queryParameters['address'] = requestParameters.address; @@ -93,35 +101,38 @@ export class FaucetsApi extends runtime.BaseAPI implements FaucetsApiInterface { const headerParameters: runtime.HTTPHeaders = {}; + headerParameters['Content-Type'] = 'application/json'; + const response = await this.request({ path: `/extended/v1/faucets/btc`, method: 'POST', headers: headerParameters, query: queryParameters, - }); + body: InlineObjectToJSON(requestParameters.inlineObject), + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RunFaucetResponseFromJSON(jsonValue)); } /** - * Get BTC tokens for the testnet - * Get BTC tokens + * Add 1 BTC token to the specified testnet BTC address. The endpoint returns the transaction ID, which you can use to view the transaction in a testnet Bitcoin block explorer. The tokens are delivered once the transaction has been included in a block. **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * Add testnet BTC tokens to address */ - async runFaucetBtc(requestParameters: RunFaucetBtcRequest): Promise { - const response = await this.runFaucetBtcRaw(requestParameters); + async runFaucetBtc(requestParameters: RunFaucetBtcRequest, initOverrides?: RequestInit): Promise { + const response = await this.runFaucetBtcRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get STX tokens for the testnet - * Get STX tokens + * Add 500 STX tokens to the specified testnet address. Testnet STX addresses begin with `ST`. If the `stacking` parameter is set to `true`, the faucet will add the required number of tokens for individual stacking to the specified testnet address. The endpoint returns the transaction ID, which you can use to view the transaction in the [Stacks Explorer](https://explorer.hiro.so/?chain=testnet). The tokens are delivered once the transaction has been included in an anchor block. A common reason for failed faucet transactions is that the faucet has run out of tokens. If you are experiencing failed faucet transactions to a testnet address, you can get help in [Discord](https://stacks.chat). **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * Get STX testnet tokens */ - async runFaucetStxRaw(requestParameters: RunFaucetStxRequest): Promise> { + async runFaucetStxRaw(requestParameters: RunFaucetStxRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.address === null || requestParameters.address === undefined) { throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling runFaucetStx.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.address !== undefined) { queryParameters['address'] = requestParameters.address; @@ -138,17 +149,17 @@ export class FaucetsApi extends runtime.BaseAPI implements FaucetsApiInterface { method: 'POST', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RunFaucetResponseFromJSON(jsonValue)); } /** - * Get STX tokens for the testnet - * Get STX tokens + * Add 500 STX tokens to the specified testnet address. Testnet STX addresses begin with `ST`. If the `stacking` parameter is set to `true`, the faucet will add the required number of tokens for individual stacking to the specified testnet address. The endpoint returns the transaction ID, which you can use to view the transaction in the [Stacks Explorer](https://explorer.hiro.so/?chain=testnet). The tokens are delivered once the transaction has been included in an anchor block. A common reason for failed faucet transactions is that the faucet has run out of tokens. If you are experiencing failed faucet transactions to a testnet address, you can get help in [Discord](https://stacks.chat). **Note:** This is a testnet only endpoint. This endpoint will not work on the mainnet. + * Get STX testnet tokens */ - async runFaucetStx(requestParameters: RunFaucetStxRequest): Promise { - const response = await this.runFaucetStxRaw(requestParameters); + async runFaucetStx(requestParameters: RunFaucetStxRequest, initOverrides?: RequestInit): Promise { + const response = await this.runFaucetStxRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/client/src/generated/apis/FeesApi.ts b/client/src/generated/apis/FeesApi.ts index 6bbd22bec4..510755aee5 100644 --- a/client/src/generated/apis/FeesApi.ts +++ b/client/src/generated/apis/FeesApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,6 +14,28 @@ import * as runtime from '../runtime'; +import { + FeeRate, + FeeRateFromJSON, + FeeRateToJSON, + FeeRateRequest, + FeeRateRequestFromJSON, + FeeRateRequestToJSON, + TransactionFeeEstimateRequest, + TransactionFeeEstimateRequestFromJSON, + TransactionFeeEstimateRequestToJSON, + TransactionFeeEstimateResponse, + TransactionFeeEstimateResponseFromJSON, + TransactionFeeEstimateResponseToJSON, +} from '../models'; + +export interface FetchFeeRateRequest { + feeRateRequest: FeeRateRequest; +} + +export interface PostFeeTransactionRequest { + transactionFeeEstimateRequest?: TransactionFeeEstimateRequest; +} /** * FeesApi - interface @@ -23,19 +45,51 @@ import * as runtime from '../runtime'; */ export interface FeesApiInterface { /** - * Get an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer + * **NOTE:** This endpoint is deprecated in favor of [Get approximate fees for a given transaction](#operation/post_fee_transaction). Retrieves estimated fee rate. + * @summary Fetch fee rate + * @param {FeeRateRequest} feeRateRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FeesApiInterface + */ + fetchFeeRateRaw(requestParameters: FetchFeeRateRequest, initOverrides?: RequestInit): Promise>; + + /** + * **NOTE:** This endpoint is deprecated in favor of [Get approximate fees for a given transaction](#operation/post_fee_transaction). Retrieves estimated fee rate. + * Fetch fee rate + */ + fetchFeeRate(requestParameters: FetchFeeRateRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer * @summary Get estimated fee * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof FeesApiInterface */ - getFeeTransferRaw(): Promise>; + getFeeTransferRaw(initOverrides?: RequestInit): Promise>; /** - * Get an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer + * Retrieves an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer * Get estimated fee */ - getFeeTransfer(): Promise; + getFeeTransfer(initOverrides?: RequestInit): Promise; + + /** + * Get an estimated fee for the supplied transaction. This estimates the execution cost of the transaction, the current fee rate of the network, and returns estimates for fee amounts. * `transaction_payload` is a hex-encoded serialization of the TransactionPayload for the transaction. * `estimated_len` is an optional argument that provides the endpoint with an estimation of the final length (in bytes) of the transaction, including any post-conditions and signatures If the node cannot provide an estimate for the transaction (e.g., if the node has never seen a contract-call for the given contract and function) or if estimation is not configured on this node, a 400 response is returned. The 400 response will be a JSON error containing a `reason` field which can be one of the following: * `DatabaseError` - this Stacks node has had an internal database error while trying to estimate the costs of the supplied transaction. * `NoEstimateAvailable` - this Stacks node has not seen this kind of contract-call before, and it cannot provide an estimate yet. * `CostEstimationDisabled` - this Stacks node does not perform fee or cost estimation, and it cannot respond on this endpoint. The 200 response contains the following data: * `estimated_cost` - the estimated multi-dimensional cost of executing the Clarity VM on the provided transaction. * `estimated_cost_scalar` - a unitless integer that the Stacks node uses to compare how much of the block limit is consumed by different transactions. This value incorporates the estimated length of the transaction and the estimated execution cost of the transaction. The range of this integer may vary between different Stacks nodes. In order to compute an estimate of total fee amount for the transaction, this value is multiplied by the same Stacks node\'s estimated fee rate. * `cost_scalar_change_by_byte` - a float value that indicates how much the `estimated_cost_scalar` value would increase for every additional byte in the final transaction. * `estimations` - an array of estimated fee rates and total fees to pay in microSTX for the transaction. This array provides a range of estimates (default: 3) that may be used. Each element of the array contains the following fields: * `fee_rate` - the estimated value for the current fee rates in the network * `fee` - the estimated value for the total fee in microSTX that the given transaction should pay. These values are the result of computing: `fee_rate` x `estimated_cost_scalar`. If the estimated fees are less than the minimum relay fee `(1 ustx x estimated_len)`, then that minimum relay fee will be returned here instead. Note: If the final transaction\'s byte size is larger than supplied to `estimated_len`, then applications should increase this fee amount by: `fee_rate` x `cost_scalar_change_by_byte` x (`final_size` - `estimated_size`) + * @summary Get approximate fees for a given transaction + * @param {TransactionFeeEstimateRequest} [transactionFeeEstimateRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FeesApiInterface + */ + postFeeTransactionRaw(requestParameters: PostFeeTransactionRequest, initOverrides?: RequestInit): Promise>; + + /** + * Get an estimated fee for the supplied transaction. This estimates the execution cost of the transaction, the current fee rate of the network, and returns estimates for fee amounts. * `transaction_payload` is a hex-encoded serialization of the TransactionPayload for the transaction. * `estimated_len` is an optional argument that provides the endpoint with an estimation of the final length (in bytes) of the transaction, including any post-conditions and signatures If the node cannot provide an estimate for the transaction (e.g., if the node has never seen a contract-call for the given contract and function) or if estimation is not configured on this node, a 400 response is returned. The 400 response will be a JSON error containing a `reason` field which can be one of the following: * `DatabaseError` - this Stacks node has had an internal database error while trying to estimate the costs of the supplied transaction. * `NoEstimateAvailable` - this Stacks node has not seen this kind of contract-call before, and it cannot provide an estimate yet. * `CostEstimationDisabled` - this Stacks node does not perform fee or cost estimation, and it cannot respond on this endpoint. The 200 response contains the following data: * `estimated_cost` - the estimated multi-dimensional cost of executing the Clarity VM on the provided transaction. * `estimated_cost_scalar` - a unitless integer that the Stacks node uses to compare how much of the block limit is consumed by different transactions. This value incorporates the estimated length of the transaction and the estimated execution cost of the transaction. The range of this integer may vary between different Stacks nodes. In order to compute an estimate of total fee amount for the transaction, this value is multiplied by the same Stacks node\'s estimated fee rate. * `cost_scalar_change_by_byte` - a float value that indicates how much the `estimated_cost_scalar` value would increase for every additional byte in the final transaction. * `estimations` - an array of estimated fee rates and total fees to pay in microSTX for the transaction. This array provides a range of estimates (default: 3) that may be used. Each element of the array contains the following fields: * `fee_rate` - the estimated value for the current fee rates in the network * `fee` - the estimated value for the total fee in microSTX that the given transaction should pay. These values are the result of computing: `fee_rate` x `estimated_cost_scalar`. If the estimated fees are less than the minimum relay fee `(1 ustx x estimated_len)`, then that minimum relay fee will be returned here instead. Note: If the final transaction\'s byte size is larger than supplied to `estimated_len`, then applications should increase this fee amount by: `fee_rate` x `cost_scalar_change_by_byte` x (`final_size` - `estimated_size`) + * Get approximate fees for a given transaction + */ + postFeeTransaction(requestParameters: PostFeeTransactionRequest, initOverrides?: RequestInit): Promise; } @@ -45,11 +99,46 @@ export interface FeesApiInterface { export class FeesApi extends runtime.BaseAPI implements FeesApiInterface { /** - * Get an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer + * **NOTE:** This endpoint is deprecated in favor of [Get approximate fees for a given transaction](#operation/post_fee_transaction). Retrieves estimated fee rate. + * Fetch fee rate + */ + async fetchFeeRateRaw(requestParameters: FetchFeeRateRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.feeRateRequest === null || requestParameters.feeRateRequest === undefined) { + throw new runtime.RequiredError('feeRateRequest','Required parameter requestParameters.feeRateRequest was null or undefined when calling fetchFeeRate.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request({ + path: `/extended/v1/fee_rate`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: FeeRateRequestToJSON(requestParameters.feeRateRequest), + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => FeeRateFromJSON(jsonValue)); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of [Get approximate fees for a given transaction](#operation/post_fee_transaction). Retrieves estimated fee rate. + * Fetch fee rate + */ + async fetchFeeRate(requestParameters: FetchFeeRateRequest, initOverrides?: RequestInit): Promise { + const response = await this.fetchFeeRateRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer * Get estimated fee */ - async getFeeTransferRaw(): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getFeeTransferRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -58,17 +147,48 @@ export class FeesApi extends runtime.BaseAPI implements FeesApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response); } /** - * Get an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer + * Retrieves an estimated fee rate for STX transfer transactions. This a a fee rate / byte, and is returned as a JSON integer * Get estimated fee */ - async getFeeTransfer(): Promise { - const response = await this.getFeeTransferRaw(); + async getFeeTransfer(initOverrides?: RequestInit): Promise { + const response = await this.getFeeTransferRaw(initOverrides); + return await response.value(); + } + + /** + * Get an estimated fee for the supplied transaction. This estimates the execution cost of the transaction, the current fee rate of the network, and returns estimates for fee amounts. * `transaction_payload` is a hex-encoded serialization of the TransactionPayload for the transaction. * `estimated_len` is an optional argument that provides the endpoint with an estimation of the final length (in bytes) of the transaction, including any post-conditions and signatures If the node cannot provide an estimate for the transaction (e.g., if the node has never seen a contract-call for the given contract and function) or if estimation is not configured on this node, a 400 response is returned. The 400 response will be a JSON error containing a `reason` field which can be one of the following: * `DatabaseError` - this Stacks node has had an internal database error while trying to estimate the costs of the supplied transaction. * `NoEstimateAvailable` - this Stacks node has not seen this kind of contract-call before, and it cannot provide an estimate yet. * `CostEstimationDisabled` - this Stacks node does not perform fee or cost estimation, and it cannot respond on this endpoint. The 200 response contains the following data: * `estimated_cost` - the estimated multi-dimensional cost of executing the Clarity VM on the provided transaction. * `estimated_cost_scalar` - a unitless integer that the Stacks node uses to compare how much of the block limit is consumed by different transactions. This value incorporates the estimated length of the transaction and the estimated execution cost of the transaction. The range of this integer may vary between different Stacks nodes. In order to compute an estimate of total fee amount for the transaction, this value is multiplied by the same Stacks node\'s estimated fee rate. * `cost_scalar_change_by_byte` - a float value that indicates how much the `estimated_cost_scalar` value would increase for every additional byte in the final transaction. * `estimations` - an array of estimated fee rates and total fees to pay in microSTX for the transaction. This array provides a range of estimates (default: 3) that may be used. Each element of the array contains the following fields: * `fee_rate` - the estimated value for the current fee rates in the network * `fee` - the estimated value for the total fee in microSTX that the given transaction should pay. These values are the result of computing: `fee_rate` x `estimated_cost_scalar`. If the estimated fees are less than the minimum relay fee `(1 ustx x estimated_len)`, then that minimum relay fee will be returned here instead. Note: If the final transaction\'s byte size is larger than supplied to `estimated_len`, then applications should increase this fee amount by: `fee_rate` x `cost_scalar_change_by_byte` x (`final_size` - `estimated_size`) + * Get approximate fees for a given transaction + */ + async postFeeTransactionRaw(requestParameters: PostFeeTransactionRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + const response = await this.request({ + path: `/v2/fees/transaction`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: TransactionFeeEstimateRequestToJSON(requestParameters.transactionFeeEstimateRequest), + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => TransactionFeeEstimateResponseFromJSON(jsonValue)); + } + + /** + * Get an estimated fee for the supplied transaction. This estimates the execution cost of the transaction, the current fee rate of the network, and returns estimates for fee amounts. * `transaction_payload` is a hex-encoded serialization of the TransactionPayload for the transaction. * `estimated_len` is an optional argument that provides the endpoint with an estimation of the final length (in bytes) of the transaction, including any post-conditions and signatures If the node cannot provide an estimate for the transaction (e.g., if the node has never seen a contract-call for the given contract and function) or if estimation is not configured on this node, a 400 response is returned. The 400 response will be a JSON error containing a `reason` field which can be one of the following: * `DatabaseError` - this Stacks node has had an internal database error while trying to estimate the costs of the supplied transaction. * `NoEstimateAvailable` - this Stacks node has not seen this kind of contract-call before, and it cannot provide an estimate yet. * `CostEstimationDisabled` - this Stacks node does not perform fee or cost estimation, and it cannot respond on this endpoint. The 200 response contains the following data: * `estimated_cost` - the estimated multi-dimensional cost of executing the Clarity VM on the provided transaction. * `estimated_cost_scalar` - a unitless integer that the Stacks node uses to compare how much of the block limit is consumed by different transactions. This value incorporates the estimated length of the transaction and the estimated execution cost of the transaction. The range of this integer may vary between different Stacks nodes. In order to compute an estimate of total fee amount for the transaction, this value is multiplied by the same Stacks node\'s estimated fee rate. * `cost_scalar_change_by_byte` - a float value that indicates how much the `estimated_cost_scalar` value would increase for every additional byte in the final transaction. * `estimations` - an array of estimated fee rates and total fees to pay in microSTX for the transaction. This array provides a range of estimates (default: 3) that may be used. Each element of the array contains the following fields: * `fee_rate` - the estimated value for the current fee rates in the network * `fee` - the estimated value for the total fee in microSTX that the given transaction should pay. These values are the result of computing: `fee_rate` x `estimated_cost_scalar`. If the estimated fees are less than the minimum relay fee `(1 ustx x estimated_len)`, then that minimum relay fee will be returned here instead. Note: If the final transaction\'s byte size is larger than supplied to `estimated_len`, then applications should increase this fee amount by: `fee_rate` x `cost_scalar_change_by_byte` x (`final_size` - `estimated_size`) + * Get approximate fees for a given transaction + */ + async postFeeTransaction(requestParameters: PostFeeTransactionRequest, initOverrides?: RequestInit): Promise { + const response = await this.postFeeTransactionRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/client/src/generated/apis/FungibleTokensApi.ts b/client/src/generated/apis/FungibleTokensApi.ts new file mode 100644 index 0000000000..b55945fee0 --- /dev/null +++ b/client/src/generated/apis/FungibleTokensApi.ts @@ -0,0 +1,150 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + FungibleTokenMetadata, + FungibleTokenMetadataFromJSON, + FungibleTokenMetadataToJSON, + FungibleTokensMetadataList, + FungibleTokensMetadataListFromJSON, + FungibleTokensMetadataListToJSON, +} from '../models'; + +export interface GetContractFtMetadataRequest { + contractId: string; +} + +export interface GetFtMetadataListRequest { + limit?: number; + offset?: number; +} + +/** + * FungibleTokensApi - interface + * + * @export + * @interface FungibleTokensApiInterface + */ +export interface FungibleTokensApiInterface { + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves the metadata for fungible tokens for a given contract id + * @summary Fungible tokens metadata for contract id + * @param {string} contractId token\'s contract id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FungibleTokensApiInterface + */ + getContractFtMetadataRaw(requestParameters: GetContractFtMetadataRequest, initOverrides?: RequestInit): Promise>; + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves the metadata for fungible tokens for a given contract id + * Fungible tokens metadata for contract id + */ + getContractFtMetadata(requestParameters: GetContractFtMetadataRequest, initOverrides?: RequestInit): Promise; + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves list of fungible tokens with their metadata. More information on Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#fungible-tokens). + * @summary Fungible tokens metadata list + * @param {number} [limit] max number of tokens to fetch. + * @param {number} [offset] index of first tokens to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FungibleTokensApiInterface + */ + getFtMetadataListRaw(requestParameters: GetFtMetadataListRequest, initOverrides?: RequestInit): Promise>; + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves list of fungible tokens with their metadata. More information on Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#fungible-tokens). + * Fungible tokens metadata list + */ + getFtMetadataList(requestParameters: GetFtMetadataListRequest, initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class FungibleTokensApi extends runtime.BaseAPI implements FungibleTokensApiInterface { + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves the metadata for fungible tokens for a given contract id + * Fungible tokens metadata for contract id + */ + async getContractFtMetadataRaw(requestParameters: GetContractFtMetadataRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.contractId === null || requestParameters.contractId === undefined) { + throw new runtime.RequiredError('contractId','Required parameter requestParameters.contractId was null or undefined when calling getContractFtMetadata.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tokens/{contractId}/ft/metadata`.replace(`{${"contractId"}}`, encodeURIComponent(String(requestParameters.contractId))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => FungibleTokenMetadataFromJSON(jsonValue)); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves the metadata for fungible tokens for a given contract id + * Fungible tokens metadata for contract id + */ + async getContractFtMetadata(requestParameters: GetContractFtMetadataRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractFtMetadataRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves list of fungible tokens with their metadata. More information on Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#fungible-tokens). + * Fungible tokens metadata list + */ + async getFtMetadataListRaw(requestParameters: GetFtMetadataListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tokens/ft/metadata`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => FungibleTokensMetadataListFromJSON(jsonValue)); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves list of fungible tokens with their metadata. More information on Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#fungible-tokens). + * Fungible tokens metadata list + */ + async getFtMetadataList(requestParameters: GetFtMetadataListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getFtMetadataListRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/client/src/generated/apis/InfoApi.ts b/client/src/generated/apis/InfoApi.ts index 26f4b5b1ab..b93cdce1f1 100644 --- a/client/src/generated/apis/InfoApi.ts +++ b/client/src/generated/apis/InfoApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -21,18 +21,35 @@ import { CoreNodePoxResponse, CoreNodePoxResponseFromJSON, CoreNodePoxResponseToJSON, + GetStxSupplyLegacyFormatResponse, + GetStxSupplyLegacyFormatResponseFromJSON, + GetStxSupplyLegacyFormatResponseToJSON, + GetStxSupplyResponse, + GetStxSupplyResponseFromJSON, + GetStxSupplyResponseToJSON, NetworkBlockTimeResponse, NetworkBlockTimeResponseFromJSON, NetworkBlockTimeResponseToJSON, NetworkBlockTimesResponse, NetworkBlockTimesResponseFromJSON, NetworkBlockTimesResponseToJSON, + ServerStatusResponse, + ServerStatusResponseFromJSON, + ServerStatusResponseToJSON, } from '../models'; export interface GetNetworkBlockTimeByNetworkRequest { network: GetNetworkBlockTimeByNetworkNetworkEnum; } +export interface GetStxSupplyRequest { + height?: number; +} + +export interface GetTotalStxSupplyLegacyFormatRequest { + height?: number; +} + /** * InfoApi - interface * @@ -41,78 +58,142 @@ export interface GetNetworkBlockTimeByNetworkRequest { */ export interface InfoApiInterface { /** - * Get Core API information + * Retrieves information about the Core API including the server version * @summary Get Core API info * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof InfoApiInterface */ - getCoreApiInfoRaw(): Promise>; + getCoreApiInfoRaw(initOverrides?: RequestInit): Promise>; /** - * Get Core API information + * Retrieves information about the Core API including the server version * Get Core API info */ - getCoreApiInfo(): Promise; + getCoreApiInfo(initOverrides?: RequestInit): Promise; /** - * + * Retrieves the target block time for a given network. The network can be mainnet or testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * @summary Get a given network\'s target block time - * @param {'testnet' | 'mainnet'} network Which network to retrieve the target block time of + * @param {'testnet' | 'mainnet'} network the target block time for a given network (testnet, mainnet). * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof InfoApiInterface */ - getNetworkBlockTimeByNetworkRaw(requestParameters: GetNetworkBlockTimeByNetworkRequest): Promise>; + getNetworkBlockTimeByNetworkRaw(requestParameters: GetNetworkBlockTimeByNetworkRequest, initOverrides?: RequestInit): Promise>; /** + * Retrieves the target block time for a given network. The network can be mainnet or testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * Get a given network\'s target block time */ - getNetworkBlockTimeByNetwork(requestParameters: GetNetworkBlockTimeByNetworkRequest): Promise; + getNetworkBlockTimeByNetwork(requestParameters: GetNetworkBlockTimeByNetworkRequest, initOverrides?: RequestInit): Promise; /** - * + * Retrieves the target block times for mainnet and testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * @summary Get the network target block time * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof InfoApiInterface */ - getNetworkBlockTimesRaw(): Promise>; + getNetworkBlockTimesRaw(initOverrides?: RequestInit): Promise>; /** + * Retrieves the target block times for mainnet and testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * Get the network target block time */ - getNetworkBlockTimes(): Promise; + getNetworkBlockTimes(initOverrides?: RequestInit): Promise; /** - * Get Proof of Transfer (PoX) information. Can be used for Stacking. - * @summary Get PoX details + * Retrieves Proof-of-Transfer (PoX) information. Can be used for Stacking. + * @summary Get Proof-of-Transfer details * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof InfoApiInterface */ - getPoxInfoRaw(): Promise>; + getPoxInfoRaw(initOverrides?: RequestInit): Promise>; /** - * Get Proof of Transfer (PoX) information. Can be used for Stacking. - * Get PoX details + * Retrieves Proof-of-Transfer (PoX) information. Can be used for Stacking. + * Get Proof-of-Transfer details */ - getPoxInfo(): Promise; + getPoxInfo(initOverrides?: RequestInit): Promise; /** - * Get Blockchain API status - * @summary Get Blockchain API status + * Retrieves the running status of the Stacks Blockchain API, including the server version and current chain tip information. + * @summary API status * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof InfoApiInterface */ - getStatusRaw(): Promise>; + getStatusRaw(initOverrides?: RequestInit): Promise>; /** - * Get Blockchain API status - * Get Blockchain API status + * Retrieves the running status of the Stacks Blockchain API, including the server version and current chain tip information. + * API status */ - getStatus(): Promise; + getStatus(initOverrides?: RequestInit): Promise; + + /** + * Retrieves the total and unlocked STX supply. More information on Stacking can be found [here] (https://docs.stacks.co/understand-stacks/stacking). **Note:** This uses the estimated future total supply for the year 2050. + * @summary Get total and unlocked STX supply + * @param {number} [height] Supply details are queried from specified block height. If the block height is not specified, the latest block height is taken as default value. Note that the `block height` is referred to the stacks blockchain. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof InfoApiInterface + */ + getStxSupplyRaw(requestParameters: GetStxSupplyRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the total and unlocked STX supply. More information on Stacking can be found [here] (https://docs.stacks.co/understand-stacks/stacking). **Note:** This uses the estimated future total supply for the year 2050. + * Get total and unlocked STX supply + */ + getStxSupply(requestParameters: GetStxSupplyRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves the STX tokens currently in circulation that have been unlocked as plain text. + * @summary Get circulating STX supply in plain text format + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof InfoApiInterface + */ + getStxSupplyCirculatingPlainRaw(initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the STX tokens currently in circulation that have been unlocked as plain text. + * Get circulating STX supply in plain text format + */ + getStxSupplyCirculatingPlain(initOverrides?: RequestInit): Promise; + + /** + * Retrieves the total supply for STX tokens as plain text. **Note:** this uses the estimated future total supply for the year 2050. + * @summary Get total STX supply in plain text format + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof InfoApiInterface + */ + getStxSupplyTotalSupplyPlainRaw(initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the total supply for STX tokens as plain text. **Note:** this uses the estimated future total supply for the year 2050. + * Get total STX supply in plain text format + */ + getStxSupplyTotalSupplyPlain(initOverrides?: RequestInit): Promise; + + /** + * Retrieves total supply of STX tokens including those currently in circulation that have been unlocked. **Note:** this uses the estimated future total supply for the year 2050. + * @summary Get total and unlocked STX supply (results formatted the same as the legacy 1.0 API) + * @param {number} [height] Supply details are queried from specified block height. If the block height is not specified, the latest block height is taken as default value. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof InfoApiInterface + */ + getTotalStxSupplyLegacyFormatRaw(requestParameters: GetTotalStxSupplyLegacyFormatRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves total supply of STX tokens including those currently in circulation that have been unlocked. **Note:** this uses the estimated future total supply for the year 2050. + * Get total and unlocked STX supply (results formatted the same as the legacy 1.0 API) + */ + getTotalStxSupplyLegacyFormat(requestParameters: GetTotalStxSupplyLegacyFormatRequest, initOverrides?: RequestInit): Promise; } @@ -122,11 +203,11 @@ export interface InfoApiInterface { export class InfoApi extends runtime.BaseAPI implements InfoApiInterface { /** - * Get Core API information + * Retrieves information about the Core API including the server version * Get Core API info */ - async getCoreApiInfoRaw(): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getCoreApiInfoRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -135,29 +216,30 @@ export class InfoApi extends runtime.BaseAPI implements InfoApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => CoreNodeInfoResponseFromJSON(jsonValue)); } /** - * Get Core API information + * Retrieves information about the Core API including the server version * Get Core API info */ - async getCoreApiInfo(): Promise { - const response = await this.getCoreApiInfoRaw(); + async getCoreApiInfo(initOverrides?: RequestInit): Promise { + const response = await this.getCoreApiInfoRaw(initOverrides); return await response.value(); } /** + * Retrieves the target block time for a given network. The network can be mainnet or testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * Get a given network\'s target block time */ - async getNetworkBlockTimeByNetworkRaw(requestParameters: GetNetworkBlockTimeByNetworkRequest): Promise> { + async getNetworkBlockTimeByNetworkRaw(requestParameters: GetNetworkBlockTimeByNetworkRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.network === null || requestParameters.network === undefined) { throw new runtime.RequiredError('network','Required parameter requestParameters.network was null or undefined when calling getNetworkBlockTimeByNetwork.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -166,24 +248,26 @@ export class InfoApi extends runtime.BaseAPI implements InfoApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => NetworkBlockTimeResponseFromJSON(jsonValue)); } /** + * Retrieves the target block time for a given network. The network can be mainnet or testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * Get a given network\'s target block time */ - async getNetworkBlockTimeByNetwork(requestParameters: GetNetworkBlockTimeByNetworkRequest): Promise { - const response = await this.getNetworkBlockTimeByNetworkRaw(requestParameters); + async getNetworkBlockTimeByNetwork(requestParameters: GetNetworkBlockTimeByNetworkRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNetworkBlockTimeByNetworkRaw(requestParameters, initOverrides); return await response.value(); } /** + * Retrieves the target block times for mainnet and testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * Get the network target block time */ - async getNetworkBlockTimesRaw(): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getNetworkBlockTimesRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -192,25 +276,26 @@ export class InfoApi extends runtime.BaseAPI implements InfoApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => NetworkBlockTimesResponseFromJSON(jsonValue)); } /** + * Retrieves the target block times for mainnet and testnet. The block time is hardcoded and will change throughout the implementation phases of the testnet. * Get the network target block time */ - async getNetworkBlockTimes(): Promise { - const response = await this.getNetworkBlockTimesRaw(); + async getNetworkBlockTimes(initOverrides?: RequestInit): Promise { + const response = await this.getNetworkBlockTimesRaw(initOverrides); return await response.value(); } /** - * Get Proof of Transfer (PoX) information. Can be used for Stacking. - * Get PoX details + * Retrieves Proof-of-Transfer (PoX) information. Can be used for Stacking. + * Get Proof-of-Transfer details */ - async getPoxInfoRaw(): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getPoxInfoRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -219,26 +304,26 @@ export class InfoApi extends runtime.BaseAPI implements InfoApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => CoreNodePoxResponseFromJSON(jsonValue)); } /** - * Get Proof of Transfer (PoX) information. Can be used for Stacking. - * Get PoX details + * Retrieves Proof-of-Transfer (PoX) information. Can be used for Stacking. + * Get Proof-of-Transfer details */ - async getPoxInfo(): Promise { - const response = await this.getPoxInfoRaw(); + async getPoxInfo(initOverrides?: RequestInit): Promise { + const response = await this.getPoxInfoRaw(initOverrides); return await response.value(); } /** - * Get Blockchain API status - * Get Blockchain API status + * Retrieves the running status of the Stacks Blockchain API, including the server version and current chain tip information. + * API status */ - async getStatusRaw(): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getStatusRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -247,17 +332,138 @@ export class InfoApi extends runtime.BaseAPI implements InfoApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); - return new runtime.VoidApiResponse(response); + return new runtime.JSONApiResponse(response, (jsonValue) => ServerStatusResponseFromJSON(jsonValue)); + } + + /** + * Retrieves the running status of the Stacks Blockchain API, including the server version and current chain tip information. + * API status + */ + async getStatus(initOverrides?: RequestInit): Promise { + const response = await this.getStatusRaw(initOverrides); + return await response.value(); } /** - * Get Blockchain API status - * Get Blockchain API status + * Retrieves the total and unlocked STX supply. More information on Stacking can be found [here] (https://docs.stacks.co/understand-stacks/stacking). **Note:** This uses the estimated future total supply for the year 2050. + * Get total and unlocked STX supply */ - async getStatus(): Promise { - await this.getStatusRaw(); + async getStxSupplyRaw(requestParameters: GetStxSupplyRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.height !== undefined) { + queryParameters['height'] = requestParameters.height; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/stx_supply`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => GetStxSupplyResponseFromJSON(jsonValue)); + } + + /** + * Retrieves the total and unlocked STX supply. More information on Stacking can be found [here] (https://docs.stacks.co/understand-stacks/stacking). **Note:** This uses the estimated future total supply for the year 2050. + * Get total and unlocked STX supply + */ + async getStxSupply(requestParameters: GetStxSupplyRequest, initOverrides?: RequestInit): Promise { + const response = await this.getStxSupplyRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves the STX tokens currently in circulation that have been unlocked as plain text. + * Get circulating STX supply in plain text format + */ + async getStxSupplyCirculatingPlainRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/stx_supply/circulating/plain`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.TextApiResponse(response) as any; + } + + /** + * Retrieves the STX tokens currently in circulation that have been unlocked as plain text. + * Get circulating STX supply in plain text format + */ + async getStxSupplyCirculatingPlain(initOverrides?: RequestInit): Promise { + const response = await this.getStxSupplyCirculatingPlainRaw(initOverrides); + return await response.value(); + } + + /** + * Retrieves the total supply for STX tokens as plain text. **Note:** this uses the estimated future total supply for the year 2050. + * Get total STX supply in plain text format + */ + async getStxSupplyTotalSupplyPlainRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/stx_supply/total/plain`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.TextApiResponse(response) as any; + } + + /** + * Retrieves the total supply for STX tokens as plain text. **Note:** this uses the estimated future total supply for the year 2050. + * Get total STX supply in plain text format + */ + async getStxSupplyTotalSupplyPlain(initOverrides?: RequestInit): Promise { + const response = await this.getStxSupplyTotalSupplyPlainRaw(initOverrides); + return await response.value(); + } + + /** + * Retrieves total supply of STX tokens including those currently in circulation that have been unlocked. **Note:** this uses the estimated future total supply for the year 2050. + * Get total and unlocked STX supply (results formatted the same as the legacy 1.0 API) + */ + async getTotalStxSupplyLegacyFormatRaw(requestParameters: GetTotalStxSupplyLegacyFormatRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.height !== undefined) { + queryParameters['height'] = requestParameters.height; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/stx_supply/legacy_format`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => GetStxSupplyLegacyFormatResponseFromJSON(jsonValue)); + } + + /** + * Retrieves total supply of STX tokens including those currently in circulation that have been unlocked. **Note:** this uses the estimated future total supply for the year 2050. + * Get total and unlocked STX supply (results formatted the same as the legacy 1.0 API) + */ + async getTotalStxSupplyLegacyFormat(requestParameters: GetTotalStxSupplyLegacyFormatRequest, initOverrides?: RequestInit): Promise { + const response = await this.getTotalStxSupplyLegacyFormatRaw(requestParameters, initOverrides); + return await response.value(); } } diff --git a/client/src/generated/apis/MempoolApi.ts b/client/src/generated/apis/MempoolApi.ts new file mode 100644 index 0000000000..94c7a8e117 --- /dev/null +++ b/client/src/generated/apis/MempoolApi.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + MempoolFeePriorities, + MempoolFeePrioritiesFromJSON, + MempoolFeePrioritiesToJSON, +} from '../models'; + +/** + * MempoolApi - interface + * + * @export + * @interface MempoolApiInterface + */ +export interface MempoolApiInterface { + /** + * Returns estimated fee priorities (in micro-STX) for all transactions that are currently in the mempool. Also returns priorities separated by transaction type. + * @summary Get mempool transaction fee priorities + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof MempoolApiInterface + */ + getMempoolFeePrioritiesRaw(initOverrides?: RequestInit): Promise>; + + /** + * Returns estimated fee priorities (in micro-STX) for all transactions that are currently in the mempool. Also returns priorities separated by transaction type. + * Get mempool transaction fee priorities + */ + getMempoolFeePriorities(initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class MempoolApi extends runtime.BaseAPI implements MempoolApiInterface { + + /** + * Returns estimated fee priorities (in micro-STX) for all transactions that are currently in the mempool. Also returns priorities separated by transaction type. + * Get mempool transaction fee priorities + */ + async getMempoolFeePrioritiesRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v2/mempool/fees`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => MempoolFeePrioritiesFromJSON(jsonValue)); + } + + /** + * Returns estimated fee priorities (in micro-STX) for all transactions that are currently in the mempool. Also returns priorities separated by transaction type. + * Get mempool transaction fee priorities + */ + async getMempoolFeePriorities(initOverrides?: RequestInit): Promise { + const response = await this.getMempoolFeePrioritiesRaw(initOverrides); + return await response.value(); + } + +} diff --git a/client/src/generated/apis/MicroblocksApi.ts b/client/src/generated/apis/MicroblocksApi.ts new file mode 100644 index 0000000000..3ce87be708 --- /dev/null +++ b/client/src/generated/apis/MicroblocksApi.ts @@ -0,0 +1,196 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + Microblock, + MicroblockFromJSON, + MicroblockToJSON, + MicroblockListResponse, + MicroblockListResponseFromJSON, + MicroblockListResponseToJSON, + UnanchoredTransactionListResponse, + UnanchoredTransactionListResponseFromJSON, + UnanchoredTransactionListResponseToJSON, +} from '../models'; + +export interface GetMicroblockByHashRequest { + hash: string; +} + +export interface GetMicroblockListRequest { + limit?: number; + offset?: number; +} + +/** + * MicroblocksApi - interface + * + * @export + * @interface MicroblocksApiInterface + */ +export interface MicroblocksApiInterface { + /** + * Retrieves a specific microblock by `hash` + * @summary Get microblock + * @param {string} hash Hash of the microblock + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof MicroblocksApiInterface + */ + getMicroblockByHashRaw(requestParameters: GetMicroblockByHashRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a specific microblock by `hash` + * Get microblock + */ + getMicroblockByHash(requestParameters: GetMicroblockByHashRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of microblocks. If you need to actively monitor new microblocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. + * @summary Get recent microblocks + * @param {number} [limit] Max number of microblocks to fetch + * @param {number} [offset] Index of the first microblock to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof MicroblocksApiInterface + */ + getMicroblockListRaw(requestParameters: GetMicroblockListRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of microblocks. If you need to actively monitor new microblocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. + * Get recent microblocks + */ + getMicroblockList(requestParameters: GetMicroblockListRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves transactions that have been streamed in microblocks but not yet accepted or rejected in an anchor block + * @summary Get the list of current transactions that belong to unanchored microblocks + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof MicroblocksApiInterface + */ + getUnanchoredTxsRaw(initOverrides?: RequestInit): Promise>; + + /** + * Retrieves transactions that have been streamed in microblocks but not yet accepted or rejected in an anchor block + * Get the list of current transactions that belong to unanchored microblocks + */ + getUnanchoredTxs(initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class MicroblocksApi extends runtime.BaseAPI implements MicroblocksApiInterface { + + /** + * Retrieves a specific microblock by `hash` + * Get microblock + */ + async getMicroblockByHashRaw(requestParameters: GetMicroblockByHashRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.hash === null || requestParameters.hash === undefined) { + throw new runtime.RequiredError('hash','Required parameter requestParameters.hash was null or undefined when calling getMicroblockByHash.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/microblock/{hash}`.replace(`{${"hash"}}`, encodeURIComponent(String(requestParameters.hash))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => MicroblockFromJSON(jsonValue)); + } + + /** + * Retrieves a specific microblock by `hash` + * Get microblock + */ + async getMicroblockByHash(requestParameters: GetMicroblockByHashRequest, initOverrides?: RequestInit): Promise { + const response = await this.getMicroblockByHashRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of microblocks. If you need to actively monitor new microblocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. + * Get recent microblocks + */ + async getMicroblockListRaw(requestParameters: GetMicroblockListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/microblock`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => MicroblockListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of microblocks. If you need to actively monitor new microblocks, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. + * Get recent microblocks + */ + async getMicroblockList(requestParameters: GetMicroblockListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getMicroblockListRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves transactions that have been streamed in microblocks but not yet accepted or rejected in an anchor block + * Get the list of current transactions that belong to unanchored microblocks + */ + async getUnanchoredTxsRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/microblock/unanchored/txs`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => UnanchoredTransactionListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves transactions that have been streamed in microblocks but not yet accepted or rejected in an anchor block + * Get the list of current transactions that belong to unanchored microblocks + */ + async getUnanchoredTxs(initOverrides?: RequestInit): Promise { + const response = await this.getUnanchoredTxsRaw(initOverrides); + return await response.value(); + } + +} diff --git a/client/src/generated/apis/NamesApi.ts b/client/src/generated/apis/NamesApi.ts new file mode 100644 index 0000000000..d605968e62 --- /dev/null +++ b/client/src/generated/apis/NamesApi.ts @@ -0,0 +1,581 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + BnsError, + BnsErrorFromJSON, + BnsErrorToJSON, + BnsGetAllNamespacesResponse, + BnsGetAllNamespacesResponseFromJSON, + BnsGetAllNamespacesResponseToJSON, + BnsGetNameInfoResponse, + BnsGetNameInfoResponseFromJSON, + BnsGetNameInfoResponseToJSON, + BnsGetNamePriceResponse, + BnsGetNamePriceResponseFromJSON, + BnsGetNamePriceResponseToJSON, + BnsGetNamespacePriceResponse, + BnsGetNamespacePriceResponseFromJSON, + BnsGetNamespacePriceResponseToJSON, + BnsNamesOwnByAddressResponse, + BnsNamesOwnByAddressResponseFromJSON, + BnsNamesOwnByAddressResponseToJSON, +} from '../models'; + +export interface FetchSubdomainsListForNameRequest { + name: string; +} + +export interface FetchZoneFileRequest { + name: string; +} + +export interface GetAllNamesRequest { + page?: number; +} + +export interface GetHistoricalZoneFileRequest { + name: string; + zoneFileHash: string; +} + +export interface GetNameInfoRequest { + name: string; +} + +export interface GetNamePriceRequest { + name: string; +} + +export interface GetNamesOwnedByAddressRequest { + blockchain: string; + address: string; +} + +export interface GetNamespaceNamesRequest { + tld: string; + page?: number; +} + +export interface GetNamespacePriceRequest { + tld: string; +} + +/** + * NamesApi - interface + * + * @export + * @interface NamesApiInterface + */ +export interface NamesApiInterface { + /** + * Retrieves the list of subdomains for a specific name + * @summary Get Name Subdomains + * @param {string} name fully-qualified name + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + fetchSubdomainsListForNameRaw(requestParameters: FetchSubdomainsListForNameRequest, initOverrides?: RequestInit): Promise>>; + + /** + * Retrieves the list of subdomains for a specific name + * Get Name Subdomains + */ + fetchSubdomainsListForName(requestParameters: FetchSubdomainsListForNameRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a user’s raw zone file. This only works for RFC-compliant zone files. This method returns an error for names that have non-standard zone files. + * @summary Get Zone File + * @param {string} name fully-qualified name + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + fetchZoneFileRaw(requestParameters: FetchZoneFileRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a user’s raw zone file. This only works for RFC-compliant zone files. This method returns an error for names that have non-standard zone files. + * Get Zone File + */ + fetchZoneFile(requestParameters: FetchZoneFileRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of all names known to the node. + * @summary Get All Names + * @param {number} [page] names are defaulted to page 1 with 100 results. You can query specific page results by using the \'page\' query parameter. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getAllNamesRaw(requestParameters: GetAllNamesRequest, initOverrides?: RequestInit): Promise>>; + + /** + * Retrieves a list of all names known to the node. + * Get All Names + */ + getAllNames(requestParameters: GetAllNamesRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of all namespaces known to the node. + * @summary Get All Namespaces + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getAllNamespacesRaw(initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of all namespaces known to the node. + * Get All Namespaces + */ + getAllNamespaces(initOverrides?: RequestInit): Promise; + + /** + * Retrieves the historical zonefile specified by the username and zone hash. + * @summary Get Historical Zone File + * @param {string} name fully-qualified name + * @param {string} zoneFileHash zone file hash + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getHistoricalZoneFileRaw(requestParameters: GetHistoricalZoneFileRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the historical zonefile specified by the username and zone hash. + * Get Historical Zone File + */ + getHistoricalZoneFile(requestParameters: GetHistoricalZoneFileRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves details of a given name including the `address`, `status` and last transaction id - `last_txid`. + * @summary Get Name Details + * @param {string} name fully-qualified name + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getNameInfoRaw(requestParameters: GetNameInfoRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves details of a given name including the `address`, `status` and last transaction id - `last_txid`. + * Get Name Details + */ + getNameInfo(requestParameters: GetNameInfoRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves the price of a name. The `amount` given will be in the smallest possible units of the currency. + * @summary Get Name Price + * @param {string} name the name to query price information for + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getNamePriceRaw(requestParameters: GetNamePriceRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the price of a name. The `amount` given will be in the smallest possible units of the currency. + * Get Name Price + */ + getNamePrice(requestParameters: GetNamePriceRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of names owned by the address provided. + * @summary Get Names Owned by Address + * @param {string} blockchain the layer-1 blockchain for the address + * @param {string} address the address to lookup + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getNamesOwnedByAddressRaw(requestParameters: GetNamesOwnedByAddressRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of names owned by the address provided. + * Get Names Owned by Address + */ + getNamesOwnedByAddress(requestParameters: GetNamesOwnedByAddressRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of names within a given namespace. + * @summary Get Namespace Names + * @param {string} tld the namespace to fetch names from. + * @param {number} [page] namespace values are defaulted to page 1 with 100 results. You can query specific page results by using the \'page\' query parameter. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getNamespaceNamesRaw(requestParameters: GetNamespaceNamesRequest, initOverrides?: RequestInit): Promise>>; + + /** + * Retrieves a list of names within a given namespace. + * Get Namespace Names + */ + getNamespaceNames(requestParameters: GetNamespaceNamesRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the price of a namespace. The `amount` given will be in the smallest possible units of the currency. + * @summary Get Namespace Price + * @param {string} tld the namespace to fetch price for + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NamesApiInterface + */ + getNamespacePriceRaw(requestParameters: GetNamespacePriceRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the price of a namespace. The `amount` given will be in the smallest possible units of the currency. + * Get Namespace Price + */ + getNamespacePrice(requestParameters: GetNamespacePriceRequest, initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class NamesApi extends runtime.BaseAPI implements NamesApiInterface { + + /** + * Retrieves the list of subdomains for a specific name + * Get Name Subdomains + */ + async fetchSubdomainsListForNameRaw(requestParameters: FetchSubdomainsListForNameRequest, initOverrides?: RequestInit): Promise>> { + if (requestParameters.name === null || requestParameters.name === undefined) { + throw new runtime.RequiredError('name','Required parameter requestParameters.name was null or undefined when calling fetchSubdomainsListForName.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/names/{name}/subdomains`.replace(`{${"name"}}`, encodeURIComponent(String(requestParameters.name))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Retrieves the list of subdomains for a specific name + * Get Name Subdomains + */ + async fetchSubdomainsListForName(requestParameters: FetchSubdomainsListForNameRequest, initOverrides?: RequestInit): Promise> { + const response = await this.fetchSubdomainsListForNameRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a user’s raw zone file. This only works for RFC-compliant zone files. This method returns an error for names that have non-standard zone files. + * Get Zone File + */ + async fetchZoneFileRaw(requestParameters: FetchZoneFileRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.name === null || requestParameters.name === undefined) { + throw new runtime.RequiredError('name','Required parameter requestParameters.name was null or undefined when calling fetchZoneFile.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/names/{name}/zonefile`.replace(`{${"name"}}`, encodeURIComponent(String(requestParameters.name))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Retrieves a user’s raw zone file. This only works for RFC-compliant zone files. This method returns an error for names that have non-standard zone files. + * Get Zone File + */ + async fetchZoneFile(requestParameters: FetchZoneFileRequest, initOverrides?: RequestInit): Promise { + const response = await this.fetchZoneFileRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of all names known to the node. + * Get All Names + */ + async getAllNamesRaw(requestParameters: GetAllNamesRequest, initOverrides?: RequestInit): Promise>> { + const queryParameters: any = {}; + + if (requestParameters.page !== undefined) { + queryParameters['page'] = requestParameters.page; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/names`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Retrieves a list of all names known to the node. + * Get All Names + */ + async getAllNames(requestParameters: GetAllNamesRequest, initOverrides?: RequestInit): Promise> { + const response = await this.getAllNamesRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of all namespaces known to the node. + * Get All Namespaces + */ + async getAllNamespacesRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/namespaces`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BnsGetAllNamespacesResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of all namespaces known to the node. + * Get All Namespaces + */ + async getAllNamespaces(initOverrides?: RequestInit): Promise { + const response = await this.getAllNamespacesRaw(initOverrides); + return await response.value(); + } + + /** + * Retrieves the historical zonefile specified by the username and zone hash. + * Get Historical Zone File + */ + async getHistoricalZoneFileRaw(requestParameters: GetHistoricalZoneFileRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.name === null || requestParameters.name === undefined) { + throw new runtime.RequiredError('name','Required parameter requestParameters.name was null or undefined when calling getHistoricalZoneFile.'); + } + + if (requestParameters.zoneFileHash === null || requestParameters.zoneFileHash === undefined) { + throw new runtime.RequiredError('zoneFileHash','Required parameter requestParameters.zoneFileHash was null or undefined when calling getHistoricalZoneFile.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/names/{name}/zonefile/{zoneFileHash}`.replace(`{${"name"}}`, encodeURIComponent(String(requestParameters.name))).replace(`{${"zoneFileHash"}}`, encodeURIComponent(String(requestParameters.zoneFileHash))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Retrieves the historical zonefile specified by the username and zone hash. + * Get Historical Zone File + */ + async getHistoricalZoneFile(requestParameters: GetHistoricalZoneFileRequest, initOverrides?: RequestInit): Promise { + const response = await this.getHistoricalZoneFileRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves details of a given name including the `address`, `status` and last transaction id - `last_txid`. + * Get Name Details + */ + async getNameInfoRaw(requestParameters: GetNameInfoRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.name === null || requestParameters.name === undefined) { + throw new runtime.RequiredError('name','Required parameter requestParameters.name was null or undefined when calling getNameInfo.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/names/{name}`.replace(`{${"name"}}`, encodeURIComponent(String(requestParameters.name))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BnsGetNameInfoResponseFromJSON(jsonValue)); + } + + /** + * Retrieves details of a given name including the `address`, `status` and last transaction id - `last_txid`. + * Get Name Details + */ + async getNameInfo(requestParameters: GetNameInfoRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNameInfoRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves the price of a name. The `amount` given will be in the smallest possible units of the currency. + * Get Name Price + */ + async getNamePriceRaw(requestParameters: GetNamePriceRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.name === null || requestParameters.name === undefined) { + throw new runtime.RequiredError('name','Required parameter requestParameters.name was null or undefined when calling getNamePrice.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v2/prices/names/{name}`.replace(`{${"name"}}`, encodeURIComponent(String(requestParameters.name))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BnsGetNamePriceResponseFromJSON(jsonValue)); + } + + /** + * Retrieves the price of a name. The `amount` given will be in the smallest possible units of the currency. + * Get Name Price + */ + async getNamePrice(requestParameters: GetNamePriceRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNamePriceRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of names owned by the address provided. + * Get Names Owned by Address + */ + async getNamesOwnedByAddressRaw(requestParameters: GetNamesOwnedByAddressRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.blockchain === null || requestParameters.blockchain === undefined) { + throw new runtime.RequiredError('blockchain','Required parameter requestParameters.blockchain was null or undefined when calling getNamesOwnedByAddress.'); + } + + if (requestParameters.address === null || requestParameters.address === undefined) { + throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling getNamesOwnedByAddress.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/addresses/{blockchain}/{address}`.replace(`{${"blockchain"}}`, encodeURIComponent(String(requestParameters.blockchain))).replace(`{${"address"}}`, encodeURIComponent(String(requestParameters.address))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BnsNamesOwnByAddressResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of names owned by the address provided. + * Get Names Owned by Address + */ + async getNamesOwnedByAddress(requestParameters: GetNamesOwnedByAddressRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNamesOwnedByAddressRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of names within a given namespace. + * Get Namespace Names + */ + async getNamespaceNamesRaw(requestParameters: GetNamespaceNamesRequest, initOverrides?: RequestInit): Promise>> { + if (requestParameters.tld === null || requestParameters.tld === undefined) { + throw new runtime.RequiredError('tld','Required parameter requestParameters.tld was null or undefined when calling getNamespaceNames.'); + } + + const queryParameters: any = {}; + + if (requestParameters.page !== undefined) { + queryParameters['page'] = requestParameters.page; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v1/namespaces/{tld}/names`.replace(`{${"tld"}}`, encodeURIComponent(String(requestParameters.tld))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Retrieves a list of names within a given namespace. + * Get Namespace Names + */ + async getNamespaceNames(requestParameters: GetNamespaceNamesRequest, initOverrides?: RequestInit): Promise> { + const response = await this.getNamespaceNamesRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves the price of a namespace. The `amount` given will be in the smallest possible units of the currency. + * Get Namespace Price + */ + async getNamespacePriceRaw(requestParameters: GetNamespacePriceRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.tld === null || requestParameters.tld === undefined) { + throw new runtime.RequiredError('tld','Required parameter requestParameters.tld was null or undefined when calling getNamespacePrice.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/v2/prices/namespaces/{tld}`.replace(`{${"tld"}}`, encodeURIComponent(String(requestParameters.tld))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BnsGetNamespacePriceResponseFromJSON(jsonValue)); + } + + /** + * Retrieves the price of a namespace. The `amount` given will be in the smallest possible units of the currency. + * Get Namespace Price + */ + async getNamespacePrice(requestParameters: GetNamespacePriceRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNamespacePriceRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/client/src/generated/apis/NonFungibleTokensApi.ts b/client/src/generated/apis/NonFungibleTokensApi.ts new file mode 100644 index 0000000000..5313556c29 --- /dev/null +++ b/client/src/generated/apis/NonFungibleTokensApi.ts @@ -0,0 +1,415 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + NonFungibleTokenHistoryEventList, + NonFungibleTokenHistoryEventListFromJSON, + NonFungibleTokenHistoryEventListToJSON, + NonFungibleTokenHoldingsList, + NonFungibleTokenHoldingsListFromJSON, + NonFungibleTokenHoldingsListToJSON, + NonFungibleTokenMetadata, + NonFungibleTokenMetadataFromJSON, + NonFungibleTokenMetadataToJSON, + NonFungibleTokenMintList, + NonFungibleTokenMintListFromJSON, + NonFungibleTokenMintListToJSON, + NonFungibleTokensMetadataList, + NonFungibleTokensMetadataListFromJSON, + NonFungibleTokensMetadataListToJSON, +} from '../models'; + +export interface GetContractNftMetadataRequest { + contractId: string; +} + +export interface GetNftHistoryRequest { + assetIdentifier: string; + value: string; + limit?: number; + offset?: number; + unanchored?: boolean; + txMetadata?: boolean; +} + +export interface GetNftHoldingsRequest { + principal: string; + assetIdentifiers?: Array; + limit?: number; + offset?: number; + unanchored?: boolean; + txMetadata?: boolean; +} + +export interface GetNftMetadataListRequest { + limit?: number; + offset?: number; +} + +export interface GetNftMintsRequest { + assetIdentifier: string; + limit?: number; + offset?: number; + unanchored?: boolean; + txMetadata?: boolean; +} + +/** + * NonFungibleTokensApi - interface + * + * @export + * @interface NonFungibleTokensApiInterface + */ +export interface NonFungibleTokensApiInterface { + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves metadata for non fungible tokens for a given contract id. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * @summary Non fungible tokens metadata for contract ID + * @param {string} contractId token\'s contract id + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NonFungibleTokensApiInterface + */ + getContractNftMetadataRaw(requestParameters: GetContractNftMetadataRequest, initOverrides?: RequestInit): Promise>; + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves metadata for non fungible tokens for a given contract id. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non fungible tokens metadata for contract ID + */ + getContractNftMetadata(requestParameters: GetContractNftMetadataRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves all events relevant to a Non-Fungible Token. Useful to determine the ownership history of a particular asset. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * @summary Non-Fungible Token history + * @param {string} assetIdentifier token asset class identifier + * @param {string} value hex representation of the token\'s unique value + * @param {number} [limit] max number of events to fetch + * @param {number} [offset] index of first event to fetch + * @param {boolean} [unanchored] whether or not to include events from unconfirmed transactions + * @param {boolean} [txMetadata] whether or not to include the complete transaction metadata instead of just `tx_id`. Enabling this option can affect performance and response times. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NonFungibleTokensApiInterface + */ + getNftHistoryRaw(requestParameters: GetNftHistoryRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves all events relevant to a Non-Fungible Token. Useful to determine the ownership history of a particular asset. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token history + */ + getNftHistory(requestParameters: GetNftHistoryRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves the list of Non-Fungible Tokens owned by the given principal (STX address or Smart Contract ID). Results can be filtered by one or more asset identifiers and can include metadata about the transaction that made the principal own each token. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * @summary Non-Fungible Token holdings + * @param {string} principal token owner\'s STX address or Smart Contract ID + * @param {Array} [assetIdentifiers] identifiers of the token asset classes to filter for + * @param {number} [limit] max number of tokens to fetch + * @param {number} [offset] index of first tokens to fetch + * @param {boolean} [unanchored] whether or not to include tokens from unconfirmed transactions + * @param {boolean} [txMetadata] whether or not to include the complete transaction metadata instead of just `tx_id`. Enabling this option can affect performance and response times. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NonFungibleTokensApiInterface + */ + getNftHoldingsRaw(requestParameters: GetNftHoldingsRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the list of Non-Fungible Tokens owned by the given principal (STX address or Smart Contract ID). Results can be filtered by one or more asset identifiers and can include metadata about the transaction that made the principal own each token. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token holdings + */ + getNftHoldings(requestParameters: GetNftHoldingsRequest, initOverrides?: RequestInit): Promise; + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves a list of non fungible tokens with their metadata. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * @summary Non fungible tokens metadata list + * @param {number} [limit] max number of tokens to fetch + * @param {number} [offset] index of first tokens to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NonFungibleTokensApiInterface + */ + getNftMetadataListRaw(requestParameters: GetNftMetadataListRequest, initOverrides?: RequestInit): Promise>; + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves a list of non fungible tokens with their metadata. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non fungible tokens metadata list + */ + getNftMetadataList(requestParameters: GetNftMetadataListRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves all mint events for a Non-Fungible Token asset class. Useful to determine which NFTs of a particular collection have been claimed. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * @summary Non-Fungible Token mints + * @param {string} assetIdentifier token asset class identifier + * @param {number} [limit] max number of events to fetch + * @param {number} [offset] index of first event to fetch + * @param {boolean} [unanchored] whether or not to include events from unconfirmed transactions + * @param {boolean} [txMetadata] whether or not to include the complete transaction metadata instead of just `tx_id`. Enabling this option can affect performance and response times. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NonFungibleTokensApiInterface + */ + getNftMintsRaw(requestParameters: GetNftMintsRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves all mint events for a Non-Fungible Token asset class. Useful to determine which NFTs of a particular collection have been claimed. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token mints + */ + getNftMints(requestParameters: GetNftMintsRequest, initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class NonFungibleTokensApi extends runtime.BaseAPI implements NonFungibleTokensApiInterface { + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves metadata for non fungible tokens for a given contract id. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non fungible tokens metadata for contract ID + */ + async getContractNftMetadataRaw(requestParameters: GetContractNftMetadataRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.contractId === null || requestParameters.contractId === undefined) { + throw new runtime.RequiredError('contractId','Required parameter requestParameters.contractId was null or undefined when calling getContractNftMetadata.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tokens/{contractId}/nft/metadata`.replace(`{${"contractId"}}`, encodeURIComponent(String(requestParameters.contractId))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => NonFungibleTokenMetadataFromJSON(jsonValue)); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves metadata for non fungible tokens for a given contract id. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non fungible tokens metadata for contract ID + */ + async getContractNftMetadata(requestParameters: GetContractNftMetadataRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractNftMetadataRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves all events relevant to a Non-Fungible Token. Useful to determine the ownership history of a particular asset. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token history + */ + async getNftHistoryRaw(requestParameters: GetNftHistoryRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.assetIdentifier === null || requestParameters.assetIdentifier === undefined) { + throw new runtime.RequiredError('assetIdentifier','Required parameter requestParameters.assetIdentifier was null or undefined when calling getNftHistory.'); + } + + if (requestParameters.value === null || requestParameters.value === undefined) { + throw new runtime.RequiredError('value','Required parameter requestParameters.value was null or undefined when calling getNftHistory.'); + } + + const queryParameters: any = {}; + + if (requestParameters.assetIdentifier !== undefined) { + queryParameters['asset_identifier'] = requestParameters.assetIdentifier; + } + + if (requestParameters.value !== undefined) { + queryParameters['value'] = requestParameters.value; + } + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.txMetadata !== undefined) { + queryParameters['tx_metadata'] = requestParameters.txMetadata; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tokens/nft/history`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => NonFungibleTokenHistoryEventListFromJSON(jsonValue)); + } + + /** + * Retrieves all events relevant to a Non-Fungible Token. Useful to determine the ownership history of a particular asset. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token history + */ + async getNftHistory(requestParameters: GetNftHistoryRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNftHistoryRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves the list of Non-Fungible Tokens owned by the given principal (STX address or Smart Contract ID). Results can be filtered by one or more asset identifiers and can include metadata about the transaction that made the principal own each token. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token holdings + */ + async getNftHoldingsRaw(requestParameters: GetNftHoldingsRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.principal === null || requestParameters.principal === undefined) { + throw new runtime.RequiredError('principal','Required parameter requestParameters.principal was null or undefined when calling getNftHoldings.'); + } + + const queryParameters: any = {}; + + if (requestParameters.principal !== undefined) { + queryParameters['principal'] = requestParameters.principal; + } + + if (requestParameters.assetIdentifiers) { + queryParameters['asset_identifiers'] = requestParameters.assetIdentifiers; + } + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.txMetadata !== undefined) { + queryParameters['tx_metadata'] = requestParameters.txMetadata; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tokens/nft/holdings`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => NonFungibleTokenHoldingsListFromJSON(jsonValue)); + } + + /** + * Retrieves the list of Non-Fungible Tokens owned by the given principal (STX address or Smart Contract ID). Results can be filtered by one or more asset identifiers and can include metadata about the transaction that made the principal own each token. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token holdings + */ + async getNftHoldings(requestParameters: GetNftHoldingsRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNftHoldingsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves a list of non fungible tokens with their metadata. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non fungible tokens metadata list + */ + async getNftMetadataListRaw(requestParameters: GetNftMetadataListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tokens/nft/metadata`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => NonFungibleTokensMetadataListFromJSON(jsonValue)); + } + + /** + * **NOTE:** This endpoint is deprecated in favor of the [Token Metadata Service](https://github.com/hirosystems/token-metadata-service). Retrieves a list of non fungible tokens with their metadata. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non fungible tokens metadata list + */ + async getNftMetadataList(requestParameters: GetNftMetadataListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNftMetadataListRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves all mint events for a Non-Fungible Token asset class. Useful to determine which NFTs of a particular collection have been claimed. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token mints + */ + async getNftMintsRaw(requestParameters: GetNftMintsRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.assetIdentifier === null || requestParameters.assetIdentifier === undefined) { + throw new runtime.RequiredError('assetIdentifier','Required parameter requestParameters.assetIdentifier was null or undefined when calling getNftMints.'); + } + + const queryParameters: any = {}; + + if (requestParameters.assetIdentifier !== undefined) { + queryParameters['asset_identifier'] = requestParameters.assetIdentifier; + } + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.txMetadata !== undefined) { + queryParameters['tx_metadata'] = requestParameters.txMetadata; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tokens/nft/mints`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => NonFungibleTokenMintListFromJSON(jsonValue)); + } + + /** + * Retrieves all mint events for a Non-Fungible Token asset class. Useful to determine which NFTs of a particular collection have been claimed. More information on Non-Fungible Tokens on the Stacks blockchain can be found [here](https://docs.stacks.co/write-smart-contracts/tokens#non-fungible-tokens-nfts). + * Non-Fungible Token mints + */ + async getNftMints(requestParameters: GetNftMintsRequest, initOverrides?: RequestInit): Promise { + const response = await this.getNftMintsRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/client/src/generated/apis/RosettaApi.ts b/client/src/generated/apis/RosettaApi.ts index 2d2db9fff9..9bcd140db6 100644 --- a/client/src/generated/apis/RosettaApi.ts +++ b/client/src/generated/apis/RosettaApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -102,6 +102,9 @@ import { RosettaNetworkOptionsResponse, RosettaNetworkOptionsResponseFromJSON, RosettaNetworkOptionsResponseToJSON, + RosettaNetworkStatusResponse, + RosettaNetworkStatusResponseFromJSON, + RosettaNetworkStatusResponseToJSON, RosettaOptionsRequest, RosettaOptionsRequestFromJSON, RosettaOptionsRequestToJSON, @@ -185,109 +188,109 @@ export interface RosettaApiInterface { * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaAccountBalanceRaw(requestParameters: RosettaAccountBalanceOperationRequest): Promise>; + rosettaAccountBalanceRaw(requestParameters: RosettaAccountBalanceOperationRequest, initOverrides?: RequestInit): Promise>; /** * An AccountBalanceRequest is utilized to make a balance request on the /account/balance endpoint. If the block_identifier is populated, a historical balance query should be performed. * Get an Account Balance */ - rosettaAccountBalance(requestParameters: RosettaAccountBalanceOperationRequest): Promise; + rosettaAccountBalance(requestParameters: RosettaAccountBalanceOperationRequest, initOverrides?: RequestInit): Promise; /** - * A BlockRequest is utilized to make a block request on the /block endpoint. + * Retrieves the Block information for a given block identifier including a list of all transactions in the block. * @summary Get a Block * @param {RosettaBlockRequest} rosettaBlockRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaBlockRaw(requestParameters: RosettaBlockOperationRequest): Promise>; + rosettaBlockRaw(requestParameters: RosettaBlockOperationRequest, initOverrides?: RequestInit): Promise>; /** - * A BlockRequest is utilized to make a block request on the /block endpoint. + * Retrieves the Block information for a given block identifier including a list of all transactions in the block. * Get a Block */ - rosettaBlock(requestParameters: RosettaBlockOperationRequest): Promise; + rosettaBlock(requestParameters: RosettaBlockOperationRequest, initOverrides?: RequestInit): Promise; /** - * A BlockTransactionRequest is used to fetch a Transaction included in a block that is not returned in a BlockResponse. + * Retrieves a Transaction included in a block that is not returned in a BlockResponse. * @summary Get a Block Transaction * @param {RosettaBlockTransactionRequest} rosettaBlockTransactionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaBlockTransactionRaw(requestParameters: RosettaBlockTransactionOperationRequest): Promise>; + rosettaBlockTransactionRaw(requestParameters: RosettaBlockTransactionOperationRequest, initOverrides?: RequestInit): Promise>; /** - * A BlockTransactionRequest is used to fetch a Transaction included in a block that is not returned in a BlockResponse. + * Retrieves a Transaction included in a block that is not returned in a BlockResponse. * Get a Block Transaction */ - rosettaBlockTransaction(requestParameters: RosettaBlockTransactionOperationRequest): Promise; + rosettaBlockTransaction(requestParameters: RosettaBlockTransactionOperationRequest, initOverrides?: RequestInit): Promise; /** - * Take unsigned transaction and signature, combine both and return signed transaction + * Take unsigned transaction and signature, combine both and return signed transaction. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * @summary Create Network Transaction from Signatures * @param {RosettaConstructionCombineRequest} rosettaConstructionCombineRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionCombineRaw(requestParameters: RosettaConstructionCombineOperationRequest): Promise>; + rosettaConstructionCombineRaw(requestParameters: RosettaConstructionCombineOperationRequest, initOverrides?: RequestInit): Promise>; /** - * Take unsigned transaction and signature, combine both and return signed transaction + * Take unsigned transaction and signature, combine both and return signed transaction. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Create Network Transaction from Signatures */ - rosettaConstructionCombine(requestParameters: RosettaConstructionCombineOperationRequest): Promise; + rosettaConstructionCombine(requestParameters: RosettaConstructionCombineOperationRequest, initOverrides?: RequestInit): Promise; /** - * TODO + * Retrieves the Account Identifier information based on a Public Key for a given network * @summary Derive an AccountIdentifier from a PublicKey * @param {RosettaConstructionDeriveRequest} rosettaConstructionDeriveRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionDeriveRaw(requestParameters: RosettaConstructionDeriveOperationRequest): Promise>; + rosettaConstructionDeriveRaw(requestParameters: RosettaConstructionDeriveOperationRequest, initOverrides?: RequestInit): Promise>; /** - * TODO + * Retrieves the Account Identifier information based on a Public Key for a given network * Derive an AccountIdentifier from a PublicKey */ - rosettaConstructionDerive(requestParameters: RosettaConstructionDeriveOperationRequest): Promise; + rosettaConstructionDerive(requestParameters: RosettaConstructionDeriveOperationRequest, initOverrides?: RequestInit): Promise; /** - * TODO + * Retrieves the network-specific transaction hash for a signed transaction. * @summary Get the Hash of a Signed Transaction * @param {RosettaConstructionHashRequest} rosettaConstructionHashRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionHashRaw(requestParameters: RosettaConstructionHashOperationRequest): Promise>; + rosettaConstructionHashRaw(requestParameters: RosettaConstructionHashOperationRequest, initOverrides?: RequestInit): Promise>; /** - * TODO + * Retrieves the network-specific transaction hash for a signed transaction. * Get the Hash of a Signed Transaction */ - rosettaConstructionHash(requestParameters: RosettaConstructionHashOperationRequest): Promise; + rosettaConstructionHash(requestParameters: RosettaConstructionHashOperationRequest, initOverrides?: RequestInit): Promise; /** - * TODO + * To Do * @summary Get Metadata for Transaction Construction * @param {RosettaConstructionMetadataRequest} rosettaConstructionMetadataRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionMetadataRaw(requestParameters: RosettaConstructionMetadataOperationRequest): Promise>; + rosettaConstructionMetadataRaw(requestParameters: RosettaConstructionMetadataOperationRequest, initOverrides?: RequestInit): Promise>; /** - * TODO + * To Do * Get Metadata for Transaction Construction */ - rosettaConstructionMetadata(requestParameters: RosettaConstructionMetadataOperationRequest): Promise; + rosettaConstructionMetadata(requestParameters: RosettaConstructionMetadataOperationRequest, initOverrides?: RequestInit): Promise; /** * TODO @@ -297,29 +300,29 @@ export interface RosettaApiInterface { * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionParseRaw(requestParameters: RosettaConstructionParseOperationRequest): Promise>; + rosettaConstructionParseRaw(requestParameters: RosettaConstructionParseOperationRequest, initOverrides?: RequestInit): Promise>; /** * TODO * Parse a Transaction */ - rosettaConstructionParse(requestParameters: RosettaConstructionParseOperationRequest): Promise; + rosettaConstructionParse(requestParameters: RosettaConstructionParseOperationRequest, initOverrides?: RequestInit): Promise; /** - * Generate and unsigned transaction from operations and metadata + * Generate an unsigned transaction from operations and metadata. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * @summary Generate an Unsigned Transaction and Signing Payloads * @param {RosettaConstructionPayloadsRequest} rosettaConstructionPayloadsRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionPayloadsRaw(requestParameters: RosettaConstructionPayloadsOperationRequest): Promise>; + rosettaConstructionPayloadsRaw(requestParameters: RosettaConstructionPayloadsOperationRequest, initOverrides?: RequestInit): Promise>; /** - * Generate and unsigned transaction from operations and metadata + * Generate an unsigned transaction from operations and metadata. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Generate an Unsigned Transaction and Signing Payloads */ - rosettaConstructionPayloads(requestParameters: RosettaConstructionPayloadsOperationRequest): Promise; + rosettaConstructionPayloads(requestParameters: RosettaConstructionPayloadsOperationRequest, initOverrides?: RequestInit): Promise; /** * TODO @@ -329,108 +332,108 @@ export interface RosettaApiInterface { * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionPreprocessRaw(requestParameters: RosettaConstructionPreprocessOperationRequest): Promise>; + rosettaConstructionPreprocessRaw(requestParameters: RosettaConstructionPreprocessOperationRequest, initOverrides?: RequestInit): Promise>; /** * TODO * Create a Request to Fetch Metadata */ - rosettaConstructionPreprocess(requestParameters: RosettaConstructionPreprocessOperationRequest): Promise; + rosettaConstructionPreprocess(requestParameters: RosettaConstructionPreprocessOperationRequest, initOverrides?: RequestInit): Promise; /** - * Submit a pre-signed transaction to the node. + * Submit a pre-signed transaction to the node. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * @summary Submit a Signed Transaction * @param {RosettaConstructionSubmitRequest} rosettaConstructionSubmitRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaConstructionSubmitRaw(requestParameters: RosettaConstructionSubmitOperationRequest): Promise>; + rosettaConstructionSubmitRaw(requestParameters: RosettaConstructionSubmitOperationRequest, initOverrides?: RequestInit): Promise>; /** - * Submit a pre-signed transaction to the node. + * Submit a pre-signed transaction to the node. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Submit a Signed Transaction */ - rosettaConstructionSubmit(requestParameters: RosettaConstructionSubmitOperationRequest): Promise; + rosettaConstructionSubmit(requestParameters: RosettaConstructionSubmitOperationRequest, initOverrides?: RequestInit): Promise; /** - * Get all Transaction Identifiers in the mempool. + * Retrieves a list of transactions currently in the mempool for a given network. * @summary Get All Mempool Transactions * @param {RosettaMempoolRequest} rosettaMempoolRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaMempoolRaw(requestParameters: RosettaMempoolOperationRequest): Promise>; + rosettaMempoolRaw(requestParameters: RosettaMempoolOperationRequest, initOverrides?: RequestInit): Promise>; /** - * Get all Transaction Identifiers in the mempool. + * Retrieves a list of transactions currently in the mempool for a given network. * Get All Mempool Transactions */ - rosettaMempool(requestParameters: RosettaMempoolOperationRequest): Promise; + rosettaMempool(requestParameters: RosettaMempoolOperationRequest, initOverrides?: RequestInit): Promise; /** - * A MempoolTransactionRequest is utilized to retrieve a transaction from the mempool. + * Retrieves transaction details from the mempool for a given transaction id from a given network. * @summary Get a Mempool Transaction * @param {RosettaMempoolTransactionRequest} rosettaMempoolTransactionRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaMempoolTransactionRaw(requestParameters: RosettaMempoolTransactionOperationRequest): Promise>; + rosettaMempoolTransactionRaw(requestParameters: RosettaMempoolTransactionOperationRequest, initOverrides?: RequestInit): Promise>; /** - * A MempoolTransactionRequest is utilized to retrieve a transaction from the mempool. + * Retrieves transaction details from the mempool for a given transaction id from a given network. * Get a Mempool Transaction */ - rosettaMempoolTransaction(requestParameters: RosettaMempoolTransactionOperationRequest): Promise; + rosettaMempoolTransaction(requestParameters: RosettaMempoolTransactionOperationRequest, initOverrides?: RequestInit): Promise; /** - * This endpoint returns a list of NetworkIdentifiers that the Rosetta server supports. + * Retrieves a list of NetworkIdentifiers that the Rosetta server supports. * @summary Get List of Available Networks * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaNetworkListRaw(): Promise>; + rosettaNetworkListRaw(initOverrides?: RequestInit): Promise>; /** - * This endpoint returns a list of NetworkIdentifiers that the Rosetta server supports. + * Retrieves a list of NetworkIdentifiers that the Rosetta server supports. * Get List of Available Networks */ - rosettaNetworkList(): Promise; + rosettaNetworkList(initOverrides?: RequestInit): Promise; /** - * This endpoint returns the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. + * Retrieves the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. * @summary Get Network Options * @param {RosettaOptionsRequest} rosettaOptionsRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaNetworkOptionsRaw(requestParameters: RosettaNetworkOptionsRequest): Promise>; + rosettaNetworkOptionsRaw(requestParameters: RosettaNetworkOptionsRequest, initOverrides?: RequestInit): Promise>; /** - * This endpoint returns the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. + * Retrieves the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. * Get Network Options */ - rosettaNetworkOptions(requestParameters: RosettaNetworkOptionsRequest): Promise; + rosettaNetworkOptions(requestParameters: RosettaNetworkOptionsRequest, initOverrides?: RequestInit): Promise; /** - * This endpoint returns the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. + * Retrieves the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. * @summary Get Network Status * @param {RosettaStatusRequest} rosettaStatusRequest * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof RosettaApiInterface */ - rosettaNetworkStatusRaw(requestParameters: RosettaNetworkStatusRequest): Promise>; + rosettaNetworkStatusRaw(requestParameters: RosettaNetworkStatusRequest, initOverrides?: RequestInit): Promise>; /** - * This endpoint returns the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. + * Retrieves the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. * Get Network Status */ - rosettaNetworkStatus(requestParameters: RosettaNetworkStatusRequest): Promise<{ [key: string]: object; }>; + rosettaNetworkStatus(requestParameters: RosettaNetworkStatusRequest, initOverrides?: RequestInit): Promise; } @@ -443,12 +446,12 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { * An AccountBalanceRequest is utilized to make a balance request on the /account/balance endpoint. If the block_identifier is populated, a historical balance query should be performed. * Get an Account Balance */ - async rosettaAccountBalanceRaw(requestParameters: RosettaAccountBalanceOperationRequest): Promise> { + async rosettaAccountBalanceRaw(requestParameters: RosettaAccountBalanceOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaAccountBalanceRequest === null || requestParameters.rosettaAccountBalanceRequest === undefined) { throw new runtime.RequiredError('rosettaAccountBalanceRequest','Required parameter requestParameters.rosettaAccountBalanceRequest was null or undefined when calling rosettaAccountBalance.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -460,7 +463,7 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaAccountBalanceRequestToJSON(requestParameters.rosettaAccountBalanceRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaAccountBalanceResponseFromJSON(jsonValue)); } @@ -469,21 +472,21 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { * An AccountBalanceRequest is utilized to make a balance request on the /account/balance endpoint. If the block_identifier is populated, a historical balance query should be performed. * Get an Account Balance */ - async rosettaAccountBalance(requestParameters: RosettaAccountBalanceOperationRequest): Promise { - const response = await this.rosettaAccountBalanceRaw(requestParameters); + async rosettaAccountBalance(requestParameters: RosettaAccountBalanceOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaAccountBalanceRaw(requestParameters, initOverrides); return await response.value(); } /** - * A BlockRequest is utilized to make a block request on the /block endpoint. + * Retrieves the Block information for a given block identifier including a list of all transactions in the block. * Get a Block */ - async rosettaBlockRaw(requestParameters: RosettaBlockOperationRequest): Promise> { + async rosettaBlockRaw(requestParameters: RosettaBlockOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaBlockRequest === null || requestParameters.rosettaBlockRequest === undefined) { throw new runtime.RequiredError('rosettaBlockRequest','Required parameter requestParameters.rosettaBlockRequest was null or undefined when calling rosettaBlock.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -495,30 +498,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaBlockRequestToJSON(requestParameters.rosettaBlockRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaBlockResponseFromJSON(jsonValue)); } /** - * A BlockRequest is utilized to make a block request on the /block endpoint. + * Retrieves the Block information for a given block identifier including a list of all transactions in the block. * Get a Block */ - async rosettaBlock(requestParameters: RosettaBlockOperationRequest): Promise { - const response = await this.rosettaBlockRaw(requestParameters); + async rosettaBlock(requestParameters: RosettaBlockOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaBlockRaw(requestParameters, initOverrides); return await response.value(); } /** - * A BlockTransactionRequest is used to fetch a Transaction included in a block that is not returned in a BlockResponse. + * Retrieves a Transaction included in a block that is not returned in a BlockResponse. * Get a Block Transaction */ - async rosettaBlockTransactionRaw(requestParameters: RosettaBlockTransactionOperationRequest): Promise> { + async rosettaBlockTransactionRaw(requestParameters: RosettaBlockTransactionOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaBlockTransactionRequest === null || requestParameters.rosettaBlockTransactionRequest === undefined) { throw new runtime.RequiredError('rosettaBlockTransactionRequest','Required parameter requestParameters.rosettaBlockTransactionRequest was null or undefined when calling rosettaBlockTransaction.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -530,30 +533,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaBlockTransactionRequestToJSON(requestParameters.rosettaBlockTransactionRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaBlockTransactionResponseFromJSON(jsonValue)); } /** - * A BlockTransactionRequest is used to fetch a Transaction included in a block that is not returned in a BlockResponse. + * Retrieves a Transaction included in a block that is not returned in a BlockResponse. * Get a Block Transaction */ - async rosettaBlockTransaction(requestParameters: RosettaBlockTransactionOperationRequest): Promise { - const response = await this.rosettaBlockTransactionRaw(requestParameters); + async rosettaBlockTransaction(requestParameters: RosettaBlockTransactionOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaBlockTransactionRaw(requestParameters, initOverrides); return await response.value(); } /** - * Take unsigned transaction and signature, combine both and return signed transaction + * Take unsigned transaction and signature, combine both and return signed transaction. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Create Network Transaction from Signatures */ - async rosettaConstructionCombineRaw(requestParameters: RosettaConstructionCombineOperationRequest): Promise> { + async rosettaConstructionCombineRaw(requestParameters: RosettaConstructionCombineOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionCombineRequest === null || requestParameters.rosettaConstructionCombineRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionCombineRequest','Required parameter requestParameters.rosettaConstructionCombineRequest was null or undefined when calling rosettaConstructionCombine.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -565,30 +568,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionCombineRequestToJSON(requestParameters.rosettaConstructionCombineRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionCombineResponseFromJSON(jsonValue)); } /** - * Take unsigned transaction and signature, combine both and return signed transaction + * Take unsigned transaction and signature, combine both and return signed transaction. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Create Network Transaction from Signatures */ - async rosettaConstructionCombine(requestParameters: RosettaConstructionCombineOperationRequest): Promise { - const response = await this.rosettaConstructionCombineRaw(requestParameters); + async rosettaConstructionCombine(requestParameters: RosettaConstructionCombineOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionCombineRaw(requestParameters, initOverrides); return await response.value(); } /** - * TODO + * Retrieves the Account Identifier information based on a Public Key for a given network * Derive an AccountIdentifier from a PublicKey */ - async rosettaConstructionDeriveRaw(requestParameters: RosettaConstructionDeriveOperationRequest): Promise> { + async rosettaConstructionDeriveRaw(requestParameters: RosettaConstructionDeriveOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionDeriveRequest === null || requestParameters.rosettaConstructionDeriveRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionDeriveRequest','Required parameter requestParameters.rosettaConstructionDeriveRequest was null or undefined when calling rosettaConstructionDerive.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -600,30 +603,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionDeriveRequestToJSON(requestParameters.rosettaConstructionDeriveRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionDeriveResponseFromJSON(jsonValue)); } /** - * TODO + * Retrieves the Account Identifier information based on a Public Key for a given network * Derive an AccountIdentifier from a PublicKey */ - async rosettaConstructionDerive(requestParameters: RosettaConstructionDeriveOperationRequest): Promise { - const response = await this.rosettaConstructionDeriveRaw(requestParameters); + async rosettaConstructionDerive(requestParameters: RosettaConstructionDeriveOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionDeriveRaw(requestParameters, initOverrides); return await response.value(); } /** - * TODO + * Retrieves the network-specific transaction hash for a signed transaction. * Get the Hash of a Signed Transaction */ - async rosettaConstructionHashRaw(requestParameters: RosettaConstructionHashOperationRequest): Promise> { + async rosettaConstructionHashRaw(requestParameters: RosettaConstructionHashOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionHashRequest === null || requestParameters.rosettaConstructionHashRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionHashRequest','Required parameter requestParameters.rosettaConstructionHashRequest was null or undefined when calling rosettaConstructionHash.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -635,30 +638,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionHashRequestToJSON(requestParameters.rosettaConstructionHashRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionHashResponseFromJSON(jsonValue)); } /** - * TODO + * Retrieves the network-specific transaction hash for a signed transaction. * Get the Hash of a Signed Transaction */ - async rosettaConstructionHash(requestParameters: RosettaConstructionHashOperationRequest): Promise { - const response = await this.rosettaConstructionHashRaw(requestParameters); + async rosettaConstructionHash(requestParameters: RosettaConstructionHashOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionHashRaw(requestParameters, initOverrides); return await response.value(); } /** - * TODO + * To Do * Get Metadata for Transaction Construction */ - async rosettaConstructionMetadataRaw(requestParameters: RosettaConstructionMetadataOperationRequest): Promise> { + async rosettaConstructionMetadataRaw(requestParameters: RosettaConstructionMetadataOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionMetadataRequest === null || requestParameters.rosettaConstructionMetadataRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionMetadataRequest','Required parameter requestParameters.rosettaConstructionMetadataRequest was null or undefined when calling rosettaConstructionMetadata.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -670,17 +673,17 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionMetadataRequestToJSON(requestParameters.rosettaConstructionMetadataRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionMetadataResponseFromJSON(jsonValue)); } /** - * TODO + * To Do * Get Metadata for Transaction Construction */ - async rosettaConstructionMetadata(requestParameters: RosettaConstructionMetadataOperationRequest): Promise { - const response = await this.rosettaConstructionMetadataRaw(requestParameters); + async rosettaConstructionMetadata(requestParameters: RosettaConstructionMetadataOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionMetadataRaw(requestParameters, initOverrides); return await response.value(); } @@ -688,12 +691,12 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { * TODO * Parse a Transaction */ - async rosettaConstructionParseRaw(requestParameters: RosettaConstructionParseOperationRequest): Promise> { + async rosettaConstructionParseRaw(requestParameters: RosettaConstructionParseOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionParseRequest === null || requestParameters.rosettaConstructionParseRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionParseRequest','Required parameter requestParameters.rosettaConstructionParseRequest was null or undefined when calling rosettaConstructionParse.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -705,7 +708,7 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionParseRequestToJSON(requestParameters.rosettaConstructionParseRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionParseResponseFromJSON(jsonValue)); } @@ -714,21 +717,21 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { * TODO * Parse a Transaction */ - async rosettaConstructionParse(requestParameters: RosettaConstructionParseOperationRequest): Promise { - const response = await this.rosettaConstructionParseRaw(requestParameters); + async rosettaConstructionParse(requestParameters: RosettaConstructionParseOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionParseRaw(requestParameters, initOverrides); return await response.value(); } /** - * Generate and unsigned transaction from operations and metadata + * Generate an unsigned transaction from operations and metadata. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Generate an Unsigned Transaction and Signing Payloads */ - async rosettaConstructionPayloadsRaw(requestParameters: RosettaConstructionPayloadsOperationRequest): Promise> { + async rosettaConstructionPayloadsRaw(requestParameters: RosettaConstructionPayloadsOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionPayloadsRequest === null || requestParameters.rosettaConstructionPayloadsRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionPayloadsRequest','Required parameter requestParameters.rosettaConstructionPayloadsRequest was null or undefined when calling rosettaConstructionPayloads.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -740,17 +743,17 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionPayloadsRequestToJSON(requestParameters.rosettaConstructionPayloadsRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionPayloadResponseFromJSON(jsonValue)); } /** - * Generate and unsigned transaction from operations and metadata + * Generate an unsigned transaction from operations and metadata. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Generate an Unsigned Transaction and Signing Payloads */ - async rosettaConstructionPayloads(requestParameters: RosettaConstructionPayloadsOperationRequest): Promise { - const response = await this.rosettaConstructionPayloadsRaw(requestParameters); + async rosettaConstructionPayloads(requestParameters: RosettaConstructionPayloadsOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionPayloadsRaw(requestParameters, initOverrides); return await response.value(); } @@ -758,12 +761,12 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { * TODO * Create a Request to Fetch Metadata */ - async rosettaConstructionPreprocessRaw(requestParameters: RosettaConstructionPreprocessOperationRequest): Promise> { + async rosettaConstructionPreprocessRaw(requestParameters: RosettaConstructionPreprocessOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionPreprocessRequest === null || requestParameters.rosettaConstructionPreprocessRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionPreprocessRequest','Required parameter requestParameters.rosettaConstructionPreprocessRequest was null or undefined when calling rosettaConstructionPreprocess.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -775,7 +778,7 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionPreprocessRequestToJSON(requestParameters.rosettaConstructionPreprocessRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionPreprocessResponseFromJSON(jsonValue)); } @@ -784,21 +787,21 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { * TODO * Create a Request to Fetch Metadata */ - async rosettaConstructionPreprocess(requestParameters: RosettaConstructionPreprocessOperationRequest): Promise { - const response = await this.rosettaConstructionPreprocessRaw(requestParameters); + async rosettaConstructionPreprocess(requestParameters: RosettaConstructionPreprocessOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionPreprocessRaw(requestParameters, initOverrides); return await response.value(); } /** - * Submit a pre-signed transaction to the node. + * Submit a pre-signed transaction to the node. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Submit a Signed Transaction */ - async rosettaConstructionSubmitRaw(requestParameters: RosettaConstructionSubmitOperationRequest): Promise> { + async rosettaConstructionSubmitRaw(requestParameters: RosettaConstructionSubmitOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaConstructionSubmitRequest === null || requestParameters.rosettaConstructionSubmitRequest === undefined) { throw new runtime.RequiredError('rosettaConstructionSubmitRequest','Required parameter requestParameters.rosettaConstructionSubmitRequest was null or undefined when calling rosettaConstructionSubmit.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -810,30 +813,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaConstructionSubmitRequestToJSON(requestParameters.rosettaConstructionSubmitRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaConstructionSubmitResponseFromJSON(jsonValue)); } /** - * Submit a pre-signed transaction to the node. + * Submit a pre-signed transaction to the node. The examples below are illustrative only. You\'ll need to use your wallet to generate actual values to use them in the request payload. * Submit a Signed Transaction */ - async rosettaConstructionSubmit(requestParameters: RosettaConstructionSubmitOperationRequest): Promise { - const response = await this.rosettaConstructionSubmitRaw(requestParameters); + async rosettaConstructionSubmit(requestParameters: RosettaConstructionSubmitOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaConstructionSubmitRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get all Transaction Identifiers in the mempool. + * Retrieves a list of transactions currently in the mempool for a given network. * Get All Mempool Transactions */ - async rosettaMempoolRaw(requestParameters: RosettaMempoolOperationRequest): Promise> { + async rosettaMempoolRaw(requestParameters: RosettaMempoolOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaMempoolRequest === null || requestParameters.rosettaMempoolRequest === undefined) { throw new runtime.RequiredError('rosettaMempoolRequest','Required parameter requestParameters.rosettaMempoolRequest was null or undefined when calling rosettaMempool.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -845,30 +848,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaMempoolRequestToJSON(requestParameters.rosettaMempoolRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaMempoolResponseFromJSON(jsonValue)); } /** - * Get all Transaction Identifiers in the mempool. + * Retrieves a list of transactions currently in the mempool for a given network. * Get All Mempool Transactions */ - async rosettaMempool(requestParameters: RosettaMempoolOperationRequest): Promise { - const response = await this.rosettaMempoolRaw(requestParameters); + async rosettaMempool(requestParameters: RosettaMempoolOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaMempoolRaw(requestParameters, initOverrides); return await response.value(); } /** - * A MempoolTransactionRequest is utilized to retrieve a transaction from the mempool. + * Retrieves transaction details from the mempool for a given transaction id from a given network. * Get a Mempool Transaction */ - async rosettaMempoolTransactionRaw(requestParameters: RosettaMempoolTransactionOperationRequest): Promise> { + async rosettaMempoolTransactionRaw(requestParameters: RosettaMempoolTransactionOperationRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaMempoolTransactionRequest === null || requestParameters.rosettaMempoolTransactionRequest === undefined) { throw new runtime.RequiredError('rosettaMempoolTransactionRequest','Required parameter requestParameters.rosettaMempoolTransactionRequest was null or undefined when calling rosettaMempoolTransaction.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -880,26 +883,26 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaMempoolTransactionRequestToJSON(requestParameters.rosettaMempoolTransactionRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaMempoolTransactionResponseFromJSON(jsonValue)); } /** - * A MempoolTransactionRequest is utilized to retrieve a transaction from the mempool. + * Retrieves transaction details from the mempool for a given transaction id from a given network. * Get a Mempool Transaction */ - async rosettaMempoolTransaction(requestParameters: RosettaMempoolTransactionOperationRequest): Promise { - const response = await this.rosettaMempoolTransactionRaw(requestParameters); + async rosettaMempoolTransaction(requestParameters: RosettaMempoolTransactionOperationRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaMempoolTransactionRaw(requestParameters, initOverrides); return await response.value(); } /** - * This endpoint returns a list of NetworkIdentifiers that the Rosetta server supports. + * Retrieves a list of NetworkIdentifiers that the Rosetta server supports. * Get List of Available Networks */ - async rosettaNetworkListRaw(): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async rosettaNetworkListRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -908,30 +911,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { method: 'POST', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaNetworkListResponseFromJSON(jsonValue)); } /** - * This endpoint returns a list of NetworkIdentifiers that the Rosetta server supports. + * Retrieves a list of NetworkIdentifiers that the Rosetta server supports. * Get List of Available Networks */ - async rosettaNetworkList(): Promise { - const response = await this.rosettaNetworkListRaw(); + async rosettaNetworkList(initOverrides?: RequestInit): Promise { + const response = await this.rosettaNetworkListRaw(initOverrides); return await response.value(); } /** - * This endpoint returns the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. + * Retrieves the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. * Get Network Options */ - async rosettaNetworkOptionsRaw(requestParameters: RosettaNetworkOptionsRequest): Promise> { + async rosettaNetworkOptionsRaw(requestParameters: RosettaNetworkOptionsRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaOptionsRequest === null || requestParameters.rosettaOptionsRequest === undefined) { throw new runtime.RequiredError('rosettaOptionsRequest','Required parameter requestParameters.rosettaOptionsRequest was null or undefined when calling rosettaNetworkOptions.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -943,30 +946,30 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaOptionsRequestToJSON(requestParameters.rosettaOptionsRequest), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RosettaNetworkOptionsResponseFromJSON(jsonValue)); } /** - * This endpoint returns the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. + * Retrieves the version information and allowed network-specific types for a NetworkIdentifier. Any NetworkIdentifier returned by /network/list should be accessible here. Because options are retrievable in the context of a NetworkIdentifier, it is possible to define unique options for each network. * Get Network Options */ - async rosettaNetworkOptions(requestParameters: RosettaNetworkOptionsRequest): Promise { - const response = await this.rosettaNetworkOptionsRaw(requestParameters); + async rosettaNetworkOptions(requestParameters: RosettaNetworkOptionsRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaNetworkOptionsRaw(requestParameters, initOverrides); return await response.value(); } /** - * This endpoint returns the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. + * Retrieves the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. * Get Network Status */ - async rosettaNetworkStatusRaw(requestParameters: RosettaNetworkStatusRequest): Promise> { + async rosettaNetworkStatusRaw(requestParameters: RosettaNetworkStatusRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.rosettaStatusRequest === null || requestParameters.rosettaStatusRequest === undefined) { throw new runtime.RequiredError('rosettaStatusRequest','Required parameter requestParameters.rosettaStatusRequest was null or undefined when calling rosettaNetworkStatus.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -978,17 +981,17 @@ export class RosettaApi extends runtime.BaseAPI implements RosettaApiInterface { headers: headerParameters, query: queryParameters, body: RosettaStatusRequestToJSON(requestParameters.rosettaStatusRequest), - }); + }, initOverrides); - return new runtime.JSONApiResponse(response); + return new runtime.JSONApiResponse(response, (jsonValue) => RosettaNetworkStatusResponseFromJSON(jsonValue)); } /** - * This endpoint returns the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. + * Retrieves the current status of the network requested. Any NetworkIdentifier returned by /network/list should be accessible here. * Get Network Status */ - async rosettaNetworkStatus(requestParameters: RosettaNetworkStatusRequest): Promise<{ [key: string]: object; }> { - const response = await this.rosettaNetworkStatusRaw(requestParameters); + async rosettaNetworkStatus(requestParameters: RosettaNetworkStatusRequest, initOverrides?: RequestInit): Promise { + const response = await this.rosettaNetworkStatusRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/client/src/generated/apis/SearchApi.ts b/client/src/generated/apis/SearchApi.ts index 1f72bb1b63..21fc1f9fd3 100644 --- a/client/src/generated/apis/SearchApi.ts +++ b/client/src/generated/apis/SearchApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -17,6 +17,7 @@ import * as runtime from '../runtime'; export interface SearchByIdRequest { id: string; + includeMetadata?: boolean; } /** @@ -30,17 +31,18 @@ export interface SearchApiInterface { * Search blocks, transactions, contracts, or accounts by hash/ID * @summary Search * @param {string} id The hex hash string for a block or transaction, account address, or contract address + * @param {boolean} [includeMetadata] This includes the detailed data for purticular hash in the response * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SearchApiInterface */ - searchByIdRaw(requestParameters: SearchByIdRequest): Promise>; + searchByIdRaw(requestParameters: SearchByIdRequest, initOverrides?: RequestInit): Promise>; /** * Search blocks, transactions, contracts, or accounts by hash/ID * Search */ - searchById(requestParameters: SearchByIdRequest): Promise; + searchById(requestParameters: SearchByIdRequest, initOverrides?: RequestInit): Promise; } @@ -53,12 +55,16 @@ export class SearchApi extends runtime.BaseAPI implements SearchApiInterface { * Search blocks, transactions, contracts, or accounts by hash/ID * Search */ - async searchByIdRaw(requestParameters: SearchByIdRequest): Promise> { + async searchByIdRaw(requestParameters: SearchByIdRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.id === null || requestParameters.id === undefined) { throw new runtime.RequiredError('id','Required parameter requestParameters.id was null or undefined when calling searchById.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; + + if (requestParameters.includeMetadata !== undefined) { + queryParameters['include_metadata'] = requestParameters.includeMetadata; + } const headerParameters: runtime.HTTPHeaders = {}; @@ -67,7 +73,7 @@ export class SearchApi extends runtime.BaseAPI implements SearchApiInterface { method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response); } @@ -76,8 +82,8 @@ export class SearchApi extends runtime.BaseAPI implements SearchApiInterface { * Search blocks, transactions, contracts, or accounts by hash/ID * Search */ - async searchById(requestParameters: SearchByIdRequest): Promise { - const response = await this.searchByIdRaw(requestParameters); + async searchById(requestParameters: SearchByIdRequest, initOverrides?: RequestInit): Promise { + const response = await this.searchByIdRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/client/src/generated/apis/SmartContractsApi.ts b/client/src/generated/apis/SmartContractsApi.ts index 1de166f32e..d23e4daab5 100644 --- a/client/src/generated/apis/SmartContractsApi.ts +++ b/client/src/generated/apis/SmartContractsApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -18,6 +18,9 @@ import { ContractInterfaceResponse, ContractInterfaceResponseFromJSON, ContractInterfaceResponseToJSON, + ContractListResponse, + ContractListResponseFromJSON, + ContractListResponseToJSON, ContractSourceResponse, ContractSourceResponseFromJSON, ContractSourceResponseToJSON, @@ -30,6 +33,9 @@ import { ReadOnlyFunctionSuccessResponse, ReadOnlyFunctionSuccessResponseFromJSON, ReadOnlyFunctionSuccessResponseToJSON, + SmartContract, + SmartContractFromJSON, + SmartContractToJSON, } from '../models'; export interface CallReadOnlyFunctionRequest { @@ -42,6 +48,7 @@ export interface CallReadOnlyFunctionRequest { export interface GetContractByIdRequest { contractId: string; + unanchored?: boolean; } export interface GetContractDataMapEntryRequest { @@ -57,6 +64,7 @@ export interface GetContractEventsByIdRequest { contractId: string; limit?: number; offset?: number; + unanchored?: boolean; } export interface GetContractInterfaceRequest { @@ -72,6 +80,12 @@ export interface GetContractSourceRequest { tip?: string; } +export interface GetContractsByTraitRequest { + traitAbi: string; + limit?: number; + offset?: number; +} + /** * SmartContractsApi - interface * @@ -91,32 +105,33 @@ export interface SmartContractsApiInterface { * @throws {RequiredError} * @memberof SmartContractsApiInterface */ - callReadOnlyFunctionRaw(requestParameters: CallReadOnlyFunctionRequest): Promise>; + callReadOnlyFunctionRaw(requestParameters: CallReadOnlyFunctionRequest, initOverrides?: RequestInit): Promise>; /** * Call a read-only public function on a given smart contract. The smart contract and function are specified using the URL path. The arguments and the simulated tx-sender are supplied via the POST body in the following JSON format: * Call read-only function */ - callReadOnlyFunction(requestParameters: CallReadOnlyFunctionRequest): Promise; + callReadOnlyFunction(requestParameters: CallReadOnlyFunctionRequest, initOverrides?: RequestInit): Promise; /** - * Get contract info using the contract ID + * Retrieves details of a contract with a given `contract_id` * @summary Get contract info * @param {string} contractId Contract identifier formatted as `<contract_address>.<contract_name>` + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SmartContractsApiInterface */ - getContractByIdRaw(requestParameters: GetContractByIdRequest): Promise>; + getContractByIdRaw(requestParameters: GetContractByIdRequest, initOverrides?: RequestInit): Promise>; /** - * Get contract info using the contract ID + * Retrieves details of a contract with a given `contract_id` * Get contract info */ - getContractById(requestParameters: GetContractByIdRequest): Promise; + getContractById(requestParameters: GetContractByIdRequest, initOverrides?: RequestInit): Promise; /** - * Attempt to fetch data from a contract data map. The contract is identified with [Stacks Address] and [Contract Name] in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. + * Attempt to fetch data from a contract data map. The contract is identified with Stacks Address `contract_address` and Contract Name `contract_address` in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. * @summary Get specific data-map inside a contract * @param {string} contractAddress Stacks address * @param {string} contractName Contract name @@ -128,34 +143,35 @@ export interface SmartContractsApiInterface { * @throws {RequiredError} * @memberof SmartContractsApiInterface */ - getContractDataMapEntryRaw(requestParameters: GetContractDataMapEntryRequest): Promise>; + getContractDataMapEntryRaw(requestParameters: GetContractDataMapEntryRequest, initOverrides?: RequestInit): Promise>; /** - * Attempt to fetch data from a contract data map. The contract is identified with [Stacks Address] and [Contract Name] in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. + * Attempt to fetch data from a contract data map. The contract is identified with Stacks Address `contract_address` and Contract Name `contract_address` in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. * Get specific data-map inside a contract */ - getContractDataMapEntry(requestParameters: GetContractDataMapEntryRequest): Promise; + getContractDataMapEntry(requestParameters: GetContractDataMapEntryRequest, initOverrides?: RequestInit): Promise; /** - * Get contract events using a contract ID + * Retrieves a list of events that have been triggered by a given `contract_id` * @summary Get contract events * @param {string} contractId Contract identifier formatted as `<contract_address>.<contract_name>` * @param {number} [limit] max number of contract events to fetch * @param {number} [offset] index of first contract event to fetch + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof SmartContractsApiInterface */ - getContractEventsByIdRaw(requestParameters: GetContractEventsByIdRequest): Promise>; + getContractEventsByIdRaw(requestParameters: GetContractEventsByIdRequest, initOverrides?: RequestInit): Promise>; /** - * Get contract events using a contract ID + * Retrieves a list of events that have been triggered by a given `contract_id` * Get contract events */ - getContractEventsById(requestParameters: GetContractEventsByIdRequest): Promise; + getContractEventsById(requestParameters: GetContractEventsByIdRequest, initOverrides?: RequestInit): Promise; /** - * Get contract interface using a `contract_address` and `contract name` + * Retrieves a contract interface with a given `contract_address` and `contract name` * @summary Get contract interface * @param {string} contractAddress Stacks address * @param {string} contractName Contract name @@ -164,16 +180,16 @@ export interface SmartContractsApiInterface { * @throws {RequiredError} * @memberof SmartContractsApiInterface */ - getContractInterfaceRaw(requestParameters: GetContractInterfaceRequest): Promise>; + getContractInterfaceRaw(requestParameters: GetContractInterfaceRequest, initOverrides?: RequestInit): Promise>; /** - * Get contract interface using a `contract_address` and `contract name` + * Retrieves a contract interface with a given `contract_address` and `contract name` * Get contract interface */ - getContractInterface(requestParameters: GetContractInterfaceRequest): Promise; + getContractInterface(requestParameters: GetContractInterfaceRequest, initOverrides?: RequestInit): Promise; /** - * Returns the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data + * Retrieves the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data * @summary Get contract source * @param {string} contractAddress Stacks address * @param {string} contractName Contract name @@ -183,13 +199,31 @@ export interface SmartContractsApiInterface { * @throws {RequiredError} * @memberof SmartContractsApiInterface */ - getContractSourceRaw(requestParameters: GetContractSourceRequest): Promise>; + getContractSourceRaw(requestParameters: GetContractSourceRequest, initOverrides?: RequestInit): Promise>; /** - * Returns the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data + * Retrieves the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data * Get contract source */ - getContractSource(requestParameters: GetContractSourceRequest): Promise; + getContractSource(requestParameters: GetContractSourceRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of contracts based on the following traits listed in JSON format - functions, variables, maps, fungible tokens and non-fungible tokens + * @summary Get contracts by trait + * @param {string} traitAbi JSON abi of the trait. + * @param {number} [limit] max number of contracts fetch + * @param {number} [offset] index of first contract event to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof SmartContractsApiInterface + */ + getContractsByTraitRaw(requestParameters: GetContractsByTraitRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of contracts based on the following traits listed in JSON format - functions, variables, maps, fungible tokens and non-fungible tokens + * Get contracts by trait + */ + getContractsByTrait(requestParameters: GetContractsByTraitRequest, initOverrides?: RequestInit): Promise; } @@ -202,7 +236,7 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts * Call a read-only public function on a given smart contract. The smart contract and function are specified using the URL path. The arguments and the simulated tx-sender are supplied via the POST body in the following JSON format: * Call read-only function */ - async callReadOnlyFunctionRaw(requestParameters: CallReadOnlyFunctionRequest): Promise> { + async callReadOnlyFunctionRaw(requestParameters: CallReadOnlyFunctionRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.contractAddress === null || requestParameters.contractAddress === undefined) { throw new runtime.RequiredError('contractAddress','Required parameter requestParameters.contractAddress was null or undefined when calling callReadOnlyFunction.'); } @@ -219,7 +253,7 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts throw new runtime.RequiredError('readOnlyFunctionArgs','Required parameter requestParameters.readOnlyFunctionArgs was null or undefined when calling callReadOnlyFunction.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.tip !== undefined) { queryParameters['tip'] = requestParameters.tip; @@ -235,7 +269,7 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts headers: headerParameters, query: queryParameters, body: ReadOnlyFunctionArgsToJSON(requestParameters.readOnlyFunctionArgs), - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => ReadOnlyFunctionSuccessResponseFromJSON(jsonValue)); } @@ -244,21 +278,25 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts * Call a read-only public function on a given smart contract. The smart contract and function are specified using the URL path. The arguments and the simulated tx-sender are supplied via the POST body in the following JSON format: * Call read-only function */ - async callReadOnlyFunction(requestParameters: CallReadOnlyFunctionRequest): Promise { - const response = await this.callReadOnlyFunctionRaw(requestParameters); + async callReadOnlyFunction(requestParameters: CallReadOnlyFunctionRequest, initOverrides?: RequestInit): Promise { + const response = await this.callReadOnlyFunctionRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get contract info using the contract ID + * Retrieves details of a contract with a given `contract_id` * Get contract info */ - async getContractByIdRaw(requestParameters: GetContractByIdRequest): Promise> { + async getContractByIdRaw(requestParameters: GetContractByIdRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.contractId === null || requestParameters.contractId === undefined) { throw new runtime.RequiredError('contractId','Required parameter requestParameters.contractId was null or undefined when calling getContractById.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } const headerParameters: runtime.HTTPHeaders = {}; @@ -267,25 +305,25 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); - return new runtime.JSONApiResponse(response); + return new runtime.JSONApiResponse(response, (jsonValue) => SmartContractFromJSON(jsonValue)); } /** - * Get contract info using the contract ID + * Retrieves details of a contract with a given `contract_id` * Get contract info */ - async getContractById(requestParameters: GetContractByIdRequest): Promise { - const response = await this.getContractByIdRaw(requestParameters); + async getContractById(requestParameters: GetContractByIdRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractByIdRaw(requestParameters, initOverrides); return await response.value(); } /** - * Attempt to fetch data from a contract data map. The contract is identified with [Stacks Address] and [Contract Name] in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. + * Attempt to fetch data from a contract data map. The contract is identified with Stacks Address `contract_address` and Contract Name `contract_address` in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. * Get specific data-map inside a contract */ - async getContractDataMapEntryRaw(requestParameters: GetContractDataMapEntryRequest): Promise> { + async getContractDataMapEntryRaw(requestParameters: GetContractDataMapEntryRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.contractAddress === null || requestParameters.contractAddress === undefined) { throw new runtime.RequiredError('contractAddress','Required parameter requestParameters.contractAddress was null or undefined when calling getContractDataMapEntry.'); } @@ -302,7 +340,7 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts throw new runtime.RequiredError('key','Required parameter requestParameters.key was null or undefined when calling getContractDataMapEntry.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.proof !== undefined) { queryParameters['proof'] = requestParameters.proof; @@ -322,30 +360,30 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts headers: headerParameters, query: queryParameters, body: requestParameters.key as any, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => MapEntryResponseFromJSON(jsonValue)); } /** - * Attempt to fetch data from a contract data map. The contract is identified with [Stacks Address] and [Contract Name] in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. + * Attempt to fetch data from a contract data map. The contract is identified with Stacks Address `contract_address` and Contract Name `contract_address` in the URL path. The map is identified with [Map Name]. The key to lookup in the map is supplied via the POST body. This should be supplied as the hex string serialization of the key (which should be a Clarity value). Note, this is a JSON string atom. In the response, `data` is the hex serialization of the map response. Note that map responses are Clarity option types, for non-existent values, this is a serialized none, and for all other responses, it is a serialized (some ...) object. * Get specific data-map inside a contract */ - async getContractDataMapEntry(requestParameters: GetContractDataMapEntryRequest): Promise { - const response = await this.getContractDataMapEntryRaw(requestParameters); + async getContractDataMapEntry(requestParameters: GetContractDataMapEntryRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractDataMapEntryRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get contract events using a contract ID + * Retrieves a list of events that have been triggered by a given `contract_id` * Get contract events */ - async getContractEventsByIdRaw(requestParameters: GetContractEventsByIdRequest): Promise> { + async getContractEventsByIdRaw(requestParameters: GetContractEventsByIdRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.contractId === null || requestParameters.contractId === undefined) { throw new runtime.RequiredError('contractId','Required parameter requestParameters.contractId was null or undefined when calling getContractEventsById.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.limit !== undefined) { queryParameters['limit'] = requestParameters.limit; @@ -355,6 +393,10 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts queryParameters['offset'] = requestParameters.offset; } + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + const headerParameters: runtime.HTTPHeaders = {}; const response = await this.request({ @@ -362,25 +404,25 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response); } /** - * Get contract events using a contract ID + * Retrieves a list of events that have been triggered by a given `contract_id` * Get contract events */ - async getContractEventsById(requestParameters: GetContractEventsByIdRequest): Promise { - const response = await this.getContractEventsByIdRaw(requestParameters); + async getContractEventsById(requestParameters: GetContractEventsByIdRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractEventsByIdRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get contract interface using a `contract_address` and `contract name` + * Retrieves a contract interface with a given `contract_address` and `contract name` * Get contract interface */ - async getContractInterfaceRaw(requestParameters: GetContractInterfaceRequest): Promise> { + async getContractInterfaceRaw(requestParameters: GetContractInterfaceRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.contractAddress === null || requestParameters.contractAddress === undefined) { throw new runtime.RequiredError('contractAddress','Required parameter requestParameters.contractAddress was null or undefined when calling getContractInterface.'); } @@ -389,7 +431,7 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts throw new runtime.RequiredError('contractName','Required parameter requestParameters.contractName was null or undefined when calling getContractInterface.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.tip !== undefined) { queryParameters['tip'] = requestParameters.tip; @@ -402,25 +444,25 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => ContractInterfaceResponseFromJSON(jsonValue)); } /** - * Get contract interface using a `contract_address` and `contract name` + * Retrieves a contract interface with a given `contract_address` and `contract name` * Get contract interface */ - async getContractInterface(requestParameters: GetContractInterfaceRequest): Promise { - const response = await this.getContractInterfaceRaw(requestParameters); + async getContractInterface(requestParameters: GetContractInterfaceRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractInterfaceRaw(requestParameters, initOverrides); return await response.value(); } /** - * Returns the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data + * Retrieves the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data * Get contract source */ - async getContractSourceRaw(requestParameters: GetContractSourceRequest): Promise> { + async getContractSourceRaw(requestParameters: GetContractSourceRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.contractAddress === null || requestParameters.contractAddress === undefined) { throw new runtime.RequiredError('contractAddress','Required parameter requestParameters.contractAddress was null or undefined when calling getContractSource.'); } @@ -429,7 +471,7 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts throw new runtime.RequiredError('contractName','Required parameter requestParameters.contractName was null or undefined when calling getContractSource.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.proof !== undefined) { queryParameters['proof'] = requestParameters.proof; @@ -446,17 +488,61 @@ export class SmartContractsApi extends runtime.BaseAPI implements SmartContracts method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => ContractSourceResponseFromJSON(jsonValue)); } /** - * Returns the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data + * Retrieves the Clarity source code of a given contract, along with the block height it was published in, and the MARF proof for the data * Get contract source */ - async getContractSource(requestParameters: GetContractSourceRequest): Promise { - const response = await this.getContractSourceRaw(requestParameters); + async getContractSource(requestParameters: GetContractSourceRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractSourceRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of contracts based on the following traits listed in JSON format - functions, variables, maps, fungible tokens and non-fungible tokens + * Get contracts by trait + */ + async getContractsByTraitRaw(requestParameters: GetContractsByTraitRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.traitAbi === null || requestParameters.traitAbi === undefined) { + throw new runtime.RequiredError('traitAbi','Required parameter requestParameters.traitAbi was null or undefined when calling getContractsByTrait.'); + } + + const queryParameters: any = {}; + + if (requestParameters.traitAbi !== undefined) { + queryParameters['trait_abi'] = requestParameters.traitAbi; + } + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/contract/by_trait`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => ContractListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of contracts based on the following traits listed in JSON format - functions, variables, maps, fungible tokens and non-fungible tokens + * Get contracts by trait + */ + async getContractsByTrait(requestParameters: GetContractsByTraitRequest, initOverrides?: RequestInit): Promise { + const response = await this.getContractsByTraitRaw(requestParameters, initOverrides); return await response.value(); } diff --git a/client/src/generated/apis/StackingApi.ts b/client/src/generated/apis/StackingApi.ts new file mode 100644 index 0000000000..e48599ad02 --- /dev/null +++ b/client/src/generated/apis/StackingApi.ts @@ -0,0 +1,113 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + PoolDelegationsResponse, + PoolDelegationsResponseFromJSON, + PoolDelegationsResponseToJSON, +} from '../models'; + +export interface GetPoolDelegationsRequest { + poolPrincipal: string; + afterBlock?: number; + unanchored?: boolean; + limit?: number; + offset?: number; +} + +/** + * StackingApi - interface + * + * @export + * @interface StackingApiInterface + */ +export interface StackingApiInterface { + /** + * Retrieves the list of stacking pool members for a given delegator principal. + * @summary Stacking pool members + * @param {string} poolPrincipal Address principal of the stacking pool delegator + * @param {number} [afterBlock] If specified, only delegation events after the given block will be included + * @param {boolean} [unanchored] whether or not to include Stackers from unconfirmed transactions + * @param {number} [limit] number of items to return + * @param {number} [offset] number of items to skip + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof StackingApiInterface + */ + getPoolDelegationsRaw(requestParameters: GetPoolDelegationsRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the list of stacking pool members for a given delegator principal. + * Stacking pool members + */ + getPoolDelegations(requestParameters: GetPoolDelegationsRequest, initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class StackingApi extends runtime.BaseAPI implements StackingApiInterface { + + /** + * Retrieves the list of stacking pool members for a given delegator principal. + * Stacking pool members + */ + async getPoolDelegationsRaw(requestParameters: GetPoolDelegationsRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.poolPrincipal === null || requestParameters.poolPrincipal === undefined) { + throw new runtime.RequiredError('poolPrincipal','Required parameter requestParameters.poolPrincipal was null or undefined when calling getPoolDelegations.'); + } + + const queryParameters: any = {}; + + if (requestParameters.afterBlock !== undefined) { + queryParameters['after_block'] = requestParameters.afterBlock; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/beta/stacking/{pool_principal}/delegations`.replace(`{${"pool_principal"}}`, encodeURIComponent(String(requestParameters.poolPrincipal))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => PoolDelegationsResponseFromJSON(jsonValue)); + } + + /** + * Retrieves the list of stacking pool members for a given delegator principal. + * Stacking pool members + */ + async getPoolDelegations(requestParameters: GetPoolDelegationsRequest, initOverrides?: RequestInit): Promise { + const response = await this.getPoolDelegationsRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/client/src/generated/apis/StackingRewardsApi.ts b/client/src/generated/apis/StackingRewardsApi.ts new file mode 100644 index 0000000000..b1facee70b --- /dev/null +++ b/client/src/generated/apis/StackingRewardsApi.ts @@ -0,0 +1,339 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import * as runtime from '../runtime'; +import { + BurnchainRewardListResponse, + BurnchainRewardListResponseFromJSON, + BurnchainRewardListResponseToJSON, + BurnchainRewardSlotHolderListResponse, + BurnchainRewardSlotHolderListResponseFromJSON, + BurnchainRewardSlotHolderListResponseToJSON, + BurnchainRewardsTotal, + BurnchainRewardsTotalFromJSON, + BurnchainRewardsTotalToJSON, +} from '../models'; + +export interface GetBurnchainRewardListRequest { + limit?: number; + offset?: number; +} + +export interface GetBurnchainRewardListByAddressRequest { + address: string; + limit?: number; + offset?: number; +} + +export interface GetBurnchainRewardSlotHoldersRequest { + limit?: number; + offset?: number; +} + +export interface GetBurnchainRewardSlotHoldersByAddressRequest { + address: string; + limit?: number; + offset?: number; +} + +export interface GetBurnchainRewardsTotalByAddressRequest { + address: string; +} + +/** + * StackingRewardsApi - interface + * + * @export + * @interface StackingRewardsApiInterface + */ +export interface StackingRewardsApiInterface { + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info + * @summary Get recent burnchain reward recipients + * @param {number} [limit] max number of rewards to fetch + * @param {number} [offset] index of first rewards to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof StackingRewardsApiInterface + */ + getBurnchainRewardListRaw(requestParameters: GetBurnchainRewardListRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info + * Get recent burnchain reward recipients + */ + getBurnchainRewardList(requestParameters: GetBurnchainRewardListRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info + * @summary Get recent burnchain reward for the given recipient + * @param {string} address Reward recipient address. Should either be in the native burnchain\'s format (e.g. B58 for Bitcoin), or if a STX principal address is provided it will be encoded as into the equivalent burnchain format + * @param {number} [limit] max number of rewards to fetch + * @param {number} [offset] index of first rewards to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof StackingRewardsApiInterface + */ + getBurnchainRewardListByAddressRaw(requestParameters: GetBurnchainRewardListByAddressRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info + * Get recent burnchain reward for the given recipient + */ + getBurnchainRewardListByAddress(requestParameters: GetBurnchainRewardListByAddressRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments. + * @summary Get recent reward slot holders + * @param {number} [limit] max number of items to fetch + * @param {number} [offset] index of the first items to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof StackingRewardsApiInterface + */ + getBurnchainRewardSlotHoldersRaw(requestParameters: GetBurnchainRewardSlotHoldersRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments. + * Get recent reward slot holders + */ + getBurnchainRewardSlotHolders(requestParameters: GetBurnchainRewardSlotHoldersRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments for a given reward slot holder recipient address. + * @summary Get recent reward slot holder entries for the given address + * @param {string} address Reward slot holder recipient address. Should either be in the native burnchain\'s format (e.g. B58 for Bitcoin), or if a STX principal address is provided it will be encoded as into the equivalent burnchain format + * @param {number} [limit] max number of items to fetch + * @param {number} [offset] index of the first items to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof StackingRewardsApiInterface + */ + getBurnchainRewardSlotHoldersByAddressRaw(requestParameters: GetBurnchainRewardSlotHoldersByAddressRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments for a given reward slot holder recipient address. + * Get recent reward slot holder entries for the given address + */ + getBurnchainRewardSlotHoldersByAddress(requestParameters: GetBurnchainRewardSlotHoldersByAddressRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves the total burnchain (e.g. Bitcoin) rewards for a given recipient `address` + * @summary Get total burnchain rewards for the given recipient + * @param {string} address Reward recipient address. Should either be in the native burnchain\'s format (e.g. B58 for Bitcoin), or if a STX principal address is provided it will be encoded as into the equivalent burnchain format + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof StackingRewardsApiInterface + */ + getBurnchainRewardsTotalByAddressRaw(requestParameters: GetBurnchainRewardsTotalByAddressRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the total burnchain (e.g. Bitcoin) rewards for a given recipient `address` + * Get total burnchain rewards for the given recipient + */ + getBurnchainRewardsTotalByAddress(requestParameters: GetBurnchainRewardsTotalByAddressRequest, initOverrides?: RequestInit): Promise; + +} + +/** + * + */ +export class StackingRewardsApi extends runtime.BaseAPI implements StackingRewardsApiInterface { + + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info + * Get recent burnchain reward recipients + */ + async getBurnchainRewardListRaw(requestParameters: GetBurnchainRewardListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/burnchain/rewards`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) reward recipients with the associated amounts and block info + * Get recent burnchain reward recipients + */ + async getBurnchainRewardList(requestParameters: GetBurnchainRewardListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBurnchainRewardListRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info + * Get recent burnchain reward for the given recipient + */ + async getBurnchainRewardListByAddressRaw(requestParameters: GetBurnchainRewardListByAddressRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.address === null || requestParameters.address === undefined) { + throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling getBurnchainRewardListByAddress.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/burnchain/rewards/{address}`.replace(`{${"address"}}`, encodeURIComponent(String(requestParameters.address))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of recent burnchain (e.g. Bitcoin) rewards for the given recipient with the associated amounts and block info + * Get recent burnchain reward for the given recipient + */ + async getBurnchainRewardListByAddress(requestParameters: GetBurnchainRewardListByAddressRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBurnchainRewardListByAddressRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments. + * Get recent reward slot holders + */ + async getBurnchainRewardSlotHoldersRaw(requestParameters: GetBurnchainRewardSlotHoldersRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/burnchain/reward_slot_holders`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardSlotHolderListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments. + * Get recent reward slot holders + */ + async getBurnchainRewardSlotHolders(requestParameters: GetBurnchainRewardSlotHoldersRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBurnchainRewardSlotHoldersRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments for a given reward slot holder recipient address. + * Get recent reward slot holder entries for the given address + */ + async getBurnchainRewardSlotHoldersByAddressRaw(requestParameters: GetBurnchainRewardSlotHoldersByAddressRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.address === null || requestParameters.address === undefined) { + throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling getBurnchainRewardSlotHoldersByAddress.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/burnchain/reward_slot_holders/{address}`.replace(`{${"address"}}`, encodeURIComponent(String(requestParameters.address))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardSlotHolderListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves a list of the Bitcoin addresses that would validly receive Proof-of-Transfer commitments for a given reward slot holder recipient address. + * Get recent reward slot holder entries for the given address + */ + async getBurnchainRewardSlotHoldersByAddress(requestParameters: GetBurnchainRewardSlotHoldersByAddressRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBurnchainRewardSlotHoldersByAddressRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves the total burnchain (e.g. Bitcoin) rewards for a given recipient `address` + * Get total burnchain rewards for the given recipient + */ + async getBurnchainRewardsTotalByAddressRaw(requestParameters: GetBurnchainRewardsTotalByAddressRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.address === null || requestParameters.address === undefined) { + throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling getBurnchainRewardsTotalByAddress.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/burnchain/rewards/{address}/total`.replace(`{${"address"}}`, encodeURIComponent(String(requestParameters.address))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => BurnchainRewardsTotalFromJSON(jsonValue)); + } + + /** + * Retrieves the total burnchain (e.g. Bitcoin) rewards for a given recipient `address` + * Get total burnchain rewards for the given recipient + */ + async getBurnchainRewardsTotalByAddress(requestParameters: GetBurnchainRewardsTotalByAddressRequest, initOverrides?: RequestInit): Promise { + const response = await this.getBurnchainRewardsTotalByAddressRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/client/src/generated/apis/TransactionsApi.ts b/client/src/generated/apis/TransactionsApi.ts index 8f24ec9133..63b6fe9899 100644 --- a/client/src/generated/apis/TransactionsApi.ts +++ b/client/src/generated/apis/TransactionsApi.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -15,35 +15,91 @@ import * as runtime from '../runtime'; import { + GetRawTransactionResult, + GetRawTransactionResultFromJSON, + GetRawTransactionResultToJSON, MempoolTransactionListResponse, MempoolTransactionListResponseFromJSON, MempoolTransactionListResponseToJSON, + MempoolTransactionStatsResponse, + MempoolTransactionStatsResponseFromJSON, + MempoolTransactionStatsResponseToJSON, PostCoreNodeTransactionsError, PostCoreNodeTransactionsErrorFromJSON, PostCoreNodeTransactionsErrorToJSON, + TransactionEventsResponse, + TransactionEventsResponseFromJSON, + TransactionEventsResponseToJSON, TransactionResults, TransactionResultsFromJSON, TransactionResultsToJSON, } from '../models'; +export interface GetAddressMempoolTransactionsRequest { + address: string; + limit?: number; + offset?: number; + unanchored?: boolean; +} + +export interface GetDroppedMempoolTransactionListRequest { + limit?: number; + offset?: number; +} + +export interface GetFilteredEventsRequest { + txId?: string; + address?: string; + limit?: number; + offset?: number; + type?: Array; +} + export interface GetMempoolTransactionListRequest { senderAddress?: string; recipientAddress?: string; address?: string; limit?: number; offset?: number; + unanchored?: boolean; +} + +export interface GetRawTransactionByIdRequest { + txId: string; } export interface GetTransactionByIdRequest { txId: string; eventOffset?: number; eventLimit?: number; + unanchored?: boolean; } export interface GetTransactionListRequest { limit?: number; offset?: number; type?: Array; + unanchored?: boolean; +} + +export interface GetTransactionsByBlockHashRequest { + blockHash: string; + limit?: number; + offset?: number; +} + +export interface GetTransactionsByBlockHeightRequest { + height: number; + limit?: number; + offset?: number; + unanchored?: boolean; +} + +export interface GetTxListDetailsRequest { + txId: Array; + eventOffset?: number; + eventLimit?: number; + unanchored?: boolean; } export interface PostCoreNodeTransactionsRequest { @@ -58,76 +114,222 @@ export interface PostCoreNodeTransactionsRequest { */ export interface TransactionsApiInterface { /** - * Get all recently-broadcast mempool transactions + * Retrieves all transactions for a given address that are currently in mempool + * @summary Transactions for address + * @param {string} address Transactions for the address + * @param {number} [limit] max number of transactions to fetch + * @param {number} [offset] index of first transaction to fetch + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getAddressMempoolTransactionsRaw(requestParameters: GetAddressMempoolTransactionsRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves all transactions for a given address that are currently in mempool + * Transactions for address + */ + getAddressMempoolTransactions(requestParameters: GetAddressMempoolTransactionsRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves all recently-broadcast transactions that have been dropped from the mempool. Transactions are dropped from the mempool if: * they were stale and awaiting garbage collection or, * were expensive, or * were replaced with a new fee + * @summary Get dropped mempool transactions + * @param {number} [limit] max number of mempool transactions to fetch + * @param {number} [offset] index of first mempool transaction to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getDroppedMempoolTransactionListRaw(requestParameters: GetDroppedMempoolTransactionListRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves all recently-broadcast transactions that have been dropped from the mempool. Transactions are dropped from the mempool if: * they were stale and awaiting garbage collection or, * were expensive, or * were replaced with a new fee + * Get dropped mempool transactions + */ + getDroppedMempoolTransactionList(requestParameters: GetDroppedMempoolTransactionListRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves the list of events filtered by principal (STX address or Smart Contract ID), transaction id or event types. The list of event types is (\'smart_contract_log\', \'stx_lock\', \'stx_asset\', \'fungible_token_asset\', \'non_fungible_token_asset\'). + * @summary Transaction Events + * @param {string} [txId] Hash of transaction + * @param {string} [address] Stacks address or a Contract identifier + * @param {number} [limit] number of items to return + * @param {number} [offset] number of items to skip + * @param {Array<'smart_contract_log' | 'stx_lock' | 'stx_asset' | 'fungible_token_asset' | 'non_fungible_token_asset'>} [type] Filter the events on event type + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getFilteredEventsRaw(requestParameters: GetFilteredEventsRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves the list of events filtered by principal (STX address or Smart Contract ID), transaction id or event types. The list of event types is (\'smart_contract_log\', \'stx_lock\', \'stx_asset\', \'fungible_token_asset\', \'non_fungible_token_asset\'). + * Transaction Events + */ + getFilteredEvents(requestParameters: GetFilteredEventsRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves all transactions that have been recently broadcast to the mempool. These are pending transactions awaiting confirmation. If you need to monitor new transactions, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * @summary Get mempool transactions - * @param {string} [senderAddress] Filter to only STX transfer transactions with this sender address. - * @param {string} [recipientAddress] Filter to only STX transfer transactions with this recipient address. - * @param {string} [address] Filter to only show STX transfer transactions with this address as the recipient or sender. + * @param {string} [senderAddress] Filter to only return transactions with this sender address. + * @param {string} [recipientAddress] Filter to only return transactions with this recipient address (only applicable for STX transfer tx types). + * @param {string} [address] Filter to only return transactions with this address as the sender or recipient (recipient only applicable for STX transfer tx types). * @param {number} [limit] max number of mempool transactions to fetch * @param {number} [offset] index of first mempool transaction to fetch + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof TransactionsApiInterface */ - getMempoolTransactionListRaw(requestParameters: GetMempoolTransactionListRequest): Promise>; + getMempoolTransactionListRaw(requestParameters: GetMempoolTransactionListRequest, initOverrides?: RequestInit): Promise>; /** - * Get all recently-broadcast mempool transactions + * Retrieves all transactions that have been recently broadcast to the mempool. These are pending transactions awaiting confirmation. If you need to monitor new transactions, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get mempool transactions */ - getMempoolTransactionList(requestParameters: GetMempoolTransactionListRequest): Promise; + getMempoolTransactionList(requestParameters: GetMempoolTransactionListRequest, initOverrides?: RequestInit): Promise; + + /** + * Queries for transactions counts, age (by block height), fees (simple average), and size. All results broken down by transaction type and percentiles (p25, p50, p75, p95). + * @summary Get statistics for mempool transactions + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getMempoolTransactionStatsRaw(initOverrides?: RequestInit): Promise>; /** - * Get a specific transaction by ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * Queries for transactions counts, age (by block height), fees (simple average), and size. All results broken down by transaction type and percentiles (p25, p50, p75, p95). + * Get statistics for mempool transactions + */ + getMempoolTransactionStats(initOverrides?: RequestInit): Promise; + + /** + * Retrieves a hex encoded serialized transaction for a given ID + * @summary Get Raw Transaction + * @param {string} txId Hash of transaction + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getRawTransactionByIdRaw(requestParameters: GetRawTransactionByIdRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a hex encoded serialized transaction for a given ID + * Get Raw Transaction + */ + getRawTransactionById(requestParameters: GetRawTransactionByIdRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves transaction details for a given transaction ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` * @summary Get transaction * @param {string} txId Hash of transaction * @param {number} [eventOffset] The number of events to skip * @param {number} [eventLimit] The numbers of events to return + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof TransactionsApiInterface */ - getTransactionByIdRaw(requestParameters: GetTransactionByIdRequest): Promise>; + getTransactionByIdRaw(requestParameters: GetTransactionByIdRequest, initOverrides?: RequestInit): Promise>; /** - * Get a specific transaction by ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * Retrieves transaction details for a given transaction ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` * Get transaction */ - getTransactionById(requestParameters: GetTransactionByIdRequest): Promise; + getTransactionById(requestParameters: GetTransactionByIdRequest, initOverrides?: RequestInit): Promise; /** - * Get all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` + * Retrieves all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` * @summary Get recent transactions * @param {number} [limit] max number of transactions to fetch * @param {number} [offset] index of first transaction to fetch * @param {Array<'coinbase' | 'token_transfer' | 'smart_contract' | 'contract_call' | 'poison_microblock'>} [type] Filter by transaction type + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof TransactionsApiInterface */ - getTransactionListRaw(requestParameters: GetTransactionListRequest): Promise>; + getTransactionListRaw(requestParameters: GetTransactionListRequest, initOverrides?: RequestInit): Promise>; /** - * Get all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` + * Retrieves all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` * Get recent transactions */ - getTransactionList(requestParameters: GetTransactionListRequest): Promise; + getTransactionList(requestParameters: GetTransactionListRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of all transactions within a block for a given block hash. + * @summary Transactions by block hash + * @param {string} blockHash Hash of block + * @param {number} [limit] max number of transactions to fetch + * @param {number} [offset] index of first transaction to fetch + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getTransactionsByBlockHashRaw(requestParameters: GetTransactionsByBlockHashRequest, initOverrides?: RequestInit): Promise>; /** - * Broadcast raw transactions on the network. You can use the [@stacks/transactions](https://github.com/hirosystems/stacks.js) project to generate a raw transaction payload. + * Retrieves a list of all transactions within a block for a given block hash. + * Transactions by block hash + */ + getTransactionsByBlockHash(requestParameters: GetTransactionsByBlockHashRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves all transactions within a block at a given height + * @summary Transactions by block height + * @param {number} height Height of block + * @param {number} [limit] max number of transactions to fetch + * @param {number} [offset] index of first transaction to fetch + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getTransactionsByBlockHeightRaw(requestParameters: GetTransactionsByBlockHeightRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves all transactions within a block at a given height + * Transactions by block height + */ + getTransactionsByBlockHeight(requestParameters: GetTransactionsByBlockHeightRequest, initOverrides?: RequestInit): Promise; + + /** + * Retrieves a list of transactions for a given list of transaction IDs If using TypeScript, import typings for this response from our types package: `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * @summary Get list of details for transactions + * @param {Array} txId Array of transaction ids + * @param {number} [eventOffset] The number of events to skip + * @param {number} [eventLimit] The numbers of events to return + * @param {boolean} [unanchored] Include transaction data from unanchored (i.e. unconfirmed) microblocks + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TransactionsApiInterface + */ + getTxListDetailsRaw(requestParameters: GetTxListDetailsRequest, initOverrides?: RequestInit): Promise>; + + /** + * Retrieves a list of transactions for a given list of transaction IDs If using TypeScript, import typings for this response from our types package: `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * Get list of details for transactions + */ + getTxListDetails(requestParameters: GetTxListDetailsRequest, initOverrides?: RequestInit): Promise<{ [key: string]: object; }>; + + /** + * Broadcasts raw transactions on the network. You can use the [@stacks/transactions](https://github.com/blockstack/stacks.js) project to generate a raw transaction payload. * @summary Broadcast raw transaction * @param {Blob} [body] * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof TransactionsApiInterface */ - postCoreNodeTransactionsRaw(requestParameters: PostCoreNodeTransactionsRequest): Promise>; + postCoreNodeTransactionsRaw(requestParameters: PostCoreNodeTransactionsRequest, initOverrides?: RequestInit): Promise>; /** - * Broadcast raw transactions on the network. You can use the [@stacks/transactions](https://github.com/hirosystems/stacks.js) project to generate a raw transaction payload. + * Broadcasts raw transactions on the network. You can use the [@stacks/transactions](https://github.com/blockstack/stacks.js) project to generate a raw transaction payload. * Broadcast raw transaction */ - postCoreNodeTransactions(requestParameters: PostCoreNodeTransactionsRequest): Promise; + postCoreNodeTransactions(requestParameters: PostCoreNodeTransactionsRequest, initOverrides?: RequestInit): Promise; } @@ -137,11 +339,139 @@ export interface TransactionsApiInterface { export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiInterface { /** - * Get all recently-broadcast mempool transactions + * Retrieves all transactions for a given address that are currently in mempool + * Transactions for address + */ + async getAddressMempoolTransactionsRaw(requestParameters: GetAddressMempoolTransactionsRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.address === null || requestParameters.address === undefined) { + throw new runtime.RequiredError('address','Required parameter requestParameters.address was null or undefined when calling getAddressMempoolTransactions.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/address/{address}/mempool`.replace(`{${"address"}}`, encodeURIComponent(String(requestParameters.address))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => MempoolTransactionListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves all transactions for a given address that are currently in mempool + * Transactions for address + */ + async getAddressMempoolTransactions(requestParameters: GetAddressMempoolTransactionsRequest, initOverrides?: RequestInit): Promise { + const response = await this.getAddressMempoolTransactionsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves all recently-broadcast transactions that have been dropped from the mempool. Transactions are dropped from the mempool if: * they were stale and awaiting garbage collection or, * were expensive, or * were replaced with a new fee + * Get dropped mempool transactions + */ + async getDroppedMempoolTransactionListRaw(requestParameters: GetDroppedMempoolTransactionListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tx/mempool/dropped`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => MempoolTransactionListResponseFromJSON(jsonValue)); + } + + /** + * Retrieves all recently-broadcast transactions that have been dropped from the mempool. Transactions are dropped from the mempool if: * they were stale and awaiting garbage collection or, * were expensive, or * were replaced with a new fee + * Get dropped mempool transactions + */ + async getDroppedMempoolTransactionList(requestParameters: GetDroppedMempoolTransactionListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getDroppedMempoolTransactionListRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves the list of events filtered by principal (STX address or Smart Contract ID), transaction id or event types. The list of event types is (\'smart_contract_log\', \'stx_lock\', \'stx_asset\', \'fungible_token_asset\', \'non_fungible_token_asset\'). + * Transaction Events + */ + async getFilteredEventsRaw(requestParameters: GetFilteredEventsRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + if (requestParameters.txId !== undefined) { + queryParameters['tx_id'] = requestParameters.txId; + } + + if (requestParameters.address !== undefined) { + queryParameters['address'] = requestParameters.address; + } + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.type) { + queryParameters['type'] = requestParameters.type; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tx/events`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => TransactionEventsResponseFromJSON(jsonValue)); + } + + /** + * Retrieves the list of events filtered by principal (STX address or Smart Contract ID), transaction id or event types. The list of event types is (\'smart_contract_log\', \'stx_lock\', \'stx_asset\', \'fungible_token_asset\', \'non_fungible_token_asset\'). + * Transaction Events + */ + async getFilteredEvents(requestParameters: GetFilteredEventsRequest, initOverrides?: RequestInit): Promise { + const response = await this.getFilteredEventsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves all transactions that have been recently broadcast to the mempool. These are pending transactions awaiting confirmation. If you need to monitor new transactions, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get mempool transactions */ - async getMempoolTransactionListRaw(requestParameters: GetMempoolTransactionListRequest): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getMempoolTransactionListRaw(requestParameters: GetMempoolTransactionListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; if (requestParameters.senderAddress !== undefined) { queryParameters['sender_address'] = requestParameters.senderAddress; @@ -163,6 +493,10 @@ export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiI queryParameters['offset'] = requestParameters.offset; } + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + const headerParameters: runtime.HTTPHeaders = {}; const response = await this.request({ @@ -170,30 +504,90 @@ export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiI method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => MempoolTransactionListResponseFromJSON(jsonValue)); } /** - * Get all recently-broadcast mempool transactions + * Retrieves all transactions that have been recently broadcast to the mempool. These are pending transactions awaiting confirmation. If you need to monitor new transactions, we highly recommend subscribing to [WebSockets or Socket.io](https://github.com/hirosystems/stacks-blockchain-api/tree/master/client) for real-time updates. * Get mempool transactions */ - async getMempoolTransactionList(requestParameters: GetMempoolTransactionListRequest): Promise { - const response = await this.getMempoolTransactionListRaw(requestParameters); + async getMempoolTransactionList(requestParameters: GetMempoolTransactionListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getMempoolTransactionListRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get a specific transaction by ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * Queries for transactions counts, age (by block height), fees (simple average), and size. All results broken down by transaction type and percentiles (p25, p50, p75, p95). + * Get statistics for mempool transactions + */ + async getMempoolTransactionStatsRaw(initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tx/mempool/stats`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => MempoolTransactionStatsResponseFromJSON(jsonValue)); + } + + /** + * Queries for transactions counts, age (by block height), fees (simple average), and size. All results broken down by transaction type and percentiles (p25, p50, p75, p95). + * Get statistics for mempool transactions + */ + async getMempoolTransactionStats(initOverrides?: RequestInit): Promise { + const response = await this.getMempoolTransactionStatsRaw(initOverrides); + return await response.value(); + } + + /** + * Retrieves a hex encoded serialized transaction for a given ID + * Get Raw Transaction + */ + async getRawTransactionByIdRaw(requestParameters: GetRawTransactionByIdRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.txId === null || requestParameters.txId === undefined) { + throw new runtime.RequiredError('txId','Required parameter requestParameters.txId was null or undefined when calling getRawTransactionById.'); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tx/{tx_id}/raw`.replace(`{${"tx_id"}}`, encodeURIComponent(String(requestParameters.txId))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => GetRawTransactionResultFromJSON(jsonValue)); + } + + /** + * Retrieves a hex encoded serialized transaction for a given ID + * Get Raw Transaction + */ + async getRawTransactionById(requestParameters: GetRawTransactionByIdRequest, initOverrides?: RequestInit): Promise { + const response = await this.getRawTransactionByIdRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves transaction details for a given transaction ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` * Get transaction */ - async getTransactionByIdRaw(requestParameters: GetTransactionByIdRequest): Promise> { + async getTransactionByIdRaw(requestParameters: GetTransactionByIdRequest, initOverrides?: RequestInit): Promise> { if (requestParameters.txId === null || requestParameters.txId === undefined) { throw new runtime.RequiredError('txId','Required parameter requestParameters.txId was null or undefined when calling getTransactionById.'); } - const queryParameters: runtime.HTTPQuery = {}; + const queryParameters: any = {}; if (requestParameters.eventOffset !== undefined) { queryParameters['event_offset'] = requestParameters.eventOffset; @@ -203,6 +597,10 @@ export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiI queryParameters['event_limit'] = requestParameters.eventLimit; } + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + const headerParameters: runtime.HTTPHeaders = {}; const response = await this.request({ @@ -210,26 +608,26 @@ export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiI method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response); } /** - * Get a specific transaction by ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * Retrieves transaction details for a given transaction ID `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` * Get transaction */ - async getTransactionById(requestParameters: GetTransactionByIdRequest): Promise { - const response = await this.getTransactionByIdRaw(requestParameters); + async getTransactionById(requestParameters: GetTransactionByIdRequest, initOverrides?: RequestInit): Promise { + const response = await this.getTransactionByIdRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` + * Retrieves all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` * Get recent transactions */ - async getTransactionListRaw(requestParameters: GetTransactionListRequest): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async getTransactionListRaw(requestParameters: GetTransactionListRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; if (requestParameters.limit !== undefined) { queryParameters['limit'] = requestParameters.limit; @@ -243,6 +641,10 @@ export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiI queryParameters['type'] = requestParameters.type; } + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + const headerParameters: runtime.HTTPHeaders = {}; const response = await this.request({ @@ -250,26 +652,158 @@ export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiI method: 'GET', headers: headerParameters, query: queryParameters, - }); + }, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => TransactionResultsFromJSON(jsonValue)); } /** - * Get all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` + * Retrieves all recently mined transactions If using TypeScript, import typings for this response from our types package: `import type { TransactionResults } from \'@stacks/stacks-blockchain-api-types\';` * Get recent transactions */ - async getTransactionList(requestParameters: GetTransactionListRequest): Promise { - const response = await this.getTransactionListRaw(requestParameters); + async getTransactionList(requestParameters: GetTransactionListRequest, initOverrides?: RequestInit): Promise { + const response = await this.getTransactionListRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of all transactions within a block for a given block hash. + * Transactions by block hash + */ + async getTransactionsByBlockHashRaw(requestParameters: GetTransactionsByBlockHashRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.blockHash === null || requestParameters.blockHash === undefined) { + throw new runtime.RequiredError('blockHash','Required parameter requestParameters.blockHash was null or undefined when calling getTransactionsByBlockHash.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tx/block/{block_hash}`.replace(`{${"block_hash"}}`, encodeURIComponent(String(requestParameters.blockHash))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => TransactionResultsFromJSON(jsonValue)); + } + + /** + * Retrieves a list of all transactions within a block for a given block hash. + * Transactions by block hash + */ + async getTransactionsByBlockHash(requestParameters: GetTransactionsByBlockHashRequest, initOverrides?: RequestInit): Promise { + const response = await this.getTransactionsByBlockHashRaw(requestParameters, initOverrides); return await response.value(); } /** - * Broadcast raw transactions on the network. You can use the [@stacks/transactions](https://github.com/hirosystems/stacks.js) project to generate a raw transaction payload. + * Retrieves all transactions within a block at a given height + * Transactions by block height + */ + async getTransactionsByBlockHeightRaw(requestParameters: GetTransactionsByBlockHeightRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.height === null || requestParameters.height === undefined) { + throw new runtime.RequiredError('height','Required parameter requestParameters.height was null or undefined when calling getTransactionsByBlockHeight.'); + } + + const queryParameters: any = {}; + + if (requestParameters.limit !== undefined) { + queryParameters['limit'] = requestParameters.limit; + } + + if (requestParameters.offset !== undefined) { + queryParameters['offset'] = requestParameters.offset; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tx/block_height/{height}`.replace(`{${"height"}}`, encodeURIComponent(String(requestParameters.height))), + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => TransactionResultsFromJSON(jsonValue)); + } + + /** + * Retrieves all transactions within a block at a given height + * Transactions by block height + */ + async getTransactionsByBlockHeight(requestParameters: GetTransactionsByBlockHeightRequest, initOverrides?: RequestInit): Promise { + const response = await this.getTransactionsByBlockHeightRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Retrieves a list of transactions for a given list of transaction IDs If using TypeScript, import typings for this response from our types package: `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * Get list of details for transactions + */ + async getTxListDetailsRaw(requestParameters: GetTxListDetailsRequest, initOverrides?: RequestInit): Promise> { + if (requestParameters.txId === null || requestParameters.txId === undefined) { + throw new runtime.RequiredError('txId','Required parameter requestParameters.txId was null or undefined when calling getTxListDetails.'); + } + + const queryParameters: any = {}; + + if (requestParameters.txId) { + queryParameters['tx_id'] = requestParameters.txId; + } + + if (requestParameters.eventOffset !== undefined) { + queryParameters['event_offset'] = requestParameters.eventOffset; + } + + if (requestParameters.eventLimit !== undefined) { + queryParameters['event_limit'] = requestParameters.eventLimit; + } + + if (requestParameters.unanchored !== undefined) { + queryParameters['unanchored'] = requestParameters.unanchored; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + const response = await this.request({ + path: `/extended/v1/tx/multiple`, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Retrieves a list of transactions for a given list of transaction IDs If using TypeScript, import typings for this response from our types package: `import type { Transaction } from \'@stacks/stacks-blockchain-api-types\';` + * Get list of details for transactions + */ + async getTxListDetails(requestParameters: GetTxListDetailsRequest, initOverrides?: RequestInit): Promise<{ [key: string]: object; }> { + const response = await this.getTxListDetailsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Broadcasts raw transactions on the network. You can use the [@stacks/transactions](https://github.com/blockstack/stacks.js) project to generate a raw transaction payload. * Broadcast raw transaction */ - async postCoreNodeTransactionsRaw(requestParameters: PostCoreNodeTransactionsRequest): Promise> { - const queryParameters: runtime.HTTPQuery = {}; + async postCoreNodeTransactionsRaw(requestParameters: PostCoreNodeTransactionsRequest, initOverrides?: RequestInit): Promise> { + const queryParameters: any = {}; const headerParameters: runtime.HTTPHeaders = {}; @@ -281,22 +815,33 @@ export class TransactionsApi extends runtime.BaseAPI implements TransactionsApiI headers: headerParameters, query: queryParameters, body: requestParameters.body as any, - }); + }, initOverrides); return new runtime.TextApiResponse(response) as any; } /** - * Broadcast raw transactions on the network. You can use the [@stacks/transactions](https://github.com/hirosystems/stacks.js) project to generate a raw transaction payload. + * Broadcasts raw transactions on the network. You can use the [@stacks/transactions](https://github.com/blockstack/stacks.js) project to generate a raw transaction payload. * Broadcast raw transaction */ - async postCoreNodeTransactions(requestParameters: PostCoreNodeTransactionsRequest): Promise { - const response = await this.postCoreNodeTransactionsRaw(requestParameters); + async postCoreNodeTransactions(requestParameters: PostCoreNodeTransactionsRequest, initOverrides?: RequestInit): Promise { + const response = await this.postCoreNodeTransactionsRaw(requestParameters, initOverrides); return await response.value(); } } +/** + * @export + * @enum {string} + */ +export enum GetFilteredEventsTypeEnum { + smart_contract_log = 'smart_contract_log', + stx_lock = 'stx_lock', + stx_asset = 'stx_asset', + fungible_token_asset = 'fungible_token_asset', + non_fungible_token_asset = 'non_fungible_token_asset' +} /** * @export * @enum {string} diff --git a/client/src/generated/apis/index.ts b/client/src/generated/apis/index.ts index 787ee7d15a..11ee668eae 100644 --- a/client/src/generated/apis/index.ts +++ b/client/src/generated/apis/index.ts @@ -1,10 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ export * from './AccountsApi'; export * from './BlocksApi'; -export * from './BurnchainApi'; export * from './FaucetsApi'; export * from './FeesApi'; +export * from './FungibleTokensApi'; export * from './InfoApi'; +export * from './MempoolApi'; +export * from './MicroblocksApi'; +export * from './NamesApi'; +export * from './NonFungibleTokensApi'; export * from './RosettaApi'; export * from './SearchApi'; export * from './SmartContractsApi'; +export * from './StackingApi'; +export * from './StackingRewardsApi'; export * from './TransactionsApi'; diff --git a/client/src/generated/index.ts b/client/src/generated/index.ts index 848ecfa4d1..be9d1edeef 100644 --- a/client/src/generated/index.ts +++ b/client/src/generated/index.ts @@ -1,3 +1,5 @@ +/* tslint:disable */ +/* eslint-disable */ export * from './runtime'; export * from './apis'; export * from './models'; diff --git a/client/src/generated/models/AccountDataResponse.ts b/client/src/generated/models/AccountDataResponse.ts index 5a6ece43f2..d262747694 100644 --- a/client/src/generated/models/AccountDataResponse.ts +++ b/client/src/generated/models/AccountDataResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -94,4 +94,3 @@ export function AccountDataResponseToJSON(value?: AccountDataResponse | null): a }; } - diff --git a/client/src/generated/models/AddressAssetsListResponse.ts b/client/src/generated/models/AddressAssetsListResponse.ts index 46dec6fa58..b38763213d 100644 --- a/client/src/generated/models/AddressAssetsListResponse.ts +++ b/client/src/generated/models/AddressAssetsListResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -78,4 +78,3 @@ export function AddressAssetsListResponseToJSON(value?: AddressAssetsListRespons }; } - diff --git a/client/src/generated/models/AddressBalanceResponse.ts b/client/src/generated/models/AddressBalanceResponse.ts index 462dd8a500..852dad1590 100644 --- a/client/src/generated/models/AddressBalanceResponse.ts +++ b/client/src/generated/models/AddressBalanceResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,10 +14,14 @@ import { exists, mapValues } from '../runtime'; import { - AddressBalanceResponseStx, - AddressBalanceResponseStxFromJSON, - AddressBalanceResponseStxFromJSONTyped, - AddressBalanceResponseStxToJSON, + AddressTokenOfferingLocked, + AddressTokenOfferingLockedFromJSON, + AddressTokenOfferingLockedFromJSONTyped, + AddressTokenOfferingLockedToJSON, + StxBalance, + StxBalanceFromJSON, + StxBalanceFromJSONTyped, + StxBalanceToJSON, } from './'; /** @@ -28,22 +32,28 @@ import { export interface AddressBalanceResponse { /** * - * @type {AddressBalanceResponseStx} + * @type {StxBalance} * @memberof AddressBalanceResponse */ - stx: AddressBalanceResponseStx; + stx: StxBalance; /** * - * @type {object} + * @type {{ [key: string]: object; }} * @memberof AddressBalanceResponse */ - fungible_tokens: object; + fungible_tokens: { [key: string]: object; }; /** * - * @type {object} + * @type {{ [key: string]: object; }} * @memberof AddressBalanceResponse */ - non_fungible_tokens: object; + non_fungible_tokens: { [key: string]: object; }; + /** + * + * @type {AddressTokenOfferingLocked} + * @memberof AddressBalanceResponse + */ + token_offering_locked?: AddressTokenOfferingLocked; } export function AddressBalanceResponseFromJSON(json: any): AddressBalanceResponse { @@ -56,9 +66,10 @@ export function AddressBalanceResponseFromJSONTyped(json: any, ignoreDiscriminat } return { - 'stx': AddressBalanceResponseStxFromJSON(json['stx']), + 'stx': StxBalanceFromJSON(json['stx']), 'fungible_tokens': json['fungible_tokens'], 'non_fungible_tokens': json['non_fungible_tokens'], + 'token_offering_locked': !exists(json, 'token_offering_locked') ? undefined : AddressTokenOfferingLockedFromJSON(json['token_offering_locked']), }; } @@ -71,10 +82,10 @@ export function AddressBalanceResponseToJSON(value?: AddressBalanceResponse | nu } return { - 'stx': AddressBalanceResponseStxToJSON(value.stx), + 'stx': StxBalanceToJSON(value.stx), 'fungible_tokens': value.fungible_tokens, 'non_fungible_tokens': value.non_fungible_tokens, + 'token_offering_locked': AddressTokenOfferingLockedToJSON(value.token_offering_locked), }; } - diff --git a/client/src/generated/models/AddressNftListResponse.ts b/client/src/generated/models/AddressNftListResponse.ts new file mode 100644 index 0000000000..3bfb1833a0 --- /dev/null +++ b/client/src/generated/models/AddressNftListResponse.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + NftEvent, + NftEventFromJSON, + NftEventFromJSONTyped, + NftEventToJSON, +} from './'; + +/** + * + * @export + * @interface AddressNftListResponse + */ +export interface AddressNftListResponse { + /** + * + * @type {number} + * @memberof AddressNftListResponse + */ + limit: number; + /** + * + * @type {number} + * @memberof AddressNftListResponse + */ + offset: number; + /** + * + * @type {number} + * @memberof AddressNftListResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof AddressNftListResponse + */ + nft_events: Array; +} + +export function AddressNftListResponseFromJSON(json: any): AddressNftListResponse { + return AddressNftListResponseFromJSONTyped(json, false); +} + +export function AddressNftListResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressNftListResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'nft_events': ((json['nft_events'] as Array).map(NftEventFromJSON)), + }; +} + +export function AddressNftListResponseToJSON(value?: AddressNftListResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'nft_events': ((value.nft_events as Array).map(NftEventToJSON)), + }; +} + diff --git a/client/src/generated/models/AddressNftListResponseValue.ts b/client/src/generated/models/AddressNftListResponseValue.ts new file mode 100644 index 0000000000..a326400dd7 --- /dev/null +++ b/client/src/generated/models/AddressNftListResponseValue.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Identifier of the NFT + * @export + * @interface AddressNftListResponseValue + */ +export interface AddressNftListResponseValue { + /** + * Hex string representing the identifier of the NFT + * @type {string} + * @memberof AddressNftListResponseValue + */ + hex: string; + /** + * Readable string of the NFT identifier + * @type {string} + * @memberof AddressNftListResponseValue + */ + repr: string; +} + +export function AddressNftListResponseValueFromJSON(json: any): AddressNftListResponseValue { + return AddressNftListResponseValueFromJSONTyped(json, false); +} + +export function AddressNftListResponseValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressNftListResponseValue { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'hex': json['hex'], + 'repr': json['repr'], + }; +} + +export function AddressNftListResponseValueToJSON(value?: AddressNftListResponseValue | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'hex': value.hex, + 'repr': value.repr, + }; +} + diff --git a/client/src/generated/models/AddressNonces.ts b/client/src/generated/models/AddressNonces.ts new file mode 100644 index 0000000000..f08de2bf50 --- /dev/null +++ b/client/src/generated/models/AddressNonces.ts @@ -0,0 +1,88 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * The latest nonce values used by an account by inspecting the mempool, microblock transactions, and anchored transactions + * @export + * @interface AddressNonces + */ +export interface AddressNonces { + /** + * The latest nonce found within mempool transactions sent by this address. Will be null if there are no current mempool transactions for this address. + * @type {number} + * @memberof AddressNonces + */ + last_mempool_tx_nonce: number | null; + /** + * The latest nonce found within transactions sent by this address, including unanchored microblock transactions. Will be null if there are no current transactions for this address. + * @type {number} + * @memberof AddressNonces + */ + last_executed_tx_nonce: number | null; + /** + * The likely nonce required for creating the next transaction, based on the last nonces seen by the API. This can be incorrect if the API's mempool or transactions aren't fully synchronized, even by a small amount, or if a previous transaction is still propagating through the Stacks blockchain network when this endpoint is called. + * @type {number} + * @memberof AddressNonces + */ + possible_next_nonce: number; + /** + * Nonces that appear to be missing and likely causing a mempool transaction to be stuck. + * @type {Array} + * @memberof AddressNonces + */ + detected_missing_nonces: Array; + /** + * Nonces currently in mempool for this address. + * @type {Array} + * @memberof AddressNonces + */ + detected_mempool_nonces?: Array; +} + +export function AddressNoncesFromJSON(json: any): AddressNonces { + return AddressNoncesFromJSONTyped(json, false); +} + +export function AddressNoncesFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressNonces { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'last_mempool_tx_nonce': json['last_mempool_tx_nonce'], + 'last_executed_tx_nonce': json['last_executed_tx_nonce'], + 'possible_next_nonce': json['possible_next_nonce'], + 'detected_missing_nonces': json['detected_missing_nonces'], + 'detected_mempool_nonces': !exists(json, 'detected_mempool_nonces') ? undefined : json['detected_mempool_nonces'], + }; +} + +export function AddressNoncesToJSON(value?: AddressNonces | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'last_mempool_tx_nonce': value.last_mempool_tx_nonce, + 'last_executed_tx_nonce': value.last_executed_tx_nonce, + 'possible_next_nonce': value.possible_next_nonce, + 'detected_missing_nonces': value.detected_missing_nonces, + 'detected_mempool_nonces': value.detected_mempool_nonces, + }; +} + diff --git a/client/src/generated/models/AddressStxBalanceResponse.ts b/client/src/generated/models/AddressStxBalanceResponse.ts deleted file mode 100644 index 51f8932dba..0000000000 --- a/client/src/generated/models/AddressStxBalanceResponse.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) - * - * The version of the OpenAPI document: 1.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * GET request that returns address balances - * @export - * @interface AddressStxBalanceResponse - */ -export interface AddressStxBalanceResponse { - /** - * - * @type {string} - * @memberof AddressStxBalanceResponse - */ - balance: string; - /** - * - * @type {string} - * @memberof AddressStxBalanceResponse - */ - total_sent: string; - /** - * - * @type {string} - * @memberof AddressStxBalanceResponse - */ - total_received: string; - /** - * - * @type {string} - * @memberof AddressStxBalanceResponse - */ - total_fees_sent: string; - /** - * - * @type {string} - * @memberof AddressStxBalanceResponse - */ - total_miner_rewards_received: string; - /** - * The transaction where the lock event occurred. Empty if no tokens are locked. - * @type {string} - * @memberof AddressStxBalanceResponse - */ - lock_tx_id: string; - /** - * The amount of locked STX, as string quoted micro-STX. Zero if no tokens are locked. - * @type {string} - * @memberof AddressStxBalanceResponse - */ - locked: string; - /** - * The STX chain block height of when the lock event occurred. Zero if no tokens are locked. - * @type {number} - * @memberof AddressStxBalanceResponse - */ - lock_height: number; - /** - * The burnchain block height of when the lock event occurred. Zero if no tokens are locked. - * @type {number} - * @memberof AddressStxBalanceResponse - */ - burnchain_lock_height: number; - /** - * The burnchain block height of when the tokens unlock. Zero if no tokens are locked. - * @type {number} - * @memberof AddressStxBalanceResponse - */ - burnchain_unlock_height: number; -} - -export function AddressStxBalanceResponseFromJSON(json: any): AddressStxBalanceResponse { - return AddressStxBalanceResponseFromJSONTyped(json, false); -} - -export function AddressStxBalanceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressStxBalanceResponse { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'balance': json['balance'], - 'total_sent': json['total_sent'], - 'total_received': json['total_received'], - 'total_fees_sent': json['total_fees_sent'], - 'total_miner_rewards_received': json['total_miner_rewards_received'], - 'lock_tx_id': json['lock_tx_id'], - 'locked': json['locked'], - 'lock_height': json['lock_height'], - 'burnchain_lock_height': json['burnchain_lock_height'], - 'burnchain_unlock_height': json['burnchain_unlock_height'], - }; -} - -export function AddressStxBalanceResponseToJSON(value?: AddressStxBalanceResponse | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'balance': value.balance, - 'total_sent': value.total_sent, - 'total_received': value.total_received, - 'total_fees_sent': value.total_fees_sent, - 'total_miner_rewards_received': value.total_miner_rewards_received, - 'lock_tx_id': value.lock_tx_id, - 'locked': value.locked, - 'lock_height': value.lock_height, - 'burnchain_lock_height': value.burnchain_lock_height, - 'burnchain_unlock_height': value.burnchain_unlock_height, - }; -} - - diff --git a/client/src/generated/models/AddressStxInboundListResponse.ts b/client/src/generated/models/AddressStxInboundListResponse.ts new file mode 100644 index 0000000000..ffd7165aee --- /dev/null +++ b/client/src/generated/models/AddressStxInboundListResponse.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + InboundStxTransfer, + InboundStxTransferFromJSON, + InboundStxTransferFromJSONTyped, + InboundStxTransferToJSON, +} from './'; + +/** + * GET request that returns a list of inbound STX transfers with a memo + * @export + * @interface AddressStxInboundListResponse + */ +export interface AddressStxInboundListResponse { + /** + * + * @type {number} + * @memberof AddressStxInboundListResponse + */ + limit: number; + /** + * + * @type {number} + * @memberof AddressStxInboundListResponse + */ + offset: number; + /** + * + * @type {number} + * @memberof AddressStxInboundListResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof AddressStxInboundListResponse + */ + results: Array; +} + +export function AddressStxInboundListResponseFromJSON(json: any): AddressStxInboundListResponse { + return AddressStxInboundListResponseFromJSONTyped(json, false); +} + +export function AddressStxInboundListResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressStxInboundListResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': ((json['results'] as Array).map(InboundStxTransferFromJSON)), + }; +} + +export function AddressStxInboundListResponseToJSON(value?: AddressStxInboundListResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': ((value.results as Array).map(InboundStxTransferToJSON)), + }; +} + diff --git a/client/src/generated/models/AddressTokenOfferingLocked.ts b/client/src/generated/models/AddressTokenOfferingLocked.ts new file mode 100644 index 0000000000..8a57a8c7d5 --- /dev/null +++ b/client/src/generated/models/AddressTokenOfferingLocked.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + AddressUnlockSchedule, + AddressUnlockScheduleFromJSON, + AddressUnlockScheduleFromJSONTyped, + AddressUnlockScheduleToJSON, +} from './'; + +/** + * Token Offering Locked + * @export + * @interface AddressTokenOfferingLocked + */ +export interface AddressTokenOfferingLocked { + /** + * Micro-STX amount still locked at current block height. + * @type {string} + * @memberof AddressTokenOfferingLocked + */ + total_locked: string; + /** + * Micro-STX amount unlocked at current block height. + * @type {string} + * @memberof AddressTokenOfferingLocked + */ + total_unlocked: string; + /** + * + * @type {Array} + * @memberof AddressTokenOfferingLocked + */ + unlock_schedule: Array; +} + +export function AddressTokenOfferingLockedFromJSON(json: any): AddressTokenOfferingLocked { + return AddressTokenOfferingLockedFromJSONTyped(json, false); +} + +export function AddressTokenOfferingLockedFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressTokenOfferingLocked { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'total_locked': json['total_locked'], + 'total_unlocked': json['total_unlocked'], + 'unlock_schedule': ((json['unlock_schedule'] as Array).map(AddressUnlockScheduleFromJSON)), + }; +} + +export function AddressTokenOfferingLockedToJSON(value?: AddressTokenOfferingLocked | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'total_locked': value.total_locked, + 'total_unlocked': value.total_unlocked, + 'unlock_schedule': ((value.unlock_schedule as Array).map(AddressUnlockScheduleToJSON)), + }; +} + diff --git a/client/src/generated/models/AddressTransactionWithTransfers.ts b/client/src/generated/models/AddressTransactionWithTransfers.ts new file mode 100644 index 0000000000..384b27146d --- /dev/null +++ b/client/src/generated/models/AddressTransactionWithTransfers.ts @@ -0,0 +1,111 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + AddressTransactionWithTransfersFtTransfers, + AddressTransactionWithTransfersFtTransfersFromJSON, + AddressTransactionWithTransfersFtTransfersFromJSONTyped, + AddressTransactionWithTransfersFtTransfersToJSON, + AddressTransactionWithTransfersNftTransfers, + AddressTransactionWithTransfersNftTransfersFromJSON, + AddressTransactionWithTransfersNftTransfersFromJSONTyped, + AddressTransactionWithTransfersNftTransfersToJSON, + AddressTransactionWithTransfersStxTransfers, + AddressTransactionWithTransfersStxTransfersFromJSON, + AddressTransactionWithTransfersStxTransfersFromJSONTyped, + AddressTransactionWithTransfersStxTransfersToJSON, +} from './'; + +/** + * Transaction with STX transfers for a given address + * @export + * @interface AddressTransactionWithTransfers + */ +export interface AddressTransactionWithTransfers { + /** + * Describes all transaction types on Stacks 2.0 blockchain + * @type {object} + * @memberof AddressTransactionWithTransfers + */ + tx: object; + /** + * Total sent from the given address, including the tx fee, in micro-STX as an integer string. + * @type {string} + * @memberof AddressTransactionWithTransfers + */ + stx_sent: string; + /** + * Total received by the given address in micro-STX as an integer string. + * @type {string} + * @memberof AddressTransactionWithTransfers + */ + stx_received: string; + /** + * + * @type {Array} + * @memberof AddressTransactionWithTransfers + */ + stx_transfers: Array; + /** + * + * @type {Array} + * @memberof AddressTransactionWithTransfers + */ + ft_transfers?: Array; + /** + * + * @type {Array} + * @memberof AddressTransactionWithTransfers + */ + nft_transfers?: Array; +} + +export function AddressTransactionWithTransfersFromJSON(json: any): AddressTransactionWithTransfers { + return AddressTransactionWithTransfersFromJSONTyped(json, false); +} + +export function AddressTransactionWithTransfersFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressTransactionWithTransfers { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'tx': json['tx'], + 'stx_sent': json['stx_sent'], + 'stx_received': json['stx_received'], + 'stx_transfers': ((json['stx_transfers'] as Array).map(AddressTransactionWithTransfersStxTransfersFromJSON)), + 'ft_transfers': !exists(json, 'ft_transfers') ? undefined : ((json['ft_transfers'] as Array).map(AddressTransactionWithTransfersFtTransfersFromJSON)), + 'nft_transfers': !exists(json, 'nft_transfers') ? undefined : ((json['nft_transfers'] as Array).map(AddressTransactionWithTransfersNftTransfersFromJSON)), + }; +} + +export function AddressTransactionWithTransfersToJSON(value?: AddressTransactionWithTransfers | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'tx': value.tx, + 'stx_sent': value.stx_sent, + 'stx_received': value.stx_received, + 'stx_transfers': ((value.stx_transfers as Array).map(AddressTransactionWithTransfersStxTransfersToJSON)), + 'ft_transfers': value.ft_transfers === undefined ? undefined : ((value.ft_transfers as Array).map(AddressTransactionWithTransfersFtTransfersToJSON)), + 'nft_transfers': value.nft_transfers === undefined ? undefined : ((value.nft_transfers as Array).map(AddressTransactionWithTransfersNftTransfersToJSON)), + }; +} + diff --git a/client/src/generated/models/AddressTransactionWithTransfersFtTransfers.ts b/client/src/generated/models/AddressTransactionWithTransfersFtTransfers.ts new file mode 100644 index 0000000000..45e60130a1 --- /dev/null +++ b/client/src/generated/models/AddressTransactionWithTransfersFtTransfers.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface AddressTransactionWithTransfersFtTransfers + */ +export interface AddressTransactionWithTransfersFtTransfers { + /** + * Fungible Token asset identifier. + * @type {string} + * @memberof AddressTransactionWithTransfersFtTransfers + */ + asset_identifier: string; + /** + * Amount transferred as an integer string. This balance does not factor in possible SIP-010 decimals. + * @type {string} + * @memberof AddressTransactionWithTransfersFtTransfers + */ + amount: string; + /** + * Principal that sent the asset. + * @type {string} + * @memberof AddressTransactionWithTransfersFtTransfers + */ + sender?: string; + /** + * Principal that received the asset. + * @type {string} + * @memberof AddressTransactionWithTransfersFtTransfers + */ + recipient?: string; +} + +export function AddressTransactionWithTransfersFtTransfersFromJSON(json: any): AddressTransactionWithTransfersFtTransfers { + return AddressTransactionWithTransfersFtTransfersFromJSONTyped(json, false); +} + +export function AddressTransactionWithTransfersFtTransfersFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressTransactionWithTransfersFtTransfers { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'asset_identifier': json['asset_identifier'], + 'amount': json['amount'], + 'sender': !exists(json, 'sender') ? undefined : json['sender'], + 'recipient': !exists(json, 'recipient') ? undefined : json['recipient'], + }; +} + +export function AddressTransactionWithTransfersFtTransfersToJSON(value?: AddressTransactionWithTransfersFtTransfers | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'asset_identifier': value.asset_identifier, + 'amount': value.amount, + 'sender': value.sender, + 'recipient': value.recipient, + }; +} + diff --git a/client/src/generated/models/AddressTransactionWithTransfersNftTransfers.ts b/client/src/generated/models/AddressTransactionWithTransfersNftTransfers.ts new file mode 100644 index 0000000000..adf8f33be9 --- /dev/null +++ b/client/src/generated/models/AddressTransactionWithTransfersNftTransfers.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + AddressTransactionWithTransfersValue, + AddressTransactionWithTransfersValueFromJSON, + AddressTransactionWithTransfersValueFromJSONTyped, + AddressTransactionWithTransfersValueToJSON, +} from './'; + +/** + * + * @export + * @interface AddressTransactionWithTransfersNftTransfers + */ +export interface AddressTransactionWithTransfersNftTransfers { + /** + * Non Fungible Token asset identifier. + * @type {string} + * @memberof AddressTransactionWithTransfersNftTransfers + */ + asset_identifier: string; + /** + * + * @type {AddressTransactionWithTransfersValue} + * @memberof AddressTransactionWithTransfersNftTransfers + */ + value: AddressTransactionWithTransfersValue; + /** + * Principal that sent the asset. + * @type {string} + * @memberof AddressTransactionWithTransfersNftTransfers + */ + sender?: string; + /** + * Principal that received the asset. + * @type {string} + * @memberof AddressTransactionWithTransfersNftTransfers + */ + recipient?: string; +} + +export function AddressTransactionWithTransfersNftTransfersFromJSON(json: any): AddressTransactionWithTransfersNftTransfers { + return AddressTransactionWithTransfersNftTransfersFromJSONTyped(json, false); +} + +export function AddressTransactionWithTransfersNftTransfersFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressTransactionWithTransfersNftTransfers { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'asset_identifier': json['asset_identifier'], + 'value': AddressTransactionWithTransfersValueFromJSON(json['value']), + 'sender': !exists(json, 'sender') ? undefined : json['sender'], + 'recipient': !exists(json, 'recipient') ? undefined : json['recipient'], + }; +} + +export function AddressTransactionWithTransfersNftTransfersToJSON(value?: AddressTransactionWithTransfersNftTransfers | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'asset_identifier': value.asset_identifier, + 'value': AddressTransactionWithTransfersValueToJSON(value.value), + 'sender': value.sender, + 'recipient': value.recipient, + }; +} + diff --git a/client/src/generated/models/AddressTransactionWithTransfersStxTransfers.ts b/client/src/generated/models/AddressTransactionWithTransfersStxTransfers.ts new file mode 100644 index 0000000000..e8b5e190df --- /dev/null +++ b/client/src/generated/models/AddressTransactionWithTransfersStxTransfers.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface AddressTransactionWithTransfersStxTransfers + */ +export interface AddressTransactionWithTransfersStxTransfers { + /** + * Amount transferred in micro-STX as an integer string. + * @type {string} + * @memberof AddressTransactionWithTransfersStxTransfers + */ + amount: string; + /** + * Principal that sent STX. This is unspecified if the STX were minted. + * @type {string} + * @memberof AddressTransactionWithTransfersStxTransfers + */ + sender?: string; + /** + * Principal that received STX. This is unspecified if the STX were burned. + * @type {string} + * @memberof AddressTransactionWithTransfersStxTransfers + */ + recipient?: string; +} + +export function AddressTransactionWithTransfersStxTransfersFromJSON(json: any): AddressTransactionWithTransfersStxTransfers { + return AddressTransactionWithTransfersStxTransfersFromJSONTyped(json, false); +} + +export function AddressTransactionWithTransfersStxTransfersFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressTransactionWithTransfersStxTransfers { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'amount': json['amount'], + 'sender': !exists(json, 'sender') ? undefined : json['sender'], + 'recipient': !exists(json, 'recipient') ? undefined : json['recipient'], + }; +} + +export function AddressTransactionWithTransfersStxTransfersToJSON(value?: AddressTransactionWithTransfersStxTransfers | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'amount': value.amount, + 'sender': value.sender, + 'recipient': value.recipient, + }; +} + diff --git a/client/src/generated/models/AddressTransactionWithTransfersValue.ts b/client/src/generated/models/AddressTransactionWithTransfersValue.ts new file mode 100644 index 0000000000..1894ee8099 --- /dev/null +++ b/client/src/generated/models/AddressTransactionWithTransfersValue.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Non Fungible Token asset value. + * @export + * @interface AddressTransactionWithTransfersValue + */ +export interface AddressTransactionWithTransfersValue { + /** + * + * @type {string} + * @memberof AddressTransactionWithTransfersValue + */ + hex: string; + /** + * + * @type {string} + * @memberof AddressTransactionWithTransfersValue + */ + repr: string; +} + +export function AddressTransactionWithTransfersValueFromJSON(json: any): AddressTransactionWithTransfersValue { + return AddressTransactionWithTransfersValueFromJSONTyped(json, false); +} + +export function AddressTransactionWithTransfersValueFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressTransactionWithTransfersValue { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'hex': json['hex'], + 'repr': json['repr'], + }; +} + +export function AddressTransactionWithTransfersValueToJSON(value?: AddressTransactionWithTransfersValue | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'hex': value.hex, + 'repr': value.repr, + }; +} + diff --git a/client/src/generated/models/AddressTransactionsListResponse.ts b/client/src/generated/models/AddressTransactionsListResponse.ts index bc0bdf3568..a493ee9b0f 100644 --- a/client/src/generated/models/AddressTransactionsListResponse.ts +++ b/client/src/generated/models/AddressTransactionsListResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -78,4 +78,3 @@ export function AddressTransactionsListResponseToJSON(value?: AddressTransaction }; } - diff --git a/client/src/generated/models/AddressTransactionsWithTransfersListResponse.ts b/client/src/generated/models/AddressTransactionsWithTransfersListResponse.ts new file mode 100644 index 0000000000..3f5e59d5f4 --- /dev/null +++ b/client/src/generated/models/AddressTransactionsWithTransfersListResponse.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + AddressTransactionWithTransfers, + AddressTransactionWithTransfersFromJSON, + AddressTransactionWithTransfersFromJSONTyped, + AddressTransactionWithTransfersToJSON, +} from './'; + +/** + * GET request that returns account transactions + * @export + * @interface AddressTransactionsWithTransfersListResponse + */ +export interface AddressTransactionsWithTransfersListResponse { + /** + * + * @type {number} + * @memberof AddressTransactionsWithTransfersListResponse + */ + limit: number; + /** + * + * @type {number} + * @memberof AddressTransactionsWithTransfersListResponse + */ + offset: number; + /** + * + * @type {number} + * @memberof AddressTransactionsWithTransfersListResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof AddressTransactionsWithTransfersListResponse + */ + results: Array; +} + +export function AddressTransactionsWithTransfersListResponseFromJSON(json: any): AddressTransactionsWithTransfersListResponse { + return AddressTransactionsWithTransfersListResponseFromJSONTyped(json, false); +} + +export function AddressTransactionsWithTransfersListResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressTransactionsWithTransfersListResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': ((json['results'] as Array).map(AddressTransactionWithTransfersFromJSON)), + }; +} + +export function AddressTransactionsWithTransfersListResponseToJSON(value?: AddressTransactionsWithTransfersListResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': ((value.results as Array).map(AddressTransactionWithTransfersToJSON)), + }; +} + diff --git a/client/src/generated/models/AddressUnlockSchedule.ts b/client/src/generated/models/AddressUnlockSchedule.ts new file mode 100644 index 0000000000..ac25d18f56 --- /dev/null +++ b/client/src/generated/models/AddressUnlockSchedule.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Unlock schedule amount and block height + * @export + * @interface AddressUnlockSchedule + */ +export interface AddressUnlockSchedule { + /** + * Micro-STX amount locked at this block height. + * @type {string} + * @memberof AddressUnlockSchedule + */ + amount: string; + /** + * + * @type {number} + * @memberof AddressUnlockSchedule + */ + block_height: number; +} + +export function AddressUnlockScheduleFromJSON(json: any): AddressUnlockSchedule { + return AddressUnlockScheduleFromJSONTyped(json, false); +} + +export function AddressUnlockScheduleFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressUnlockSchedule { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'amount': json['amount'], + 'block_height': json['block_height'], + }; +} + +export function AddressUnlockScheduleToJSON(value?: AddressUnlockSchedule | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'amount': value.amount, + 'block_height': value.block_height, + }; +} + diff --git a/client/src/generated/models/Block.ts b/client/src/generated/models/Block.ts index 64837c0ddf..4114018502 100644 --- a/client/src/generated/models/Block.ts +++ b/client/src/generated/models/Block.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -37,6 +37,12 @@ export interface Block { * @memberof Block */ hash: string; + /** + * The only hash that can uniquely identify an anchored block or an unconfirmed state trie + * @type {string} + * @memberof Block + */ + index_block_hash: string; /** * Hash of the parent block * @type {string} @@ -73,12 +79,72 @@ export interface Block { * @memberof Block */ miner_txid: string; + /** + * The hash of the last streamed block that precedes this block to which this block is to be appended. Not every anchored block will have a parent microblock stream. An anchored block that does not have a parent microblock stream has the parent microblock hash set to an empty string, and the parent microblock sequence number set to -1. + * @type {string} + * @memberof Block + */ + parent_microblock_hash: string; + /** + * The hash of the last streamed block that precedes this block to which this block is to be appended. Not every anchored block will have a parent microblock stream. An anchored block that does not have a parent microblock stream has the parent microblock hash set to an empty string, and the parent microblock sequence number set to -1. + * @type {number} + * @memberof Block + */ + parent_microblock_sequence: number; /** * List of transactions included in the block * @type {Array} * @memberof Block */ txs: Array; + /** + * List of microblocks that were accepted in this anchor block. Not every anchored block will have a accepted all (or any) of the previously streamed microblocks. Microblocks that were orphaned are not included in this list. + * @type {Array} + * @memberof Block + */ + microblocks_accepted: Array; + /** + * List of microblocks that were streamed/produced by this anchor block's miner. This list only includes microblocks that were accepted in the following anchor block. Microblocks that were orphaned are not included in this list. + * @type {Array} + * @memberof Block + */ + microblocks_streamed: Array; + /** + * Execution cost read count. + * @type {number} + * @memberof Block + */ + execution_cost_read_count: number; + /** + * Execution cost read length. + * @type {number} + * @memberof Block + */ + execution_cost_read_length: number; + /** + * Execution cost runtime. + * @type {number} + * @memberof Block + */ + execution_cost_runtime: number; + /** + * Execution cost write count. + * @type {number} + * @memberof Block + */ + execution_cost_write_count: number; + /** + * Execution cost write length. + * @type {number} + * @memberof Block + */ + execution_cost_write_length: number; + /** + * List of txs counts in each accepted microblock + * @type {{ [key: string]: number; }} + * @memberof Block + */ + microblock_tx_count: { [key: string]: number; }; } export function BlockFromJSON(json: any): Block { @@ -94,13 +160,24 @@ export function BlockFromJSONTyped(json: any, ignoreDiscriminator: boolean): Blo 'canonical': json['canonical'], 'height': json['height'], 'hash': json['hash'], + 'index_block_hash': json['index_block_hash'], 'parent_block_hash': json['parent_block_hash'], 'burn_block_time': json['burn_block_time'], 'burn_block_time_iso': json['burn_block_time_iso'], 'burn_block_hash': json['burn_block_hash'], 'burn_block_height': json['burn_block_height'], 'miner_txid': json['miner_txid'], + 'parent_microblock_hash': json['parent_microblock_hash'], + 'parent_microblock_sequence': json['parent_microblock_sequence'], 'txs': json['txs'], + 'microblocks_accepted': json['microblocks_accepted'], + 'microblocks_streamed': json['microblocks_streamed'], + 'execution_cost_read_count': json['execution_cost_read_count'], + 'execution_cost_read_length': json['execution_cost_read_length'], + 'execution_cost_runtime': json['execution_cost_runtime'], + 'execution_cost_write_count': json['execution_cost_write_count'], + 'execution_cost_write_length': json['execution_cost_write_length'], + 'microblock_tx_count': json['microblock_tx_count'], }; } @@ -116,14 +193,24 @@ export function BlockToJSON(value?: Block | null): any { 'canonical': value.canonical, 'height': value.height, 'hash': value.hash, + 'index_block_hash': value.index_block_hash, 'parent_block_hash': value.parent_block_hash, 'burn_block_time': value.burn_block_time, 'burn_block_time_iso': value.burn_block_time_iso, 'burn_block_hash': value.burn_block_hash, 'burn_block_height': value.burn_block_height, 'miner_txid': value.miner_txid, + 'parent_microblock_hash': value.parent_microblock_hash, + 'parent_microblock_sequence': value.parent_microblock_sequence, 'txs': value.txs, + 'microblocks_accepted': value.microblocks_accepted, + 'microblocks_streamed': value.microblocks_streamed, + 'execution_cost_read_count': value.execution_cost_read_count, + 'execution_cost_read_length': value.execution_cost_read_length, + 'execution_cost_runtime': value.execution_cost_runtime, + 'execution_cost_write_count': value.execution_cost_write_count, + 'execution_cost_write_length': value.execution_cost_write_length, + 'microblock_tx_count': value.microblock_tx_count, }; } - diff --git a/client/src/generated/models/BlockListResponse.ts b/client/src/generated/models/BlockListResponse.ts index 8b68d54671..a6d4d2abf5 100644 --- a/client/src/generated/models/BlockListResponse.ts +++ b/client/src/generated/models/BlockListResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -85,4 +85,3 @@ export function BlockListResponseToJSON(value?: BlockListResponse | null): any { }; } - diff --git a/client/src/generated/models/BnsError.ts b/client/src/generated/models/BnsError.ts new file mode 100644 index 0000000000..3eb24ec09e --- /dev/null +++ b/client/src/generated/models/BnsError.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Error + * @export + * @interface BnsError + */ +export interface BnsError { + /** + * + * @type {string} + * @memberof BnsError + */ + error?: string; +} + +export function BnsErrorFromJSON(json: any): BnsError { + return BnsErrorFromJSONTyped(json, false); +} + +export function BnsErrorFromJSONTyped(json: any, ignoreDiscriminator: boolean): BnsError { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'error': !exists(json, 'error') ? undefined : json['error'], + }; +} + +export function BnsErrorToJSON(value?: BnsError | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'error': value.error, + }; +} + diff --git a/client/src/generated/models/BnsGetAllNamespacesResponse.ts b/client/src/generated/models/BnsGetAllNamespacesResponse.ts new file mode 100644 index 0000000000..3951a07291 --- /dev/null +++ b/client/src/generated/models/BnsGetAllNamespacesResponse.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Fetch a list of all namespaces known to the node. + * @export + * @interface BnsGetAllNamespacesResponse + */ +export interface BnsGetAllNamespacesResponse { + /** + * + * @type {Array} + * @memberof BnsGetAllNamespacesResponse + */ + namespaces: Array; +} + +export function BnsGetAllNamespacesResponseFromJSON(json: any): BnsGetAllNamespacesResponse { + return BnsGetAllNamespacesResponseFromJSONTyped(json, false); +} + +export function BnsGetAllNamespacesResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): BnsGetAllNamespacesResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'namespaces': json['namespaces'], + }; +} + +export function BnsGetAllNamespacesResponseToJSON(value?: BnsGetAllNamespacesResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'namespaces': value.namespaces, + }; +} + diff --git a/client/src/generated/models/BnsGetNameInfoResponse.ts b/client/src/generated/models/BnsGetNameInfoResponse.ts new file mode 100644 index 0000000000..0c5e82a2c8 --- /dev/null +++ b/client/src/generated/models/BnsGetNameInfoResponse.ts @@ -0,0 +1,120 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Get name details + * @export + * @interface BnsGetNameInfoResponse + */ +export interface BnsGetNameInfoResponse { + /** + * + * @type {string} + * @memberof BnsGetNameInfoResponse + */ + address: string; + /** + * + * @type {string} + * @memberof BnsGetNameInfoResponse + */ + blockchain: string; + /** + * + * @type {number} + * @memberof BnsGetNameInfoResponse + */ + expire_block?: number; + /** + * + * @type {number} + * @memberof BnsGetNameInfoResponse + */ + grace_period?: number; + /** + * + * @type {string} + * @memberof BnsGetNameInfoResponse + */ + last_txid: string; + /** + * + * @type {string} + * @memberof BnsGetNameInfoResponse + */ + resolver?: string; + /** + * + * @type {string} + * @memberof BnsGetNameInfoResponse + */ + status: string; + /** + * + * @type {string} + * @memberof BnsGetNameInfoResponse + */ + zonefile: string; + /** + * + * @type {string} + * @memberof BnsGetNameInfoResponse + */ + zonefile_hash: string; +} + +export function BnsGetNameInfoResponseFromJSON(json: any): BnsGetNameInfoResponse { + return BnsGetNameInfoResponseFromJSONTyped(json, false); +} + +export function BnsGetNameInfoResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): BnsGetNameInfoResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'address': json['address'], + 'blockchain': json['blockchain'], + 'expire_block': !exists(json, 'expire_block') ? undefined : json['expire_block'], + 'grace_period': !exists(json, 'grace_period') ? undefined : json['grace_period'], + 'last_txid': json['last_txid'], + 'resolver': !exists(json, 'resolver') ? undefined : json['resolver'], + 'status': json['status'], + 'zonefile': json['zonefile'], + 'zonefile_hash': json['zonefile_hash'], + }; +} + +export function BnsGetNameInfoResponseToJSON(value?: BnsGetNameInfoResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'address': value.address, + 'blockchain': value.blockchain, + 'expire_block': value.expire_block, + 'grace_period': value.grace_period, + 'last_txid': value.last_txid, + 'resolver': value.resolver, + 'status': value.status, + 'zonefile': value.zonefile, + 'zonefile_hash': value.zonefile_hash, + }; +} + diff --git a/client/src/generated/models/BnsGetNamePriceResponse.ts b/client/src/generated/models/BnsGetNamePriceResponse.ts new file mode 100644 index 0000000000..13c03e48a4 --- /dev/null +++ b/client/src/generated/models/BnsGetNamePriceResponse.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Fetch price for name. + * @export + * @interface BnsGetNamePriceResponse + */ +export interface BnsGetNamePriceResponse { + /** + * + * @type {string} + * @memberof BnsGetNamePriceResponse + */ + units: string; + /** + * + * @type {string} + * @memberof BnsGetNamePriceResponse + */ + amount: string; +} + +export function BnsGetNamePriceResponseFromJSON(json: any): BnsGetNamePriceResponse { + return BnsGetNamePriceResponseFromJSONTyped(json, false); +} + +export function BnsGetNamePriceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): BnsGetNamePriceResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'units': json['units'], + 'amount': json['amount'], + }; +} + +export function BnsGetNamePriceResponseToJSON(value?: BnsGetNamePriceResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'units': value.units, + 'amount': value.amount, + }; +} + diff --git a/client/src/generated/models/BnsGetNamespacePriceResponse.ts b/client/src/generated/models/BnsGetNamespacePriceResponse.ts new file mode 100644 index 0000000000..56f293be23 --- /dev/null +++ b/client/src/generated/models/BnsGetNamespacePriceResponse.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Fetch price for namespace. + * @export + * @interface BnsGetNamespacePriceResponse + */ +export interface BnsGetNamespacePriceResponse { + /** + * + * @type {string} + * @memberof BnsGetNamespacePriceResponse + */ + units: string; + /** + * + * @type {string} + * @memberof BnsGetNamespacePriceResponse + */ + amount: string; +} + +export function BnsGetNamespacePriceResponseFromJSON(json: any): BnsGetNamespacePriceResponse { + return BnsGetNamespacePriceResponseFromJSONTyped(json, false); +} + +export function BnsGetNamespacePriceResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): BnsGetNamespacePriceResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'units': json['units'], + 'amount': json['amount'], + }; +} + +export function BnsGetNamespacePriceResponseToJSON(value?: BnsGetNamespacePriceResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'units': value.units, + 'amount': value.amount, + }; +} + diff --git a/client/src/generated/models/BnsNamesOwnByAddressResponse.ts b/client/src/generated/models/BnsNamesOwnByAddressResponse.ts new file mode 100644 index 0000000000..9617a59b0c --- /dev/null +++ b/client/src/generated/models/BnsNamesOwnByAddressResponse.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Retrieves a list of names owned by the address provided. + * @export + * @interface BnsNamesOwnByAddressResponse + */ +export interface BnsNamesOwnByAddressResponse { + /** + * + * @type {Array} + * @memberof BnsNamesOwnByAddressResponse + */ + names: Array; +} + +export function BnsNamesOwnByAddressResponseFromJSON(json: any): BnsNamesOwnByAddressResponse { + return BnsNamesOwnByAddressResponseFromJSONTyped(json, false); +} + +export function BnsNamesOwnByAddressResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): BnsNamesOwnByAddressResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'names': json['names'], + }; +} + +export function BnsNamesOwnByAddressResponseToJSON(value?: BnsNamesOwnByAddressResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'names': value.names, + }; +} + diff --git a/client/src/generated/models/BurnchainReward.ts b/client/src/generated/models/BurnchainReward.ts index b85fc9b653..b605981ce9 100644 --- a/client/src/generated/models/BurnchainReward.ts +++ b/client/src/generated/models/BurnchainReward.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -102,4 +102,3 @@ export function BurnchainRewardToJSON(value?: BurnchainReward | null): any { }; } - diff --git a/client/src/generated/models/BurnchainRewardListResponse.ts b/client/src/generated/models/BurnchainRewardListResponse.ts index ed5010c3fb..b5cacf3edd 100644 --- a/client/src/generated/models/BurnchainRewardListResponse.ts +++ b/client/src/generated/models/BurnchainRewardListResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -77,4 +77,3 @@ export function BurnchainRewardListResponseToJSON(value?: BurnchainRewardListRes }; } - diff --git a/client/src/generated/models/BurnchainRewardSlotHolder.ts b/client/src/generated/models/BurnchainRewardSlotHolder.ts new file mode 100644 index 0000000000..1963ae1bd0 --- /dev/null +++ b/client/src/generated/models/BurnchainRewardSlotHolder.ts @@ -0,0 +1,88 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Reward slot holder on the burnchain + * @export + * @interface BurnchainRewardSlotHolder + */ +export interface BurnchainRewardSlotHolder { + /** + * Set to `true` if block corresponds to the canonical burchchain tip + * @type {boolean} + * @memberof BurnchainRewardSlotHolder + */ + canonical: boolean; + /** + * The hash representing the burnchain block + * @type {string} + * @memberof BurnchainRewardSlotHolder + */ + burn_block_hash: string; + /** + * Height of the burnchain block + * @type {number} + * @memberof BurnchainRewardSlotHolder + */ + burn_block_height: number; + /** + * The recipient address that validly received PoX commitments, in the format native to the burnchain (e.g. B58 encoded for Bitcoin) + * @type {string} + * @memberof BurnchainRewardSlotHolder + */ + address: string; + /** + * The index position of the reward entry, useful for ordering when there's more than one slot per burnchain block + * @type {number} + * @memberof BurnchainRewardSlotHolder + */ + slot_index: number; +} + +export function BurnchainRewardSlotHolderFromJSON(json: any): BurnchainRewardSlotHolder { + return BurnchainRewardSlotHolderFromJSONTyped(json, false); +} + +export function BurnchainRewardSlotHolderFromJSONTyped(json: any, ignoreDiscriminator: boolean): BurnchainRewardSlotHolder { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'canonical': json['canonical'], + 'burn_block_hash': json['burn_block_hash'], + 'burn_block_height': json['burn_block_height'], + 'address': json['address'], + 'slot_index': json['slot_index'], + }; +} + +export function BurnchainRewardSlotHolderToJSON(value?: BurnchainRewardSlotHolder | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'canonical': value.canonical, + 'burn_block_hash': value.burn_block_hash, + 'burn_block_height': value.burn_block_height, + 'address': value.address, + 'slot_index': value.slot_index, + }; +} + diff --git a/client/src/generated/models/BurnchainRewardSlotHolderListResponse.ts b/client/src/generated/models/BurnchainRewardSlotHolderListResponse.ts new file mode 100644 index 0000000000..81738f1a2a --- /dev/null +++ b/client/src/generated/models/BurnchainRewardSlotHolderListResponse.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + BurnchainRewardSlotHolder, + BurnchainRewardSlotHolderFromJSON, + BurnchainRewardSlotHolderFromJSONTyped, + BurnchainRewardSlotHolderToJSON, +} from './'; + +/** + * GET request that returns reward slot holders + * @export + * @interface BurnchainRewardSlotHolderListResponse + */ +export interface BurnchainRewardSlotHolderListResponse { + /** + * The number of items to return + * @type {number} + * @memberof BurnchainRewardSlotHolderListResponse + */ + limit: number; + /** + * The number of items to skip (starting at `0`) + * @type {number} + * @memberof BurnchainRewardSlotHolderListResponse + */ + offset: number; + /** + * Total number of available items + * @type {number} + * @memberof BurnchainRewardSlotHolderListResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof BurnchainRewardSlotHolderListResponse + */ + results: Array; +} + +export function BurnchainRewardSlotHolderListResponseFromJSON(json: any): BurnchainRewardSlotHolderListResponse { + return BurnchainRewardSlotHolderListResponseFromJSONTyped(json, false); +} + +export function BurnchainRewardSlotHolderListResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): BurnchainRewardSlotHolderListResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': ((json['results'] as Array).map(BurnchainRewardSlotHolderFromJSON)), + }; +} + +export function BurnchainRewardSlotHolderListResponseToJSON(value?: BurnchainRewardSlotHolderListResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': ((value.results as Array).map(BurnchainRewardSlotHolderToJSON)), + }; +} + diff --git a/client/src/generated/models/BurnchainRewardsTotal.ts b/client/src/generated/models/BurnchainRewardsTotal.ts index b668541728..69e309a700 100644 --- a/client/src/generated/models/BurnchainRewardsTotal.ts +++ b/client/src/generated/models/BurnchainRewardsTotal.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function BurnchainRewardsTotalToJSON(value?: BurnchainRewardsTotal | null }; } - diff --git a/client/src/generated/models/ChainTip.ts b/client/src/generated/models/ChainTip.ts new file mode 100644 index 0000000000..c7b3e00bcb --- /dev/null +++ b/client/src/generated/models/ChainTip.ts @@ -0,0 +1,96 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Current chain tip information + * @export + * @interface ChainTip + */ +export interface ChainTip { + /** + * the current block height + * @type {number} + * @memberof ChainTip + */ + block_height: number; + /** + * the current block hash + * @type {string} + * @memberof ChainTip + */ + block_hash: string; + /** + * the current index block hash + * @type {string} + * @memberof ChainTip + */ + index_block_hash: string; + /** + * the current microblock hash + * @type {string} + * @memberof ChainTip + */ + microblock_hash?: string; + /** + * the current microblock sequence number + * @type {number} + * @memberof ChainTip + */ + microblock_sequence?: number; + /** + * the current burn chain block height + * @type {number} + * @memberof ChainTip + */ + burn_block_height: number; +} + +export function ChainTipFromJSON(json: any): ChainTip { + return ChainTipFromJSONTyped(json, false); +} + +export function ChainTipFromJSONTyped(json: any, ignoreDiscriminator: boolean): ChainTip { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'block_height': json['block_height'], + 'block_hash': json['block_hash'], + 'index_block_hash': json['index_block_hash'], + 'microblock_hash': !exists(json, 'microblock_hash') ? undefined : json['microblock_hash'], + 'microblock_sequence': !exists(json, 'microblock_sequence') ? undefined : json['microblock_sequence'], + 'burn_block_height': json['burn_block_height'], + }; +} + +export function ChainTipToJSON(value?: ChainTip | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'block_height': value.block_height, + 'block_hash': value.block_hash, + 'index_block_hash': value.index_block_hash, + 'microblock_hash': value.microblock_hash, + 'microblock_sequence': value.microblock_sequence, + 'burn_block_height': value.burn_block_height, + }; +} + diff --git a/client/src/generated/models/ContractInterfaceResponse.ts b/client/src/generated/models/ContractInterfaceResponse.ts index d572aa5319..981323e1df 100644 --- a/client/src/generated/models/ContractInterfaceResponse.ts +++ b/client/src/generated/models/ContractInterfaceResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -86,4 +86,3 @@ export function ContractInterfaceResponseToJSON(value?: ContractInterfaceRespons }; } - diff --git a/client/src/generated/models/ContractListResponse.ts b/client/src/generated/models/ContractListResponse.ts new file mode 100644 index 0000000000..af1711e8f5 --- /dev/null +++ b/client/src/generated/models/ContractListResponse.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + SmartContract, + SmartContractFromJSON, + SmartContractFromJSONTyped, + SmartContractToJSON, +} from './'; + +/** + * GET list of contracts + * @export + * @interface ContractListResponse + */ +export interface ContractListResponse { + /** + * The number of contracts to return + * @type {number} + * @memberof ContractListResponse + */ + limit: number; + /** + * The number to contracts to skip (starting at `0`) + * @type {number} + * @memberof ContractListResponse + */ + offset: number; + /** + * + * @type {Array} + * @memberof ContractListResponse + */ + results: Array; +} + +export function ContractListResponseFromJSON(json: any): ContractListResponse { + return ContractListResponseFromJSONTyped(json, false); +} + +export function ContractListResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ContractListResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'results': ((json['results'] as Array).map(SmartContractFromJSON)), + }; +} + +export function ContractListResponseToJSON(value?: ContractListResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'results': ((value.results as Array).map(SmartContractToJSON)), + }; +} + diff --git a/client/src/generated/models/ContractSourceResponse.ts b/client/src/generated/models/ContractSourceResponse.ts index d46000d90f..2bc9c50fdb 100644 --- a/client/src/generated/models/ContractSourceResponse.ts +++ b/client/src/generated/models/ContractSourceResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -70,4 +70,3 @@ export function ContractSourceResponseToJSON(value?: ContractSourceResponse | nu }; } - diff --git a/client/src/generated/models/CoreNodeInfoResponse.ts b/client/src/generated/models/CoreNodeInfoResponse.ts index 5506ecac08..b9fc0597a0 100644 --- a/client/src/generated/models/CoreNodeInfoResponse.ts +++ b/client/src/generated/models/CoreNodeInfoResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -150,4 +150,3 @@ export function CoreNodeInfoResponseToJSON(value?: CoreNodeInfoResponse | null): }; } - diff --git a/client/src/generated/models/CoreNodePoxResponse.ts b/client/src/generated/models/CoreNodePoxResponse.ts index 0c513afd76..079c566a97 100644 --- a/client/src/generated/models/CoreNodePoxResponse.ts +++ b/client/src/generated/models/CoreNodePoxResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -118,4 +118,3 @@ export function CoreNodePoxResponseToJSON(value?: CoreNodePoxResponse | null): a }; } - diff --git a/client/src/generated/models/FeeRate.ts b/client/src/generated/models/FeeRate.ts new file mode 100644 index 0000000000..15482f7f4b --- /dev/null +++ b/client/src/generated/models/FeeRate.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Get fee rate information. + * @export + * @interface FeeRate + */ +export interface FeeRate { + /** + * + * @type {number} + * @memberof FeeRate + */ + fee_rate: number; +} + +export function FeeRateFromJSON(json: any): FeeRate { + return FeeRateFromJSONTyped(json, false); +} + +export function FeeRateFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeeRate { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'fee_rate': json['fee_rate'], + }; +} + +export function FeeRateToJSON(value?: FeeRate | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'fee_rate': value.fee_rate, + }; +} + diff --git a/client/src/generated/models/FeeRateRequest.ts b/client/src/generated/models/FeeRateRequest.ts new file mode 100644 index 0000000000..a98b20acc0 --- /dev/null +++ b/client/src/generated/models/FeeRateRequest.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Request to fetch fee for a transaction + * @export + * @interface FeeRateRequest + */ +export interface FeeRateRequest { + /** + * A serialized transaction + * @type {string} + * @memberof FeeRateRequest + */ + transaction: string; +} + +export function FeeRateRequestFromJSON(json: any): FeeRateRequest { + return FeeRateRequestFromJSONTyped(json, false); +} + +export function FeeRateRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): FeeRateRequest { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'transaction': json['transaction'], + }; +} + +export function FeeRateRequestToJSON(value?: FeeRateRequest | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'transaction': value.transaction, + }; +} + diff --git a/client/src/generated/models/FungibleTokenMetadata.ts b/client/src/generated/models/FungibleTokenMetadata.ts new file mode 100644 index 0000000000..e83645ec49 --- /dev/null +++ b/client/src/generated/models/FungibleTokenMetadata.ts @@ -0,0 +1,120 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface FungibleTokenMetadata + */ +export interface FungibleTokenMetadata { + /** + * An optional string that is a valid URI which resolves to this token's metadata. Can be empty. + * @type {string} + * @memberof FungibleTokenMetadata + */ + token_uri: string; + /** + * Identifies the asset to which this token represents + * @type {string} + * @memberof FungibleTokenMetadata + */ + name: string; + /** + * Describes the asset to which this token represents + * @type {string} + * @memberof FungibleTokenMetadata + */ + description: string; + /** + * A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI. + * @type {string} + * @memberof FungibleTokenMetadata + */ + image_uri: string; + /** + * The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive. + * @type {string} + * @memberof FungibleTokenMetadata + */ + image_canonical_uri: string; + /** + * A shorter representation of a token. This is sometimes referred to as a "ticker". Examples: "STX", "COOL", etc. Typically, a token could be referred to as $SYMBOL when referencing it in writing. + * @type {string} + * @memberof FungibleTokenMetadata + */ + symbol: string; + /** + * The number of decimal places in a token. + * @type {number} + * @memberof FungibleTokenMetadata + */ + decimals: number; + /** + * Tx id that deployed the contract + * @type {string} + * @memberof FungibleTokenMetadata + */ + tx_id: string; + /** + * principle that deployed the contract + * @type {string} + * @memberof FungibleTokenMetadata + */ + sender_address: string; +} + +export function FungibleTokenMetadataFromJSON(json: any): FungibleTokenMetadata { + return FungibleTokenMetadataFromJSONTyped(json, false); +} + +export function FungibleTokenMetadataFromJSONTyped(json: any, ignoreDiscriminator: boolean): FungibleTokenMetadata { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'token_uri': json['token_uri'], + 'name': json['name'], + 'description': json['description'], + 'image_uri': json['image_uri'], + 'image_canonical_uri': json['image_canonical_uri'], + 'symbol': json['symbol'], + 'decimals': json['decimals'], + 'tx_id': json['tx_id'], + 'sender_address': json['sender_address'], + }; +} + +export function FungibleTokenMetadataToJSON(value?: FungibleTokenMetadata | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'token_uri': value.token_uri, + 'name': value.name, + 'description': value.description, + 'image_uri': value.image_uri, + 'image_canonical_uri': value.image_canonical_uri, + 'symbol': value.symbol, + 'decimals': value.decimals, + 'tx_id': value.tx_id, + 'sender_address': value.sender_address, + }; +} + diff --git a/client/src/generated/models/FungibleTokensMetadataList.ts b/client/src/generated/models/FungibleTokensMetadataList.ts new file mode 100644 index 0000000000..e9a059f26c --- /dev/null +++ b/client/src/generated/models/FungibleTokensMetadataList.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + FungibleTokenMetadata, + FungibleTokenMetadataFromJSON, + FungibleTokenMetadataFromJSONTyped, + FungibleTokenMetadataToJSON, +} from './'; + +/** + * List of fungible tokens metadata + * @export + * @interface FungibleTokensMetadataList + */ +export interface FungibleTokensMetadataList { + /** + * The number of tokens metadata to return + * @type {number} + * @memberof FungibleTokensMetadataList + */ + limit: number; + /** + * The number to tokens metadata to skip (starting at `0`) + * @type {number} + * @memberof FungibleTokensMetadataList + */ + offset: number; + /** + * The number of tokens metadata available + * @type {number} + * @memberof FungibleTokensMetadataList + */ + total: number; + /** + * + * @type {Array} + * @memberof FungibleTokensMetadataList + */ + results: Array; +} + +export function FungibleTokensMetadataListFromJSON(json: any): FungibleTokensMetadataList { + return FungibleTokensMetadataListFromJSONTyped(json, false); +} + +export function FungibleTokensMetadataListFromJSONTyped(json: any, ignoreDiscriminator: boolean): FungibleTokensMetadataList { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': ((json['results'] as Array).map(FungibleTokenMetadataFromJSON)), + }; +} + +export function FungibleTokensMetadataListToJSON(value?: FungibleTokensMetadataList | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': ((value.results as Array).map(FungibleTokenMetadataToJSON)), + }; +} + diff --git a/client/src/generated/models/GetRawTransactionResult.ts b/client/src/generated/models/GetRawTransactionResult.ts new file mode 100644 index 0000000000..c43bf46498 --- /dev/null +++ b/client/src/generated/models/GetRawTransactionResult.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * GET raw transaction + * @export + * @interface GetRawTransactionResult + */ +export interface GetRawTransactionResult { + /** + * A hex encoded serialized transaction + * @type {string} + * @memberof GetRawTransactionResult + */ + raw_tx: string; +} + +export function GetRawTransactionResultFromJSON(json: any): GetRawTransactionResult { + return GetRawTransactionResultFromJSONTyped(json, false); +} + +export function GetRawTransactionResultFromJSONTyped(json: any, ignoreDiscriminator: boolean): GetRawTransactionResult { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'raw_tx': json['raw_tx'], + }; +} + +export function GetRawTransactionResultToJSON(value?: GetRawTransactionResult | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'raw_tx': value.raw_tx, + }; +} + diff --git a/client/src/generated/models/GetStxSupplyLegacyFormatResponse.ts b/client/src/generated/models/GetStxSupplyLegacyFormatResponse.ts new file mode 100644 index 0000000000..4e0aad3d4a --- /dev/null +++ b/client/src/generated/models/GetStxSupplyLegacyFormatResponse.ts @@ -0,0 +1,96 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * GET request that returns network target block times + * @export + * @interface GetStxSupplyLegacyFormatResponse + */ +export interface GetStxSupplyLegacyFormatResponse { + /** + * String quoted decimal number of the percentage of STX that have unlocked + * @type {string} + * @memberof GetStxSupplyLegacyFormatResponse + */ + unlockedPercent: string; + /** + * String quoted decimal number of the total possible number of STX + * @type {string} + * @memberof GetStxSupplyLegacyFormatResponse + */ + totalStacks: string; + /** + * Same as `totalStacks` but formatted with comma thousands separators + * @type {string} + * @memberof GetStxSupplyLegacyFormatResponse + */ + totalStacksFormatted: string; + /** + * String quoted decimal number of the STX that have been mined or unlocked + * @type {string} + * @memberof GetStxSupplyLegacyFormatResponse + */ + unlockedSupply: string; + /** + * Same as `unlockedSupply` but formatted with comma thousands separators + * @type {string} + * @memberof GetStxSupplyLegacyFormatResponse + */ + unlockedSupplyFormatted: string; + /** + * The block height at which this information was queried + * @type {string} + * @memberof GetStxSupplyLegacyFormatResponse + */ + blockHeight: string; +} + +export function GetStxSupplyLegacyFormatResponseFromJSON(json: any): GetStxSupplyLegacyFormatResponse { + return GetStxSupplyLegacyFormatResponseFromJSONTyped(json, false); +} + +export function GetStxSupplyLegacyFormatResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): GetStxSupplyLegacyFormatResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'unlockedPercent': json['unlockedPercent'], + 'totalStacks': json['totalStacks'], + 'totalStacksFormatted': json['totalStacksFormatted'], + 'unlockedSupply': json['unlockedSupply'], + 'unlockedSupplyFormatted': json['unlockedSupplyFormatted'], + 'blockHeight': json['blockHeight'], + }; +} + +export function GetStxSupplyLegacyFormatResponseToJSON(value?: GetStxSupplyLegacyFormatResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'unlockedPercent': value.unlockedPercent, + 'totalStacks': value.totalStacks, + 'totalStacksFormatted': value.totalStacksFormatted, + 'unlockedSupply': value.unlockedSupply, + 'unlockedSupplyFormatted': value.unlockedSupplyFormatted, + 'blockHeight': value.blockHeight, + }; +} + diff --git a/client/src/generated/models/GetStxSupplyResponse.ts b/client/src/generated/models/GetStxSupplyResponse.ts new file mode 100644 index 0000000000..b9928b3de0 --- /dev/null +++ b/client/src/generated/models/GetStxSupplyResponse.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * GET request that returns network target block times + * @export + * @interface GetStxSupplyResponse + */ +export interface GetStxSupplyResponse { + /** + * String quoted decimal number of the percentage of STX that have unlocked + * @type {string} + * @memberof GetStxSupplyResponse + */ + unlocked_percent: string; + /** + * String quoted decimal number of the total possible number of STX + * @type {string} + * @memberof GetStxSupplyResponse + */ + total_stx: string; + /** + * String quoted decimal number of the STX that have been mined or unlocked + * @type {string} + * @memberof GetStxSupplyResponse + */ + unlocked_stx: string; + /** + * The block height at which this information was queried + * @type {number} + * @memberof GetStxSupplyResponse + */ + block_height: number; +} + +export function GetStxSupplyResponseFromJSON(json: any): GetStxSupplyResponse { + return GetStxSupplyResponseFromJSONTyped(json, false); +} + +export function GetStxSupplyResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): GetStxSupplyResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'unlocked_percent': json['unlocked_percent'], + 'total_stx': json['total_stx'], + 'unlocked_stx': json['unlocked_stx'], + 'block_height': json['block_height'], + }; +} + +export function GetStxSupplyResponseToJSON(value?: GetStxSupplyResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'unlocked_percent': value.unlocked_percent, + 'total_stx': value.total_stx, + 'unlocked_stx': value.unlocked_stx, + 'block_height': value.block_height, + }; +} + diff --git a/client/src/generated/models/InboundStxTransfer.ts b/client/src/generated/models/InboundStxTransfer.ts new file mode 100644 index 0000000000..4efee836f1 --- /dev/null +++ b/client/src/generated/models/InboundStxTransfer.ts @@ -0,0 +1,114 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * A inbound STX transfer with a memo + * @export + * @interface InboundStxTransfer + */ +export interface InboundStxTransfer { + /** + * Principal that sent this transfer + * @type {string} + * @memberof InboundStxTransfer + */ + sender: string; + /** + * Transfer amount in micro-STX as integer string + * @type {string} + * @memberof InboundStxTransfer + */ + amount: string; + /** + * Hex encoded memo bytes associated with the transfer + * @type {string} + * @memberof InboundStxTransfer + */ + memo: string; + /** + * Block height at which this transfer occurred + * @type {number} + * @memberof InboundStxTransfer + */ + block_height: number; + /** + * The transaction ID in which this transfer occurred + * @type {string} + * @memberof InboundStxTransfer + */ + tx_id: string; + /** + * Indicates if the transfer is from a stx-transfer transaction or a contract-call transaction + * @type {string} + * @memberof InboundStxTransfer + */ + transfer_type: InboundStxTransferTransferTypeEnum; + /** + * Index of the transaction within a block + * @type {number} + * @memberof InboundStxTransfer + */ + tx_index: number; +} + +/** +* @export +* @enum {string} +*/ +export enum InboundStxTransferTransferTypeEnum { + bulk_send = 'bulk-send', + stx_transfer = 'stx-transfer', + stx_transfer_memo = 'stx-transfer-memo' +} + +export function InboundStxTransferFromJSON(json: any): InboundStxTransfer { + return InboundStxTransferFromJSONTyped(json, false); +} + +export function InboundStxTransferFromJSONTyped(json: any, ignoreDiscriminator: boolean): InboundStxTransfer { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'sender': json['sender'], + 'amount': json['amount'], + 'memo': json['memo'], + 'block_height': json['block_height'], + 'tx_id': json['tx_id'], + 'transfer_type': json['transfer_type'], + 'tx_index': json['tx_index'], + }; +} + +export function InboundStxTransferToJSON(value?: InboundStxTransfer | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'sender': value.sender, + 'amount': value.amount, + 'memo': value.memo, + 'block_height': value.block_height, + 'tx_id': value.tx_id, + 'transfer_type': value.transfer_type, + 'tx_index': value.tx_index, + }; +} + diff --git a/client/src/generated/models/InlineObject.ts b/client/src/generated/models/InlineObject.ts new file mode 100644 index 0000000000..1ce31af828 --- /dev/null +++ b/client/src/generated/models/InlineObject.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface InlineObject + */ +export interface InlineObject { + /** + * BTC testnet address + * @type {string} + * @memberof InlineObject + */ + address?: string; +} + +export function InlineObjectFromJSON(json: any): InlineObject { + return InlineObjectFromJSONTyped(json, false); +} + +export function InlineObjectFromJSONTyped(json: any, ignoreDiscriminator: boolean): InlineObject { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'address': !exists(json, 'address') ? undefined : json['address'], + }; +} + +export function InlineObjectToJSON(value?: InlineObject | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'address': value.address, + }; +} + diff --git a/client/src/generated/models/InlineResponse403.ts b/client/src/generated/models/InlineResponse403.ts new file mode 100644 index 0000000000..7e8bbd4333 --- /dev/null +++ b/client/src/generated/models/InlineResponse403.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface InlineResponse403 + */ +export interface InlineResponse403 { + /** + * + * @type {string} + * @memberof InlineResponse403 + */ + error?: string; + /** + * + * @type {boolean} + * @memberof InlineResponse403 + */ + success?: boolean; +} + +export function InlineResponse403FromJSON(json: any): InlineResponse403 { + return InlineResponse403FromJSONTyped(json, false); +} + +export function InlineResponse403FromJSONTyped(json: any, ignoreDiscriminator: boolean): InlineResponse403 { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'error': !exists(json, 'error') ? undefined : json['error'], + 'success': !exists(json, 'success') ? undefined : json['success'], + }; +} + +export function InlineResponse403ToJSON(value?: InlineResponse403 | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'error': value.error, + 'success': value.success, + }; +} + diff --git a/client/src/generated/models/MapEntryResponse.ts b/client/src/generated/models/MapEntryResponse.ts index 700c3a5584..7a709eb570 100644 --- a/client/src/generated/models/MapEntryResponse.ts +++ b/client/src/generated/models/MapEntryResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function MapEntryResponseToJSON(value?: MapEntryResponse | null): any { }; } - diff --git a/client/src/generated/models/MempoolFeePriorities.ts b/client/src/generated/models/MempoolFeePriorities.ts new file mode 100644 index 0000000000..f59cd3ce9b --- /dev/null +++ b/client/src/generated/models/MempoolFeePriorities.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + MempoolFeePrioritiesAll, + MempoolFeePrioritiesAllFromJSON, + MempoolFeePrioritiesAllFromJSONTyped, + MempoolFeePrioritiesAllToJSON, +} from './'; + +/** + * GET request that returns fee priorities from mempool transactions + * @export + * @interface MempoolFeePriorities + */ +export interface MempoolFeePriorities { + /** + * + * @type {MempoolFeePrioritiesAll} + * @memberof MempoolFeePriorities + */ + all: MempoolFeePrioritiesAll; + /** + * + * @type {MempoolFeePrioritiesAll} + * @memberof MempoolFeePriorities + */ + token_transfer?: MempoolFeePrioritiesAll; + /** + * + * @type {MempoolFeePrioritiesAll} + * @memberof MempoolFeePriorities + */ + smart_contract?: MempoolFeePrioritiesAll; + /** + * + * @type {MempoolFeePrioritiesAll} + * @memberof MempoolFeePriorities + */ + contract_call?: MempoolFeePrioritiesAll; +} + +export function MempoolFeePrioritiesFromJSON(json: any): MempoolFeePriorities { + return MempoolFeePrioritiesFromJSONTyped(json, false); +} + +export function MempoolFeePrioritiesFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolFeePriorities { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'all': MempoolFeePrioritiesAllFromJSON(json['all']), + 'token_transfer': !exists(json, 'token_transfer') ? undefined : MempoolFeePrioritiesAllFromJSON(json['token_transfer']), + 'smart_contract': !exists(json, 'smart_contract') ? undefined : MempoolFeePrioritiesAllFromJSON(json['smart_contract']), + 'contract_call': !exists(json, 'contract_call') ? undefined : MempoolFeePrioritiesAllFromJSON(json['contract_call']), + }; +} + +export function MempoolFeePrioritiesToJSON(value?: MempoolFeePriorities | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'all': MempoolFeePrioritiesAllToJSON(value.all), + 'token_transfer': MempoolFeePrioritiesAllToJSON(value.token_transfer), + 'smart_contract': MempoolFeePrioritiesAllToJSON(value.smart_contract), + 'contract_call': MempoolFeePrioritiesAllToJSON(value.contract_call), + }; +} + diff --git a/client/src/generated/models/MempoolFeePrioritiesAll.ts b/client/src/generated/models/MempoolFeePrioritiesAll.ts new file mode 100644 index 0000000000..ff361674b7 --- /dev/null +++ b/client/src/generated/models/MempoolFeePrioritiesAll.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface MempoolFeePrioritiesAll + */ +export interface MempoolFeePrioritiesAll { + /** + * + * @type {number} + * @memberof MempoolFeePrioritiesAll + */ + no_priority: number; + /** + * + * @type {number} + * @memberof MempoolFeePrioritiesAll + */ + low_priority: number; + /** + * + * @type {number} + * @memberof MempoolFeePrioritiesAll + */ + medium_priority: number; + /** + * + * @type {number} + * @memberof MempoolFeePrioritiesAll + */ + high_priority: number; +} + +export function MempoolFeePrioritiesAllFromJSON(json: any): MempoolFeePrioritiesAll { + return MempoolFeePrioritiesAllFromJSONTyped(json, false); +} + +export function MempoolFeePrioritiesAllFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolFeePrioritiesAll { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'no_priority': json['no_priority'], + 'low_priority': json['low_priority'], + 'medium_priority': json['medium_priority'], + 'high_priority': json['high_priority'], + }; +} + +export function MempoolFeePrioritiesAllToJSON(value?: MempoolFeePrioritiesAll | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'no_priority': value.no_priority, + 'low_priority': value.low_priority, + 'medium_priority': value.medium_priority, + 'high_priority': value.high_priority, + }; +} + diff --git a/client/src/generated/models/MempoolTransactionListResponse.ts b/client/src/generated/models/MempoolTransactionListResponse.ts index 8b42e12e2c..c832556344 100644 --- a/client/src/generated/models/MempoolTransactionListResponse.ts +++ b/client/src/generated/models/MempoolTransactionListResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -78,4 +78,3 @@ export function MempoolTransactionListResponseToJSON(value?: MempoolTransactionL }; } - diff --git a/client/src/generated/models/MempoolTransactionStatsResponse.ts b/client/src/generated/models/MempoolTransactionStatsResponse.ts new file mode 100644 index 0000000000..42c0a28612 --- /dev/null +++ b/client/src/generated/models/MempoolTransactionStatsResponse.ts @@ -0,0 +1,99 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + MempoolTransactionStatsResponseTxAges, + MempoolTransactionStatsResponseTxAgesFromJSON, + MempoolTransactionStatsResponseTxAgesFromJSONTyped, + MempoolTransactionStatsResponseTxAgesToJSON, + MempoolTransactionStatsResponseTxByteSizes, + MempoolTransactionStatsResponseTxByteSizesFromJSON, + MempoolTransactionStatsResponseTxByteSizesFromJSONTyped, + MempoolTransactionStatsResponseTxByteSizesToJSON, + MempoolTransactionStatsResponseTxSimpleFeeAverages, + MempoolTransactionStatsResponseTxSimpleFeeAveragesFromJSON, + MempoolTransactionStatsResponseTxSimpleFeeAveragesFromJSONTyped, + MempoolTransactionStatsResponseTxSimpleFeeAveragesToJSON, + MempoolTransactionStatsResponseTxTypeCounts, + MempoolTransactionStatsResponseTxTypeCountsFromJSON, + MempoolTransactionStatsResponseTxTypeCountsFromJSONTyped, + MempoolTransactionStatsResponseTxTypeCountsToJSON, +} from './'; + +/** + * GET request that returns stats on mempool transactions + * @export + * @interface MempoolTransactionStatsResponse + */ +export interface MempoolTransactionStatsResponse { + /** + * + * @type {MempoolTransactionStatsResponseTxTypeCounts} + * @memberof MempoolTransactionStatsResponse + */ + tx_type_counts: MempoolTransactionStatsResponseTxTypeCounts; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAverages} + * @memberof MempoolTransactionStatsResponse + */ + tx_simple_fee_averages: MempoolTransactionStatsResponseTxSimpleFeeAverages; + /** + * + * @type {MempoolTransactionStatsResponseTxAges} + * @memberof MempoolTransactionStatsResponse + */ + tx_ages: MempoolTransactionStatsResponseTxAges; + /** + * + * @type {MempoolTransactionStatsResponseTxByteSizes} + * @memberof MempoolTransactionStatsResponse + */ + tx_byte_sizes: MempoolTransactionStatsResponseTxByteSizes; +} + +export function MempoolTransactionStatsResponseFromJSON(json: any): MempoolTransactionStatsResponse { + return MempoolTransactionStatsResponseFromJSONTyped(json, false); +} + +export function MempoolTransactionStatsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolTransactionStatsResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'tx_type_counts': MempoolTransactionStatsResponseTxTypeCountsFromJSON(json['tx_type_counts']), + 'tx_simple_fee_averages': MempoolTransactionStatsResponseTxSimpleFeeAveragesFromJSON(json['tx_simple_fee_averages']), + 'tx_ages': MempoolTransactionStatsResponseTxAgesFromJSON(json['tx_ages']), + 'tx_byte_sizes': MempoolTransactionStatsResponseTxByteSizesFromJSON(json['tx_byte_sizes']), + }; +} + +export function MempoolTransactionStatsResponseToJSON(value?: MempoolTransactionStatsResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'tx_type_counts': MempoolTransactionStatsResponseTxTypeCountsToJSON(value.tx_type_counts), + 'tx_simple_fee_averages': MempoolTransactionStatsResponseTxSimpleFeeAveragesToJSON(value.tx_simple_fee_averages), + 'tx_ages': MempoolTransactionStatsResponseTxAgesToJSON(value.tx_ages), + 'tx_byte_sizes': MempoolTransactionStatsResponseTxByteSizesToJSON(value.tx_byte_sizes), + }; +} + diff --git a/client/src/generated/models/MempoolTransactionStatsResponseTxAges.ts b/client/src/generated/models/MempoolTransactionStatsResponseTxAges.ts new file mode 100644 index 0000000000..46e2ba5d29 --- /dev/null +++ b/client/src/generated/models/MempoolTransactionStatsResponseTxAges.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSONTyped, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON, +} from './'; + +/** + * The average time (in blocks) that transactions have lived in the mempool. The start block height is simply the current chain-tip of when the attached Stacks node receives the transaction. This timing can be different across Stacks nodes / API instances due to propagation timing differences in the p2p network. + * @export + * @interface MempoolTransactionStatsResponseTxAges + */ +export interface MempoolTransactionStatsResponseTxAges { + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxAges + */ + token_transfer: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxAges + */ + smart_contract: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxAges + */ + contract_call: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxAges + */ + poison_microblock: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; +} + +export function MempoolTransactionStatsResponseTxAgesFromJSON(json: any): MempoolTransactionStatsResponseTxAges { + return MempoolTransactionStatsResponseTxAgesFromJSONTyped(json, false); +} + +export function MempoolTransactionStatsResponseTxAgesFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolTransactionStatsResponseTxAges { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'token_transfer': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['token_transfer']), + 'smart_contract': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['smart_contract']), + 'contract_call': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['contract_call']), + 'poison_microblock': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['poison_microblock']), + }; +} + +export function MempoolTransactionStatsResponseTxAgesToJSON(value?: MempoolTransactionStatsResponseTxAges | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'token_transfer': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.token_transfer), + 'smart_contract': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.smart_contract), + 'contract_call': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.contract_call), + 'poison_microblock': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.poison_microblock), + }; +} + diff --git a/client/src/generated/models/MempoolTransactionStatsResponseTxByteSizes.ts b/client/src/generated/models/MempoolTransactionStatsResponseTxByteSizes.ts new file mode 100644 index 0000000000..7978098c52 --- /dev/null +++ b/client/src/generated/models/MempoolTransactionStatsResponseTxByteSizes.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSONTyped, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON, +} from './'; + +/** + * The average byte size of transactions in the mempool, broken down by transaction type. + * @export + * @interface MempoolTransactionStatsResponseTxByteSizes + */ +export interface MempoolTransactionStatsResponseTxByteSizes { + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxByteSizes + */ + token_transfer: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxByteSizes + */ + smart_contract: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxByteSizes + */ + contract_call: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxByteSizes + */ + poison_microblock: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; +} + +export function MempoolTransactionStatsResponseTxByteSizesFromJSON(json: any): MempoolTransactionStatsResponseTxByteSizes { + return MempoolTransactionStatsResponseTxByteSizesFromJSONTyped(json, false); +} + +export function MempoolTransactionStatsResponseTxByteSizesFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolTransactionStatsResponseTxByteSizes { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'token_transfer': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['token_transfer']), + 'smart_contract': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['smart_contract']), + 'contract_call': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['contract_call']), + 'poison_microblock': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['poison_microblock']), + }; +} + +export function MempoolTransactionStatsResponseTxByteSizesToJSON(value?: MempoolTransactionStatsResponseTxByteSizes | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'token_transfer': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.token_transfer), + 'smart_contract': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.smart_contract), + 'contract_call': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.contract_call), + 'poison_microblock': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.poison_microblock), + }; +} + diff --git a/client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAverages.ts b/client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAverages.ts new file mode 100644 index 0000000000..567b4242cd --- /dev/null +++ b/client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAverages.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSONTyped, + MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON, +} from './'; + +/** + * The simple mean (average) transaction fee, broken down by transaction type. Note that this does not factor in actual execution costs. The average fee is not a reliable metric for calculating a fee for a new transaction. + * @export + * @interface MempoolTransactionStatsResponseTxSimpleFeeAverages + */ +export interface MempoolTransactionStatsResponseTxSimpleFeeAverages { + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAverages + */ + token_transfer: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAverages + */ + smart_contract: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAverages + */ + contract_call: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; + /** + * + * @type {MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAverages + */ + poison_microblock: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer; +} + +export function MempoolTransactionStatsResponseTxSimpleFeeAveragesFromJSON(json: any): MempoolTransactionStatsResponseTxSimpleFeeAverages { + return MempoolTransactionStatsResponseTxSimpleFeeAveragesFromJSONTyped(json, false); +} + +export function MempoolTransactionStatsResponseTxSimpleFeeAveragesFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolTransactionStatsResponseTxSimpleFeeAverages { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'token_transfer': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['token_transfer']), + 'smart_contract': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['smart_contract']), + 'contract_call': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['contract_call']), + 'poison_microblock': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json['poison_microblock']), + }; +} + +export function MempoolTransactionStatsResponseTxSimpleFeeAveragesToJSON(value?: MempoolTransactionStatsResponseTxSimpleFeeAverages | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'token_transfer': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.token_transfer), + 'smart_contract': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.smart_contract), + 'contract_call': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.contract_call), + 'poison_microblock': MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value.poison_microblock), + }; +} + diff --git a/client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer.ts b/client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer.ts new file mode 100644 index 0000000000..b1fb3a49b8 --- /dev/null +++ b/client/src/generated/models/MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer + */ +export interface MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer { + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer + */ + p25: number | null; + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer + */ + p50: number | null; + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer + */ + p75: number | null; + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer + */ + p95: number | null; +} + +export function MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSON(json: any): MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer { + return MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSONTyped(json, false); +} + +export function MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'p25': json['p25'], + 'p50': json['p50'], + 'p75': json['p75'], + 'p95': json['p95'], + }; +} + +export function MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransferToJSON(value?: MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'p25': value.p25, + 'p50': value.p50, + 'p75': value.p75, + 'p95': value.p95, + }; +} + diff --git a/client/src/generated/models/MempoolTransactionStatsResponseTxTypeCounts.ts b/client/src/generated/models/MempoolTransactionStatsResponseTxTypeCounts.ts new file mode 100644 index 0000000000..4527e4b902 --- /dev/null +++ b/client/src/generated/models/MempoolTransactionStatsResponseTxTypeCounts.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Number of tranasction in the mempool, broken down by transaction type. + * @export + * @interface MempoolTransactionStatsResponseTxTypeCounts + */ +export interface MempoolTransactionStatsResponseTxTypeCounts { + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxTypeCounts + */ + token_transfer: number; + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxTypeCounts + */ + smart_contract: number; + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxTypeCounts + */ + contract_call: number; + /** + * + * @type {number} + * @memberof MempoolTransactionStatsResponseTxTypeCounts + */ + poison_microblock: number; +} + +export function MempoolTransactionStatsResponseTxTypeCountsFromJSON(json: any): MempoolTransactionStatsResponseTxTypeCounts { + return MempoolTransactionStatsResponseTxTypeCountsFromJSONTyped(json, false); +} + +export function MempoolTransactionStatsResponseTxTypeCountsFromJSONTyped(json: any, ignoreDiscriminator: boolean): MempoolTransactionStatsResponseTxTypeCounts { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'token_transfer': json['token_transfer'], + 'smart_contract': json['smart_contract'], + 'contract_call': json['contract_call'], + 'poison_microblock': json['poison_microblock'], + }; +} + +export function MempoolTransactionStatsResponseTxTypeCountsToJSON(value?: MempoolTransactionStatsResponseTxTypeCounts | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'token_transfer': value.token_transfer, + 'smart_contract': value.smart_contract, + 'contract_call': value.contract_call, + 'poison_microblock': value.poison_microblock, + }; +} + diff --git a/client/src/generated/models/Microblock.ts b/client/src/generated/models/Microblock.ts new file mode 100644 index 0000000000..ecafb1782a --- /dev/null +++ b/client/src/generated/models/Microblock.ts @@ -0,0 +1,160 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * A microblock + * @export + * @interface Microblock + */ +export interface Microblock { + /** + * Set to `true` if the microblock corresponds to the canonical chain tip. + * @type {boolean} + * @memberof Microblock + */ + canonical: boolean; + /** + * Set to `true` if the microblock was not orphaned in a following anchor block. Defaults to `true` if the following anchor block has not yet been created. + * @type {boolean} + * @memberof Microblock + */ + microblock_canonical: boolean; + /** + * The SHA512/256 hash of this microblock. + * @type {string} + * @memberof Microblock + */ + microblock_hash: string; + /** + * A hint to describe how to order a set of microblocks. Starts at 0. + * @type {number} + * @memberof Microblock + */ + microblock_sequence: number; + /** + * The SHA512/256 hash of the previous signed microblock in this stream. + * @type {string} + * @memberof Microblock + */ + microblock_parent_hash: string; + /** + * The anchor block height that confirmed this microblock. + * @type {number} + * @memberof Microblock + */ + block_height: number; + /** + * The height of the anchor block that preceded this microblock. + * @type {number} + * @memberof Microblock + */ + parent_block_height: number; + /** + * The hash of the anchor block that preceded this microblock. + * @type {string} + * @memberof Microblock + */ + parent_block_hash: string; + /** + * The hash of the Bitcoin block that preceded this microblock. + * @type {string} + * @memberof Microblock + */ + parent_burn_block_hash: string; + /** + * The block timestamp of the Bitcoin block that preceded this microblock. + * @type {number} + * @memberof Microblock + */ + parent_burn_block_time: number; + /** + * The ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) formatted block time of the bitcoin block that preceded this microblock. + * @type {string} + * @memberof Microblock + */ + parent_burn_block_time_iso: string; + /** + * The height of the Bitcoin block that preceded this microblock. + * @type {number} + * @memberof Microblock + */ + parent_burn_block_height: number; + /** + * The hash of the anchor block that confirmed this microblock. This wil be empty for unanchored microblocks + * @type {string} + * @memberof Microblock + */ + block_hash: string | null; + /** + * List of transactions included in the microblock + * @type {Array} + * @memberof Microblock + */ + txs: Array; +} + +export function MicroblockFromJSON(json: any): Microblock { + return MicroblockFromJSONTyped(json, false); +} + +export function MicroblockFromJSONTyped(json: any, ignoreDiscriminator: boolean): Microblock { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'canonical': json['canonical'], + 'microblock_canonical': json['microblock_canonical'], + 'microblock_hash': json['microblock_hash'], + 'microblock_sequence': json['microblock_sequence'], + 'microblock_parent_hash': json['microblock_parent_hash'], + 'block_height': json['block_height'], + 'parent_block_height': json['parent_block_height'], + 'parent_block_hash': json['parent_block_hash'], + 'parent_burn_block_hash': json['parent_burn_block_hash'], + 'parent_burn_block_time': json['parent_burn_block_time'], + 'parent_burn_block_time_iso': json['parent_burn_block_time_iso'], + 'parent_burn_block_height': json['parent_burn_block_height'], + 'block_hash': json['block_hash'], + 'txs': json['txs'], + }; +} + +export function MicroblockToJSON(value?: Microblock | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'canonical': value.canonical, + 'microblock_canonical': value.microblock_canonical, + 'microblock_hash': value.microblock_hash, + 'microblock_sequence': value.microblock_sequence, + 'microblock_parent_hash': value.microblock_parent_hash, + 'block_height': value.block_height, + 'parent_block_height': value.parent_block_height, + 'parent_block_hash': value.parent_block_hash, + 'parent_burn_block_hash': value.parent_burn_block_hash, + 'parent_burn_block_time': value.parent_burn_block_time, + 'parent_burn_block_time_iso': value.parent_burn_block_time_iso, + 'parent_burn_block_height': value.parent_burn_block_height, + 'block_hash': value.block_hash, + 'txs': value.txs, + }; +} + diff --git a/client/src/generated/models/MicroblockListResponse.ts b/client/src/generated/models/MicroblockListResponse.ts new file mode 100644 index 0000000000..70865e8f68 --- /dev/null +++ b/client/src/generated/models/MicroblockListResponse.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + Microblock, + MicroblockFromJSON, + MicroblockFromJSONTyped, + MicroblockToJSON, +} from './'; + +/** + * GET request that returns microblocks + * @export + * @interface MicroblockListResponse + */ +export interface MicroblockListResponse { + /** + * The number of microblocks to return + * @type {number} + * @memberof MicroblockListResponse + */ + limit: number; + /** + * The number to microblocks to skip (starting at `0`) + * @type {number} + * @memberof MicroblockListResponse + */ + offset: number; + /** + * The number of microblocks available + * @type {number} + * @memberof MicroblockListResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof MicroblockListResponse + */ + results: Array; +} + +export function MicroblockListResponseFromJSON(json: any): MicroblockListResponse { + return MicroblockListResponseFromJSONTyped(json, false); +} + +export function MicroblockListResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): MicroblockListResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': ((json['results'] as Array).map(MicroblockFromJSON)), + }; +} + +export function MicroblockListResponseToJSON(value?: MicroblockListResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': ((value.results as Array).map(MicroblockToJSON)), + }; +} + diff --git a/client/src/generated/models/NetworkBlockTimeResponse.ts b/client/src/generated/models/NetworkBlockTimeResponse.ts index edfaffadd8..245838cb94 100644 --- a/client/src/generated/models/NetworkBlockTimeResponse.ts +++ b/client/src/generated/models/NetworkBlockTimeResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -54,4 +54,3 @@ export function NetworkBlockTimeResponseToJSON(value?: NetworkBlockTimeResponse }; } - diff --git a/client/src/generated/models/NetworkBlockTimesResponse.ts b/client/src/generated/models/NetworkBlockTimesResponse.ts index e6042cc236..2471adcbbc 100644 --- a/client/src/generated/models/NetworkBlockTimesResponse.ts +++ b/client/src/generated/models/NetworkBlockTimesResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,10 +14,10 @@ import { exists, mapValues } from '../runtime'; import { - NetworkBlockTimesResponseMainnet, - NetworkBlockTimesResponseMainnetFromJSON, - NetworkBlockTimesResponseMainnetFromJSONTyped, - NetworkBlockTimesResponseMainnetToJSON, + TargetBlockTime, + TargetBlockTimeFromJSON, + TargetBlockTimeFromJSONTyped, + TargetBlockTimeToJSON, } from './'; /** @@ -28,16 +28,16 @@ import { export interface NetworkBlockTimesResponse { /** * - * @type {NetworkBlockTimesResponseMainnet} + * @type {TargetBlockTime} * @memberof NetworkBlockTimesResponse */ - mainnet: NetworkBlockTimesResponseMainnet; + mainnet: TargetBlockTime; /** * - * @type {NetworkBlockTimesResponseMainnet} + * @type {TargetBlockTime} * @memberof NetworkBlockTimesResponse */ - testnet: NetworkBlockTimesResponseMainnet; + testnet: TargetBlockTime; } export function NetworkBlockTimesResponseFromJSON(json: any): NetworkBlockTimesResponse { @@ -50,8 +50,8 @@ export function NetworkBlockTimesResponseFromJSONTyped(json: any, ignoreDiscrimi } return { - 'mainnet': NetworkBlockTimesResponseMainnetFromJSON(json['mainnet']), - 'testnet': NetworkBlockTimesResponseMainnetFromJSON(json['testnet']), + 'mainnet': TargetBlockTimeFromJSON(json['mainnet']), + 'testnet': TargetBlockTimeFromJSON(json['testnet']), }; } @@ -64,9 +64,8 @@ export function NetworkBlockTimesResponseToJSON(value?: NetworkBlockTimesRespons } return { - 'mainnet': NetworkBlockTimesResponseMainnetToJSON(value.mainnet), - 'testnet': NetworkBlockTimesResponseMainnetToJSON(value.testnet), + 'mainnet': TargetBlockTimeToJSON(value.mainnet), + 'testnet': TargetBlockTimeToJSON(value.testnet), }; } - diff --git a/client/src/generated/models/NetworkBlockTimesResponseMainnet.ts b/client/src/generated/models/NetworkBlockTimesResponseMainnet.ts deleted file mode 100644 index ffdbdf25a1..0000000000 --- a/client/src/generated/models/NetworkBlockTimesResponseMainnet.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) - * - * The version of the OpenAPI document: 1.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * TargetBlockTime - * @export - * @interface NetworkBlockTimesResponseMainnet - */ -export interface NetworkBlockTimesResponseMainnet { - /** - * - * @type {number} - * @memberof NetworkBlockTimesResponseMainnet - */ - target_block_time: number; -} - -export function NetworkBlockTimesResponseMainnetFromJSON(json: any): NetworkBlockTimesResponseMainnet { - return NetworkBlockTimesResponseMainnetFromJSONTyped(json, false); -} - -export function NetworkBlockTimesResponseMainnetFromJSONTyped(json: any, ignoreDiscriminator: boolean): NetworkBlockTimesResponseMainnet { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'target_block_time': json['target_block_time'], - }; -} - -export function NetworkBlockTimesResponseMainnetToJSON(value?: NetworkBlockTimesResponseMainnet | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'target_block_time': value.target_block_time, - }; -} - - diff --git a/client/src/generated/models/NetworkIdentifier.ts b/client/src/generated/models/NetworkIdentifier.ts index 85e2e18a54..cb5dacde67 100644 --- a/client/src/generated/models/NetworkIdentifier.ts +++ b/client/src/generated/models/NetworkIdentifier.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -77,4 +77,3 @@ export function NetworkIdentifierToJSON(value?: NetworkIdentifier | null): any { }; } - diff --git a/client/src/generated/models/NftEvent.ts b/client/src/generated/models/NftEvent.ts new file mode 100644 index 0000000000..d6b73f8ba1 --- /dev/null +++ b/client/src/generated/models/NftEvent.ts @@ -0,0 +1,127 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + AddressNftListResponseValue, + AddressNftListResponseValueFromJSON, + AddressNftListResponseValueFromJSONTyped, + AddressNftListResponseValueToJSON, +} from './'; + +/** + * + * @export + * @interface NftEvent + */ +export interface NftEvent { + /** + * + * @type {string} + * @memberof NftEvent + */ + sender?: string; + /** + * + * @type {string} + * @memberof NftEvent + */ + recipient?: string; + /** + * + * @type {string} + * @memberof NftEvent + */ + asset_identifier: string; + /** + * + * @type {string} + * @memberof NftEvent + */ + asset_event_type: string; + /** + * + * @type {AddressNftListResponseValue} + * @memberof NftEvent + */ + value: AddressNftListResponseValue; + /** + * + * @type {string} + * @memberof NftEvent + */ + tx_id: string; + /** + * + * @type {number} + * @memberof NftEvent + */ + tx_index: number; + /** + * + * @type {number} + * @memberof NftEvent + */ + block_height: number; + /** + * + * @type {number} + * @memberof NftEvent + */ + event_index: number; +} + +export function NftEventFromJSON(json: any): NftEvent { + return NftEventFromJSONTyped(json, false); +} + +export function NftEventFromJSONTyped(json: any, ignoreDiscriminator: boolean): NftEvent { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'sender': !exists(json, 'sender') ? undefined : json['sender'], + 'recipient': !exists(json, 'recipient') ? undefined : json['recipient'], + 'asset_identifier': json['asset_identifier'], + 'asset_event_type': json['asset_event_type'], + 'value': AddressNftListResponseValueFromJSON(json['value']), + 'tx_id': json['tx_id'], + 'tx_index': json['tx_index'], + 'block_height': json['block_height'], + 'event_index': json['event_index'], + }; +} + +export function NftEventToJSON(value?: NftEvent | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'sender': value.sender, + 'recipient': value.recipient, + 'asset_identifier': value.asset_identifier, + 'asset_event_type': value.asset_event_type, + 'value': AddressNftListResponseValueToJSON(value.value), + 'tx_id': value.tx_id, + 'tx_index': value.tx_index, + 'block_height': value.block_height, + 'event_index': value.event_index, + }; +} + diff --git a/client/src/generated/models/NonFungibleTokenHistoryEventList.ts b/client/src/generated/models/NonFungibleTokenHistoryEventList.ts new file mode 100644 index 0000000000..bfbbd26d9f --- /dev/null +++ b/client/src/generated/models/NonFungibleTokenHistoryEventList.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * List of Non-Fungible Token history events + * @export + * @interface NonFungibleTokenHistoryEventList + */ +export interface NonFungibleTokenHistoryEventList { + /** + * The number of events to return + * @type {number} + * @memberof NonFungibleTokenHistoryEventList + */ + limit: number; + /** + * The number to events to skip (starting at `0`) + * @type {number} + * @memberof NonFungibleTokenHistoryEventList + */ + offset: number; + /** + * The number of events available + * @type {number} + * @memberof NonFungibleTokenHistoryEventList + */ + total: number; + /** + * + * @type {Array} + * @memberof NonFungibleTokenHistoryEventList + */ + results: Array; +} + +export function NonFungibleTokenHistoryEventListFromJSON(json: any): NonFungibleTokenHistoryEventList { + return NonFungibleTokenHistoryEventListFromJSONTyped(json, false); +} + +export function NonFungibleTokenHistoryEventListFromJSONTyped(json: any, ignoreDiscriminator: boolean): NonFungibleTokenHistoryEventList { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': json['results'], + }; +} + +export function NonFungibleTokenHistoryEventListToJSON(value?: NonFungibleTokenHistoryEventList | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': value.results, + }; +} + diff --git a/client/src/generated/models/NonFungibleTokenHoldingsList.ts b/client/src/generated/models/NonFungibleTokenHoldingsList.ts new file mode 100644 index 0000000000..5f190e2264 --- /dev/null +++ b/client/src/generated/models/NonFungibleTokenHoldingsList.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * List of Non-Fungible Token holdings + * @export + * @interface NonFungibleTokenHoldingsList + */ +export interface NonFungibleTokenHoldingsList { + /** + * The number of Non-Fungible Token holdings to return + * @type {number} + * @memberof NonFungibleTokenHoldingsList + */ + limit: number; + /** + * The number to Non-Fungible Token holdings to skip (starting at `0`) + * @type {number} + * @memberof NonFungibleTokenHoldingsList + */ + offset: number; + /** + * The number of Non-Fungible Token holdings available + * @type {number} + * @memberof NonFungibleTokenHoldingsList + */ + total: number; + /** + * + * @type {Array} + * @memberof NonFungibleTokenHoldingsList + */ + results: Array; +} + +export function NonFungibleTokenHoldingsListFromJSON(json: any): NonFungibleTokenHoldingsList { + return NonFungibleTokenHoldingsListFromJSONTyped(json, false); +} + +export function NonFungibleTokenHoldingsListFromJSONTyped(json: any, ignoreDiscriminator: boolean): NonFungibleTokenHoldingsList { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': json['results'], + }; +} + +export function NonFungibleTokenHoldingsListToJSON(value?: NonFungibleTokenHoldingsList | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': value.results, + }; +} + diff --git a/client/src/generated/models/NonFungibleTokenMetadata.ts b/client/src/generated/models/NonFungibleTokenMetadata.ts new file mode 100644 index 0000000000..e64fbb2c67 --- /dev/null +++ b/client/src/generated/models/NonFungibleTokenMetadata.ts @@ -0,0 +1,104 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface NonFungibleTokenMetadata + */ +export interface NonFungibleTokenMetadata { + /** + * An optional string that is a valid URI which resolves to this token's metadata. Can be empty. + * @type {string} + * @memberof NonFungibleTokenMetadata + */ + token_uri: string; + /** + * Identifies the asset to which this token represents + * @type {string} + * @memberof NonFungibleTokenMetadata + */ + name: string; + /** + * Describes the asset to which this token represents + * @type {string} + * @memberof NonFungibleTokenMetadata + */ + description: string; + /** + * A URI pointing to a resource with mime type image/* representing the asset to which this token represents. The API may provide a URI to a cached resource, dependending on configuration. Otherwise, this can be the same value as the canonical image URI. + * @type {string} + * @memberof NonFungibleTokenMetadata + */ + image_uri: string; + /** + * The original image URI specified by the contract. A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive. + * @type {string} + * @memberof NonFungibleTokenMetadata + */ + image_canonical_uri: string; + /** + * Tx id that deployed the contract + * @type {string} + * @memberof NonFungibleTokenMetadata + */ + tx_id: string; + /** + * principle that deployed the contract + * @type {string} + * @memberof NonFungibleTokenMetadata + */ + sender_address: string; +} + +export function NonFungibleTokenMetadataFromJSON(json: any): NonFungibleTokenMetadata { + return NonFungibleTokenMetadataFromJSONTyped(json, false); +} + +export function NonFungibleTokenMetadataFromJSONTyped(json: any, ignoreDiscriminator: boolean): NonFungibleTokenMetadata { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'token_uri': json['token_uri'], + 'name': json['name'], + 'description': json['description'], + 'image_uri': json['image_uri'], + 'image_canonical_uri': json['image_canonical_uri'], + 'tx_id': json['tx_id'], + 'sender_address': json['sender_address'], + }; +} + +export function NonFungibleTokenMetadataToJSON(value?: NonFungibleTokenMetadata | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'token_uri': value.token_uri, + 'name': value.name, + 'description': value.description, + 'image_uri': value.image_uri, + 'image_canonical_uri': value.image_canonical_uri, + 'tx_id': value.tx_id, + 'sender_address': value.sender_address, + }; +} + diff --git a/client/src/generated/models/NonFungibleTokenMintList.ts b/client/src/generated/models/NonFungibleTokenMintList.ts new file mode 100644 index 0000000000..2e3b5a7579 --- /dev/null +++ b/client/src/generated/models/NonFungibleTokenMintList.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * List of Non-Fungible Token mint events for an asset identifier + * @export + * @interface NonFungibleTokenMintList + */ +export interface NonFungibleTokenMintList { + /** + * The number of mint events to return + * @type {number} + * @memberof NonFungibleTokenMintList + */ + limit: number; + /** + * The number to mint events to skip (starting at `0`) + * @type {number} + * @memberof NonFungibleTokenMintList + */ + offset: number; + /** + * The number of mint events available + * @type {number} + * @memberof NonFungibleTokenMintList + */ + total: number; + /** + * + * @type {Array} + * @memberof NonFungibleTokenMintList + */ + results: Array; +} + +export function NonFungibleTokenMintListFromJSON(json: any): NonFungibleTokenMintList { + return NonFungibleTokenMintListFromJSONTyped(json, false); +} + +export function NonFungibleTokenMintListFromJSONTyped(json: any, ignoreDiscriminator: boolean): NonFungibleTokenMintList { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': json['results'], + }; +} + +export function NonFungibleTokenMintListToJSON(value?: NonFungibleTokenMintList | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': value.results, + }; +} + diff --git a/client/src/generated/models/NonFungibleTokensMetadataList.ts b/client/src/generated/models/NonFungibleTokensMetadataList.ts new file mode 100644 index 0000000000..b9f20627c2 --- /dev/null +++ b/client/src/generated/models/NonFungibleTokensMetadataList.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + NonFungibleTokenMetadata, + NonFungibleTokenMetadataFromJSON, + NonFungibleTokenMetadataFromJSONTyped, + NonFungibleTokenMetadataToJSON, +} from './'; + +/** + * List of non fungible tokens metadata + * @export + * @interface NonFungibleTokensMetadataList + */ +export interface NonFungibleTokensMetadataList { + /** + * The number of tokens metadata to return + * @type {number} + * @memberof NonFungibleTokensMetadataList + */ + limit: number; + /** + * The number to tokens metadata to skip (starting at `0`) + * @type {number} + * @memberof NonFungibleTokensMetadataList + */ + offset: number; + /** + * The number of tokens metadata available + * @type {number} + * @memberof NonFungibleTokensMetadataList + */ + total: number; + /** + * + * @type {Array} + * @memberof NonFungibleTokensMetadataList + */ + results: Array; +} + +export function NonFungibleTokensMetadataListFromJSON(json: any): NonFungibleTokensMetadataList { + return NonFungibleTokensMetadataListFromJSONTyped(json, false); +} + +export function NonFungibleTokensMetadataListFromJSONTyped(json: any, ignoreDiscriminator: boolean): NonFungibleTokensMetadataList { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': ((json['results'] as Array).map(NonFungibleTokenMetadataFromJSON)), + }; +} + +export function NonFungibleTokensMetadataListToJSON(value?: NonFungibleTokensMetadataList | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': ((value.results as Array).map(NonFungibleTokenMetadataToJSON)), + }; +} + diff --git a/client/src/generated/models/OtherTransactionIdentifier.ts b/client/src/generated/models/OtherTransactionIdentifier.ts new file mode 100644 index 0000000000..fcaa8f0468 --- /dev/null +++ b/client/src/generated/models/OtherTransactionIdentifier.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * The transaction_identifier uniquely identifies a transaction in a particular network and block or in the mempool. + * @export + * @interface OtherTransactionIdentifier + */ +export interface OtherTransactionIdentifier { + /** + * Any transactions that are attributable only to a block (ex: a block event) should use the hash of the block as the identifier. + * @type {string} + * @memberof OtherTransactionIdentifier + */ + hash: string; +} + +export function OtherTransactionIdentifierFromJSON(json: any): OtherTransactionIdentifier { + return OtherTransactionIdentifierFromJSONTyped(json, false); +} + +export function OtherTransactionIdentifierFromJSONTyped(json: any, ignoreDiscriminator: boolean): OtherTransactionIdentifier { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'hash': json['hash'], + }; +} + +export function OtherTransactionIdentifierToJSON(value?: OtherTransactionIdentifier | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'hash': value.hash, + }; +} + diff --git a/client/src/generated/models/PoolDelegation.ts b/client/src/generated/models/PoolDelegation.ts new file mode 100644 index 0000000000..06165beb3f --- /dev/null +++ b/client/src/generated/models/PoolDelegation.ts @@ -0,0 +1,96 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface PoolDelegation + */ +export interface PoolDelegation { + /** + * The principal of the pool member that issued the delegation + * @type {string} + * @memberof PoolDelegation + */ + stacker: string; + /** + * The pox-addr value specified by the stacker in the delegation operation + * @type {string} + * @memberof PoolDelegation + */ + pox_addr?: string; + /** + * The amount of uSTX delegated by the stacker + * @type {string} + * @memberof PoolDelegation + */ + amount_ustx: string; + /** + * The optional burnchain block unlock height that the stacker may have specified + * @type {number} + * @memberof PoolDelegation + */ + burn_block_unlock_height?: number; + /** + * The block height at which the stacker delegation transaction was mined at + * @type {number} + * @memberof PoolDelegation + */ + block_height: number; + /** + * The tx_id of the stacker delegation operation + * @type {string} + * @memberof PoolDelegation + */ + tx_id: string; +} + +export function PoolDelegationFromJSON(json: any): PoolDelegation { + return PoolDelegationFromJSONTyped(json, false); +} + +export function PoolDelegationFromJSONTyped(json: any, ignoreDiscriminator: boolean): PoolDelegation { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'stacker': json['stacker'], + 'pox_addr': !exists(json, 'pox_addr') ? undefined : json['pox_addr'], + 'amount_ustx': json['amount_ustx'], + 'burn_block_unlock_height': !exists(json, 'burn_block_unlock_height') ? undefined : json['burn_block_unlock_height'], + 'block_height': json['block_height'], + 'tx_id': json['tx_id'], + }; +} + +export function PoolDelegationToJSON(value?: PoolDelegation | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'stacker': value.stacker, + 'pox_addr': value.pox_addr, + 'amount_ustx': value.amount_ustx, + 'burn_block_unlock_height': value.burn_block_unlock_height, + 'block_height': value.block_height, + 'tx_id': value.tx_id, + }; +} + diff --git a/client/src/generated/models/PoolDelegationsResponse.ts b/client/src/generated/models/PoolDelegationsResponse.ts new file mode 100644 index 0000000000..0e931bdf75 --- /dev/null +++ b/client/src/generated/models/PoolDelegationsResponse.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + PoolDelegation, + PoolDelegationFromJSON, + PoolDelegationFromJSONTyped, + PoolDelegationToJSON, +} from './'; + +/** + * GET request that returns stacking pool member details for a given pool (delegator) principal + * @export + * @interface PoolDelegationsResponse + */ +export interface PoolDelegationsResponse { + /** + * The number of Stackers to return + * @type {number} + * @memberof PoolDelegationsResponse + */ + limit: number; + /** + * The number to Stackers to skip (starting at `0`) + * @type {number} + * @memberof PoolDelegationsResponse + */ + offset: number; + /** + * The total number of Stackers + * @type {number} + * @memberof PoolDelegationsResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof PoolDelegationsResponse + */ + results: Array; +} + +export function PoolDelegationsResponseFromJSON(json: any): PoolDelegationsResponse { + return PoolDelegationsResponseFromJSONTyped(json, false); +} + +export function PoolDelegationsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): PoolDelegationsResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'total': json['total'], + 'results': ((json['results'] as Array).map(PoolDelegationFromJSON)), + }; +} + +export function PoolDelegationsResponseToJSON(value?: PoolDelegationsResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'total': value.total, + 'results': ((value.results as Array).map(PoolDelegationToJSON)), + }; +} + diff --git a/client/src/generated/models/PostCoreNodeTransactionsError.ts b/client/src/generated/models/PostCoreNodeTransactionsError.ts index 23d10050f1..6c7d850454 100644 --- a/client/src/generated/models/PostCoreNodeTransactionsError.ts +++ b/client/src/generated/models/PostCoreNodeTransactionsError.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -78,4 +78,3 @@ export function PostCoreNodeTransactionsErrorToJSON(value?: PostCoreNodeTransact }; } - diff --git a/client/src/generated/models/ReadOnlyFunctionArgs.ts b/client/src/generated/models/ReadOnlyFunctionArgs.ts index 0b103702f5..0feaed7d22 100644 --- a/client/src/generated/models/ReadOnlyFunctionArgs.ts +++ b/client/src/generated/models/ReadOnlyFunctionArgs.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function ReadOnlyFunctionArgsToJSON(value?: ReadOnlyFunctionArgs | null): }; } - diff --git a/client/src/generated/models/ReadOnlyFunctionSuccessResponse.ts b/client/src/generated/models/ReadOnlyFunctionSuccessResponse.ts index 5f03861002..01a24eb90c 100644 --- a/client/src/generated/models/ReadOnlyFunctionSuccessResponse.ts +++ b/client/src/generated/models/ReadOnlyFunctionSuccessResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -70,4 +70,3 @@ export function ReadOnlyFunctionSuccessResponseToJSON(value?: ReadOnlyFunctionSu }; } - diff --git a/client/src/generated/models/RosettaAccount.ts b/client/src/generated/models/RosettaAccount.ts index baaf5c29e7..7fa9faa752 100644 --- a/client/src/generated/models/RosettaAccount.ts +++ b/client/src/generated/models/RosettaAccount.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -77,4 +77,3 @@ export function RosettaAccountToJSON(value?: RosettaAccount | null): any { }; } - diff --git a/client/src/generated/models/RosettaAccountBalanceRequest.ts b/client/src/generated/models/RosettaAccountBalanceRequest.ts index db92d4910f..c3148c87a2 100644 --- a/client/src/generated/models/RosettaAccountBalanceRequest.ts +++ b/client/src/generated/models/RosettaAccountBalanceRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -81,4 +81,3 @@ export function RosettaAccountBalanceRequestToJSON(value?: RosettaAccountBalance }; } - diff --git a/client/src/generated/models/RosettaAccountBalanceResponse.ts b/client/src/generated/models/RosettaAccountBalanceResponse.ts index d7958063a3..667eac2428 100644 --- a/client/src/generated/models/RosettaAccountBalanceResponse.ts +++ b/client/src/generated/models/RosettaAccountBalanceResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -39,7 +39,7 @@ export interface RosettaAccountBalanceResponse { * @type {object} * @memberof RosettaAccountBalanceResponse */ - block_identifier: object; + block_identifier: object | null; /** * A single account balance may have multiple currencies * @type {Array} @@ -93,4 +93,3 @@ export function RosettaAccountBalanceResponseToJSON(value?: RosettaAccountBalanc }; } - diff --git a/client/src/generated/models/RosettaAccountBalanceResponseCoinIdentifier.ts b/client/src/generated/models/RosettaAccountBalanceResponseCoinIdentifier.ts index 508700f6f3..1e179d5ca5 100644 --- a/client/src/generated/models/RosettaAccountBalanceResponseCoinIdentifier.ts +++ b/client/src/generated/models/RosettaAccountBalanceResponseCoinIdentifier.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -54,4 +54,3 @@ export function RosettaAccountBalanceResponseCoinIdentifierToJSON(value?: Rosett }; } - diff --git a/client/src/generated/models/RosettaAccountBalanceResponseMetadata.ts b/client/src/generated/models/RosettaAccountBalanceResponseMetadata.ts index 0e94579f7e..2b46f2c558 100644 --- a/client/src/generated/models/RosettaAccountBalanceResponseMetadata.ts +++ b/client/src/generated/models/RosettaAccountBalanceResponseMetadata.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -54,4 +54,3 @@ export function RosettaAccountBalanceResponseMetadataToJSON(value?: RosettaAccou }; } - diff --git a/client/src/generated/models/RosettaAccountIdentifier.ts b/client/src/generated/models/RosettaAccountIdentifier.ts new file mode 100644 index 0000000000..8a2ddaae6a --- /dev/null +++ b/client/src/generated/models/RosettaAccountIdentifier.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + RosettaSubAccount, + RosettaSubAccountFromJSON, + RosettaSubAccountFromJSONTyped, + RosettaSubAccountToJSON, +} from './'; + +/** + * The account_identifier uniquely identifies an account within a network. All fields in the account_identifier are utilized to determine this uniqueness (including the metadata field, if populated). + * @export + * @interface RosettaAccountIdentifier + */ +export interface RosettaAccountIdentifier { + /** + * The address may be a cryptographic public key (or some encoding of it) or a provided username. + * @type {string} + * @memberof RosettaAccountIdentifier + */ + address: string; + /** + * + * @type {RosettaSubAccount} + * @memberof RosettaAccountIdentifier + */ + sub_account?: RosettaSubAccount; + /** + * Blockchains that utilize a username model (where the address is not a derivative of a cryptographic public key) should specify the public key(s) owned by the address in metadata. + * @type {object} + * @memberof RosettaAccountIdentifier + */ + metadata?: object; +} + +export function RosettaAccountIdentifierFromJSON(json: any): RosettaAccountIdentifier { + return RosettaAccountIdentifierFromJSONTyped(json, false); +} + +export function RosettaAccountIdentifierFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaAccountIdentifier { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'address': json['address'], + 'sub_account': !exists(json, 'sub_account') ? undefined : RosettaSubAccountFromJSON(json['sub_account']), + 'metadata': !exists(json, 'metadata') ? undefined : json['metadata'], + }; +} + +export function RosettaAccountIdentifierToJSON(value?: RosettaAccountIdentifier | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'address': value.address, + 'sub_account': RosettaSubAccountToJSON(value.sub_account), + 'metadata': value.metadata, + }; +} + diff --git a/client/src/generated/models/RosettaAmount.ts b/client/src/generated/models/RosettaAmount.ts index e54c4f9b53..75f6302f63 100644 --- a/client/src/generated/models/RosettaAmount.ts +++ b/client/src/generated/models/RosettaAmount.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -77,4 +77,3 @@ export function RosettaAmountToJSON(value?: RosettaAmount | null): any { }; } - diff --git a/client/src/generated/models/RosettaBlock.ts b/client/src/generated/models/RosettaBlock.ts index 1ca85eee7b..03143ae957 100644 --- a/client/src/generated/models/RosettaBlock.ts +++ b/client/src/generated/models/RosettaBlock.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,10 +14,10 @@ import { exists, mapValues } from '../runtime'; import { - RosettaBlockMetadata2, - RosettaBlockMetadata2FromJSON, - RosettaBlockMetadata2FromJSONTyped, - RosettaBlockMetadata2ToJSON, + RosettaBlockMetadata1, + RosettaBlockMetadata1FromJSON, + RosettaBlockMetadata1FromJSONTyped, + RosettaBlockMetadata1ToJSON, RosettaParentBlockIdentifier, RosettaParentBlockIdentifierFromJSON, RosettaParentBlockIdentifierFromJSONTyped, @@ -39,7 +39,7 @@ export interface RosettaBlock { * @type {object} * @memberof RosettaBlock */ - block_identifier: object; + block_identifier: object | null; /** * * @type {RosettaParentBlockIdentifier} @@ -60,10 +60,10 @@ export interface RosettaBlock { transactions: Array; /** * - * @type {RosettaBlockMetadata2} + * @type {RosettaBlockMetadata1} * @memberof RosettaBlock */ - metadata?: RosettaBlockMetadata2; + metadata?: RosettaBlockMetadata1; } export function RosettaBlockFromJSON(json: any): RosettaBlock { @@ -80,7 +80,7 @@ export function RosettaBlockFromJSONTyped(json: any, ignoreDiscriminator: boolea 'parent_block_identifier': RosettaParentBlockIdentifierFromJSON(json['parent_block_identifier']), 'timestamp': json['timestamp'], 'transactions': ((json['transactions'] as Array).map(RosettaTransactionFromJSON)), - 'metadata': !exists(json, 'metadata') ? undefined : RosettaBlockMetadata2FromJSON(json['metadata']), + 'metadata': !exists(json, 'metadata') ? undefined : RosettaBlockMetadata1FromJSON(json['metadata']), }; } @@ -97,8 +97,7 @@ export function RosettaBlockToJSON(value?: RosettaBlock | null): any { 'parent_block_identifier': RosettaParentBlockIdentifierToJSON(value.parent_block_identifier), 'timestamp': value.timestamp, 'transactions': ((value.transactions as Array).map(RosettaTransactionToJSON)), - 'metadata': RosettaBlockMetadata2ToJSON(value.metadata), + 'metadata': RosettaBlockMetadata1ToJSON(value.metadata), }; } - diff --git a/client/src/generated/models/RosettaBlockMetadata.ts b/client/src/generated/models/RosettaBlockMetadata.ts index 7840036b1c..82fa5fd047 100644 --- a/client/src/generated/models/RosettaBlockMetadata.ts +++ b/client/src/generated/models/RosettaBlockMetadata.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,23 +14,29 @@ import { exists, mapValues } from '../runtime'; /** - * Operations Meta Data + * Transactions that are related to other transactions (like a cross-shard transaction) should include the tranaction_identifier of these transactions in the metadata. * @export * @interface RosettaBlockMetadata */ export interface RosettaBlockMetadata { /** - * The asm + * STX token transfer memo. * @type {string} * @memberof RosettaBlockMetadata */ - asm: string; + memo?: string; /** - * The hex - * @type {string} + * The Size + * @type {number} * @memberof RosettaBlockMetadata */ - hex: string; + size?: number; + /** + * The locktime + * @type {number} + * @memberof RosettaBlockMetadata + */ + lockTime?: number; } export function RosettaBlockMetadataFromJSON(json: any): RosettaBlockMetadata { @@ -43,8 +49,9 @@ export function RosettaBlockMetadataFromJSONTyped(json: any, ignoreDiscriminator } return { - 'asm': json['asm'], - 'hex': json['hex'], + 'memo': !exists(json, 'memo') ? undefined : json['memo'], + 'size': !exists(json, 'size') ? undefined : json['size'], + 'lockTime': !exists(json, 'lockTime') ? undefined : json['lockTime'], }; } @@ -57,9 +64,9 @@ export function RosettaBlockMetadataToJSON(value?: RosettaBlockMetadata | null): } return { - 'asm': value.asm, - 'hex': value.hex, + 'memo': value.memo, + 'size': value.size, + 'lockTime': value.lockTime, }; } - diff --git a/client/src/generated/models/RosettaBlockMetadata1.ts b/client/src/generated/models/RosettaBlockMetadata1.ts index 589c0f4202..301da689c0 100644 --- a/client/src/generated/models/RosettaBlockMetadata1.ts +++ b/client/src/generated/models/RosettaBlockMetadata1.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,23 +14,23 @@ import { exists, mapValues } from '../runtime'; /** - * Transactions that are related to other transactions (like a cross-shard transaction) should include the tranaction_identifier of these transactions in the metadata. + * meta data * @export * @interface RosettaBlockMetadata1 */ export interface RosettaBlockMetadata1 { /** - * The Size - * @type {number} + * + * @type {string} * @memberof RosettaBlockMetadata1 */ - size: number; + transactions_root: string; /** - * The locktime - * @type {number} + * + * @type {string} * @memberof RosettaBlockMetadata1 */ - lockTime: number; + difficulty: string; } export function RosettaBlockMetadata1FromJSON(json: any): RosettaBlockMetadata1 { @@ -43,8 +43,8 @@ export function RosettaBlockMetadata1FromJSONTyped(json: any, ignoreDiscriminato } return { - 'size': json['size'], - 'lockTime': json['lockTime'], + 'transactions_root': json['transactions_root'], + 'difficulty': json['difficulty'], }; } @@ -57,9 +57,8 @@ export function RosettaBlockMetadata1ToJSON(value?: RosettaBlockMetadata1 | null } return { - 'size': value.size, - 'lockTime': value.lockTime, + 'transactions_root': value.transactions_root, + 'difficulty': value.difficulty, }; } - diff --git a/client/src/generated/models/RosettaBlockMetadata2.ts b/client/src/generated/models/RosettaBlockMetadata2.ts deleted file mode 100644 index 60e730d11e..0000000000 --- a/client/src/generated/models/RosettaBlockMetadata2.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) - * - * The version of the OpenAPI document: 1.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { exists, mapValues } from '../runtime'; -/** - * meta data - * @export - * @interface RosettaBlockMetadata2 - */ -export interface RosettaBlockMetadata2 { - /** - * - * @type {string} - * @memberof RosettaBlockMetadata2 - */ - transactions_root: string; - /** - * - * @type {string} - * @memberof RosettaBlockMetadata2 - */ - difficulty: string; -} - -export function RosettaBlockMetadata2FromJSON(json: any): RosettaBlockMetadata2 { - return RosettaBlockMetadata2FromJSONTyped(json, false); -} - -export function RosettaBlockMetadata2FromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaBlockMetadata2 { - if ((json === undefined) || (json === null)) { - return json; - } - return { - - 'transactions_root': json['transactions_root'], - 'difficulty': json['difficulty'], - }; -} - -export function RosettaBlockMetadata2ToJSON(value?: RosettaBlockMetadata2 | null): any { - if (value === undefined) { - return undefined; - } - if (value === null) { - return null; - } - return { - - 'transactions_root': value.transactions_root, - 'difficulty': value.difficulty, - }; -} - - diff --git a/client/src/generated/models/RosettaBlockRequest.ts b/client/src/generated/models/RosettaBlockRequest.ts index 9e603a0974..2422df9c8d 100644 --- a/client/src/generated/models/RosettaBlockRequest.ts +++ b/client/src/generated/models/RosettaBlockRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -37,7 +37,7 @@ export interface RosettaBlockRequest { * @type {object} * @memberof RosettaBlockRequest */ - block_identifier?: object; + block_identifier: object; } export function RosettaBlockRequestFromJSON(json: any): RosettaBlockRequest { @@ -51,7 +51,7 @@ export function RosettaBlockRequestFromJSONTyped(json: any, ignoreDiscriminator: return { 'network_identifier': NetworkIdentifierFromJSON(json['network_identifier']), - 'block_identifier': !exists(json, 'block_identifier') ? undefined : json['block_identifier'], + 'block_identifier': json['block_identifier'], }; } @@ -69,4 +69,3 @@ export function RosettaBlockRequestToJSON(value?: RosettaBlockRequest | null): a }; } - diff --git a/client/src/generated/models/RosettaBlockResponse.ts b/client/src/generated/models/RosettaBlockResponse.ts index d8cdc08622..9fabd951e4 100644 --- a/client/src/generated/models/RosettaBlockResponse.ts +++ b/client/src/generated/models/RosettaBlockResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,14 +14,14 @@ import { exists, mapValues } from '../runtime'; import { + OtherTransactionIdentifier, + OtherTransactionIdentifierFromJSON, + OtherTransactionIdentifierFromJSONTyped, + OtherTransactionIdentifierToJSON, RosettaBlock, RosettaBlockFromJSON, RosettaBlockFromJSONTyped, RosettaBlockToJSON, - TransactionIdentifier, - TransactionIdentifierFromJSON, - TransactionIdentifierFromJSONTyped, - TransactionIdentifierToJSON, } from './'; /** @@ -38,10 +38,10 @@ export interface RosettaBlockResponse { block?: RosettaBlock; /** * Some blockchains may require additional transactions to be fetched that weren't returned in the block response (ex: block only returns transaction hashes). For blockchains with a lot of transactions in each block, this can be very useful as consumers can concurrently fetch all transactions returned. - * @type {Array} + * @type {Array} * @memberof RosettaBlockResponse */ - other_transactions?: Array; + other_transactions?: Array; } export function RosettaBlockResponseFromJSON(json: any): RosettaBlockResponse { @@ -55,7 +55,7 @@ export function RosettaBlockResponseFromJSONTyped(json: any, ignoreDiscriminator return { 'block': !exists(json, 'block') ? undefined : RosettaBlockFromJSON(json['block']), - 'other_transactions': !exists(json, 'other_transactions') ? undefined : ((json['other_transactions'] as Array).map(TransactionIdentifierFromJSON)), + 'other_transactions': !exists(json, 'other_transactions') ? undefined : ((json['other_transactions'] as Array).map(OtherTransactionIdentifierFromJSON)), }; } @@ -69,8 +69,7 @@ export function RosettaBlockResponseToJSON(value?: RosettaBlockResponse | null): return { 'block': RosettaBlockToJSON(value.block), - 'other_transactions': value.other_transactions === undefined ? undefined : ((value.other_transactions as Array).map(TransactionIdentifierToJSON)), + 'other_transactions': value.other_transactions === undefined ? undefined : ((value.other_transactions as Array).map(OtherTransactionIdentifierToJSON)), }; } - diff --git a/client/src/generated/models/RosettaBlockTransactionRequest.ts b/client/src/generated/models/RosettaBlockTransactionRequest.ts index 14fd0d288f..c42c7e2d38 100644 --- a/client/src/generated/models/RosettaBlockTransactionRequest.ts +++ b/client/src/generated/models/RosettaBlockTransactionRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -37,7 +37,7 @@ export interface RosettaBlockTransactionRequest { */ network_identifier: NetworkIdentifier; /** - * The block_identifier uniquely identifies a block in a particular network. + * When fetching data by BlockIdentifier, it may be possible to only specify the index or hash. If neither property is specified, it is assumed that the client is making a request at the current block. * @type {object} * @memberof RosettaBlockTransactionRequest */ @@ -81,4 +81,3 @@ export function RosettaBlockTransactionRequestToJSON(value?: RosettaBlockTransac }; } - diff --git a/client/src/generated/models/RosettaBlockTransactionResponse.ts b/client/src/generated/models/RosettaBlockTransactionResponse.ts index 50d57cfba4..0adb687890 100644 --- a/client/src/generated/models/RosettaBlockTransactionResponse.ts +++ b/client/src/generated/models/RosettaBlockTransactionResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -61,4 +61,3 @@ export function RosettaBlockTransactionResponseToJSON(value?: RosettaBlockTransa }; } - diff --git a/client/src/generated/models/RosettaCoin.ts b/client/src/generated/models/RosettaCoin.ts index 782179e07e..56b305fb0f 100644 --- a/client/src/generated/models/RosettaCoin.ts +++ b/client/src/generated/models/RosettaCoin.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -73,4 +73,3 @@ export function RosettaCoinToJSON(value?: RosettaCoin | null): any { }; } - diff --git a/client/src/generated/models/RosettaCoinChange.ts b/client/src/generated/models/RosettaCoinChange.ts index b55ee5c8bb..50c504ffd4 100644 --- a/client/src/generated/models/RosettaCoinChange.ts +++ b/client/src/generated/models/RosettaCoinChange.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -40,6 +40,15 @@ export interface RosettaCoinChange { coin_action: RosettaCoinChangeCoinActionEnum; } +/** +* @export +* @enum {string} +*/ +export enum RosettaCoinChangeCoinActionEnum { + created = 'coin_created', + spent = 'coin_spent' +} + export function RosettaCoinChangeFromJSON(json: any): RosettaCoinChange { return RosettaCoinChangeFromJSONTyped(json, false); } @@ -69,13 +78,3 @@ export function RosettaCoinChangeToJSON(value?: RosettaCoinChange | null): any { }; } -/** -* @export -* @enum {string} -*/ -export enum RosettaCoinChangeCoinActionEnum { - created = 'coin_created', - spent = 'coin_spent' -} - - diff --git a/client/src/generated/models/RosettaConstructionCombineRequest.ts b/client/src/generated/models/RosettaConstructionCombineRequest.ts index 5a0b6a70dc..e2f49f6a6a 100644 --- a/client/src/generated/models/RosettaConstructionCombineRequest.ts +++ b/client/src/generated/models/RosettaConstructionCombineRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -81,4 +81,3 @@ export function RosettaConstructionCombineRequestToJSON(value?: RosettaConstruct }; } - diff --git a/client/src/generated/models/RosettaConstructionCombineResponse.ts b/client/src/generated/models/RosettaConstructionCombineResponse.ts index d69c9c4c69..67ef31766c 100644 --- a/client/src/generated/models/RosettaConstructionCombineResponse.ts +++ b/client/src/generated/models/RosettaConstructionCombineResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -54,4 +54,3 @@ export function RosettaConstructionCombineResponseToJSON(value?: RosettaConstruc }; } - diff --git a/client/src/generated/models/RosettaConstructionDeriveRequest.ts b/client/src/generated/models/RosettaConstructionDeriveRequest.ts index f12ba2ad46..40441e7ab0 100644 --- a/client/src/generated/models/RosettaConstructionDeriveRequest.ts +++ b/client/src/generated/models/RosettaConstructionDeriveRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -81,4 +81,3 @@ export function RosettaConstructionDeriveRequestToJSON(value?: RosettaConstructi }; } - diff --git a/client/src/generated/models/RosettaConstructionDeriveResponse.ts b/client/src/generated/models/RosettaConstructionDeriveResponse.ts index eb38b8ff0f..014f1f3da3 100644 --- a/client/src/generated/models/RosettaConstructionDeriveResponse.ts +++ b/client/src/generated/models/RosettaConstructionDeriveResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -13,6 +13,13 @@ */ import { exists, mapValues } from '../runtime'; +import { + RosettaAccountIdentifier, + RosettaAccountIdentifierFromJSON, + RosettaAccountIdentifierFromJSONTyped, + RosettaAccountIdentifierToJSON, +} from './'; + /** * ConstructionDeriveResponse is returned by the /construction/derive endpoint. * @export @@ -20,11 +27,17 @@ import { exists, mapValues } from '../runtime'; */ export interface RosettaConstructionDeriveResponse { /** - * Address in network-specific format. + * [DEPRECATED by account_identifier in v1.4.4] Address in network-specific format. * @type {string} * @memberof RosettaConstructionDeriveResponse */ - address: string; + address?: string; + /** + * + * @type {RosettaAccountIdentifier} + * @memberof RosettaConstructionDeriveResponse + */ + account_identifier?: RosettaAccountIdentifier; /** * * @type {object} @@ -43,7 +56,8 @@ export function RosettaConstructionDeriveResponseFromJSONTyped(json: any, ignore } return { - 'address': json['address'], + 'address': !exists(json, 'address') ? undefined : json['address'], + 'account_identifier': !exists(json, 'account_identifier') ? undefined : RosettaAccountIdentifierFromJSON(json['account_identifier']), 'metadata': !exists(json, 'metadata') ? undefined : json['metadata'], }; } @@ -58,8 +72,8 @@ export function RosettaConstructionDeriveResponseToJSON(value?: RosettaConstruct return { 'address': value.address, + 'account_identifier': RosettaAccountIdentifierToJSON(value.account_identifier), 'metadata': value.metadata, }; } - diff --git a/client/src/generated/models/RosettaConstructionHashRequest.ts b/client/src/generated/models/RosettaConstructionHashRequest.ts index 60ac23488a..230e5edea4 100644 --- a/client/src/generated/models/RosettaConstructionHashRequest.ts +++ b/client/src/generated/models/RosettaConstructionHashRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaConstructionHashRequestToJSON(value?: RosettaConstruction }; } - diff --git a/client/src/generated/models/RosettaConstructionHashResponse.ts b/client/src/generated/models/RosettaConstructionHashResponse.ts index 856d7e890d..9b05d8e3ae 100644 --- a/client/src/generated/models/RosettaConstructionHashResponse.ts +++ b/client/src/generated/models/RosettaConstructionHashResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaConstructionHashResponseToJSON(value?: RosettaConstructio }; } - diff --git a/client/src/generated/models/RosettaConstructionMetadataRequest.ts b/client/src/generated/models/RosettaConstructionMetadataRequest.ts index 0e697a2568..6af1d813b2 100644 --- a/client/src/generated/models/RosettaConstructionMetadataRequest.ts +++ b/client/src/generated/models/RosettaConstructionMetadataRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -85,4 +85,3 @@ export function RosettaConstructionMetadataRequestToJSON(value?: RosettaConstruc }; } - diff --git a/client/src/generated/models/RosettaConstructionMetadataResponse.ts b/client/src/generated/models/RosettaConstructionMetadataResponse.ts index f35defb935..c818946147 100644 --- a/client/src/generated/models/RosettaConstructionMetadataResponse.ts +++ b/client/src/generated/models/RosettaConstructionMetadataResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -38,10 +38,10 @@ export interface RosettaConstructionMetadataResponse { metadata: RosettaConstructionMetadataResponseMetadata; /** * - * @type {RosettaAmount} + * @type {Array} * @memberof RosettaConstructionMetadataResponse */ - suggested_fee?: RosettaAmount; + suggested_fee?: Array; } export function RosettaConstructionMetadataResponseFromJSON(json: any): RosettaConstructionMetadataResponse { @@ -55,7 +55,7 @@ export function RosettaConstructionMetadataResponseFromJSONTyped(json: any, igno return { 'metadata': RosettaConstructionMetadataResponseMetadataFromJSON(json['metadata']), - 'suggested_fee': !exists(json, 'suggested_fee') ? undefined : RosettaAmountFromJSON(json['suggested_fee']), + 'suggested_fee': !exists(json, 'suggested_fee') ? undefined : ((json['suggested_fee'] as Array).map(RosettaAmountFromJSON)), }; } @@ -69,8 +69,7 @@ export function RosettaConstructionMetadataResponseToJSON(value?: RosettaConstru return { 'metadata': RosettaConstructionMetadataResponseMetadataToJSON(value.metadata), - 'suggested_fee': RosettaAmountToJSON(value.suggested_fee), + 'suggested_fee': value.suggested_fee === undefined ? undefined : ((value.suggested_fee as Array).map(RosettaAmountToJSON)), }; } - diff --git a/client/src/generated/models/RosettaConstructionMetadataResponseMetadata.ts b/client/src/generated/models/RosettaConstructionMetadataResponseMetadata.ts index 539cb5b182..41619da360 100644 --- a/client/src/generated/models/RosettaConstructionMetadataResponseMetadata.ts +++ b/client/src/generated/models/RosettaConstructionMetadataResponseMetadata.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function RosettaConstructionMetadataResponseMetadataToJSON(value?: Rosett }; } - diff --git a/client/src/generated/models/RosettaConstructionParseRequest.ts b/client/src/generated/models/RosettaConstructionParseRequest.ts index 40d0009968..8056092f73 100644 --- a/client/src/generated/models/RosettaConstructionParseRequest.ts +++ b/client/src/generated/models/RosettaConstructionParseRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -77,4 +77,3 @@ export function RosettaConstructionParseRequestToJSON(value?: RosettaConstructio }; } - diff --git a/client/src/generated/models/RosettaConstructionParseResponse.ts b/client/src/generated/models/RosettaConstructionParseResponse.ts index c8be53a5e5..b959cabf2a 100644 --- a/client/src/generated/models/RosettaConstructionParseResponse.ts +++ b/client/src/generated/models/RosettaConstructionParseResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,10 +14,10 @@ import { exists, mapValues } from '../runtime'; import { - RosettaAccount, - RosettaAccountFromJSON, - RosettaAccountFromJSONTyped, - RosettaAccountToJSON, + RosettaAccountIdentifier, + RosettaAccountIdentifierFromJSON, + RosettaAccountIdentifierFromJSONTyped, + RosettaAccountIdentifierToJSON, RosettaOperation, RosettaOperationFromJSON, RosettaOperationFromJSONTyped, @@ -44,10 +44,16 @@ export interface RosettaConstructionParseResponse { signers?: Array; /** * - * @type {Array} + * @type {Array} * @memberof RosettaConstructionParseResponse */ - account_identifier_signers?: Array; + account_identifier_signers?: Array; + /** + * + * @type {object} + * @memberof RosettaConstructionParseResponse + */ + metadata?: object; } export function RosettaConstructionParseResponseFromJSON(json: any): RosettaConstructionParseResponse { @@ -62,7 +68,8 @@ export function RosettaConstructionParseResponseFromJSONTyped(json: any, ignoreD 'operations': ((json['operations'] as Array).map(RosettaOperationFromJSON)), 'signers': !exists(json, 'signers') ? undefined : json['signers'], - 'account_identifier_signers': !exists(json, 'account_identifier_signers') ? undefined : ((json['account_identifier_signers'] as Array).map(RosettaAccountFromJSON)), + 'account_identifier_signers': !exists(json, 'account_identifier_signers') ? undefined : ((json['account_identifier_signers'] as Array).map(RosettaAccountIdentifierFromJSON)), + 'metadata': !exists(json, 'metadata') ? undefined : json['metadata'], }; } @@ -77,8 +84,8 @@ export function RosettaConstructionParseResponseToJSON(value?: RosettaConstructi 'operations': ((value.operations as Array).map(RosettaOperationToJSON)), 'signers': value.signers, - 'account_identifier_signers': value.account_identifier_signers === undefined ? undefined : ((value.account_identifier_signers as Array).map(RosettaAccountToJSON)), + 'account_identifier_signers': value.account_identifier_signers === undefined ? undefined : ((value.account_identifier_signers as Array).map(RosettaAccountIdentifierToJSON)), + 'metadata': value.metadata, }; } - diff --git a/client/src/generated/models/RosettaConstructionPayloadResponse.ts b/client/src/generated/models/RosettaConstructionPayloadResponse.ts index ebdfb8230b..40e208cc83 100644 --- a/client/src/generated/models/RosettaConstructionPayloadResponse.ts +++ b/client/src/generated/models/RosettaConstructionPayloadResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaConstructionPayloadResponseToJSON(value?: RosettaConstruc }; } - diff --git a/client/src/generated/models/RosettaConstructionPayloadsRequest.ts b/client/src/generated/models/RosettaConstructionPayloadsRequest.ts index 81ff6021dd..3192753a63 100644 --- a/client/src/generated/models/RosettaConstructionPayloadsRequest.ts +++ b/client/src/generated/models/RosettaConstructionPayloadsRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -18,6 +18,10 @@ import { NetworkIdentifierFromJSON, NetworkIdentifierFromJSONTyped, NetworkIdentifierToJSON, + RosettaConstructionMetadataResponseMetadata, + RosettaConstructionMetadataResponseMetadataFromJSON, + RosettaConstructionMetadataResponseMetadataFromJSONTyped, + RosettaConstructionMetadataResponseMetadataToJSON, RosettaOperation, RosettaOperationFromJSON, RosettaOperationFromJSONTyped, @@ -52,6 +56,12 @@ export interface RosettaConstructionPayloadsRequest { * @memberof RosettaConstructionPayloadsRequest */ public_keys?: Array; + /** + * + * @type {RosettaConstructionMetadataResponseMetadata} + * @memberof RosettaConstructionPayloadsRequest + */ + metadata?: RosettaConstructionMetadataResponseMetadata; } export function RosettaConstructionPayloadsRequestFromJSON(json: any): RosettaConstructionPayloadsRequest { @@ -67,6 +77,7 @@ export function RosettaConstructionPayloadsRequestFromJSONTyped(json: any, ignor 'network_identifier': NetworkIdentifierFromJSON(json['network_identifier']), 'operations': ((json['operations'] as Array).map(RosettaOperationFromJSON)), 'public_keys': !exists(json, 'public_keys') ? undefined : ((json['public_keys'] as Array).map(RosettaPublicKeyFromJSON)), + 'metadata': !exists(json, 'metadata') ? undefined : RosettaConstructionMetadataResponseMetadataFromJSON(json['metadata']), }; } @@ -82,7 +93,7 @@ export function RosettaConstructionPayloadsRequestToJSON(value?: RosettaConstruc 'network_identifier': NetworkIdentifierToJSON(value.network_identifier), 'operations': ((value.operations as Array).map(RosettaOperationToJSON)), 'public_keys': value.public_keys === undefined ? undefined : ((value.public_keys as Array).map(RosettaPublicKeyToJSON)), + 'metadata': RosettaConstructionMetadataResponseMetadataToJSON(value.metadata), }; } - diff --git a/client/src/generated/models/RosettaConstructionPreprocessRequest.ts b/client/src/generated/models/RosettaConstructionPreprocessRequest.ts index 6776a07ce2..97afbc15e8 100644 --- a/client/src/generated/models/RosettaConstructionPreprocessRequest.ts +++ b/client/src/generated/models/RosettaConstructionPreprocessRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -18,10 +18,10 @@ import { NetworkIdentifierFromJSON, NetworkIdentifierFromJSONTyped, NetworkIdentifierToJSON, - RosettaAmount, - RosettaAmountFromJSON, - RosettaAmountFromJSONTyped, - RosettaAmountToJSON, + RosettaMaxFeeAmount, + RosettaMaxFeeAmountFromJSON, + RosettaMaxFeeAmountFromJSONTyped, + RosettaMaxFeeAmountToJSON, RosettaOperation, RosettaOperationFromJSON, RosettaOperationFromJSONTyped, @@ -54,10 +54,10 @@ export interface RosettaConstructionPreprocessRequest { metadata?: object; /** * - * @type {Array} + * @type {Array} * @memberof RosettaConstructionPreprocessRequest */ - max_fee?: Array; + max_fee?: Array; /** * The caller can also provide a suggested fee multiplier to indicate that the suggested fee should be scaled. This may be used to set higher fees for urgent transactions or to pay lower fees when there is less urgency. It is assumed that providing a very low multiplier (like 0.0001) will never lead to a transaction being created with a fee less than the minimum network fee (if applicable). In the case that the caller provides both a max fee and a suggested fee multiplier, the max fee will set an upper bound on the suggested fee (regardless of the multiplier provided). * @type {number} @@ -79,7 +79,7 @@ export function RosettaConstructionPreprocessRequestFromJSONTyped(json: any, ign 'network_identifier': NetworkIdentifierFromJSON(json['network_identifier']), 'operations': ((json['operations'] as Array).map(RosettaOperationFromJSON)), 'metadata': !exists(json, 'metadata') ? undefined : json['metadata'], - 'max_fee': !exists(json, 'max_fee') ? undefined : ((json['max_fee'] as Array).map(RosettaAmountFromJSON)), + 'max_fee': !exists(json, 'max_fee') ? undefined : ((json['max_fee'] as Array).map(RosettaMaxFeeAmountFromJSON)), 'suggested_fee_multiplier': !exists(json, 'suggested_fee_multiplier') ? undefined : json['suggested_fee_multiplier'], }; } @@ -96,9 +96,8 @@ export function RosettaConstructionPreprocessRequestToJSON(value?: RosettaConstr 'network_identifier': NetworkIdentifierToJSON(value.network_identifier), 'operations': ((value.operations as Array).map(RosettaOperationToJSON)), 'metadata': value.metadata, - 'max_fee': value.max_fee === undefined ? undefined : ((value.max_fee as Array).map(RosettaAmountToJSON)), + 'max_fee': value.max_fee === undefined ? undefined : ((value.max_fee as Array).map(RosettaMaxFeeAmountToJSON)), 'suggested_fee_multiplier': value.suggested_fee_multiplier, }; } - diff --git a/client/src/generated/models/RosettaConstructionPreprocessResponse.ts b/client/src/generated/models/RosettaConstructionPreprocessResponse.ts index 60ad99074f..d83b7f0039 100644 --- a/client/src/generated/models/RosettaConstructionPreprocessResponse.ts +++ b/client/src/generated/models/RosettaConstructionPreprocessResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -73,4 +73,3 @@ export function RosettaConstructionPreprocessResponseToJSON(value?: RosettaConst }; } - diff --git a/client/src/generated/models/RosettaConstructionSubmitRequest.ts b/client/src/generated/models/RosettaConstructionSubmitRequest.ts index 9dc3748874..a1d86391f3 100644 --- a/client/src/generated/models/RosettaConstructionSubmitRequest.ts +++ b/client/src/generated/models/RosettaConstructionSubmitRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaConstructionSubmitRequestToJSON(value?: RosettaConstructi }; } - diff --git a/client/src/generated/models/RosettaConstructionSubmitResponse.ts b/client/src/generated/models/RosettaConstructionSubmitResponse.ts index 078756a3dc..2dd054d58f 100644 --- a/client/src/generated/models/RosettaConstructionSubmitResponse.ts +++ b/client/src/generated/models/RosettaConstructionSubmitResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaConstructionSubmitResponseToJSON(value?: RosettaConstruct }; } - diff --git a/client/src/generated/models/RosettaCurrency.ts b/client/src/generated/models/RosettaCurrency.ts index a82c640117..911b731eef 100644 --- a/client/src/generated/models/RosettaCurrency.ts +++ b/client/src/generated/models/RosettaCurrency.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -70,4 +70,3 @@ export function RosettaCurrencyToJSON(value?: RosettaCurrency | null): any { }; } - diff --git a/client/src/generated/models/RosettaError.ts b/client/src/generated/models/RosettaError.ts index 128f80c521..21854759ba 100644 --- a/client/src/generated/models/RosettaError.ts +++ b/client/src/generated/models/RosettaError.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -85,4 +85,3 @@ export function RosettaErrorToJSON(value?: RosettaError | null): any { }; } - diff --git a/client/src/generated/models/RosettaErrorDetails.ts b/client/src/generated/models/RosettaErrorDetails.ts index beb9749d35..67728872fb 100644 --- a/client/src/generated/models/RosettaErrorDetails.ts +++ b/client/src/generated/models/RosettaErrorDetails.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function RosettaErrorDetailsToJSON(value?: RosettaErrorDetails | null): a }; } - diff --git a/client/src/generated/models/RosettaErrorNoDetails.ts b/client/src/generated/models/RosettaErrorNoDetails.ts new file mode 100644 index 0000000000..a0c4271140 --- /dev/null +++ b/client/src/generated/models/RosettaErrorNoDetails.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * Instead of utilizing HTTP status codes to describe node errors (which often do not have a good analog), rich errors are returned using this object. Both the code and message fields can be individually used to correctly identify an error. Implementations MUST use unique values for both fields. + * @export + * @interface RosettaErrorNoDetails + */ +export interface RosettaErrorNoDetails { + /** + * Code is a network-specific error code. If desired, this code can be equivalent to an HTTP status code. + * @type {number} + * @memberof RosettaErrorNoDetails + */ + code: number; + /** + * Message is a network-specific error message. The message MUST NOT change for a given code. In particular, this means that any contextual information should be included in the details field. + * @type {string} + * @memberof RosettaErrorNoDetails + */ + message: string; + /** + * An error is retriable if the same request may succeed if submitted again. + * @type {boolean} + * @memberof RosettaErrorNoDetails + */ + retriable: boolean; +} + +export function RosettaErrorNoDetailsFromJSON(json: any): RosettaErrorNoDetails { + return RosettaErrorNoDetailsFromJSONTyped(json, false); +} + +export function RosettaErrorNoDetailsFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaErrorNoDetails { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'code': json['code'], + 'message': json['message'], + 'retriable': json['retriable'], + }; +} + +export function RosettaErrorNoDetailsToJSON(value?: RosettaErrorNoDetails | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'code': value.code, + 'message': value.message, + 'retriable': value.retriable, + }; +} + diff --git a/client/src/generated/models/RosettaGenesisBlockIdentifier.ts b/client/src/generated/models/RosettaGenesisBlockIdentifier.ts new file mode 100644 index 0000000000..e733434cd1 --- /dev/null +++ b/client/src/generated/models/RosettaGenesisBlockIdentifier.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * The block_identifier uniquely identifies a block in a particular network. + * @export + * @interface RosettaGenesisBlockIdentifier + */ +export interface RosettaGenesisBlockIdentifier { + /** + * This is also known as the block height. + * @type {number} + * @memberof RosettaGenesisBlockIdentifier + */ + index: number; + /** + * Block hash + * @type {string} + * @memberof RosettaGenesisBlockIdentifier + */ + hash: string; +} + +export function RosettaGenesisBlockIdentifierFromJSON(json: any): RosettaGenesisBlockIdentifier { + return RosettaGenesisBlockIdentifierFromJSONTyped(json, false); +} + +export function RosettaGenesisBlockIdentifierFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaGenesisBlockIdentifier { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'index': json['index'], + 'hash': json['hash'], + }; +} + +export function RosettaGenesisBlockIdentifierToJSON(value?: RosettaGenesisBlockIdentifier | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'index': value.index, + 'hash': value.hash, + }; +} + diff --git a/client/src/generated/models/RosettaMaxFeeAmount.ts b/client/src/generated/models/RosettaMaxFeeAmount.ts new file mode 100644 index 0000000000..71e15a10b1 --- /dev/null +++ b/client/src/generated/models/RosettaMaxFeeAmount.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + RosettaCurrency, + RosettaCurrencyFromJSON, + RosettaCurrencyFromJSONTyped, + RosettaCurrencyToJSON, +} from './'; + +/** + * Amount is some Value of a Currency. It is considered invalid to specify a Value without a Currency. + * @export + * @interface RosettaMaxFeeAmount + */ +export interface RosettaMaxFeeAmount { + /** + * Value of the transaction in atomic units represented as an arbitrary-sized signed integer. For example, 1 BTC would be represented by a value of 100000000. + * @type {string} + * @memberof RosettaMaxFeeAmount + */ + value: string; + /** + * + * @type {RosettaCurrency} + * @memberof RosettaMaxFeeAmount + */ + currency: RosettaCurrency; + /** + * + * @type {object} + * @memberof RosettaMaxFeeAmount + */ + metadata?: object; +} + +export function RosettaMaxFeeAmountFromJSON(json: any): RosettaMaxFeeAmount { + return RosettaMaxFeeAmountFromJSONTyped(json, false); +} + +export function RosettaMaxFeeAmountFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaMaxFeeAmount { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'value': json['value'], + 'currency': RosettaCurrencyFromJSON(json['currency']), + 'metadata': !exists(json, 'metadata') ? undefined : json['metadata'], + }; +} + +export function RosettaMaxFeeAmountToJSON(value?: RosettaMaxFeeAmount | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'value': value.value, + 'currency': RosettaCurrencyToJSON(value.currency), + 'metadata': value.metadata, + }; +} + diff --git a/client/src/generated/models/RosettaMempoolRequest.ts b/client/src/generated/models/RosettaMempoolRequest.ts index fab229e16e..ba1ab8234d 100644 --- a/client/src/generated/models/RosettaMempoolRequest.ts +++ b/client/src/generated/models/RosettaMempoolRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaMempoolRequestToJSON(value?: RosettaMempoolRequest | null }; } - diff --git a/client/src/generated/models/RosettaMempoolResponse.ts b/client/src/generated/models/RosettaMempoolResponse.ts index 3ea288b3e1..2e7fa178e3 100644 --- a/client/src/generated/models/RosettaMempoolResponse.ts +++ b/client/src/generated/models/RosettaMempoolResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaMempoolResponseToJSON(value?: RosettaMempoolResponse | nu }; } - diff --git a/client/src/generated/models/RosettaMempoolTransactionRequest.ts b/client/src/generated/models/RosettaMempoolTransactionRequest.ts index 7711c6b134..92793a46c8 100644 --- a/client/src/generated/models/RosettaMempoolTransactionRequest.ts +++ b/client/src/generated/models/RosettaMempoolTransactionRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -73,4 +73,3 @@ export function RosettaMempoolTransactionRequestToJSON(value?: RosettaMempoolTra }; } - diff --git a/client/src/generated/models/RosettaMempoolTransactionResponse.ts b/client/src/generated/models/RosettaMempoolTransactionResponse.ts index 72f60baaae..6e340106f4 100644 --- a/client/src/generated/models/RosettaMempoolTransactionResponse.ts +++ b/client/src/generated/models/RosettaMempoolTransactionResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaMempoolTransactionResponseToJSON(value?: RosettaMempoolTr }; } - diff --git a/client/src/generated/models/RosettaNetworkListResponse.ts b/client/src/generated/models/RosettaNetworkListResponse.ts index 37d457172b..ac1cdc1340 100644 --- a/client/src/generated/models/RosettaNetworkListResponse.ts +++ b/client/src/generated/models/RosettaNetworkListResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -61,4 +61,3 @@ export function RosettaNetworkListResponseToJSON(value?: RosettaNetworkListRespo }; } - diff --git a/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifier.ts b/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifier.ts index ef98b1a45a..4929199084 100644 --- a/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifier.ts +++ b/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifier.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -27,7 +27,7 @@ import { */ export interface RosettaNetworkListResponseSubNetworkIdentifier { /** - * Netowork name + * Network name * @type {string} * @memberof RosettaNetworkListResponseSubNetworkIdentifier */ @@ -69,4 +69,3 @@ export function RosettaNetworkListResponseSubNetworkIdentifierToJSON(value?: Ros }; } - diff --git a/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifierMetadata.ts b/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifierMetadata.ts index 5d065766f9..c2ab08cfa7 100644 --- a/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifierMetadata.ts +++ b/client/src/generated/models/RosettaNetworkListResponseSubNetworkIdentifierMetadata.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -54,4 +54,3 @@ export function RosettaNetworkListResponseSubNetworkIdentifierMetadataToJSON(val }; } - diff --git a/client/src/generated/models/RosettaNetworkOptionsResponse.ts b/client/src/generated/models/RosettaNetworkOptionsResponse.ts index ca9be373c4..993b81c198 100644 --- a/client/src/generated/models/RosettaNetworkOptionsResponse.ts +++ b/client/src/generated/models/RosettaNetworkOptionsResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -73,4 +73,3 @@ export function RosettaNetworkOptionsResponseToJSON(value?: RosettaNetworkOption }; } - diff --git a/client/src/generated/models/RosettaNetworkOptionsResponseAllow.ts b/client/src/generated/models/RosettaNetworkOptionsResponseAllow.ts index f39201f453..779157a2d2 100644 --- a/client/src/generated/models/RosettaNetworkOptionsResponseAllow.ts +++ b/client/src/generated/models/RosettaNetworkOptionsResponseAllow.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,10 +14,10 @@ import { exists, mapValues } from '../runtime'; import { - RosettaError, - RosettaErrorFromJSON, - RosettaErrorFromJSONTyped, - RosettaErrorToJSON, + RosettaErrorNoDetails, + RosettaErrorNoDetailsFromJSON, + RosettaErrorNoDetailsFromJSONTyped, + RosettaErrorNoDetailsToJSON, RosettaOperationStatus, RosettaOperationStatusFromJSON, RosettaOperationStatusFromJSONTyped, @@ -44,10 +44,10 @@ export interface RosettaNetworkOptionsResponseAllow { operation_types: Array; /** * All Errors that this implementation could return. Any error that is returned during parsing that is not listed here will cause client validation to error. - * @type {Array} + * @type {Array} * @memberof RosettaNetworkOptionsResponseAllow */ - errors: Array; + errors: Array; /** * Any Rosetta implementation that supports querying the balance of an account at any height in the past should set this to true. * @type {boolean} @@ -68,7 +68,7 @@ export function RosettaNetworkOptionsResponseAllowFromJSONTyped(json: any, ignor 'operation_statuses': ((json['operation_statuses'] as Array).map(RosettaOperationStatusFromJSON)), 'operation_types': json['operation_types'], - 'errors': ((json['errors'] as Array).map(RosettaErrorFromJSON)), + 'errors': ((json['errors'] as Array).map(RosettaErrorNoDetailsFromJSON)), 'historical_balance_lookup': json['historical_balance_lookup'], }; } @@ -84,9 +84,8 @@ export function RosettaNetworkOptionsResponseAllowToJSON(value?: RosettaNetworkO 'operation_statuses': ((value.operation_statuses as Array).map(RosettaOperationStatusToJSON)), 'operation_types': value.operation_types, - 'errors': ((value.errors as Array).map(RosettaErrorToJSON)), + 'errors': ((value.errors as Array).map(RosettaErrorNoDetailsToJSON)), 'historical_balance_lookup': value.historical_balance_lookup, }; } - diff --git a/client/src/generated/models/RosettaNetworkOptionsResponseVersion.ts b/client/src/generated/models/RosettaNetworkOptionsResponseVersion.ts index f918c46233..e5dd88e1c2 100644 --- a/client/src/generated/models/RosettaNetworkOptionsResponseVersion.ts +++ b/client/src/generated/models/RosettaNetworkOptionsResponseVersion.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -78,4 +78,3 @@ export function RosettaNetworkOptionsResponseVersionToJSON(value?: RosettaNetwor }; } - diff --git a/client/src/generated/models/RosettaNetworkStatusResponse.ts b/client/src/generated/models/RosettaNetworkStatusResponse.ts new file mode 100644 index 0000000000..f49d0599aa --- /dev/null +++ b/client/src/generated/models/RosettaNetworkStatusResponse.ts @@ -0,0 +1,115 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + RosettaGenesisBlockIdentifier, + RosettaGenesisBlockIdentifierFromJSON, + RosettaGenesisBlockIdentifierFromJSONTyped, + RosettaGenesisBlockIdentifierToJSON, + RosettaOldestBlockIdentifier, + RosettaOldestBlockIdentifierFromJSON, + RosettaOldestBlockIdentifierFromJSONTyped, + RosettaOldestBlockIdentifierToJSON, + RosettaPeers, + RosettaPeersFromJSON, + RosettaPeersFromJSONTyped, + RosettaPeersToJSON, + RosettaSyncStatus, + RosettaSyncStatusFromJSON, + RosettaSyncStatusFromJSONTyped, + RosettaSyncStatusToJSON, +} from './'; + +/** + * NetworkStatusResponse contains basic information about the node's view of a blockchain network. It is assumed that any BlockIdentifier.Index less than or equal to CurrentBlockIdentifier.Index can be queried. If a Rosetta implementation prunes historical state, it should populate the optional oldest_block_identifier field with the oldest block available to query. If this is not populated, it is assumed that the genesis_block_identifier is the oldest queryable block. If a Rosetta implementation performs some pre-sync before it is possible to query blocks, sync_status should be populated so that clients can still monitor healthiness. Without this field, it may appear that the implementation is stuck syncing and needs to be terminated. + * @export + * @interface RosettaNetworkStatusResponse + */ +export interface RosettaNetworkStatusResponse { + /** + * The block_identifier uniquely identifies a block in a particular network. + * @type {object} + * @memberof RosettaNetworkStatusResponse + */ + current_block_identifier: object | null; + /** + * The timestamp of the block in milliseconds since the Unix Epoch. The timestamp is stored in milliseconds because some blockchains produce blocks more often than once a second. + * @type {number} + * @memberof RosettaNetworkStatusResponse + */ + current_block_timestamp: number; + /** + * + * @type {RosettaGenesisBlockIdentifier} + * @memberof RosettaNetworkStatusResponse + */ + genesis_block_identifier: RosettaGenesisBlockIdentifier; + /** + * + * @type {RosettaOldestBlockIdentifier} + * @memberof RosettaNetworkStatusResponse + */ + oldest_block_identifier?: RosettaOldestBlockIdentifier; + /** + * + * @type {RosettaSyncStatus} + * @memberof RosettaNetworkStatusResponse + */ + sync_status?: RosettaSyncStatus; + /** + * Peers information + * @type {Array} + * @memberof RosettaNetworkStatusResponse + */ + peers: Array; +} + +export function RosettaNetworkStatusResponseFromJSON(json: any): RosettaNetworkStatusResponse { + return RosettaNetworkStatusResponseFromJSONTyped(json, false); +} + +export function RosettaNetworkStatusResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaNetworkStatusResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'current_block_identifier': json['current_block_identifier'], + 'current_block_timestamp': json['current_block_timestamp'], + 'genesis_block_identifier': RosettaGenesisBlockIdentifierFromJSON(json['genesis_block_identifier']), + 'oldest_block_identifier': !exists(json, 'oldest_block_identifier') ? undefined : RosettaOldestBlockIdentifierFromJSON(json['oldest_block_identifier']), + 'sync_status': !exists(json, 'sync_status') ? undefined : RosettaSyncStatusFromJSON(json['sync_status']), + 'peers': ((json['peers'] as Array).map(RosettaPeersFromJSON)), + }; +} + +export function RosettaNetworkStatusResponseToJSON(value?: RosettaNetworkStatusResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'current_block_identifier': value.current_block_identifier, + 'current_block_timestamp': value.current_block_timestamp, + 'genesis_block_identifier': RosettaGenesisBlockIdentifierToJSON(value.genesis_block_identifier), + 'oldest_block_identifier': RosettaOldestBlockIdentifierToJSON(value.oldest_block_identifier), + 'sync_status': RosettaSyncStatusToJSON(value.sync_status), + 'peers': ((value.peers as Array).map(RosettaPeersToJSON)), + }; +} + diff --git a/client/src/generated/models/RosettaOldestBlockIdentifier.ts b/client/src/generated/models/RosettaOldestBlockIdentifier.ts new file mode 100644 index 0000000000..3291bafa28 --- /dev/null +++ b/client/src/generated/models/RosettaOldestBlockIdentifier.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * The block_identifier uniquely identifies a block in a particular network. + * @export + * @interface RosettaOldestBlockIdentifier + */ +export interface RosettaOldestBlockIdentifier { + /** + * This is also known as the block height. + * @type {number} + * @memberof RosettaOldestBlockIdentifier + */ + index: number; + /** + * Block hash + * @type {string} + * @memberof RosettaOldestBlockIdentifier + */ + hash: string; +} + +export function RosettaOldestBlockIdentifierFromJSON(json: any): RosettaOldestBlockIdentifier { + return RosettaOldestBlockIdentifierFromJSONTyped(json, false); +} + +export function RosettaOldestBlockIdentifierFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaOldestBlockIdentifier { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'index': json['index'], + 'hash': json['hash'], + }; +} + +export function RosettaOldestBlockIdentifierToJSON(value?: RosettaOldestBlockIdentifier | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'index': value.index, + 'hash': value.hash, + }; +} + diff --git a/client/src/generated/models/RosettaOperation.ts b/client/src/generated/models/RosettaOperation.ts index b533be67be..1935e135d1 100644 --- a/client/src/generated/models/RosettaOperation.ts +++ b/client/src/generated/models/RosettaOperation.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -22,10 +22,6 @@ import { RosettaAmountFromJSON, RosettaAmountFromJSONTyped, RosettaAmountToJSON, - RosettaBlockMetadata, - RosettaBlockMetadataFromJSON, - RosettaBlockMetadataFromJSONTyped, - RosettaBlockMetadataToJSON, RosettaCoinChange, RosettaCoinChangeFromJSON, RosettaCoinChangeFromJSONTyped, @@ -69,7 +65,7 @@ export interface RosettaOperation { * @type {string} * @memberof RosettaOperation */ - status: string; + status?: string; /** * * @type {RosettaAccount} @@ -89,11 +85,11 @@ export interface RosettaOperation { */ coin_change?: RosettaCoinChange; /** - * - * @type {RosettaBlockMetadata} + * Operations Meta Data + * @type {object} * @memberof RosettaOperation */ - metadata?: RosettaBlockMetadata; + metadata?: object; } export function RosettaOperationFromJSON(json: any): RosettaOperation { @@ -109,11 +105,11 @@ export function RosettaOperationFromJSONTyped(json: any, ignoreDiscriminator: bo 'operation_identifier': RosettaOperationIdentifierFromJSON(json['operation_identifier']), 'related_operations': !exists(json, 'related_operations') ? undefined : ((json['related_operations'] as Array).map(RosettaRelatedOperationFromJSON)), 'type': json['type'], - 'status': json['status'], + 'status': !exists(json, 'status') ? undefined : json['status'], 'account': !exists(json, 'account') ? undefined : RosettaAccountFromJSON(json['account']), 'amount': !exists(json, 'amount') ? undefined : RosettaAmountFromJSON(json['amount']), 'coin_change': !exists(json, 'coin_change') ? undefined : RosettaCoinChangeFromJSON(json['coin_change']), - 'metadata': !exists(json, 'metadata') ? undefined : RosettaBlockMetadataFromJSON(json['metadata']), + 'metadata': !exists(json, 'metadata') ? undefined : json['metadata'], }; } @@ -133,8 +129,7 @@ export function RosettaOperationToJSON(value?: RosettaOperation | null): any { 'account': RosettaAccountToJSON(value.account), 'amount': RosettaAmountToJSON(value.amount), 'coin_change': RosettaCoinChangeToJSON(value.coin_change), - 'metadata': RosettaBlockMetadataToJSON(value.metadata), + 'metadata': value.metadata, }; } - diff --git a/client/src/generated/models/RosettaOperationIdentifier.ts b/client/src/generated/models/RosettaOperationIdentifier.ts index d2609403f9..b779123b89 100644 --- a/client/src/generated/models/RosettaOperationIdentifier.ts +++ b/client/src/generated/models/RosettaOperationIdentifier.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function RosettaOperationIdentifierToJSON(value?: RosettaOperationIdentif }; } - diff --git a/client/src/generated/models/RosettaOperationStatus.ts b/client/src/generated/models/RosettaOperationStatus.ts index 637e5df924..f55c4f76fd 100644 --- a/client/src/generated/models/RosettaOperationStatus.ts +++ b/client/src/generated/models/RosettaOperationStatus.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function RosettaOperationStatusToJSON(value?: RosettaOperationStatus | nu }; } - diff --git a/client/src/generated/models/RosettaOptions.ts b/client/src/generated/models/RosettaOptions.ts index 8eef051fe6..00c1f0e698 100644 --- a/client/src/generated/models/RosettaOptions.ts +++ b/client/src/generated/models/RosettaOptions.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -44,7 +44,7 @@ export interface RosettaOptions { */ token_transfer_recipient_address?: string; /** - * Amount to be transfeered. + * Amount to be transfered. * @type {string} * @memberof RosettaOptions */ @@ -91,6 +91,54 @@ export interface RosettaOptions { * @memberof RosettaOptions */ fee?: string; + /** + * Transaction approximative size (used to calculate total fee). + * @type {number} + * @memberof RosettaOptions + */ + size?: number; + /** + * STX token transfer memo. + * @type {string} + * @memberof RosettaOptions + */ + memo?: string; + /** + * Number of cycles when stacking. + * @type {number} + * @memberof RosettaOptions + */ + number_of_cycles?: number; + /** + * Address of the contract to call. + * @type {string} + * @memberof RosettaOptions + */ + contract_address?: string; + /** + * Name of the contract to call. + * @type {string} + * @memberof RosettaOptions + */ + contract_name?: string; + /** + * Set the burnchain (BTC) block for stacking lock to start. + * @type {number} + * @memberof RosettaOptions + */ + burn_block_height?: number; + /** + * Delegator address for when calling `delegate-stacking`. + * @type {string} + * @memberof RosettaOptions + */ + delegate_to?: string; + /** + * The reward address for stacking transaction. It should be a valid Bitcoin address + * @type {string} + * @memberof RosettaOptions + */ + pox_addr?: string; } export function RosettaOptionsFromJSON(json: any): RosettaOptions { @@ -115,6 +163,14 @@ export function RosettaOptionsFromJSONTyped(json: any, ignoreDiscriminator: bool 'suggested_fee_multiplier': !exists(json, 'suggested_fee_multiplier') ? undefined : json['suggested_fee_multiplier'], 'max_fee': !exists(json, 'max_fee') ? undefined : json['max_fee'], 'fee': !exists(json, 'fee') ? undefined : json['fee'], + 'size': !exists(json, 'size') ? undefined : json['size'], + 'memo': !exists(json, 'memo') ? undefined : json['memo'], + 'number_of_cycles': !exists(json, 'number_of_cycles') ? undefined : json['number_of_cycles'], + 'contract_address': !exists(json, 'contract_address') ? undefined : json['contract_address'], + 'contract_name': !exists(json, 'contract_name') ? undefined : json['contract_name'], + 'burn_block_height': !exists(json, 'burn_block_height') ? undefined : json['burn_block_height'], + 'delegate_to': !exists(json, 'delegate_to') ? undefined : json['delegate_to'], + 'pox_addr': !exists(json, 'pox_addr') ? undefined : json['pox_addr'], }; } @@ -139,7 +195,14 @@ export function RosettaOptionsToJSON(value?: RosettaOptions | null): any { 'suggested_fee_multiplier': value.suggested_fee_multiplier, 'max_fee': value.max_fee, 'fee': value.fee, + 'size': value.size, + 'memo': value.memo, + 'number_of_cycles': value.number_of_cycles, + 'contract_address': value.contract_address, + 'contract_name': value.contract_name, + 'burn_block_height': value.burn_block_height, + 'delegate_to': value.delegate_to, + 'pox_addr': value.pox_addr, }; } - diff --git a/client/src/generated/models/RosettaOptionsRequest.ts b/client/src/generated/models/RosettaOptionsRequest.ts index 7b5b628775..4f20419940 100644 --- a/client/src/generated/models/RosettaOptionsRequest.ts +++ b/client/src/generated/models/RosettaOptionsRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaOptionsRequestToJSON(value?: RosettaOptionsRequest | null }; } - diff --git a/client/src/generated/models/RosettaParentBlockIdentifier.ts b/client/src/generated/models/RosettaParentBlockIdentifier.ts index 81bc1d495e..e2eb22b611 100644 --- a/client/src/generated/models/RosettaParentBlockIdentifier.ts +++ b/client/src/generated/models/RosettaParentBlockIdentifier.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function RosettaParentBlockIdentifierToJSON(value?: RosettaParentBlockIde }; } - diff --git a/client/src/generated/models/RosettaPeers.ts b/client/src/generated/models/RosettaPeers.ts new file mode 100644 index 0000000000..ab6d65c224 --- /dev/null +++ b/client/src/generated/models/RosettaPeers.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * A Peer is a representation of a node's peer. + * @export + * @interface RosettaPeers + */ +export interface RosettaPeers { + /** + * peer id + * @type {string} + * @memberof RosettaPeers + */ + peer_id: string; + /** + * meta data + * @type {object} + * @memberof RosettaPeers + */ + metadata?: object; +} + +export function RosettaPeersFromJSON(json: any): RosettaPeers { + return RosettaPeersFromJSONTyped(json, false); +} + +export function RosettaPeersFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaPeers { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'peer_id': json['peer_id'], + 'metadata': !exists(json, 'metadata') ? undefined : json['metadata'], + }; +} + +export function RosettaPeersToJSON(value?: RosettaPeers | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'peer_id': value.peer_id, + 'metadata': value.metadata, + }; +} + diff --git a/client/src/generated/models/RosettaPublicKey.ts b/client/src/generated/models/RosettaPublicKey.ts index 28a7aa31f8..e501860e1a 100644 --- a/client/src/generated/models/RosettaPublicKey.ts +++ b/client/src/generated/models/RosettaPublicKey.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -33,6 +33,15 @@ export interface RosettaPublicKey { curve_type: RosettaPublicKeyCurveTypeEnum; } +/** +* @export +* @enum {string} +*/ +export enum RosettaPublicKeyCurveTypeEnum { + secp256k1 = 'secp256k1', + edwards25519 = 'edwards25519' +} + export function RosettaPublicKeyFromJSON(json: any): RosettaPublicKey { return RosettaPublicKeyFromJSONTyped(json, false); } @@ -62,13 +71,3 @@ export function RosettaPublicKeyToJSON(value?: RosettaPublicKey | null): any { }; } -/** -* @export -* @enum {string} -*/ -export enum RosettaPublicKeyCurveTypeEnum { - secp256k1 = 'secp256k1', - edwards25519 = 'edwards25519' -} - - diff --git a/client/src/generated/models/RosettaRelatedOperation.ts b/client/src/generated/models/RosettaRelatedOperation.ts index 93777da593..7177c893d6 100644 --- a/client/src/generated/models/RosettaRelatedOperation.ts +++ b/client/src/generated/models/RosettaRelatedOperation.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -13,13 +13,6 @@ */ import { exists, mapValues } from '../runtime'; -import { - RosettaOperationIdentifier, - RosettaOperationIdentifierFromJSON, - RosettaOperationIdentifierFromJSONTyped, - RosettaOperationIdentifierToJSON, -} from './'; - /** * Restrict referenced related_operations to identifier indexes < the current operation_identifier.index. This ensures there exists a clear DAG-structure of relations. Since operations are one-sided, one could imagine relating operations in a single transfer or linking operations in a call tree. * @export @@ -31,13 +24,13 @@ export interface RosettaRelatedOperation { * @type {number} * @memberof RosettaRelatedOperation */ - index?: number; + index: number; /** - * - * @type {RosettaOperationIdentifier} + * Some blockchains specify an operation index that is essential for client use. network_index should not be populated if there is no notion of an operation index in a blockchain (typically most account-based blockchains). + * @type {number} * @memberof RosettaRelatedOperation */ - operation_identifier: RosettaOperationIdentifier; + network_index?: number; } export function RosettaRelatedOperationFromJSON(json: any): RosettaRelatedOperation { @@ -50,8 +43,8 @@ export function RosettaRelatedOperationFromJSONTyped(json: any, ignoreDiscrimina } return { - 'index': !exists(json, 'index') ? undefined : json['index'], - 'operation_identifier': RosettaOperationIdentifierFromJSON(json['operation_identifier']), + 'index': json['index'], + 'network_index': !exists(json, 'network_index') ? undefined : json['network_index'], }; } @@ -65,8 +58,7 @@ export function RosettaRelatedOperationToJSON(value?: RosettaRelatedOperation | return { 'index': value.index, - 'operation_identifier': RosettaOperationIdentifierToJSON(value.operation_identifier), + 'network_index': value.network_index, }; } - diff --git a/client/src/generated/models/RosettaSignature.ts b/client/src/generated/models/RosettaSignature.ts index ed3e7da645..d2997957d1 100644 --- a/client/src/generated/models/RosettaSignature.ts +++ b/client/src/generated/models/RosettaSignature.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -56,6 +56,18 @@ export interface RosettaSignature { hex_bytes: string; } +/** +* @export +* @enum {string} +*/ +export enum RosettaSignatureSignatureTypeEnum { + ecdsa = 'ecdsa', + ecdsa_recovery = 'ecdsa_recovery', + ed25519 = 'ed25519', + schnorr_1 = 'schnorr_1', + schnorr_poseidon = 'schnorr_poseidon' +} + export function RosettaSignatureFromJSON(json: any): RosettaSignature { return RosettaSignatureFromJSONTyped(json, false); } @@ -89,16 +101,3 @@ export function RosettaSignatureToJSON(value?: RosettaSignature | null): any { }; } -/** -* @export -* @enum {string} -*/ -export enum RosettaSignatureSignatureTypeEnum { - ecdsa = 'ecdsa', - ecdsa_recovery = 'ecdsa_recovery', - ed25519 = 'ed25519', - schnorr_1 = 'schnorr_1', - schnorr_poseidon = 'schnorr_poseidon' -} - - diff --git a/client/src/generated/models/RosettaStatusRequest.ts b/client/src/generated/models/RosettaStatusRequest.ts index 3db8f6f129..91ea2c1dea 100644 --- a/client/src/generated/models/RosettaStatusRequest.ts +++ b/client/src/generated/models/RosettaStatusRequest.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -69,4 +69,3 @@ export function RosettaStatusRequestToJSON(value?: RosettaStatusRequest | null): }; } - diff --git a/client/src/generated/models/RosettaSubAccount.ts b/client/src/generated/models/RosettaSubAccount.ts index 90de66a382..0f21e3ff17 100644 --- a/client/src/generated/models/RosettaSubAccount.ts +++ b/client/src/generated/models/RosettaSubAccount.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -62,4 +62,3 @@ export function RosettaSubAccountToJSON(value?: RosettaSubAccount | null): any { }; } - diff --git a/client/src/generated/models/RosettaSyncStatus.ts b/client/src/generated/models/RosettaSyncStatus.ts new file mode 100644 index 0000000000..01c769ce8f --- /dev/null +++ b/client/src/generated/models/RosettaSyncStatus.ts @@ -0,0 +1,80 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * SyncStatus is used to provide additional context about an implementation's sync status. It is often used to indicate that an implementation is healthy when it cannot be queried until some sync phase occurs. If an implementation is immediately queryable, this model is often not populated. + * @export + * @interface RosettaSyncStatus + */ +export interface RosettaSyncStatus { + /** + * CurrentIndex is the index of the last synced block in the current stage. + * @type {number} + * @memberof RosettaSyncStatus + */ + current_index: number; + /** + * TargetIndex is the index of the block that the implementation is attempting to sync to in the current stage. + * @type {number} + * @memberof RosettaSyncStatus + */ + target_index?: number; + /** + * Stage is the phase of the sync process. + * @type {string} + * @memberof RosettaSyncStatus + */ + stage?: string; + /** + * Synced indicates if an implementation has synced up to the most recent block. + * @type {boolean} + * @memberof RosettaSyncStatus + */ + synced?: boolean; +} + +export function RosettaSyncStatusFromJSON(json: any): RosettaSyncStatus { + return RosettaSyncStatusFromJSONTyped(json, false); +} + +export function RosettaSyncStatusFromJSONTyped(json: any, ignoreDiscriminator: boolean): RosettaSyncStatus { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'current_index': json['current_index'], + 'target_index': !exists(json, 'target_index') ? undefined : json['target_index'], + 'stage': !exists(json, 'stage') ? undefined : json['stage'], + 'synced': !exists(json, 'synced') ? undefined : json['synced'], + }; +} + +export function RosettaSyncStatusToJSON(value?: RosettaSyncStatus | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'current_index': value.current_index, + 'target_index': value.target_index, + 'stage': value.stage, + 'synced': value.synced, + }; +} + diff --git a/client/src/generated/models/RosettaTransaction.ts b/client/src/generated/models/RosettaTransaction.ts index 5fc9875714..cc94bf1d4d 100644 --- a/client/src/generated/models/RosettaTransaction.ts +++ b/client/src/generated/models/RosettaTransaction.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,10 +14,10 @@ import { exists, mapValues } from '../runtime'; import { - RosettaBlockMetadata1, - RosettaBlockMetadata1FromJSON, - RosettaBlockMetadata1FromJSONTyped, - RosettaBlockMetadata1ToJSON, + RosettaBlockMetadata, + RosettaBlockMetadataFromJSON, + RosettaBlockMetadataFromJSONTyped, + RosettaBlockMetadataToJSON, RosettaOperation, RosettaOperationFromJSON, RosettaOperationFromJSONTyped, @@ -48,10 +48,10 @@ export interface RosettaTransaction { operations: Array; /** * - * @type {RosettaBlockMetadata1} + * @type {RosettaBlockMetadata} * @memberof RosettaTransaction */ - metadata?: RosettaBlockMetadata1; + metadata?: RosettaBlockMetadata; } export function RosettaTransactionFromJSON(json: any): RosettaTransaction { @@ -66,7 +66,7 @@ export function RosettaTransactionFromJSONTyped(json: any, ignoreDiscriminator: 'transaction_identifier': TransactionIdentifierFromJSON(json['transaction_identifier']), 'operations': ((json['operations'] as Array).map(RosettaOperationFromJSON)), - 'metadata': !exists(json, 'metadata') ? undefined : RosettaBlockMetadata1FromJSON(json['metadata']), + 'metadata': !exists(json, 'metadata') ? undefined : RosettaBlockMetadataFromJSON(json['metadata']), }; } @@ -81,8 +81,7 @@ export function RosettaTransactionToJSON(value?: RosettaTransaction | null): any 'transaction_identifier': TransactionIdentifierToJSON(value.transaction_identifier), 'operations': ((value.operations as Array).map(RosettaOperationToJSON)), - 'metadata': RosettaBlockMetadata1ToJSON(value.metadata), + 'metadata': RosettaBlockMetadataToJSON(value.metadata), }; } - diff --git a/client/src/generated/models/RunFaucetResponse.ts b/client/src/generated/models/RunFaucetResponse.ts index 1975ab9d26..96b1a75120 100644 --- a/client/src/generated/models/RunFaucetResponse.ts +++ b/client/src/generated/models/RunFaucetResponse.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,7 +14,7 @@ import { exists, mapValues } from '../runtime'; /** - * POST request that runs the faucet + * POST request that initiates a transfer of tokens to a specified testnet address * @export * @interface RunFaucetResponse */ @@ -70,4 +70,3 @@ export function RunFaucetResponseToJSON(value?: RunFaucetResponse | null): any { }; } - diff --git a/client/src/generated/models/ServerStatusResponse.ts b/client/src/generated/models/ServerStatusResponse.ts new file mode 100644 index 0000000000..23fd807407 --- /dev/null +++ b/client/src/generated/models/ServerStatusResponse.ts @@ -0,0 +1,95 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + ChainTip, + ChainTipFromJSON, + ChainTipFromJSONTyped, + ChainTipToJSON, +} from './'; + +/** + * GET blockchain API status + * @export + * @interface ServerStatusResponse + */ +export interface ServerStatusResponse { + /** + * the server version that is currently running + * @type {string} + * @memberof ServerStatusResponse + */ + server_version?: string; + /** + * the current server status + * @type {string} + * @memberof ServerStatusResponse + */ + status: string; + /** + * + * @type {number} + * @memberof ServerStatusResponse + */ + pox_v1_unlock_height?: number | null; + /** + * + * @type {number} + * @memberof ServerStatusResponse + */ + pox_v2_unlock_height?: number | null; + /** + * + * @type {ChainTip} + * @memberof ServerStatusResponse + */ + chain_tip?: ChainTip; +} + +export function ServerStatusResponseFromJSON(json: any): ServerStatusResponse { + return ServerStatusResponseFromJSONTyped(json, false); +} + +export function ServerStatusResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): ServerStatusResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'server_version': !exists(json, 'server_version') ? undefined : json['server_version'], + 'status': json['status'], + 'pox_v1_unlock_height': !exists(json, 'pox_v1_unlock_height') ? undefined : json['pox_v1_unlock_height'], + 'pox_v2_unlock_height': !exists(json, 'pox_v2_unlock_height') ? undefined : json['pox_v2_unlock_height'], + 'chain_tip': !exists(json, 'chain_tip') ? undefined : ChainTipFromJSON(json['chain_tip']), + }; +} + +export function ServerStatusResponseToJSON(value?: ServerStatusResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'server_version': value.server_version, + 'status': value.status, + 'pox_v1_unlock_height': value.pox_v1_unlock_height, + 'pox_v2_unlock_height': value.pox_v2_unlock_height, + 'chain_tip': ChainTipToJSON(value.chain_tip), + }; +} + diff --git a/client/src/generated/models/SigningPayload.ts b/client/src/generated/models/SigningPayload.ts index 3862c96922..2d455c7214 100644 --- a/client/src/generated/models/SigningPayload.ts +++ b/client/src/generated/models/SigningPayload.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -27,7 +27,7 @@ import { */ export interface SigningPayload { /** - * The network-specific address of the account that should sign the payload. + * [DEPRECATED by account_identifier in v1.4.4] The network-specific address of the account that should sign the payload. * @type {string} * @memberof SigningPayload */ @@ -52,6 +52,18 @@ export interface SigningPayload { signature_type?: SigningPayloadSignatureTypeEnum; } +/** +* @export +* @enum {string} +*/ +export enum SigningPayloadSignatureTypeEnum { + ecdsa = 'ecdsa', + ecdsa_recovery = 'ecdsa_recovery', + ed25519 = 'ed25519', + schnorr_1 = 'schnorr_1', + schnorr_poseidon = 'schnorr_poseidon' +} + export function SigningPayloadFromJSON(json: any): SigningPayload { return SigningPayloadFromJSONTyped(json, false); } @@ -85,16 +97,3 @@ export function SigningPayloadToJSON(value?: SigningPayload | null): any { }; } -/** -* @export -* @enum {string} -*/ -export enum SigningPayloadSignatureTypeEnum { - ecdsa = 'ecdsa', - ecdsa_recovery = 'ecdsa_recovery', - ed25519 = 'ed25519', - schnorr_1 = 'schnorr_1', - schnorr_poseidon = 'schnorr_poseidon' -} - - diff --git a/client/src/generated/models/SmartContract.ts b/client/src/generated/models/SmartContract.ts new file mode 100644 index 0000000000..434386b650 --- /dev/null +++ b/client/src/generated/models/SmartContract.ts @@ -0,0 +1,96 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * A Smart Contract Detail + * @export + * @interface SmartContract + */ +export interface SmartContract { + /** + * + * @type {string} + * @memberof SmartContract + */ + tx_id: string; + /** + * + * @type {boolean} + * @memberof SmartContract + */ + canonical: boolean; + /** + * + * @type {string} + * @memberof SmartContract + */ + contract_id: string; + /** + * + * @type {number} + * @memberof SmartContract + */ + block_height: number; + /** + * + * @type {string} + * @memberof SmartContract + */ + source_code: string; + /** + * + * @type {string} + * @memberof SmartContract + */ + abi: string; +} + +export function SmartContractFromJSON(json: any): SmartContract { + return SmartContractFromJSONTyped(json, false); +} + +export function SmartContractFromJSONTyped(json: any, ignoreDiscriminator: boolean): SmartContract { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'tx_id': json['tx_id'], + 'canonical': json['canonical'], + 'contract_id': json['contract_id'], + 'block_height': json['block_height'], + 'source_code': json['source_code'], + 'abi': json['abi'], + }; +} + +export function SmartContractToJSON(value?: SmartContract | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'tx_id': value.tx_id, + 'canonical': value.canonical, + 'contract_id': value.contract_id, + 'block_height': value.block_height, + 'source_code': value.source_code, + 'abi': value.abi, + }; +} + diff --git a/client/src/generated/models/AddressBalanceResponseStx.ts b/client/src/generated/models/StxBalance.ts similarity index 53% rename from client/src/generated/models/AddressBalanceResponseStx.ts rename to client/src/generated/models/StxBalance.ts index dccbec6dcc..1bfdc71358 100644 --- a/client/src/generated/models/AddressBalanceResponseStx.ts +++ b/client/src/generated/models/StxBalance.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -14,78 +14,78 @@ import { exists, mapValues } from '../runtime'; /** - * StxBalance + * * @export - * @interface AddressBalanceResponseStx + * @interface StxBalance */ -export interface AddressBalanceResponseStx { +export interface StxBalance { /** * * @type {string} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ balance: string; /** * * @type {string} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ total_sent: string; /** * * @type {string} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ total_received: string; /** * * @type {string} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ total_fees_sent: string; /** * * @type {string} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ total_miner_rewards_received: string; /** * The transaction where the lock event occurred. Empty if no tokens are locked. * @type {string} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ lock_tx_id: string; /** * The amount of locked STX, as string quoted micro-STX. Zero if no tokens are locked. * @type {string} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ locked: string; /** * The STX chain block height of when the lock event occurred. Zero if no tokens are locked. * @type {number} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ lock_height: number; /** * The burnchain block height of when the lock event occurred. Zero if no tokens are locked. * @type {number} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ burnchain_lock_height: number; /** * The burnchain block height of when the tokens unlock. Zero if no tokens are locked. * @type {number} - * @memberof AddressBalanceResponseStx + * @memberof StxBalance */ burnchain_unlock_height: number; } -export function AddressBalanceResponseStxFromJSON(json: any): AddressBalanceResponseStx { - return AddressBalanceResponseStxFromJSONTyped(json, false); +export function StxBalanceFromJSON(json: any): StxBalance { + return StxBalanceFromJSONTyped(json, false); } -export function AddressBalanceResponseStxFromJSONTyped(json: any, ignoreDiscriminator: boolean): AddressBalanceResponseStx { +export function StxBalanceFromJSONTyped(json: any, ignoreDiscriminator: boolean): StxBalance { if ((json === undefined) || (json === null)) { return json; } @@ -104,7 +104,7 @@ export function AddressBalanceResponseStxFromJSONTyped(json: any, ignoreDiscrimi }; } -export function AddressBalanceResponseStxToJSON(value?: AddressBalanceResponseStx | null): any { +export function StxBalanceToJSON(value?: StxBalance | null): any { if (value === undefined) { return undefined; } @@ -126,4 +126,3 @@ export function AddressBalanceResponseStxToJSON(value?: AddressBalanceResponseSt }; } - diff --git a/client/src/generated/models/TargetBlockTime.ts b/client/src/generated/models/TargetBlockTime.ts new file mode 100644 index 0000000000..d232ca9ee5 --- /dev/null +++ b/client/src/generated/models/TargetBlockTime.ts @@ -0,0 +1,56 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface TargetBlockTime + */ +export interface TargetBlockTime { + /** + * + * @type {number} + * @memberof TargetBlockTime + */ + target_block_time: number; +} + +export function TargetBlockTimeFromJSON(json: any): TargetBlockTime { + return TargetBlockTimeFromJSONTyped(json, false); +} + +export function TargetBlockTimeFromJSONTyped(json: any, ignoreDiscriminator: boolean): TargetBlockTime { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'target_block_time': json['target_block_time'], + }; +} + +export function TargetBlockTimeToJSON(value?: TargetBlockTime | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'target_block_time': value.target_block_time, + }; +} + diff --git a/client/src/generated/models/TransactionEventsResponse.ts b/client/src/generated/models/TransactionEventsResponse.ts new file mode 100644 index 0000000000..b0ef8b76eb --- /dev/null +++ b/client/src/generated/models/TransactionEventsResponse.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * GET event for the given transaction + * @export + * @interface TransactionEventsResponse + */ +export interface TransactionEventsResponse { + /** + * + * @type {number} + * @memberof TransactionEventsResponse + */ + limit: number; + /** + * + * @type {number} + * @memberof TransactionEventsResponse + */ + offset: number; + /** + * + * @type {Array} + * @memberof TransactionEventsResponse + */ + results: Array; +} + +export function TransactionEventsResponseFromJSON(json: any): TransactionEventsResponse { + return TransactionEventsResponseFromJSONTyped(json, false); +} + +export function TransactionEventsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): TransactionEventsResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'limit': json['limit'], + 'offset': json['offset'], + 'results': json['results'], + }; +} + +export function TransactionEventsResponseToJSON(value?: TransactionEventsResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'limit': value.limit, + 'offset': value.offset, + 'results': value.results, + }; +} + diff --git a/client/src/generated/models/TransactionFeeEstimateRequest.ts b/client/src/generated/models/TransactionFeeEstimateRequest.ts new file mode 100644 index 0000000000..e34df71d21 --- /dev/null +++ b/client/src/generated/models/TransactionFeeEstimateRequest.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * POST request for estimated fee + * @export + * @interface TransactionFeeEstimateRequest + */ +export interface TransactionFeeEstimateRequest { + /** + * + * @type {string} + * @memberof TransactionFeeEstimateRequest + */ + transaction_payload: string; + /** + * + * @type {number} + * @memberof TransactionFeeEstimateRequest + */ + estimated_len?: number; +} + +export function TransactionFeeEstimateRequestFromJSON(json: any): TransactionFeeEstimateRequest { + return TransactionFeeEstimateRequestFromJSONTyped(json, false); +} + +export function TransactionFeeEstimateRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): TransactionFeeEstimateRequest { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'transaction_payload': json['transaction_payload'], + 'estimated_len': !exists(json, 'estimated_len') ? undefined : json['estimated_len'], + }; +} + +export function TransactionFeeEstimateRequestToJSON(value?: TransactionFeeEstimateRequest | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'transaction_payload': value.transaction_payload, + 'estimated_len': value.estimated_len, + }; +} + diff --git a/client/src/generated/models/TransactionFeeEstimateResponse.ts b/client/src/generated/models/TransactionFeeEstimateResponse.ts new file mode 100644 index 0000000000..39bd7fcbdd --- /dev/null +++ b/client/src/generated/models/TransactionFeeEstimateResponse.ts @@ -0,0 +1,91 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +import { + TransactionFeeEstimateResponseEstimatedCost, + TransactionFeeEstimateResponseEstimatedCostFromJSON, + TransactionFeeEstimateResponseEstimatedCostFromJSONTyped, + TransactionFeeEstimateResponseEstimatedCostToJSON, + TransactionFeeEstimateResponseEstimations, + TransactionFeeEstimateResponseEstimationsFromJSON, + TransactionFeeEstimateResponseEstimationsFromJSONTyped, + TransactionFeeEstimateResponseEstimationsToJSON, +} from './'; + +/** + * POST response for estimated fee + * @export + * @interface TransactionFeeEstimateResponse + */ +export interface TransactionFeeEstimateResponse { + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponse + */ + estimated_cost_scalar: number; + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponse + */ + cost_scalar_change_by_byte?: number; + /** + * + * @type {TransactionFeeEstimateResponseEstimatedCost} + * @memberof TransactionFeeEstimateResponse + */ + estimated_cost: TransactionFeeEstimateResponseEstimatedCost; + /** + * + * @type {Array} + * @memberof TransactionFeeEstimateResponse + */ + estimations?: Array; +} + +export function TransactionFeeEstimateResponseFromJSON(json: any): TransactionFeeEstimateResponse { + return TransactionFeeEstimateResponseFromJSONTyped(json, false); +} + +export function TransactionFeeEstimateResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): TransactionFeeEstimateResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'estimated_cost_scalar': json['estimated_cost_scalar'], + 'cost_scalar_change_by_byte': !exists(json, 'cost_scalar_change_by_byte') ? undefined : json['cost_scalar_change_by_byte'], + 'estimated_cost': TransactionFeeEstimateResponseEstimatedCostFromJSON(json['estimated_cost']), + 'estimations': !exists(json, 'estimations') ? undefined : ((json['estimations'] as Array).map(TransactionFeeEstimateResponseEstimationsFromJSON)), + }; +} + +export function TransactionFeeEstimateResponseToJSON(value?: TransactionFeeEstimateResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'estimated_cost_scalar': value.estimated_cost_scalar, + 'cost_scalar_change_by_byte': value.cost_scalar_change_by_byte, + 'estimated_cost': TransactionFeeEstimateResponseEstimatedCostToJSON(value.estimated_cost), + 'estimations': value.estimations === undefined ? undefined : ((value.estimations as Array).map(TransactionFeeEstimateResponseEstimationsToJSON)), + }; +} + diff --git a/client/src/generated/models/TransactionFeeEstimateResponseEstimatedCost.ts b/client/src/generated/models/TransactionFeeEstimateResponseEstimatedCost.ts new file mode 100644 index 0000000000..dc4160a3a0 --- /dev/null +++ b/client/src/generated/models/TransactionFeeEstimateResponseEstimatedCost.ts @@ -0,0 +1,88 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface TransactionFeeEstimateResponseEstimatedCost + */ +export interface TransactionFeeEstimateResponseEstimatedCost { + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponseEstimatedCost + */ + read_count: number; + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponseEstimatedCost + */ + read_length: number; + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponseEstimatedCost + */ + runtime: number; + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponseEstimatedCost + */ + write_count: number; + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponseEstimatedCost + */ + write_length: number; +} + +export function TransactionFeeEstimateResponseEstimatedCostFromJSON(json: any): TransactionFeeEstimateResponseEstimatedCost { + return TransactionFeeEstimateResponseEstimatedCostFromJSONTyped(json, false); +} + +export function TransactionFeeEstimateResponseEstimatedCostFromJSONTyped(json: any, ignoreDiscriminator: boolean): TransactionFeeEstimateResponseEstimatedCost { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'read_count': json['read_count'], + 'read_length': json['read_length'], + 'runtime': json['runtime'], + 'write_count': json['write_count'], + 'write_length': json['write_length'], + }; +} + +export function TransactionFeeEstimateResponseEstimatedCostToJSON(value?: TransactionFeeEstimateResponseEstimatedCost | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'read_count': value.read_count, + 'read_length': value.read_length, + 'runtime': value.runtime, + 'write_count': value.write_count, + 'write_length': value.write_length, + }; +} + diff --git a/client/src/generated/models/TransactionFeeEstimateResponseEstimations.ts b/client/src/generated/models/TransactionFeeEstimateResponseEstimations.ts new file mode 100644 index 0000000000..ccb1484e89 --- /dev/null +++ b/client/src/generated/models/TransactionFeeEstimateResponseEstimations.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * + * @export + * @interface TransactionFeeEstimateResponseEstimations + */ +export interface TransactionFeeEstimateResponseEstimations { + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponseEstimations + */ + fee_rate?: number; + /** + * + * @type {number} + * @memberof TransactionFeeEstimateResponseEstimations + */ + fee?: number; +} + +export function TransactionFeeEstimateResponseEstimationsFromJSON(json: any): TransactionFeeEstimateResponseEstimations { + return TransactionFeeEstimateResponseEstimationsFromJSONTyped(json, false); +} + +export function TransactionFeeEstimateResponseEstimationsFromJSONTyped(json: any, ignoreDiscriminator: boolean): TransactionFeeEstimateResponseEstimations { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'fee_rate': !exists(json, 'fee_rate') ? undefined : json['fee_rate'], + 'fee': !exists(json, 'fee') ? undefined : json['fee'], + }; +} + +export function TransactionFeeEstimateResponseEstimationsToJSON(value?: TransactionFeeEstimateResponseEstimations | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'fee_rate': value.fee_rate, + 'fee': value.fee, + }; +} + diff --git a/client/src/generated/models/TransactionIdentifier.ts b/client/src/generated/models/TransactionIdentifier.ts index f7cc96773e..539bb6983e 100644 --- a/client/src/generated/models/TransactionIdentifier.ts +++ b/client/src/generated/models/TransactionIdentifier.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -54,4 +54,3 @@ export function TransactionIdentifierToJSON(value?: TransactionIdentifier | null }; } - diff --git a/client/src/generated/models/TransactionResults.ts b/client/src/generated/models/TransactionResults.ts index 1defa58877..6d9353ee16 100644 --- a/client/src/generated/models/TransactionResults.ts +++ b/client/src/generated/models/TransactionResults.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -78,4 +78,3 @@ export function TransactionResultsToJSON(value?: TransactionResults | null): any }; } - diff --git a/client/src/generated/models/UnanchoredTransactionListResponse.ts b/client/src/generated/models/UnanchoredTransactionListResponse.ts new file mode 100644 index 0000000000..ff248f61fb --- /dev/null +++ b/client/src/generated/models/UnanchoredTransactionListResponse.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection + * + * The version of the OpenAPI document: STACKS_API_VERSION + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { exists, mapValues } from '../runtime'; +/** + * GET request that returns unanchored transactions + * @export + * @interface UnanchoredTransactionListResponse + */ +export interface UnanchoredTransactionListResponse { + /** + * The number of unanchored transactions available + * @type {number} + * @memberof UnanchoredTransactionListResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof UnanchoredTransactionListResponse + */ + results: Array; +} + +export function UnanchoredTransactionListResponseFromJSON(json: any): UnanchoredTransactionListResponse { + return UnanchoredTransactionListResponseFromJSONTyped(json, false); +} + +export function UnanchoredTransactionListResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): UnanchoredTransactionListResponse { + if ((json === undefined) || (json === null)) { + return json; + } + return { + + 'total': json['total'], + 'results': json['results'], + }; +} + +export function UnanchoredTransactionListResponseToJSON(value?: UnanchoredTransactionListResponse | null): any { + if (value === undefined) { + return undefined; + } + if (value === null) { + return null; + } + return { + + 'total': value.total, + 'results': value.results, + }; +} + diff --git a/client/src/generated/models/index.ts b/client/src/generated/models/index.ts index e6735df4c5..8523717aef 100644 --- a/client/src/generated/models/index.ts +++ b/client/src/generated/models/index.ts @@ -1,24 +1,74 @@ +/* tslint:disable */ +/* eslint-disable */ export * from './AccountDataResponse'; export * from './AddressAssetsListResponse'; export * from './AddressBalanceResponse'; -export * from './AddressBalanceResponseStx'; -export * from './AddressStxBalanceResponse'; +export * from './AddressNftListResponse'; +export * from './AddressNftListResponseValue'; +export * from './AddressNonces'; +export * from './AddressStxInboundListResponse'; +export * from './AddressTokenOfferingLocked'; +export * from './AddressTransactionWithTransfers'; +export * from './AddressTransactionWithTransfersFtTransfers'; +export * from './AddressTransactionWithTransfersNftTransfers'; +export * from './AddressTransactionWithTransfersStxTransfers'; +export * from './AddressTransactionWithTransfersValue'; export * from './AddressTransactionsListResponse'; +export * from './AddressTransactionsWithTransfersListResponse'; +export * from './AddressUnlockSchedule'; export * from './Block'; export * from './BlockListResponse'; +export * from './BnsError'; +export * from './BnsGetAllNamespacesResponse'; +export * from './BnsGetNameInfoResponse'; +export * from './BnsGetNamePriceResponse'; +export * from './BnsGetNamespacePriceResponse'; +export * from './BnsNamesOwnByAddressResponse'; export * from './BurnchainReward'; export * from './BurnchainRewardListResponse'; +export * from './BurnchainRewardSlotHolder'; +export * from './BurnchainRewardSlotHolderListResponse'; export * from './BurnchainRewardsTotal'; +export * from './ChainTip'; export * from './ContractInterfaceResponse'; +export * from './ContractListResponse'; export * from './ContractSourceResponse'; export * from './CoreNodeInfoResponse'; export * from './CoreNodePoxResponse'; +export * from './FeeRate'; +export * from './FeeRateRequest'; +export * from './FungibleTokenMetadata'; +export * from './FungibleTokensMetadataList'; +export * from './GetRawTransactionResult'; +export * from './GetStxSupplyLegacyFormatResponse'; +export * from './GetStxSupplyResponse'; +export * from './InboundStxTransfer'; +export * from './InlineObject'; +export * from './InlineResponse403'; export * from './MapEntryResponse'; +export * from './MempoolFeePriorities'; +export * from './MempoolFeePrioritiesAll'; export * from './MempoolTransactionListResponse'; +export * from './MempoolTransactionStatsResponse'; +export * from './MempoolTransactionStatsResponseTxAges'; +export * from './MempoolTransactionStatsResponseTxByteSizes'; +export * from './MempoolTransactionStatsResponseTxSimpleFeeAverages'; +export * from './MempoolTransactionStatsResponseTxSimpleFeeAveragesTokenTransfer'; +export * from './MempoolTransactionStatsResponseTxTypeCounts'; +export * from './Microblock'; +export * from './MicroblockListResponse'; export * from './NetworkBlockTimeResponse'; export * from './NetworkBlockTimesResponse'; -export * from './NetworkBlockTimesResponseMainnet'; export * from './NetworkIdentifier'; +export * from './NftEvent'; +export * from './NonFungibleTokenHistoryEventList'; +export * from './NonFungibleTokenHoldingsList'; +export * from './NonFungibleTokenMetadata'; +export * from './NonFungibleTokenMintList'; +export * from './NonFungibleTokensMetadataList'; +export * from './OtherTransactionIdentifier'; +export * from './PoolDelegation'; +export * from './PoolDelegationsResponse'; export * from './PostCoreNodeTransactionsError'; export * from './ReadOnlyFunctionArgs'; export * from './ReadOnlyFunctionSuccessResponse'; @@ -27,11 +77,11 @@ export * from './RosettaAccountBalanceRequest'; export * from './RosettaAccountBalanceResponse'; export * from './RosettaAccountBalanceResponseCoinIdentifier'; export * from './RosettaAccountBalanceResponseMetadata'; +export * from './RosettaAccountIdentifier'; export * from './RosettaAmount'; export * from './RosettaBlock'; export * from './RosettaBlockMetadata'; export * from './RosettaBlockMetadata1'; -export * from './RosettaBlockMetadata2'; export * from './RosettaBlockRequest'; export * from './RosettaBlockResponse'; export * from './RosettaBlockTransactionRequest'; @@ -58,6 +108,9 @@ export * from './RosettaConstructionSubmitResponse'; export * from './RosettaCurrency'; export * from './RosettaError'; export * from './RosettaErrorDetails'; +export * from './RosettaErrorNoDetails'; +export * from './RosettaGenesisBlockIdentifier'; +export * from './RosettaMaxFeeAmount'; export * from './RosettaMempoolRequest'; export * from './RosettaMempoolResponse'; export * from './RosettaMempoolTransactionRequest'; @@ -68,19 +121,33 @@ export * from './RosettaNetworkListResponseSubNetworkIdentifierMetadata'; export * from './RosettaNetworkOptionsResponse'; export * from './RosettaNetworkOptionsResponseAllow'; export * from './RosettaNetworkOptionsResponseVersion'; +export * from './RosettaNetworkStatusResponse'; +export * from './RosettaOldestBlockIdentifier'; export * from './RosettaOperation'; export * from './RosettaOperationIdentifier'; export * from './RosettaOperationStatus'; export * from './RosettaOptions'; export * from './RosettaOptionsRequest'; export * from './RosettaParentBlockIdentifier'; +export * from './RosettaPeers'; export * from './RosettaPublicKey'; export * from './RosettaRelatedOperation'; export * from './RosettaSignature'; export * from './RosettaStatusRequest'; export * from './RosettaSubAccount'; +export * from './RosettaSyncStatus'; export * from './RosettaTransaction'; export * from './RunFaucetResponse'; +export * from './ServerStatusResponse'; export * from './SigningPayload'; +export * from './SmartContract'; +export * from './StxBalance'; +export * from './TargetBlockTime'; +export * from './TransactionEventsResponse'; +export * from './TransactionFeeEstimateRequest'; +export * from './TransactionFeeEstimateResponse'; +export * from './TransactionFeeEstimateResponseEstimatedCost'; +export * from './TransactionFeeEstimateResponseEstimations'; export * from './TransactionIdentifier'; export * from './TransactionResults'; +export * from './UnanchoredTransactionListResponse'; diff --git a/client/src/generated/runtime.ts b/client/src/generated/runtime.ts index 8557681453..7ff36f09e5 100644 --- a/client/src/generated/runtime.ts +++ b/client/src/generated/runtime.ts @@ -1,10 +1,10 @@ /* tslint:disable */ /* eslint-disable */ /** - * Stacks 2.0 Blockchain API - * This is the documentation for the Stacks 2.0 Blockchain API. It is comprised of two parts; the Stacks Blockchain API and the Stacks Core API. [![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/614feab5c108d292bffa#?env%5BStacks%20Blockchain%20API%5D=W3sia2V5Ijoic3R4X2FkZHJlc3MiLCJ2YWx1ZSI6IlNUMlRKUkhESE1ZQlE0MTdIRkIwQkRYNDMwVFFBNVBYUlg2NDk1RzFWIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJibG9ja19pZCIsInZhbHVlIjoiMHgiLCJlbmFibGVkIjp0cnVlfSx7ImtleSI6Im9mZnNldCIsInZhbHVlIjoiMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfdHgiLCJ2YWx1ZSI6IjIwMCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoibGltaXRfYmxvY2siLCJ2YWx1ZSI6IjMwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJ0eF9pZCIsInZhbHVlIjoiMHg1NDA5MGMxNmE3MDJiNzUzYjQzMTE0ZTg4NGJjMTlhODBhNzk2MzhmZDQ0OWE0MGY4MDY4Y2RmMDAzY2RlNmUwIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9pZCIsInZhbHVlIjoiU1RKVFhFSlBKUFBWRE5BOUIwNTJOU1JSQkdRQ0ZOS1ZTMTc4VkdIMS5oZWxsb193b3JsZFxuIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJidGNfYWRkcmVzcyIsInZhbHVlIjoiYWJjIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9hZGRyZXNzIiwidmFsdWUiOiJTVEpUWEVKUEpQUFZETkE5QjA1Mk5TUlJCR1FDRk5LVlMxNzhWR0gxIiwiZW5hYmxlZCI6dHJ1ZX0seyJrZXkiOiJjb250cmFjdF9uYW1lIiwidmFsdWUiOiJoZWxsb193b3JsZCIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWFwIiwidmFsdWUiOiJzdG9yZSIsImVuYWJsZWQiOnRydWV9LHsia2V5IjoiY29udHJhY3RfbWV0aG9kIiwidmFsdWUiOiJnZXQtdmFsdWUiLCJlbmFibGVkIjp0cnVlfV0=) + * Stacks Blockchain API + * Welcome to the API reference overview for the Stacks Blockchain API. Download Postman collection * - * The version of the OpenAPI document: 1.0.0 + * The version of the OpenAPI document: STACKS_API_VERSION * * * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). @@ -44,8 +44,8 @@ export class BaseAPI { return this.withMiddleware(...middlewares); } - protected async request(context: RequestOpts): Promise { - const { url, init } = this.createFetchParams(context); + protected async request(context: RequestOpts, initOverrides?: RequestInit): Promise { + const { url, init } = this.createFetchParams(context, initOverrides); const response = await this.fetchApi(url, init); if (response.status >= 200 && response.status < 300) { return response; @@ -53,7 +53,7 @@ export class BaseAPI { throw response; } - private createFetchParams(context: RequestOpts) { + private createFetchParams(context: RequestOpts, initOverrides?: RequestInit) { let url = this.configuration.basePath + context.path; if (context.query !== undefined && Object.keys(context.query).length !== 0) { // only add the querystring to the URL if there are query parameters. @@ -62,15 +62,16 @@ export class BaseAPI { url += '?' + this.configuration.queryParamsStringify(context.query); } const body = ((typeof FormData !== "undefined" && context.body instanceof FormData) || context.body instanceof URLSearchParams || isBlob(context.body)) - ? context.body - : JSON.stringify(context.body); + ? context.body + : JSON.stringify(context.body); const headers = Object.assign({}, this.configuration.headers, context.headers); const init = { method: context.method, headers: headers, body, - credentials: this.configuration.credentials + credentials: this.configuration.credentials, + ...initOverrides }; return { url, init }; } @@ -85,13 +86,13 @@ export class BaseAPI { }) || fetchParams; } } - let response = await this.configuration.fetchApi(fetchParams.url, fetchParams.init); + let response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init); for (const middleware of this.middleware) { if (middleware.post) { response = await middleware.post({ fetch: this.fetchApi, - url, - init, + url: fetchParams.url, + init: fetchParams.init, response: response.clone(), }) || response; } @@ -135,7 +136,7 @@ export interface ConfigurationParameters { username?: string; // parameter for basic security password?: string; // parameter for basic security apiKey?: string | ((name: string) => string); // parameter for apiKey security - accessToken?: string | ((name?: string, scopes?: string[]) => string); // parameter for oauth2 security + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // parameter for oauth2 security headers?: HTTPHeaders; //header params we want to use on every request credentials?: RequestCredentials; //value for the credentials param we want to use on each request } @@ -147,8 +148,8 @@ export class Configuration { return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH; } - get fetchApi(): FetchAPI { - return this.configuration.fetchApi || window.fetch.bind(window); + get fetchApi(): FetchAPI | undefined { + return this.configuration.fetchApi; } get middleware(): Middleware[] { @@ -175,15 +176,15 @@ export class Configuration { return undefined; } - get accessToken(): ((name: string, scopes?: string[]) => string) | undefined { + get accessToken(): ((name?: string, scopes?: string[]) => string | Promise) | undefined { const accessToken = this.configuration.accessToken; if (accessToken) { - return typeof accessToken === 'function' ? accessToken : () => accessToken; + return typeof accessToken === 'function' ? accessToken : async () => accessToken; } return undefined; } - get headers(): HTTPHeaders | undefined { + get headers(): HTTPHeaders | undefined { return this.configuration.headers; } @@ -227,6 +228,9 @@ export function querystring(params: HTTPQuery, prefix: string = ''): string { .join(`&${encodeURIComponent(fullKey)}=`); return `${encodeURIComponent(fullKey)}=${multiValue}`; } + if (value instanceof Date) { + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`; + } if (value instanceof Object) { return querystring(value as HTTPQuery, fullKey); } diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 7e3394ed43..7c5030d407 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -312,9 +312,9 @@ paths: content: application/json: schema: - $ref: ./api/transaction/get-mempool-transactions.schema.json + $ref: ./api/mempool/get-fee-priorities.schema.json example: - $ref: ./api/transaction/get-mempool-transactions.example.json + $ref: ./api/mempool/get-fee-priorities.example.json /extended/v1/tx/mempool/dropped: get: From 6b4e55d56d82efee5f40ae75ddd2e95184f52aa0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 4 Jan 2024 17:25:44 +0000 Subject: [PATCH 66/91] chore(release): 7.4.0-beta.2 [skip ci] ## [7.4.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-beta.1...v7.4.0-beta.2) (2024-01-04) ### Bug Fixes * update client code, fix mempool fee return type ([#1797](https://github.com/hirosystems/stacks-blockchain-api/issues/1797)) ([9853e29](https://github.com/hirosystems/stacks-blockchain-api/commit/9853e29d89b2846454197438c7d1b4b636384d6d)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf11711912..edcd066282 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-beta.1...v7.4.0-beta.2) (2024-01-04) + + +### Bug Fixes + +* update client code, fix mempool fee return type ([#1797](https://github.com/hirosystems/stacks-blockchain-api/issues/1797)) ([9853e29](https://github.com/hirosystems/stacks-blockchain-api/commit/9853e29d89b2846454197438c7d1b4b636384d6d)) + ## [7.4.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.7-beta.1...v7.4.0-beta.1) (2024-01-03) From 5050763e3f9838b1bf16080747e80dc0b4abf261 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 4 Jan 2024 18:42:20 +0000 Subject: [PATCH 67/91] chore(release): 7.4.0 [skip ci] ## [7.4.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.6...v7.4.0) (2024-01-04) ### Features * add `/extended/v2/mempool/fees` endpoint ([#1795](https://github.com/hirosystems/stacks-blockchain-api/issues/1795)) ([ea9c378](https://github.com/hirosystems/stacks-blockchain-api/commit/ea9c3783e62715747db06eea5dd837297271c21e)) ### Bug Fixes * convert `chain_tip` materialized view into a table ([#1789](https://github.com/hirosystems/stacks-blockchain-api/issues/1789)) ([0211932](https://github.com/hirosystems/stacks-blockchain-api/commit/02119326993891cc586274fab0e0fc3f5fd15ef1)), closes [#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751) * optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([#1792](https://github.com/hirosystems/stacks-blockchain-api/issues/1792)) ([2700642](https://github.com/hirosystems/stacks-blockchain-api/commit/2700642ed2225ce8598ee5fff833603007d5289f)) * release pino logger and mempool nonces ([16d3593](https://github.com/hirosystems/stacks-blockchain-api/commit/16d359370b413de36444d15a3a48cf479823367f)) * update client code, fix mempool fee return type ([#1797](https://github.com/hirosystems/stacks-blockchain-api/issues/1797)) ([9853e29](https://github.com/hirosystems/stacks-blockchain-api/commit/9853e29d89b2846454197438c7d1b4b636384d6d)) --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index edcd066282..29a61b63ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +## [7.4.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.6...v7.4.0) (2024-01-04) + + +### Features + +* add `/extended/v2/mempool/fees` endpoint ([#1795](https://github.com/hirosystems/stacks-blockchain-api/issues/1795)) ([ea9c378](https://github.com/hirosystems/stacks-blockchain-api/commit/ea9c3783e62715747db06eea5dd837297271c21e)) + + +### Bug Fixes + +* convert `chain_tip` materialized view into a table ([#1789](https://github.com/hirosystems/stacks-blockchain-api/issues/1789)) ([0211932](https://github.com/hirosystems/stacks-blockchain-api/commit/02119326993891cc586274fab0e0fc3f5fd15ef1)), closes [#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751) +* optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([#1792](https://github.com/hirosystems/stacks-blockchain-api/issues/1792)) ([2700642](https://github.com/hirosystems/stacks-blockchain-api/commit/2700642ed2225ce8598ee5fff833603007d5289f)) +* release pino logger and mempool nonces ([16d3593](https://github.com/hirosystems/stacks-blockchain-api/commit/16d359370b413de36444d15a3a48cf479823367f)) +* update client code, fix mempool fee return type ([#1797](https://github.com/hirosystems/stacks-blockchain-api/issues/1797)) ([9853e29](https://github.com/hirosystems/stacks-blockchain-api/commit/9853e29d89b2846454197438c7d1b4b636384d6d)) + ## [7.4.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-beta.1...v7.4.0-beta.2) (2024-01-04) From 5634522132448fa480fcb18978a9cf2bf6f50a37 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 5 Jan 2024 16:41:32 +0100 Subject: [PATCH 68/91] feat: add listener callback to socket-io client subscription functions (#1799) * feat: add listener callback to socket-io client subscription functions * chore: fix test * test: add unit tests for socket-io-client * docs: update socket-io client docs * chore: lint fix in client lib src * test: fix flaky pox test --- client/.prettierignore | 1 + client/README.md | 29 +- client/package-lock.json | 4623 +++++++++-------- client/package.json | 31 +- client/src/socket-io/index.ts | 138 +- client/src/ws/index.ts | 19 +- client/tsconfig.json | 2 +- docs/socket-io/index.d.ts | 17 +- .../routes/ws/channels/socket-io-channel.ts | 36 +- src/tests-2.4/pox-3-delegate-aggregation.ts | 1 + src/tests/socket-io-tests.ts | 79 +- 11 files changed, 2785 insertions(+), 2191 deletions(-) create mode 100644 client/.prettierignore diff --git a/client/.prettierignore b/client/.prettierignore new file mode 100644 index 0000000000..e20b710386 --- /dev/null +++ b/client/.prettierignore @@ -0,0 +1 @@ +src/generated/* diff --git a/client/README.md b/client/README.md index 85e5285c47..4087009b7c 100644 --- a/client/README.md +++ b/client/README.md @@ -51,12 +51,13 @@ import * as stacks from '@stacks/blockchain-api-client'; // for testnet, replace with https://api.testnet.hiro.so/ const socketUrl = "https://api.mainnet.hiro.so/"; -const socket = io(socketUrl, { - transports: [ "websocket" ] -}); +const socket = io(socketUrl); const sc = new stacks.StacksApiSocketClient(socket); -sc.subscribeAddressTransactions('ST3GQB6WGCWKDNFNPSQRV8DY93JN06XPZ2ZE9EVMA'); +sc.subscribeAddressTransactions('ST3GQB6WGCWKDNFNPSQRV8DY93JN06XPZ2ZE9EVMA', (address, tx) => { + console.log('address:', address); + console.log('tx:', tx); +}); ``` ## Available Updates @@ -108,7 +109,7 @@ client.subscribeBlocks(event => {}); ``` Subscribe via Socket.io: ```js -sc.subscribeBlocks(); +sc.subscribeBlocks(block => {}); ``` ### Microblock Updates @@ -149,7 +150,7 @@ client.subscribeMicroblocks(event => {}); ``` Subscribe via Socket.io: ```js -sc.subscribeMicroblocks(); +sc.subscribeMicroblocks(microblock => {}); ``` ### Mempool Updates @@ -210,7 +211,7 @@ client.subscribeMempool(event => {}); ``` Subscribe via Socket.io: ```js -sc.subscribeMempool(); +sc.subscribeMempool(mempoolTx => {}); ``` ### Transaction Updates @@ -277,7 +278,7 @@ client.subscribeTxUpdates('0xd78988664aaa9a1b751cd58c55b253914f790e95ca6f3d402a8 ``` Subscribe via Socket.io: ```js -sc.subscribeTransaction('0xd78988664aaa9a1b751cd58c55b253914f790e95ca6f3d402a866559e1cbe0b3'); +sc.subscribeTransaction('0xd78988664aaa9a1b751cd58c55b253914f790e95ca6f3d402a866559e1cbe0b3', tx => {}); ``` ### Address Transaction Updates @@ -366,7 +367,7 @@ client.subscribeAddressTransactions('SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q', ``` Subscribe via Socket.io: ```js -sc.subscribeAddressTransactions('SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q'); +sc.subscribeAddressTransactions('SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q', (address, tx) => {}); ``` ### Address Balance Updates @@ -412,7 +413,7 @@ client.subscribeAddressBalanceUpdates('SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q ``` Subscribe via Socket.io: ```js -sc.subscribeAddressStxBalance('SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q'); +sc.subscribeAddressStxBalance('SP3C5SSYVKPAWTR8Y63CVYBR65GD3MG7K80526D1Q', (addr, balance) => {}); ``` ### NFT event updates @@ -451,13 +452,15 @@ client.subscribeNftCollectionEventUpdates( ``` Subscribe via Socket.io: ```js -sc.subscribeNftEventUpdates(); -sc.subscribeNftAssetEventUpdates( +sc.subscribeNftEvent(nftEvent => {}); +sc.subscribeNftAssetEvent( 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1::Project-Indigo-Act1', '0x0100000000000000000000000000000095', + (assetId, value, nftEvent) => {} ); -sc.subscribeNftCollectionEventUpdates( +sc.subscribeNftCollectionEvent( 'SP176ZMV706NZGDDX8VSQRGMB7QN33BBDVZ6BMNHD.project-indigo-act1::Project-Indigo-Act1', + (assetId, nftEvent) => {} ); ``` diff --git a/client/package-lock.json b/client/package-lock.json index 530d7919ef..d5c17d8d93 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -14,28 +14,39 @@ "cross-fetch": "3.1.5", "eventemitter3": "4.0.7", "jsonrpc-lite": "2.2.0", - "socket.io-client": "4.6.1", - "ws": "7.5.6" + "socket.io-client": "4.7.3", + "ws": "8.16.0" }, "devDependencies": { "@apidevtools/swagger-cli": "4.0.4", "@openapitools/openapi-generator-cli": "2.4.21", - "@stacks/eslint-config": "1.2.0", - "@stacks/prettier-config": "0.0.7", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", + "@stacks/eslint-config": "2.0.0", + "@stacks/prettier-config": "0.0.10", + "@types/node": "20.10.6", + "@typescript-eslint/eslint-plugin": "6.17.0", + "@typescript-eslint/parser": "6.17.0", "concurrently": "7.6.0", - "eslint": "7.32.0", - "eslint-config-prettier": "8.3.0", - "eslint-plugin-prettier": "3.4.1", + "eslint": "8.56.0", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-prettier": "5.1.2", + "eslint-plugin-unused-imports": "3.0.0", "http-server": "14.0.0", "microbundle": "0.13.3", - "prettier": "2.8.6", + "prettier": "3.1.1", "rimraf": "5.0.0", "shx": "0.3.3", - "ts-node": "9.1.1", - "typedoc": "0.23.10", - "typescript": "4.6.2" + "ts-node": "10.9.2", + "typedoc": "0.25.6", + "typescript": "5.3.3" + } + }, + "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/@apidevtools/json-schema-ref-parser": { @@ -2004,53 +2015,133 @@ "node": ">=6.9.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/@cspotcode/source-map-support/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/@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": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "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.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, "engines": { - "node": ">= 4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "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": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@jridgewell/gen-mapping": { @@ -2408,6 +2499,18 @@ "node": ">=10" } }, + "node_modules/@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@rollup/plugin-alias": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-3.1.8.tgz", @@ -2528,101 +2631,170 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@stacks/eslint-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@stacks/eslint-config/-/eslint-config-1.2.0.tgz", - "integrity": "sha512-uKPmUuLU57mRuF8pA9ilinSCgc/EvWs+yPf/P88m/Zt7TgGmvZmqPvt8BlxS4MM1ROsDDCRzTZkupOzuLrksGQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stacks/eslint-config/-/eslint-config-2.0.0.tgz", + "integrity": "sha512-GrRiJE7nadre+wCGAkaxCmHGD8tEYOtVW/cjjMdh/H37yl3vGj/lX723MfiXj/YcQDJ1qs/8V9Rx9b4VsFp10Q==", "dev": true, "dependencies": { - "@stacks/prettier-config": "0.0.10", - "@typescript-eslint/eslint-plugin": "5.5.0", - "@typescript-eslint/parser": "5.5.0", - "eslint": "8.3.0", - "eslint-config-prettier": "^8.3.0", - "eslint-import-resolver-typescript": "2.5.0", - "eslint-plugin-import": "2.25.3", - "eslint-plugin-prettier": "4.0.0" + "@stacks/prettier-config": "^0.0.10", + "@typescript-eslint/eslint-plugin": ">=6", + "@typescript-eslint/parser": ">=6", + "eslint": ">=8", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": ">=3", + "eslint-plugin-import": ">=2", + "eslint-plugin-prettier": ">=5", + "eslint-plugin-unused-imports": ">=3" }, "peerDependencies": { - "eslint": ">=7" + "eslint": ">=8", + "eslint-plugin-import": ">=2", + "eslint-plugin-prettier": ">=5", + "eslint-plugin-unused-imports": ">=3" } }, - "node_modules/@stacks/eslint-config/node_modules/@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", + "node_modules/@stacks/prettier-config": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.10.tgz", + "integrity": "sha512-MrYWGEgO/mYR8TOZIKknQEHbFQZ5VyAD/s8eF2Yxr6Lgalt2alVEh+6ODehVP2uepkyXPmJzLbaQYs8/L4E78Q==", "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" + "prettier": "2.5" + } + }, + "node_modules/@stacks/prettier-config/node_modules/prettier": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", + "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10.13.0" } }, - "node_modules/@stacks/eslint-config/node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "node_modules/@stacks/stacks-blockchain-api-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-1.0.4.tgz", + "integrity": "sha512-PjZaZFcsADrGqcAYnW9xkwJIAt8gEgkaBP7R9wKYMACFDuEwoHZ22NntiI636wRf1bMkDIa3T/+4naP6jv5f/A==" + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true, "engines": { - "node": ">= 4" + "node": ">=10.13.0" } }, - "node_modules/@stacks/eslint-config/node_modules/@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", - "dev": true, + "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/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "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/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", + "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" + "undici-types": "~5.26.4" } }, - "node_modules/@stacks/eslint-config/node_modules/@stacks/prettier-config": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.10.tgz", - "integrity": "sha512-MrYWGEgO/mYR8TOZIKknQEHbFQZ5VyAD/s8eF2Yxr6Lgalt2alVEh+6ODehVP2uepkyXPmJzLbaQYs8/L4E78Q==", + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", "dev": true, "dependencies": { - "prettier": "2.5" + "@types/node": "*" } }, - "node_modules/@stacks/eslint-config/node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", - "integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==", - "dev": true, + "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": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", "dependencies": { - "@typescript-eslint/experimental-utils": "5.5.0", - "@typescript-eslint/scope-manager": "5.5.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", + "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/type-utils": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.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" + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -2630,103 +2802,108 @@ } } }, - "node_modules/@stacks/eslint-config/node_modules/@typescript-eslint/experimental-utils": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz", - "integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==", + "node_modules/@typescript-eslint/parser": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", + "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.5.0", - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/typescript-estree": "5.5.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@stacks/eslint-config/node_modules/@typescript-eslint/parser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz", - "integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.5.0", - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/typescript-estree": "5.5.0", - "debug": "^4.3.2" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.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/@stacks/eslint-config/node_modules/@typescript-eslint/scope-manager": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", - "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", + "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0" + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@stacks/eslint-config/node_modules/@typescript-eslint/types": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", - "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", + "node_modules/@typescript-eslint/types": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@stacks/eslint-config/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", - "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0", - "debug": "^4.3.2", - "globby": "^11.0.4", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", @@ -2738,434 +2915,82 @@ } } }, - "node_modules/@stacks/eslint-config/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", - "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.5.0", - "eslint-visitor-keys": "^3.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/@stacks/eslint-config/node_modules/acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@typescript-eslint/types": "6.17.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=0.4.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@stacks/eslint-config/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==", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, - "node_modules/@stacks/eslint-config/node_modules/eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", - "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.0.4", - "@humanwhocodes/config-array": "^0.6.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@stacks/eslint-config/node_modules/eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/@stacks/eslint-config/node_modules/eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@stacks/eslint-config/node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@stacks/eslint-config/node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@stacks/eslint-config/node_modules/espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", - "dev": true, - "dependencies": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@stacks/eslint-config/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/@stacks/eslint-config/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/@stacks/eslint-config/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/@stacks/eslint-config/node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@stacks/prettier-config": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.7.tgz", - "integrity": "sha512-fXd5X4SV5GqskCYZxqExZJ7wF5sOggmzFP4Q7ttmR/eXZKar3c9fqEpbrpRZyHUBZv2Nss46MvwTLQk2YlpIeg==", - "dev": true - }, - "node_modules/@stacks/stacks-blockchain-api-types": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-1.0.4.tgz", - "integrity": "sha512-PjZaZFcsADrGqcAYnW9xkwJIAt8gEgkaBP7R9wKYMACFDuEwoHZ22NntiI636wRf1bMkDIa3T/+4naP6jv5f/A==" - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", - "dev": true - }, - "node_modules/@types/node": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.4.tgz", - "integrity": "sha512-6xwbrW4JJiJLgF+zNypN5wr2ykM9/jHcL7rQ8fZe2vuftggjzZeRSM4OwRc6Xk8qWjwJ99qVHo/JgOGmomWRog==" - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", - "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", - "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", - "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", - "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", - "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", - "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", - "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "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" @@ -3183,6 +3008,15 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", + "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", @@ -3205,15 +3039,6 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, - "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-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -3250,6 +3075,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -3280,16 +3111,29 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" }, "engines": { @@ -3308,15 +3152,35 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", - "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3325,13 +3189,43 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/async": { @@ -3376,6 +3270,18 @@ "postcss": "^8.1.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", @@ -3630,13 +3536,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4235,9 +4142,9 @@ } }, "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -4283,16 +4190,35 @@ "clone": "^1.0.2" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { - "object-keys": "^1.0.12" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/diff": { @@ -4411,13 +4337,13 @@ "dev": true }, "node_modules/engine.io-client": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", - "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", + "engine.io-parser": "~5.2.1", "ws": "~8.11.0", "xmlhttprequest-ssl": "~2.0.0" } @@ -4443,23 +4369,24 @@ } }, "node_modules/engine.io-parser": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", - "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", "engines": { "node": ">=10.0.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">=8.6" + "node": ">=10.13.0" } }, "node_modules/entities": { @@ -4481,31 +4408,50 @@ } }, "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", + "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -4514,6 +4460,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -4553,66 +4522,64 @@ } }, "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", - "debug": "^4.0.1", + "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -4622,13 +4589,14 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -4641,57 +4609,45 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz", - "integrity": "sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", "dev": true, "dependencies": { - "debug": "^4.3.1", - "glob": "^7.1.7", - "is-glob": "^4.0.1", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" }, "engines": { - "node": ">=4" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*" } }, - "node_modules/eslint-import-resolver-typescript/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/eslint-module-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", - "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0", - "pkg-dir": "^2.0.0" + "debug": "^3.2.7" }, "engines": { "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, "node_modules/eslint-module-utils/node_modules/debug": { @@ -4704,24 +4660,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz", - "integrity": "sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.1", - "has": "^1.0.3", - "is-core-module": "^2.8.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.11.0" + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -4731,12 +4691,12 @@ } }, "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import/node_modules/doctrine": { @@ -4751,127 +4711,157 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } }, "node_modules/eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", + "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" }, "engines": { - "node": ">=6.0.0" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" }, "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, "eslint-config-prettier": { "optional": true } } }, - "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==", + "node_modules/eslint-plugin-unused-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.0.0.tgz", + "integrity": "sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "eslint-rule-composer": "^0.3.0" }, "engines": { - "node": ">=8.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^6.0.0", + "eslint": "^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "node_modules/eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" + "node": ">=4.0.0" } }, "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "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": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "node_modules/eslint/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/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": { - "eslint-visitor-keys": "^1.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "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" + "node": ">=4.0" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "node_modules/eslint/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": ">= 4" + "node": ">=10.13.0" } }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "node_modules/eslint/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": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "argparse": "^2.0.1" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "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": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -4888,9 +4878,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "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" @@ -4929,15 +4919,6 @@ "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/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -4985,9 +4966,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "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", @@ -4997,7 +4978,7 @@ "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, "node_modules/fast-json-stable-stringify": { @@ -5162,15 +5143,6 @@ "node": ">=6" } }, - "node_modules/find-cache-dir/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/find-cache-dir/node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -5184,15 +5156,19 @@ } }, "node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "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": "^2.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat-cache": { @@ -5249,6 +5225,15 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fraction.js": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", @@ -5297,16 +5282,40 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/generic-names": { "version": "4.0.0", @@ -5336,14 +5345,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5365,6 +5375,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -5398,9 +5420,9 @@ } }, "node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "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" @@ -5412,6 +5434,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globalyzer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", @@ -5419,16 +5456,16 @@ "dev": true }, "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "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.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" }, "engines": { @@ -5444,12 +5481,30 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "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/gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -5471,18 +5526,6 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -5505,9 +5548,9 @@ } }, "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5522,10 +5565,34 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true, "engines": { "node": ">= 0.4" @@ -5549,6 +5616,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -5662,9 +5741,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -5770,13 +5849,13 @@ } }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -5792,6 +5871,20 @@ "node": ">= 0.10" } }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5827,9 +5920,9 @@ } }, "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "engines": { "node": ">= 0.4" @@ -5839,12 +5932,12 @@ } }, "node_modules/is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5932,9 +6025,9 @@ } }, "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" @@ -5946,6 +6039,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -5972,10 +6074,13 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5986,7 +6091,22 @@ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5995,13 +6115,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "which-typed-array": "^1.1.11" }, "engines": { "node": ">= 0.4" @@ -6034,6 +6154,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -6125,9 +6251,9 @@ } }, "node_modules/jsonc-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", - "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, "node_modules/jsonfile": { @@ -6194,16 +6320,18 @@ } }, "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "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": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -6248,12 +6376,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -6334,9 +6456,9 @@ "dev": true }, "node_modules/marked": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", - "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", + "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" @@ -6533,6 +6655,19 @@ "microbundle": "dist/cli.js" } }, + "node_modules/microbundle/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", @@ -6730,9 +6865,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6748,14 +6883,14 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -6765,15 +6900,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, "node_modules/object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -6823,17 +6987,17 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "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", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" @@ -6881,27 +7045,33 @@ } }, "node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "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": { - "p-try": "^1.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "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": "^1.1.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-queue": { @@ -6932,15 +7102,6 @@ "node": ">=8" } }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6972,12 +7133,12 @@ } }, "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "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": ">=4" + "node": ">=8" } }, "node_modules/path-is-absolute": { @@ -7074,18 +7235,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -7671,15 +7820,15 @@ } }, "node_modules/prettier": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", - "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "dev": true, "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -7709,15 +7858,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/promise.series": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", @@ -7845,16 +7985,21 @@ "@babel/runtime": "^7.8.4" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/regexpu-core": { @@ -7910,15 +8055,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -7932,13 +8068,17 @@ "dev": true }, "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7953,6 +8093,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -8308,6 +8457,24 @@ "node": ">= 6" } }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -8320,6 +8487,20 @@ "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", "dev": true }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -8333,9 +8514,9 @@ "dev": true }, "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -8362,6 +8543,35 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -8410,14 +8620,15 @@ } }, "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==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", "dev": true, "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" } }, "node_modules/shx": { @@ -8465,41 +8676,24 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/socket.io-client": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", - "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.3.tgz", + "integrity": "sha512-nU+ywttCyBitXIl9Xe0RSEfek4LneYkJxCeNnKCuhwoH4jGXO1ipIUw/VA/+Vvv2G1MTym11fzFC0SxkrcfXDw==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", - "engine.io-client": "~6.4.0", - "socket.io-parser": "~4.2.1" + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" }, "engines": { "node": ">=10.0.0" } }, "node_modules/socket.io-parser": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", - "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -8618,27 +8812,46 @@ "node": ">=8" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8659,7 +8872,7 @@ "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "engines": { "node": ">=4" @@ -8711,6 +8924,18 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", @@ -8741,44 +8966,37 @@ "node": ">= 10" } }, - "node_modules/table": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", - "integrity": "sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==", + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", "dev": true, "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://opencollective.com/unts" } }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "node_modules/synckit/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/terser": { "version": "5.14.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", @@ -8797,18 +9015,6 @@ "node": ">=10" } }, - "node_modules/terser/node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -8890,41 +9096,70 @@ "tree-kill": "cli.js" } }, - "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", "dev": true, - "dependencies": { + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.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", - "source-map-support": "^0.5.17", + "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" }, - "engines": { - "node": ">=10.0.0" - }, "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/tsconfig-paths": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", - "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", + "json5": "^1.0.2", + "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, @@ -8936,35 +9171,14 @@ "dependencies": { "minimist": "^1.2.0" }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", - "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" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "node_modules/tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", "dev": true }, "node_modules/type-check": { @@ -8991,25 +9205,90 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typedoc": { - "version": "0.23.10", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.10.tgz", - "integrity": "sha512-03EUiu/ZuScUBMnY6p0lY+HTH8SwhzvRE3gImoemdPDWXPXlks83UGTx++lyquWeB1MTwm9D9Ca8RIjkK3AFfQ==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.6.tgz", + "integrity": "sha512-1rdionQMpOkpA58qfym1J+YD+ukyA1IEIa4VZahQI2ZORez7dhOvEyUotQL/8rSoMBopdzOS+vAIsORpQO4cTA==", "dev": true, "dependencies": { "lunr": "^2.3.9", - "marked": "^4.0.18", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.7" }, "bin": { "typedoc": "bin/typedoc" }, "engines": { - "node": ">= 14.14" + "node": ">= 16" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" } }, "node_modules/typedoc/node_modules/brace-expansion": { @@ -9022,45 +9301,53 @@ } }, "node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "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/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -9152,10 +9439,10 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "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/validator": { @@ -9168,15 +9455,15 @@ } }, "node_modules/vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "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==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "dev": true }, "node_modules/wcwidth": { @@ -9263,13 +9550,23 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/wrap-ansi": { @@ -9293,15 +9590,15 @@ "dev": true }, "node_modules/ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -9446,15 +9743,6 @@ "node": ">=6" } }, - "node_modules/yargs/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/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -9464,6 +9752,18 @@ "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" + } + }, "node_modules/z-schema": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.2.tgz", @@ -9493,6 +9793,12 @@ } }, "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 + }, "@apidevtools/json-schema-ref-parser": { "version": "9.0.9", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", @@ -10888,46 +11194,103 @@ "to-fast-properties": "^2.0.0" } }, + "@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" + }, + "dependencies": { + "@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" + } + } + } + }, + "@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": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "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.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "dependencies": { - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "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 + }, + "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" + } } } }, + "@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true + }, "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.0", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "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": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "@jridgewell/gen-mapping": { @@ -11181,6 +11544,12 @@ } } }, + "@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", + "dev": true + }, "@rollup/plugin-alias": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-3.1.8.tgz", @@ -11245,293 +11614,49 @@ "dev": true, "requires": { "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "dependencies": { - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - } - } - }, - "@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" - }, - "@stacks/eslint-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@stacks/eslint-config/-/eslint-config-1.2.0.tgz", - "integrity": "sha512-uKPmUuLU57mRuF8pA9ilinSCgc/EvWs+yPf/P88m/Zt7TgGmvZmqPvt8BlxS4MM1ROsDDCRzTZkupOzuLrksGQ==", - "dev": true, - "requires": { - "@stacks/prettier-config": "0.0.10", - "@typescript-eslint/eslint-plugin": "5.5.0", - "@typescript-eslint/parser": "5.5.0", - "eslint": "8.3.0", - "eslint-config-prettier": "^8.3.0", - "eslint-import-resolver-typescript": "2.5.0", - "eslint-plugin-import": "2.25.3", - "eslint-plugin-prettier": "4.0.0" - }, - "dependencies": { - "@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz", - "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@stacks/prettier-config": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.10.tgz", - "integrity": "sha512-MrYWGEgO/mYR8TOZIKknQEHbFQZ5VyAD/s8eF2Yxr6Lgalt2alVEh+6ODehVP2uepkyXPmJzLbaQYs8/L4E78Q==", - "dev": true, - "requires": { - "prettier": "2.5" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz", - "integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "5.5.0", - "@typescript-eslint/scope-manager": "5.5.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/experimental-utils": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz", - "integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.5.0", - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/typescript-estree": "5.5.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz", - "integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.5.0", - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/typescript-estree": "5.5.0", - "debug": "^4.3.2" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz", - "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0" - } - }, - "@typescript-eslint/types": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz", - "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz", - "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "@typescript-eslint/visitor-keys": "5.5.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz", - "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.5.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", - "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 - }, - "eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz", - "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.0.4", - "@humanwhocodes/config-array": "^0.6.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.1.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - } - } - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", - "dev": true - }, - "espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", - "dev": true, - "requires": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", "dev": true - }, - "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" - } - }, - "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" - } - }, + } + } + }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "@stacks/eslint-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@stacks/eslint-config/-/eslint-config-2.0.0.tgz", + "integrity": "sha512-GrRiJE7nadre+wCGAkaxCmHGD8tEYOtVW/cjjMdh/H37yl3vGj/lX723MfiXj/YcQDJ1qs/8V9Rx9b4VsFp10Q==", + "dev": true, + "requires": { + "@stacks/prettier-config": "^0.0.10", + "@typescript-eslint/eslint-plugin": ">=6", + "@typescript-eslint/parser": ">=6", + "eslint": ">=8", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": ">=3", + "eslint-plugin-import": ">=2", + "eslint-plugin-prettier": ">=5", + "eslint-plugin-unused-imports": ">=3" + } + }, + "@stacks/prettier-config": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.10.tgz", + "integrity": "sha512-MrYWGEgO/mYR8TOZIKknQEHbFQZ5VyAD/s8eF2Yxr6Lgalt2alVEh+6ODehVP2uepkyXPmJzLbaQYs8/L4E78Q==", + "dev": true, + "requires": { + "prettier": "2.5" + }, + "dependencies": { "prettier": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", @@ -11540,12 +11665,6 @@ } } }, - "@stacks/prettier-config": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@stacks/prettier-config/-/prettier-config-0.0.7.tgz", - "integrity": "sha512-fXd5X4SV5GqskCYZxqExZJ7wF5sOggmzFP4Q7ttmR/eXZKar3c9fqEpbrpRZyHUBZv2Nss46MvwTLQk2YlpIeg==", - "dev": true - }, "@stacks/stacks-blockchain-api-types": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@stacks/stacks-blockchain-api-types/-/stacks-blockchain-api-types-1.0.4.tgz", @@ -11557,6 +11676,30 @@ "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true }, + "@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/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -11564,21 +11707,24 @@ "dev": true }, "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "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/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, "@types/node": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.4.tgz", - "integrity": "sha512-6xwbrW4JJiJLgF+zNypN5wr2ykM9/jHcL7rQ8fZe2vuftggjzZeRSM4OwRc6Xk8qWjwJ99qVHo/JgOGmomWRog==" + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", + "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", + "requires": { + "undici-types": "~5.26.4" + } }, "@types/parse-json": { "version": "4.0.0", @@ -11595,6 +11741,12 @@ "@types/node": "*" } }, + "@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": "7.4.7", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", @@ -11604,92 +11756,136 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", - "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.17.0.tgz", + "integrity": "sha512-Vih/4xLXmY7V490dGwBQJTpIZxH4ZFH6eCVmQ4RFkB+wmaCTDAx4dtgoWwMNGKLkqRY1L6rPqzEbjorRnDo4rQ==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/type-utils": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" } }, - "@typescript-eslint/experimental-utils": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", - "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "@typescript-eslint/parser": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.17.0.tgz", + "integrity": "sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==", "dev": true, "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4" } }, - "@typescript-eslint/parser": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", - "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "@typescript-eslint/scope-manager": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.17.0.tgz", + "integrity": "sha512-RX7a8lwgOi7am0k17NUO0+ZmMOX4PpjLtLRgLmT1d3lBYdWH4ssBUbwdmc5pdRX8rXon8v9x8vaoOSpkHfcXGA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0" } }, - "@typescript-eslint/scope-manager": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", - "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "@typescript-eslint/type-utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.17.0.tgz", + "integrity": "sha512-hDXcWmnbtn4P2B37ka3nil3yi3VCQO2QEB9gBiHJmQp5wmyQWqnjA85+ZcE8c4FqnaB6lBwMrPkgd4aBYz3iNg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0" + "@typescript-eslint/typescript-estree": "6.17.0", + "@typescript-eslint/utils": "6.17.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/types": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", - "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.17.0.tgz", + "integrity": "sha512-qRKs9tvc3a4RBcL/9PXtKSehI/q8wuU9xYJxe97WFxnzH8NWWtcW3ffNS+EWg8uPvIerhjsEZ+rHtDqOCiH57A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", - "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.17.0.tgz", + "integrity": "sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/visitor-keys": "6.17.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.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" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.17.0.tgz", + "integrity": "sha512-LofsSPjN/ITNkzV47hxas2JCsNCEnGhVvocfyOcLzT9c/tSZE7SfhS/iWtzP1lKNOEfLhRTZz6xqI8N2RzweSQ==", "dev": true, "requires": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.17.0", + "@typescript-eslint/types": "6.17.0", + "@typescript-eslint/typescript-estree": "6.17.0", + "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", - "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.17.0.tgz", + "integrity": "sha512-H6VwB/k3IuIeQOyYczyyKN8wH6ed8EwliaYHLxOIhyF0dYEIsN8+Bk3GE19qafeMKyZJJHP8+O1HiFhFLUNKSg==", "dev": true, "requires": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" + "@typescript-eslint/types": "6.17.0", + "eslint-visitor-keys": "^3.4.1" } }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true }, "acorn-jsx": { @@ -11699,6 +11895,12 @@ "dev": true, "requires": {} }, + "acorn-walk": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", + "dev": true + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -11717,12 +11919,6 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -11746,6 +11942,12 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, + "ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -11770,16 +11972,26 @@ "sprintf-js": "~1.0.2" } }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, "array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", "is-string": "^1.0.7" } }, @@ -11789,22 +12001,57 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, "array.prototype.flat": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", - "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" } }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true + "array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } }, "async": { "version": "2.6.4", @@ -11835,6 +12082,12 @@ "postcss-value-parser": "^4.1.0" } }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "axios": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", @@ -12019,13 +12272,14 @@ "dev": true }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" } }, "call-me-maybe": { @@ -12472,9 +12726,9 @@ "dev": true }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -12506,13 +12760,26 @@ "clone": "^1.0.2" } }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "diff": { @@ -12604,13 +12871,13 @@ "dev": true }, "engine.io-client": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", - "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", "requires": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", + "engine.io-parser": "~5.2.1", "ws": "~8.11.0", "xmlhttprequest-ssl": "~2.0.0" }, @@ -12624,17 +12891,18 @@ } }, "engine.io-parser": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", - "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==" }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dev": true, "requires": { - "ansi-colors": "^4.1.1" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" } }, "entities": { @@ -12653,31 +12921,70 @@ } }, "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", + "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + } + }, + "es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + } + }, + "es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" } }, "es-to-primitive": { @@ -12704,93 +13011,109 @@ "dev": true }, "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", - "debug": "^4.0.1", + "debug": "^4.3.2", "doctrine": "^3.0.0", - "enquirer": "^2.3.5", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" }, "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "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 + }, + "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": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" } }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true + }, + "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" + } + }, + "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" + } } } }, "eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "requires": {} }, "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "requires": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" }, "dependencies": { "debug": { @@ -12805,43 +13128,27 @@ } }, "eslint-import-resolver-typescript": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz", - "integrity": "sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", "dev": true, "requires": { - "debug": "^4.3.1", - "glob": "^7.1.7", - "is-glob": "^4.0.1", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.9.0" - }, - "dependencies": { - "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" - } - } + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" } }, "eslint-module-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz", - "integrity": "sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0", - "pkg-dir": "^2.0.0" + "debug": "^3.2.7" }, "dependencies": { "debug": { @@ -12856,33 +13163,37 @@ } }, "eslint-plugin-import": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz", - "integrity": "sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.1", - "has": "^1.0.3", - "is-core-module": "^2.8.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.11.0" + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "doctrine": { @@ -12894,65 +13205,54 @@ "esutils": "^2.0.2" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } }, "eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz", + "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==", "dev": true, "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" } }, - "eslint-utils": { + "eslint-plugin-unused-imports": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.0.0.tgz", + "integrity": "sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==", "dev": true, "requires": { - "eslint-visitor-keys": "^2.0.0" + "eslint-rule-composer": "^0.3.0" } }, + "eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", + "dev": true + }, "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "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": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "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": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" } }, "esprima": { @@ -12962,9 +13262,9 @@ "dev": true }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "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" @@ -12995,12 +13295,6 @@ } } }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -13042,9 +13336,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "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", @@ -13176,12 +13470,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -13194,12 +13482,13 @@ } }, "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "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": "^2.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" } }, "flat-cache": { @@ -13235,6 +13524,15 @@ "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "fraction.js": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", @@ -13266,15 +13564,27 @@ "optional": true }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, "generic-names": { @@ -13299,14 +13609,15 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } }, "get-symbol-description": { @@ -13319,6 +13630,15 @@ "get-intrinsic": "^1.1.1" } }, + "get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -13343,14 +13663,23 @@ } }, "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "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" } }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, "globalyzer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", @@ -13358,16 +13687,16 @@ "dev": true }, "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "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.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" } }, @@ -13377,12 +13706,27 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "gzip-size": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", @@ -13400,15 +13744,6 @@ } } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -13427,9 +13762,9 @@ } }, "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true }, "has-flag": { @@ -13438,10 +13773,25 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.2" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true + }, "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true }, "has-tostringtag": { @@ -13453,6 +13803,15 @@ "has-symbols": "^1.0.2" } }, + "hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -13529,9 +13888,9 @@ "dev": true }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true }, "import-cwd": { @@ -13615,13 +13974,13 @@ } }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, @@ -13631,6 +13990,17 @@ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -13657,18 +14027,18 @@ } }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true }, "is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "is-date-object": { @@ -13726,14 +14096,20 @@ "dev": true }, "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "requires": { "has-tostringtag": "^1.0.0" } }, + "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-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -13754,10 +14130,13 @@ } }, "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } }, "is-string": { "version": "1.0.7", @@ -13777,6 +14156,15 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "requires": { + "which-typed-array": "^1.1.11" + } + }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -13792,6 +14180,12 @@ "call-bind": "^1.0.2" } }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -13862,9 +14256,9 @@ "dev": true }, "jsonc-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", - "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, "jsonfile": { @@ -13917,13 +14311,12 @@ "dev": true }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "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": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" } }, "lodash": { @@ -13968,12 +14361,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -14038,9 +14425,9 @@ "dev": true }, "marked": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", - "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true }, "maxmin": { @@ -14195,6 +14582,14 @@ "tiny-glob": "^0.2.8", "tslib": "^2.0.3", "typescript": "^4.1.3" + }, + "dependencies": { + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true + } } }, "micromatch": { @@ -14332,9 +14727,9 @@ "dev": true }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true }, "object-keys": { @@ -14344,26 +14739,49 @@ "dev": true }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, + "object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, + "object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, "object.values": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", - "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "once": { @@ -14398,17 +14816,17 @@ "dev": true }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "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", - "word-wrap": "^1.2.3" + "type-check": "^0.4.0" } }, "ora": { @@ -14441,21 +14859,21 @@ "dev": true }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "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": { - "p-try": "^1.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "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": "^1.1.0" + "p-limit": "^3.0.2" } }, "p-queue": { @@ -14477,12 +14895,6 @@ "p-finally": "^1.0.0" } }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -14505,9 +14917,9 @@ } }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "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": { @@ -14576,15 +14988,6 @@ "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", "dev": true }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - }, "portfinder": { "version": "1.0.28", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", @@ -14961,9 +15364,9 @@ "dev": true }, "prettier": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.6.tgz", - "integrity": "sha512-mtuzdiBbHwPEgl7NxWlqOkithPyp4VN93V7VeHVWBF+ad3I5avc0RVDT4oImXQy9H/AqxA2NSQH8pSxHW6FYbQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "dev": true }, "prettier-linter-helpers": { @@ -14981,12 +15384,6 @@ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, "promise.series": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", @@ -15079,11 +15476,16 @@ "@babel/runtime": "^7.8.4" } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true + "regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + } }, "regexpu-core": { "version": "4.8.0", @@ -15128,12 +15530,6 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -15147,13 +15543,14 @@ "dev": true }, "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-from": { @@ -15162,6 +15559,12 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -15433,6 +15836,18 @@ "mri": "^1.1.0" } }, + "safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -15445,6 +15860,17 @@ "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", "dev": true }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -15458,9 +15884,9 @@ "dev": true }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -15481,6 +15907,29 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -15514,14 +15963,15 @@ } }, "shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", "dev": true, "requires": { - "jsonc-parser": "^3.0.0", - "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" } }, "shx": { @@ -15557,32 +16007,21 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, "socket.io-client": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", - "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.3.tgz", + "integrity": "sha512-nU+ywttCyBitXIl9Xe0RSEfek4LneYkJxCeNnKCuhwoH4jGXO1ipIUw/VA/+Vvv2G1MTym11fzFC0SxkrcfXDw==", "requires": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", - "engine.io-client": "~6.4.0", - "socket.io-parser": "~4.2.1" + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" } }, "socket.io-parser": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", - "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "requires": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -15676,24 +16115,37 @@ "strip-ansi": "^6.0.1" } }, + "string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + } + }, "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "strip-ansi": { @@ -15708,7 +16160,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, "strip-json-comments": { @@ -15742,6 +16194,12 @@ "has-flag": "^4.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, "svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", @@ -15765,39 +16223,30 @@ } } }, - "table": { - "version": "6.7.5", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", - "integrity": "sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==", + "synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", "dev": true, "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" }, "dependencies": { - "ajv": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz", - "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true } } }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, "terser": { "version": "5.14.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", @@ -15810,12 +16259,6 @@ "source-map-support": "~0.5.20" }, "dependencies": { - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true - }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -15887,29 +16330,43 @@ "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true }, - "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", "dev": true, - "requires": { + "requires": {} + }, + "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", - "source-map-support": "^0.5.17", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" } }, "tsconfig-paths": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", - "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "requires": { "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.0", + "json5": "^1.0.2", + "minimist": "^1.2.6", "strip-bom": "^3.0.0" }, "dependencies": { @@ -15930,23 +16387,6 @@ "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", "dev": true }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -15962,16 +16402,63 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "typedoc": { - "version": "0.23.10", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.10.tgz", - "integrity": "sha512-03EUiu/ZuScUBMnY6p0lY+HTH8SwhzvRE3gImoemdPDWXPXlks83UGTx++lyquWeB1MTwm9D9Ca8RIjkK3AFfQ==", + "version": "0.25.6", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.6.tgz", + "integrity": "sha512-1rdionQMpOkpA58qfym1J+YD+ukyA1IEIa4VZahQI2ZORez7dhOvEyUotQL/8rSoMBopdzOS+vAIsORpQO4cTA==", "dev": true, "requires": { "lunr": "^2.3.9", - "marked": "^4.0.18", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.7" }, "dependencies": { "brace-expansion": { @@ -15984,9 +16471,9 @@ } }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -15995,23 +16482,28 @@ } }, "typescript": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", - "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, + "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==" + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -16082,10 +16574,10 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "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 }, "validator": { @@ -16095,15 +16587,15 @@ "dev": true }, "vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "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==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "dev": true }, "wcwidth": { @@ -16177,11 +16669,18 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } }, "wrap-ansi": { "version": "6.2.0", @@ -16201,9 +16700,9 @@ "dev": true }, "ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", "requires": {} }, "xmlhttprequest-ssl": { @@ -16290,12 +16789,6 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true - }, - "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 } } }, @@ -16323,6 +16816,12 @@ "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 + }, "z-schema": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.2.tgz", diff --git a/client/package.json b/client/package.json index 10641261dd..5a18b3e3cc 100644 --- a/client/package.json +++ b/client/package.json @@ -24,8 +24,9 @@ "build:browser:watch": "npm run build:browser -- watch", "start": "concurrently npm:build:browser:watch npm:open", "test": "ts-node test/test.ts", - "lint": "eslint . --ext .ts -f codeframe", + "lint": "eslint . --ext .ts -f unix", "lint:prettier": "prettier --check ./src/**/*.ts", + "lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx -f unix --fix && prettier --write --check src/**/*.ts", "open": "http-server -o 9222 -o index.html", "prep-openapi": "rimraf ./.tmp && rimraf ./src/generated && swagger-cli bundle --dereference -o ./.tmp/openapi-temp.json ../docs/openapi.yaml && shx sed -i '^.*\\$schema.*$' '' ./.tmp/openapi-temp.json > ./.tmp/openapi.json", "generate-openapi": "npm run prep-openapi && openapi-generator-cli generate --skip-validate-spec -g typescript-fetch --additional-properties=withInterfaces=true,typescriptThreePlus=true,supportsES6=true,legacyDiscriminatorBehavior=false,enumPropertyNaming=original,modelPropertyNaming=original -i ./.tmp/openapi.json -o ./src/generated > ./.tmp/gen.log", @@ -43,27 +44,29 @@ "cross-fetch": "3.1.5", "eventemitter3": "4.0.7", "jsonrpc-lite": "2.2.0", - "socket.io-client": "4.6.1", - "ws": "7.5.6" + "socket.io-client": "4.7.3", + "ws": "8.16.0" }, "devDependencies": { "@apidevtools/swagger-cli": "4.0.4", "@openapitools/openapi-generator-cli": "2.4.21", - "@stacks/eslint-config": "1.2.0", - "@stacks/prettier-config": "0.0.7", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", + "@stacks/eslint-config": "2.0.0", + "@stacks/prettier-config": "0.0.10", + "@types/node": "20.10.6", + "@typescript-eslint/eslint-plugin": "6.17.0", + "@typescript-eslint/parser": "6.17.0", "concurrently": "7.6.0", - "eslint": "7.32.0", - "eslint-config-prettier": "8.3.0", - "eslint-plugin-prettier": "3.4.1", + "eslint": "8.56.0", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-prettier": "5.1.2", + "eslint-plugin-unused-imports": "3.0.0", "http-server": "14.0.0", "microbundle": "0.13.3", - "prettier": "2.8.6", + "prettier": "3.1.1", "rimraf": "5.0.0", "shx": "0.3.3", - "ts-node": "9.1.1", - "typedoc": "0.23.10", - "typescript": "4.6.2" + "ts-node": "10.9.2", + "typedoc": "0.25.6", + "typescript": "5.3.3" } } diff --git a/client/src/socket-io/index.ts b/client/src/socket-io/index.ts index b4f38c999e..913bb490ce 100644 --- a/client/src/socket-io/index.ts +++ b/client/src/socket-io/index.ts @@ -1,9 +1,16 @@ -import { io } from 'socket.io-client'; -import type { Socket } from 'socket.io-client'; +import { io, Socket } from 'socket.io-client'; +import type { ManagerOptions, SocketOptions } from 'socket.io-client'; import { ClientToServerMessages, Topic, ServerToClientMessages, + MempoolTransaction, + Transaction, + Block, + Microblock, + AddressTransactionWithTransfers, + NftEvent, + AddressStxBalanceResponse, } from '@stacks/stacks-blockchain-api-types'; import { BASE_PATH } from '../generated/runtime'; @@ -23,34 +30,46 @@ function getWsUrl(url: string): URL { return urlObj; } -export interface StacksApiSocketConnectionOptions { +export type StacksApiSocketConnectionOptions = { url?: string; /** Initial topics to subscribe to. */ subscriptions?: Topic[]; + socketOpts?: Partial; +}; + +function createStacksApiSocket(opts?: StacksApiSocketConnectionOptions) { + const socketOpts = { + ...opts?.socketOpts, + query: { + ...opts?.socketOpts?.query, + // Subscriptions can be specified on init using this handshake query param. + subscriptions: Array.from(new Set(opts?.subscriptions)).join(','), + }, + }; + const socket: StacksApiSocket = io(getWsUrl(opts?.url ?? BASE_PATH).href, socketOpts); + return socket; } export class StacksApiSocketClient { readonly socket: StacksApiSocket; - constructor(socket: StacksApiSocket) { - this.socket = socket; + constructor(socket: StacksApiSocket); + constructor(opts?: StacksApiSocketConnectionOptions); + constructor(args?: StacksApiSocket | StacksApiSocketConnectionOptions) { + if (args instanceof Socket) { + this.socket = args; + } else { + this.socket = createStacksApiSocket(args); + } } - public static connect({ - url = BASE_PATH, - subscriptions = [], - }: StacksApiSocketConnectionOptions = {}) { - const socket: StacksApiSocket = io(getWsUrl(url).href, { - query: { - // Subscriptions can be specified on init using this handshake query param. - subscriptions: Array.from(new Set(subscriptions)).join(','), - }, - }); - return new StacksApiSocketClient(socket); + public static connect(opts?: StacksApiSocketConnectionOptions) { + return new StacksApiSocketClient(opts); } - handleSubscription(topic: Topic, subscribe = false) { - const subscriptions = new Set(this.socket.io.opts.query?.subscriptions.split(',') ?? []); + handleSubscription(topic: Topic, subscribe = false, listener?: (...args: any[]) => void) { + const subsQuery = this.socket.io.opts.query?.subscriptions as string | undefined; + const subscriptions = new Set(subsQuery?.split(',') ?? []); if (subscribe) { this.socket.emit('subscribe', topic, error => { if (error) console.error(`Error subscribing: ${error}`); @@ -67,81 +86,106 @@ export class StacksApiSocketClient { this.socket.io.opts.query.subscriptions = Array.from(subscriptions).join(','); return { unsubscribe: () => { + if (listener) { + this.socket.off(topic, listener); + } this.handleSubscription(topic, false); }, }; } - subscribeBlocks() { - return this.handleSubscription('block', true); + subscribeBlocks(listener?: (tx: Block) => void) { + if (listener) this.socket.on('block', listener); + return this.handleSubscription('block', true, listener); } unsubscribeBlocks() { this.handleSubscription('block', false); } - subscribeMicroblocks() { - return this.handleSubscription('microblock', true); + subscribeMicroblocks(listener?: (tx: Microblock) => void) { + if (listener) this.socket.on('microblock', listener); + return this.handleSubscription('microblock', true, listener); } unsubscribeMicroblocks() { this.handleSubscription('microblock', false); } - subscribeMempool() { - return this.handleSubscription('mempool', true); + subscribeMempool(listener?: (tx: MempoolTransaction) => void) { + if (listener) this.socket.on('mempool', listener); + return this.handleSubscription('mempool', true, listener); } unsubscribeMempool() { this.handleSubscription('mempool', false); } - subscribeAddressTransactions(address: string) { - return this.handleSubscription(`address-transaction:${address}` as const, true); + subscribeAddressTransactions( + address: string, + listener?: (address: string, tx: AddressTransactionWithTransfers) => void + ) { + if (listener) this.socket.on(`address-transaction:${address}`, listener); + return this.handleSubscription(`address-transaction:${address}`, true, listener); } unsubscribeAddressTransactions(address: string) { - this.handleSubscription(`address-transaction:${address}` as const, false); + this.handleSubscription(`address-transaction:${address}`, false); } - subscribeAddressStxBalance(address: string) { - return this.handleSubscription(`address-stx-balance:${address}` as const, true); + subscribeAddressStxBalance( + address: string, + listener?: (address: string, stxBalance: AddressStxBalanceResponse) => void + ) { + if (listener) this.socket.on(`address-stx-balance:${address}`, listener); + return this.handleSubscription(`address-stx-balance:${address}`, true, listener); } unsubscribeAddressStxBalance(address: string) { - this.handleSubscription(`address-stx-balance:${address}` as const, false); + this.handleSubscription(`address-stx-balance:${address}`, false); } - subscribeTransaction(txId: string) { - return this.handleSubscription(`transaction:${txId}` as const, true); + subscribeTransaction(txId: string, listener?: (tx: MempoolTransaction | Transaction) => void) { + if (listener) this.socket.on(`transaction:${txId}`, listener); + return this.handleSubscription(`transaction:${txId}`, true, listener); } unsubscribeTransaction(txId: string) { - this.handleSubscription(`transaction:${txId}` as const, false); + this.handleSubscription(`transaction:${txId}`, false); } - subscribeNftEvent() { - return this.handleSubscription('nft-event', true); + subscribeNftEvent(listener?: (event: NftEvent) => void) { + if (listener) this.socket.on('nft-event', listener); + return this.handleSubscription('nft-event', true, listener); } unsubscribeNftEvent() { this.handleSubscription('nft-event', false); } - subscribeNftAssetEvent(assetIdentifier: string, value: string) { - return this.handleSubscription(`nft-asset-event:${assetIdentifier}+${value}` as const, true); + subscribeNftAssetEvent( + assetIdentifier: string, + value: string, + listener?: (assetIdentifier: string, value: string, event: NftEvent) => void + ) { + if (listener) this.socket.on(`nft-asset-event:${assetIdentifier}+${value}`, listener); + return this.handleSubscription(`nft-asset-event:${assetIdentifier}+${value}`, true, listener); } unsubscribeNftAssetEvent(assetIdentifier: string, value: string) { - this.handleSubscription(`nft-asset-event:${assetIdentifier}+${value}` as const, false); + this.handleSubscription(`nft-asset-event:${assetIdentifier}+${value}`, false); } - subscribeNftCollectionEvent(assetIdentifier: string) { - return this.handleSubscription(`nft-collection-event:${assetIdentifier}` as const, true); + subscribeNftCollectionEvent( + assetIdentifier: string, + listener?: (assetIdentifier: string, event: NftEvent) => void + ) { + if (listener) this.socket.on(`nft-collection-event:${assetIdentifier}`, listener); + return this.handleSubscription(`nft-collection-event:${assetIdentifier}`, true, listener); } unsubscribeNftCollectionEvent(assetIdentifier: string) { - this.handleSubscription(`nft-collection-event:${assetIdentifier}` as const, false); + this.handleSubscription(`nft-collection-event:${assetIdentifier}`, false); } logEvents() { @@ -151,18 +195,6 @@ export class StacksApiSocketClient { this.socket.on('block', block => console.log('block', block)); this.socket.on('microblock', microblock => console.log('microblock', microblock)); this.socket.on('mempool', tx => console.log('mempool', tx)); - this.socket.on('address-transaction', (address, data) => - console.log('address-transaction', address, data) - ); - this.socket.on('address-stx-balance', (address, data) => - console.log('address-stx-balance', address, data) - ); this.socket.on('nft-event', event => console.log('nft-event', event)); - this.socket.on('nft-asset-event', (assetIdentifier, value, event) => - console.log('nft-asset-event', assetIdentifier, value, event) - ); - this.socket.on('nft-collection-event', (assetIdentifier, event) => - console.log('nft-collection-event', assetIdentifier, event) - ); } } diff --git a/client/src/ws/index.ts b/client/src/ws/index.ts index be222b45c1..dd712650f4 100644 --- a/client/src/ws/index.ts +++ b/client/src/ws/index.ts @@ -74,7 +74,7 @@ export class StacksApiWebSocketClient { constructor(webSocket: IWebSocket) { this.webSocket = webSocket; (webSocket as WebSocket).addEventListener('message', event => { - const parsed = JsonRpcLite.parse(event.data); + const parsed = JsonRpcLite.parse(event.data as string); const rpcObjects = Array.isArray(parsed) ? parsed : [parsed]; rpcObjects.forEach(obj => { if (obj.type === JsonRpcLite.RpcStatusType.notification) { @@ -100,11 +100,10 @@ export class StacksApiWebSocketClient { const method = data.method as RpcSubscriptionType; switch (method) { case 'tx_update': - this.eventEmitter.emit('txUpdate', data.params as (Transaction | MempoolTransaction)); + this.eventEmitter.emit('txUpdate', data.params as Transaction | MempoolTransaction); break; case 'address_tx_update': - this.eventEmitter.emit('addressTxUpdate', - data.params as RpcAddressTxNotificationParams); + this.eventEmitter.emit('addressTxUpdate', data.params as RpcAddressTxNotificationParams); break; case 'address_balance_update': this.eventEmitter.emit( @@ -134,7 +133,7 @@ export class StacksApiWebSocketClient { } private rpcCall(method: string, params: any): Promise { - const rpcReq = JsonRpcLite.request(++this.idCursor, method, params); + const rpcReq = JsonRpcLite.request(++this.idCursor, method, params as JsonRpcLite.RpcParams); return new Promise((resolve, reject) => { this.pendingRequests.set(rpcReq.id, { resolve, reject }); this.webSocket.send(rpcReq.serialize()); @@ -276,9 +275,15 @@ export class StacksApiWebSocketClient { asset_identifier: assetIdentifier, value, }; - const subscribed = await this.rpcCall<{ asset_identifier: string, value: string }>('subscribe', params); + const subscribed = await this.rpcCall<{ asset_identifier: string; value: string }>( + 'subscribe', + params + ); const listener = (event: NftEvent) => { - if (event.asset_identifier === subscribed.asset_identifier && event.value.hex === subscribed.value) { + if ( + event.asset_identifier === subscribed.asset_identifier && + event.value.hex === subscribed.value + ) { update(event); } }; diff --git a/client/tsconfig.json b/client/tsconfig.json index 88716f08d0..929775ea1a 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es2017", + "target": "es2020", "module": "commonjs", "moduleResolution": "node", "declaration": true, diff --git a/docs/socket-io/index.d.ts b/docs/socket-io/index.d.ts index 441c8fbcc1..7fe1ea030b 100644 --- a/docs/socket-io/index.d.ts +++ b/docs/socket-io/index.d.ts @@ -37,25 +37,10 @@ export interface ServerToClientMessages { block: (block: Block, callback: (...args: WithTimeoutAck) => void) => void; microblock: (microblock: Microblock, callback: (...args: WithTimeoutAck) => void) => void; mempool: (transaction: MempoolTransaction, callback: (...args: WithTimeoutAck) => void) => void; - transaction: (transaction: Transaction | MempoolTransaction, callback: (...args: WithTimeoutAck) => void) => void; - - // @ts-ignore scheduled for support in TS v4.3 https://github.com/microsoft/TypeScript/pull/26797 - [key: 'nft-event']: (event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; 'nft-event': (event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - - // @ts-ignore scheduled for support in TS v4.3 https://github.com/microsoft/TypeScript/pull/26797 + [key: TransactionTopic]: (transaction: Transaction | MempoolTransaction, callback: (...args: WithTimeoutAck) => void) => void; [key: NftAssetEventTopic]: (assetIdentifier: string, value: string, event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - 'nft-asset-event': (assetIdentifier: string, value: string, event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - - // @ts-ignore scheduled for support in TS v4.3 https://github.com/microsoft/TypeScript/pull/26797 [key: NftCollectionEventTopic]: (assetIdentifier: string, event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - 'nft-collection-event': (assetIdentifier: string, event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - - // @ts-ignore scheduled for support in TS v4.3 https://github.com/microsoft/TypeScript/pull/26797 [key: AddressTransactionTopic]: (address: string, stxBalance: AddressTransactionWithTransfers, callback: (...args: WithTimeoutAck) => void) => void; - 'address-transaction': (address: string, tx: AddressTransactionWithTransfers, callback: (...args: WithTimeoutAck) => void) => void; - - // @ts-ignore scheduled for support in TS v4.3 https://github.com/microsoft/TypeScript/pull/26797 [key: AddressStxBalanceTopic]: (address: string, stxBalance: AddressStxBalanceResponse, callback: (...args: WithTimeoutAck) => void) => void; - 'address-stx-balance': (address: string, stxBalance: AddressStxBalanceResponse, callback: (...args: WithTimeoutAck) => void) => void; } diff --git a/src/api/routes/ws/channels/socket-io-channel.ts b/src/api/routes/ws/channels/socket-io-channel.ts index f8b0a7d487..c354fca1e0 100644 --- a/src/api/routes/ws/channels/socket-io-channel.ts +++ b/src/api/routes/ws/channels/socket-io-channel.ts @@ -2,8 +2,11 @@ import { AddressStxBalanceTopic, AddressTransactionTopic, ClientToServerMessages, + NftAssetEventTopic, + NftCollectionEventTopic, ServerToClientMessages, Topic, + TransactionTopic, } from 'docs/socket-io'; import * as http from 'http'; import { Server as SocketIOServer } from 'socket.io'; @@ -63,8 +66,8 @@ export class SocketIOChannel extends WebSocketChannel { const topics = [...[subscriptions]].flat().flatMap(r => r.split(',')); for (const topic of topics) { this.prometheus?.subscribe(socket, topic); - await socket.join(topic); } + await socket.join(topics); } socket.on('disconnect', reason => { logger.debug(`disconnected ${socket.id}: ${reason}`, component); @@ -170,15 +173,7 @@ export class SocketIOChannel extends WebSocketChannel { if (!this.io) { return; } - const sockets = []; - const socketIds = await this.io.to(room).allSockets(); - for (const id of socketIds) { - const socket = this.io.sockets.sockets.get(id); - if (socket) { - sockets.push(socket); - } - } - return sockets; + return await this.io.to(room).fetchSockets(); } send

( @@ -225,9 +220,10 @@ export class SocketIOChannel extends WebSocketChannel { case 'transaction': { const [tx] = args as ListenerType; this.prometheus?.sendEvent('transaction'); - void this.getTopicSockets(`transaction:${tx.tx_id}`).then(sockets => + const topic: TransactionTopic = `transaction:${tx.tx_id}`; + void this.getTopicSockets(topic).then(sockets => sockets?.forEach(socket => - socket.timeout(timeout).emit('transaction', tx, _ => socket.disconnect(true)) + socket.timeout(timeout).emit(topic, tx, _ => socket.disconnect(true)) ) ); break; @@ -247,11 +243,12 @@ export class SocketIOChannel extends WebSocketChannel { WebSocketPayload['nftAssetEvent'] >; this.prometheus?.sendEvent('nft-asset-event'); - void this.getTopicSockets(`nft-event`).then(sockets => + const topic: NftAssetEventTopic = `nft-asset-event:${assetIdentifier}+${value}`; + void this.getTopicSockets(topic).then(sockets => sockets?.forEach(socket => socket .timeout(timeout) - .emit('nft-asset-event', assetIdentifier, value, event, _ => socket.disconnect(true)) + .emit(topic, assetIdentifier, value, event, _ => socket.disconnect(true)) ) ); break; @@ -261,11 +258,12 @@ export class SocketIOChannel extends WebSocketChannel { WebSocketPayload['nftCollectionEvent'] >; this.prometheus?.sendEvent('nft-collection-event'); - void this.getTopicSockets(`nft-event`).then(sockets => + const topic: NftCollectionEventTopic = `nft-collection-event:${assetIdentifier}`; + void this.getTopicSockets(topic).then(sockets => sockets?.forEach(socket => socket .timeout(timeout) - .emit('nft-collection-event', assetIdentifier, event, _ => socket.disconnect(true)) + .emit(topic, assetIdentifier, event, _ => socket.disconnect(true)) ) ); break; @@ -276,9 +274,6 @@ export class SocketIOChannel extends WebSocketChannel { this.prometheus?.sendEvent('address-transaction'); void this.getTopicSockets(topic).then(sockets => sockets?.forEach(socket => { - socket - .timeout(timeout) - .emit('address-transaction', principal, tx, _ => socket.disconnect(true)); socket.timeout(timeout).emit(topic, principal, tx, _ => socket.disconnect(true)); }) ); @@ -290,9 +285,6 @@ export class SocketIOChannel extends WebSocketChannel { this.prometheus?.sendEvent('address-stx-balance'); void this.getTopicSockets(topic).then(sockets => sockets?.forEach(socket => { - socket - .timeout(timeout) - .emit('address-stx-balance', principal, balance, _ => socket.disconnect(true)); socket.timeout(timeout).emit(topic, principal, balance, _ => socket.disconnect(true)); }) ); diff --git a/src/tests-2.4/pox-3-delegate-aggregation.ts b/src/tests-2.4/pox-3-delegate-aggregation.ts index 2fda6c1484..84619fbdc3 100644 --- a/src/tests-2.4/pox-3-delegate-aggregation.ts +++ b/src/tests-2.4/pox-3-delegate-aggregation.ts @@ -427,6 +427,7 @@ describe('PoX-3 - Delegate aggregation increase operations', () => { pox1: { height: poxStatus1.current_burnchain_block_height, ...poxStatus1.next_cycle }, pox2: { height: poxStatus2.current_burnchain_block_height, ...poxStatus2.next_cycle }, }); + await standByForPoxCycle(); }); test('Validate account balances are unlocked', async () => { diff --git a/src/tests/socket-io-tests.ts b/src/tests/socket-io-tests.ts index 2c381a6b65..993c9c57b8 100644 --- a/src/tests/socket-io-tests.ts +++ b/src/tests/socket-io-tests.ts @@ -19,6 +19,7 @@ import { } from '../test-utils/test-builders'; import { PgWriteStore } from '../datastore/pg-write-store'; import { cycleMigrations, runMigrations } from '../datastore/migrations'; +import { StacksApiSocketClient } from '../../client/src/socket-io'; describe('socket-io', () => { let apiServer: ApiServer; @@ -34,6 +35,78 @@ describe('socket-io', () => { }); }); + test('socket-io-client > block updates', async () => { + const client = new StacksApiSocketClient({ + url: `http://${apiServer.address}`, + socketOpts: { reconnection: false }, + }); + + const updateWaiter: Waiter = waiter(); + const subResult = client.subscribeBlocks(block => updateWaiter.finish(block)); + + const block = new TestBlockBuilder({ block_hash: '0x1234', burn_block_hash: '0x5454' }) + .addTx({ tx_id: '0x4321' }) + .build(); + await db.update(block); + + const result = await updateWaiter; + try { + expect(result.hash).toEqual('0x1234'); + expect(result.burn_block_hash).toEqual('0x5454'); + expect(result.txs[0]).toEqual('0x4321'); + } finally { + subResult.unsubscribe(); + client.socket.close(); + } + }); + + test('socket-io-client > tx updates', async () => { + const client = new StacksApiSocketClient({ + url: `http://${apiServer.address}`, + socketOpts: { reconnection: false }, + }); + + const mempoolWaiter: Waiter = waiter(); + const txWaiters: Waiter[] = [waiter(), waiter()]; + + const mempoolSub = client.subscribeMempool(tx => mempoolWaiter.finish(tx)); + const txSub = client.subscribeTransaction('0x01', tx => { + if (tx.tx_status === 'pending') { + txWaiters[0].finish(tx); + } else { + txWaiters[1].finish(tx); + } + }); + + const block = new TestBlockBuilder().addTx().build(); + await db.update(block); + + const mempoolTx = testMempoolTx({ tx_id: '0x01', status: DbTxStatus.Pending }); + await db.updateMempoolTxs({ mempoolTxs: [mempoolTx] }); + const mempoolResult = await mempoolWaiter; + const txResult = await txWaiters[0]; + + const microblock = new TestMicroblockStreamBuilder() + .addMicroblock() + .addTx({ tx_id: '0x01' }) + .build(); + await db.updateMicroblocks(microblock); + const txMicroblockResult = await txWaiters[1]; + + try { + expect(mempoolResult.tx_status).toEqual('pending'); + expect(mempoolResult.tx_id).toEqual('0x01'); + expect(txResult.tx_status).toEqual('pending'); + expect(txResult.tx_id).toEqual('0x01'); + expect(txMicroblockResult.tx_id).toEqual('0x01'); + expect(txMicroblockResult.tx_status).toEqual('success'); + } finally { + mempoolSub.unsubscribe(); + txSub.unsubscribe(); + client.socket.close(); + } + }); + test('socket-io > block updates', async () => { const address = apiServer.address; const socket = io(`http://${address}`, { @@ -106,7 +179,7 @@ describe('socket-io', () => { socket.on('mempool', tx => { mempoolWaiter.finish(tx); }); - socket.on('transaction', tx => { + socket.on('transaction:0x01', tx => { if (tx.tx_status === 'pending') { txWaiters[0].finish(tx); } else { @@ -293,12 +366,12 @@ describe('socket-io', () => { socket.on(`nft-event`, event => { nftEventWaiters[event.event_index].finish(event); }); - socket.on(`nft-asset-event`, (assetIdentifier, value, event) => { + socket.on(`nft-asset-event:${crashPunks}+${valueHex1}`, (assetIdentifier, value, event) => { if (assetIdentifier == crashPunks && value == valueHex1) { crashPunksWaiter.finish(event); } }); - socket.on(`nft-collection-event`, (assetIdentifier, event) => { + socket.on(`nft-collection-event:${wastelandApes}`, (assetIdentifier, event) => { if (assetIdentifier == wastelandApes) { if (event.event_index == 2) { apeWaiters[0].finish(event); From 242cb04da9ddaceb9f344d11695fea6d764df102 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 5 Jan 2024 15:47:58 +0000 Subject: [PATCH 69/91] chore(release): 7.5.0-beta.1 [skip ci] ## [7.5.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0...v7.5.0-beta.1) (2024-01-05) ### Features * add listener callback to socket-io client subscription functions ([#1799](https://github.com/hirosystems/stacks-blockchain-api/issues/1799)) ([5634522](https://github.com/hirosystems/stacks-blockchain-api/commit/5634522132448fa480fcb18978a9cf2bf6f50a37)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29a61b63ab..268b04565a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.5.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0...v7.5.0-beta.1) (2024-01-05) + + +### Features + +* add listener callback to socket-io client subscription functions ([#1799](https://github.com/hirosystems/stacks-blockchain-api/issues/1799)) ([5634522](https://github.com/hirosystems/stacks-blockchain-api/commit/5634522132448fa480fcb18978a9cf2bf6f50a37)) + ## [7.4.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.3.6...v7.4.0) (2024-01-04) From d596fd5cc7efe588983d8a902771cc38c21fee82 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 5 Jan 2024 18:00:40 +0100 Subject: [PATCH 70/91] fix: socket-io client should not disconnect with no event reply (#1800) * fix: socket-io client should not disconnect with no event reply * ci: disable socket-io per-message timeout test --- docs/socket-io/index.d.ts | 24 +++--- .../routes/ws/channels/socket-io-channel.ts | 80 ++++--------------- src/tests/socket-io-tests.ts | 3 +- 3 files changed, 27 insertions(+), 80 deletions(-) diff --git a/docs/socket-io/index.d.ts b/docs/socket-io/index.d.ts index 7fe1ea030b..136f43d6a8 100644 --- a/docs/socket-io/index.d.ts +++ b/docs/socket-io/index.d.ts @@ -24,23 +24,19 @@ export type Topic = | NftAssetEventTopic | NftCollectionEventTopic; -// Allows timeout callbacks for messages. See -// https://socket.io/docs/v4/typescript/#emitting-with-a-timeout -type WithTimeoutAck = isSender extends true ? [Error, ...args] : args; - export interface ClientToServerMessages { subscribe: (topic: Topic | Topic[], callback: (error: string | null) => void) => void; unsubscribe: (...topic: Topic[]) => void; } -export interface ServerToClientMessages { - block: (block: Block, callback: (...args: WithTimeoutAck) => void) => void; - microblock: (microblock: Microblock, callback: (...args: WithTimeoutAck) => void) => void; - mempool: (transaction: MempoolTransaction, callback: (...args: WithTimeoutAck) => void) => void; - 'nft-event': (event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - [key: TransactionTopic]: (transaction: Transaction | MempoolTransaction, callback: (...args: WithTimeoutAck) => void) => void; - [key: NftAssetEventTopic]: (assetIdentifier: string, value: string, event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - [key: NftCollectionEventTopic]: (assetIdentifier: string, event: NftEvent, callback: (...args: WithTimeoutAck) => void) => void; - [key: AddressTransactionTopic]: (address: string, stxBalance: AddressTransactionWithTransfers, callback: (...args: WithTimeoutAck) => void) => void; - [key: AddressStxBalanceTopic]: (address: string, stxBalance: AddressStxBalanceResponse, callback: (...args: WithTimeoutAck) => void) => void; +export interface ServerToClientMessages { + block: (block: Block) => void; + microblock: (microblock: Microblock) => void; + mempool: (transaction: MempoolTransaction) => void; + 'nft-event': (event: NftEvent) => void; + [key: TransactionTopic]: (transaction: Transaction | MempoolTransaction) => void; + [key: NftAssetEventTopic]: (assetIdentifier: string, value: string, event: NftEvent) => void; + [key: NftCollectionEventTopic]: (assetIdentifier: string, event: NftEvent) => void; + [key: AddressTransactionTopic]: (address: string, stxBalance: AddressTransactionWithTransfers) => void; + [key: AddressStxBalanceTopic]: (address: string, stxBalance: AddressStxBalanceResponse) => void; } diff --git a/src/api/routes/ws/channels/socket-io-channel.ts b/src/api/routes/ws/channels/socket-io-channel.ts index c354fca1e0..844b42301d 100644 --- a/src/api/routes/ws/channels/socket-io-channel.ts +++ b/src/api/routes/ws/channels/socket-io-channel.ts @@ -33,7 +33,7 @@ const component = { component: 'socket-io' }; * SocketIO channel for sending real time API updates. */ export class SocketIOChannel extends WebSocketChannel { - private io?: SocketIOServer>; + private io?: SocketIOServer; private adapter?: Adapter; constructor(server: http.Server) { @@ -44,14 +44,11 @@ export class SocketIOChannel extends WebSocketChannel { } connect(): void { - const io = new SocketIOServer>( - this.server, - { - cors: { origin: '*' }, - pingInterval: getWsPingIntervalMs(), - pingTimeout: getWsPingTimeoutMs(), - } - ); + const io = new SocketIOServer(this.server, { + cors: { origin: '*' }, + pingInterval: getWsPingIntervalMs(), + pingTimeout: getWsPingTimeoutMs(), + }); this.io = io; io.on('connection', async socket => { @@ -169,13 +166,6 @@ export class SocketIOChannel extends WebSocketChannel { return false; } - private async getTopicSockets(room: Topic) { - if (!this.io) { - return; - } - return await this.io.to(room).fetchSockets(); - } - send

( payload: P, ...args: ListenerType @@ -190,52 +180,32 @@ export class SocketIOChannel extends WebSocketChannel { case 'block': { const [block] = args as ListenerType; this.prometheus?.sendEvent('block'); - void this.getTopicSockets('block').then(sockets => - sockets?.forEach(socket => - socket.timeout(timeout).emit('block', block, _ => socket.disconnect(true)) - ) - ); + this.io?.to('block').emit('block', block); break; } case 'microblock': { const [microblock] = args as ListenerType; this.prometheus?.sendEvent('microblock'); - void this.getTopicSockets('microblock').then(sockets => - sockets?.forEach(socket => - socket.timeout(timeout).emit('microblock', microblock, _ => socket.disconnect(true)) - ) - ); + this.io?.to('microblock').emit('microblock', microblock); break; } case 'mempoolTransaction': { const [tx] = args as ListenerType; this.prometheus?.sendEvent('mempool'); - void this.getTopicSockets('mempool').then(sockets => - sockets?.forEach(socket => - socket.timeout(timeout).emit('mempool', tx, _ => socket.disconnect(true)) - ) - ); + this.io?.to('mempool').emit('mempool', tx); break; } case 'transaction': { const [tx] = args as ListenerType; this.prometheus?.sendEvent('transaction'); const topic: TransactionTopic = `transaction:${tx.tx_id}`; - void this.getTopicSockets(topic).then(sockets => - sockets?.forEach(socket => - socket.timeout(timeout).emit(topic, tx, _ => socket.disconnect(true)) - ) - ); + this.io?.to(topic).emit(topic, tx); break; } case 'nftEvent': { const [event] = args as ListenerType; this.prometheus?.sendEvent('nft-event'); - void this.getTopicSockets(`nft-event`).then(sockets => - sockets?.forEach(socket => - socket.timeout(timeout).emit('nft-event', event, _ => socket.disconnect(true)) - ) - ); + this.io?.to('nft-event').emit('nft-event', event); break; } case 'nftAssetEvent': { @@ -244,13 +214,7 @@ export class SocketIOChannel extends WebSocketChannel { >; this.prometheus?.sendEvent('nft-asset-event'); const topic: NftAssetEventTopic = `nft-asset-event:${assetIdentifier}+${value}`; - void this.getTopicSockets(topic).then(sockets => - sockets?.forEach(socket => - socket - .timeout(timeout) - .emit(topic, assetIdentifier, value, event, _ => socket.disconnect(true)) - ) - ); + this.io?.to(topic).emit(topic, assetIdentifier, value, event); break; } case 'nftCollectionEvent': { @@ -259,35 +223,21 @@ export class SocketIOChannel extends WebSocketChannel { >; this.prometheus?.sendEvent('nft-collection-event'); const topic: NftCollectionEventTopic = `nft-collection-event:${assetIdentifier}`; - void this.getTopicSockets(topic).then(sockets => - sockets?.forEach(socket => - socket - .timeout(timeout) - .emit(topic, assetIdentifier, event, _ => socket.disconnect(true)) - ) - ); + this.io?.to(topic).emit(topic, assetIdentifier, event); break; } case 'principalTransaction': { const [principal, tx] = args as ListenerType; const topic: AddressTransactionTopic = `address-transaction:${principal}`; this.prometheus?.sendEvent('address-transaction'); - void this.getTopicSockets(topic).then(sockets => - sockets?.forEach(socket => { - socket.timeout(timeout).emit(topic, principal, tx, _ => socket.disconnect(true)); - }) - ); + this.io?.to(topic).emit(topic, principal, tx); break; } case 'principalStxBalance': { const [principal, balance] = args as ListenerType; const topic: AddressStxBalanceTopic = `address-stx-balance:${principal}`; this.prometheus?.sendEvent('address-stx-balance'); - void this.getTopicSockets(topic).then(sockets => - sockets?.forEach(socket => { - socket.timeout(timeout).emit(topic, principal, balance, _ => socket.disconnect(true)); - }) - ); + this.io?.to(topic).emit(topic, principal, balance); break; } } diff --git a/src/tests/socket-io-tests.ts b/src/tests/socket-io-tests.ts index 993c9c57b8..c019dbe66d 100644 --- a/src/tests/socket-io-tests.ts +++ b/src/tests/socket-io-tests.ts @@ -565,7 +565,8 @@ describe('socket-io', () => { } }); - test('message timeout disconnects client', async () => { + // Per message timeout is not enabled (we don't want to require clients to explicitly reply to events) + test.skip('message timeout disconnects client', async () => { const address = apiServer.address; const socket = io(`http://${address}`, { reconnection: false, From d4bbf179b686dcd33cc620c2ad6dd23d8f102a50 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 5 Jan 2024 17:07:05 +0000 Subject: [PATCH 71/91] chore(release): 7.5.0-beta.2 [skip ci] ## [7.5.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0-beta.1...v7.5.0-beta.2) (2024-01-05) ### Bug Fixes * socket-io client should not disconnect with no event reply ([#1800](https://github.com/hirosystems/stacks-blockchain-api/issues/1800)) ([d596fd5](https://github.com/hirosystems/stacks-blockchain-api/commit/d596fd5cc7efe588983d8a902771cc38c21fee82)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 268b04565a..907e8df087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.5.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0-beta.1...v7.5.0-beta.2) (2024-01-05) + + +### Bug Fixes + +* socket-io client should not disconnect with no event reply ([#1800](https://github.com/hirosystems/stacks-blockchain-api/issues/1800)) ([d596fd5](https://github.com/hirosystems/stacks-blockchain-api/commit/d596fd5cc7efe588983d8a902771cc38c21fee82)) + ## [7.5.0-beta.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0...v7.5.0-beta.1) (2024-01-05) From 3acbb853b9c67165585fbd56234c904ca4db0d87 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 5 Jan 2024 18:24:50 +0000 Subject: [PATCH 72/91] chore(release): 7.5.0 [skip ci] ## [7.5.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0...v7.5.0) (2024-01-05) ### Features * add listener callback to socket-io client subscription functions ([#1799](https://github.com/hirosystems/stacks-blockchain-api/issues/1799)) ([5634522](https://github.com/hirosystems/stacks-blockchain-api/commit/5634522132448fa480fcb18978a9cf2bf6f50a37)) ### Bug Fixes * socket-io client should not disconnect with no event reply ([#1800](https://github.com/hirosystems/stacks-blockchain-api/issues/1800)) ([d596fd5](https://github.com/hirosystems/stacks-blockchain-api/commit/d596fd5cc7efe588983d8a902771cc38c21fee82)) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 907e8df087..97a245a585 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [7.5.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0...v7.5.0) (2024-01-05) + + +### Features + +* add listener callback to socket-io client subscription functions ([#1799](https://github.com/hirosystems/stacks-blockchain-api/issues/1799)) ([5634522](https://github.com/hirosystems/stacks-blockchain-api/commit/5634522132448fa480fcb18978a9cf2bf6f50a37)) + + +### Bug Fixes + +* socket-io client should not disconnect with no event reply ([#1800](https://github.com/hirosystems/stacks-blockchain-api/issues/1800)) ([d596fd5](https://github.com/hirosystems/stacks-blockchain-api/commit/d596fd5cc7efe588983d8a902771cc38c21fee82)) + ## [7.5.0-beta.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0-beta.1...v7.5.0-beta.2) (2024-01-05) From 2d2aee38263c3e457462ba5fd4cf4fd305178039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Mon, 8 Jan 2024 12:12:55 -0600 Subject: [PATCH 73/91] feat: disable rosetta via an ENV var (#1804) --- .env | 3 +++ src/api/init.ts | 35 +++++++++++++++++++------------- src/tests-rosetta/disable-api.ts | 33 ++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 src/tests-rosetta/disable-api.ts diff --git a/.env b/.env index ed6d6d26ba..e870524c78 100644 --- a/.env +++ b/.env @@ -122,6 +122,9 @@ STACKS_NODE_TYPE=L1 # Override the default file path for the proxy cache control file # STACKS_API_PROXY_CACHE_CONTROL_FILE=/path/to/.proxy-cache-control.json +# Enable Rosetta endpoints. +# STACKS_API_ENABLE_ROSETTA=1 + # Enable FT metadata processing for Rosetta operations display. Disabled by default. # STACKS_API_ENABLE_FT_METADATA=1 diff --git a/src/api/init.ts b/src/api/init.ts index 29c239ebc9..43dfc7022d 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -42,7 +42,13 @@ import { PgWriteStore } from '../datastore/pg-write-store'; import { WebSocketTransmitter } from './routes/ws/web-socket-transmitter'; import { createPoxEventsRouter } from './routes/pox'; import { logger, loggerMiddleware } from '../logger'; -import { SERVER_VERSION, isPgConnectionError, isProdEnv, waiter } from '@hirosystems/api-toolkit'; +import { + SERVER_VERSION, + isPgConnectionError, + isProdEnv, + parseBoolean, + waiter, +} from '@hirosystems/api-toolkit'; import { createV2BlocksRouter } from './routes/v2/blocks'; import { getReqQuery } from './query-helpers'; import { createV2BurnBlocksRouter } from './routes/v2/burn-blocks'; @@ -263,19 +269,20 @@ export async function startApiServer(opts: { ); // Rosetta API -- https://www.rosetta-api.org - app.use( - '/rosetta/v1', - (() => { - const router = express.Router(); - router.use(cors()); - router.use('/network', createRosettaNetworkRouter(datastore, chainId)); - router.use('/mempool', createRosettaMempoolRouter(datastore, chainId)); - router.use('/block', createRosettaBlockRouter(datastore, chainId)); - router.use('/account', createRosettaAccountRouter(datastore, chainId)); - router.use('/construction', createRosettaConstructionRouter(datastore, chainId)); - return router; - })() - ); + if (parseBoolean(process.env['STACKS_API_ENABLE_ROSETTA'] ?? '1')) + app.use( + '/rosetta/v1', + (() => { + const router = express.Router(); + router.use(cors()); + router.use('/network', createRosettaNetworkRouter(datastore, chainId)); + router.use('/mempool', createRosettaMempoolRouter(datastore, chainId)); + router.use('/block', createRosettaBlockRouter(datastore, chainId)); + router.use('/account', createRosettaAccountRouter(datastore, chainId)); + router.use('/construction', createRosettaConstructionRouter(datastore, chainId)); + return router; + })() + ); // Setup legacy API v1 and v2 routes app.use( diff --git a/src/tests-rosetta/disable-api.ts b/src/tests-rosetta/disable-api.ts new file mode 100644 index 0000000000..b8df673302 --- /dev/null +++ b/src/tests-rosetta/disable-api.ts @@ -0,0 +1,33 @@ +import * as supertest from 'supertest'; +import { PgSqlClient } from "@hirosystems/api-toolkit"; +import { ChainID } from "@stacks/common"; +import { ApiServer, startApiServer } from "../api/init"; +import { PgWriteStore } from "../datastore/pg-write-store"; +import { migrate } from "../test-utils/test-helpers"; + +describe('Rosetta API toggle', () => { + let db: PgWriteStore; + let client: PgSqlClient; + let api: ApiServer; + + beforeEach(async () => { + process.env.STACKS_CHAIN_ID = '0x80000000'; + await migrate('up'); + db = await PgWriteStore.connect({ usageName: 'tests' }); + client = db.sql; + process.env.STACKS_API_ENABLE_ROSETTA = '0'; + api = await startApiServer({ datastore: db, chainId: ChainID.Testnet }); + }); + + test('rosetta is disabled', async () => { + const query1 = await supertest(api.server).post(`/rosetta/v1/network/list`); + expect(query1.status).toBe(404); + }); + + afterEach(async () => { + await api.terminate(); + process.env.STACKS_API_ENABLE_ROSETTA = '1'; + await db?.close(); + await migrate('down'); + }); +}); From 9c06a5a4bcaa798355aa36dcd4b74feb5a674102 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 8 Jan 2024 18:19:02 +0000 Subject: [PATCH 74/91] chore(release): 7.4.0-nakamoto.12 [skip ci] ## [7.4.0-nakamoto.12](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.11...v7.4.0-nakamoto.12) (2024-01-08) ### Features * disable rosetta via an ENV var ([#1804](https://github.com/hirosystems/stacks-blockchain-api/issues/1804)) ([2d2aee3](https://github.com/hirosystems/stacks-blockchain-api/commit/2d2aee38263c3e457462ba5fd4cf4fd305178039)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a6c9f6680..e58f77dff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.4.0-nakamoto.12](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.11...v7.4.0-nakamoto.12) (2024-01-08) + + +### Features + +* disable rosetta via an ENV var ([#1804](https://github.com/hirosystems/stacks-blockchain-api/issues/1804)) ([2d2aee3](https://github.com/hirosystems/stacks-blockchain-api/commit/2d2aee38263c3e457462ba5fd4cf4fd305178039)) + ## [7.4.0-nakamoto.11](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0-nakamoto.10...v7.4.0-nakamoto.11) (2024-01-03) From 775a62ede9192e260480a840d81943c7fea56189 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 9 Jan 2024 14:36:45 +0000 Subject: [PATCH 75/91] chore(release): 7.6.0-nakamoto.1 [skip ci] ## [7.6.0-nakamoto.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0...v7.6.0-nakamoto.1) (2024-01-09) ### Features * `GET /extended/v1/burn_block` ([#1766](https://github.com/hirosystems/stacks-blockchain-api/issues/1766)) ([cb38b68](https://github.com/hirosystems/stacks-blockchain-api/commit/cb38b6811c65aa700d4de527329216ba3c2ff6c9)) * add `/extended/v2/blocks/:height_or_hash` ([#1774](https://github.com/hirosystems/stacks-blockchain-api/issues/1774)) ([e532a5e](https://github.com/hirosystems/stacks-blockchain-api/commit/e532a5e173340f732536b9236d60585501f2da5f)) * add `/extended/v2/blocks` endpoint with burn block filters ([#1769](https://github.com/hirosystems/stacks-blockchain-api/issues/1769)) ([ceb7be0](https://github.com/hirosystems/stacks-blockchain-api/commit/ceb7be08daa5ca2d9baaa1a3de9f6c0569987724)) * add `tx_count` property to `/extended/v2/blocks` ([#1778](https://github.com/hirosystems/stacks-blockchain-api/issues/1778)) ([da4cd56](https://github.com/hirosystems/stacks-blockchain-api/commit/da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f)) * add dataset store ([4211328](https://github.com/hirosystems/stacks-blockchain-api/commit/42113284381bc7d0913feb05cfecc65b37fdf814)) * add step to compile duckdb for Alpine image ([0f40e14](https://github.com/hirosystems/stacks-blockchain-api/commit/0f40e14aecd8390b90ea6c5c34a47601f3866e23)) * better handling of raw events insertion ([bb70ca9](https://github.com/hirosystems/stacks-blockchain-api/commit/bb70ca99c07bf777557bca5e4b9924d104d8f7fd)) * create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint ([#1782](https://github.com/hirosystems/stacks-blockchain-api/issues/1782)) ([20466a1](https://github.com/hirosystems/stacks-blockchain-api/commit/20466a16573bff1634bc9b6ff1180bb8e0f620a0)) * disable rosetta via an ENV var ([#1804](https://github.com/hirosystems/stacks-blockchain-api/issues/1804)) ([2d2aee3](https://github.com/hirosystems/stacks-blockchain-api/commit/2d2aee38263c3e457462ba5fd4cf4fd305178039)) * event-replay new_block events handling ([1708b42](https://github.com/hirosystems/stacks-blockchain-api/commit/1708b42c02b75882ec8ce8d05df5eddc7ef835b9)) * event-replay new_burn_block events handling ([6c0f448](https://github.com/hirosystems/stacks-blockchain-api/commit/6c0f4481c0f903d707c09e4e46a2330e67f32fff)) * event-replay raw events handling ([81f43cf](https://github.com/hirosystems/stacks-blockchain-api/commit/81f43cf7c314853f0d849ed8c8f6c0d0d6130a79)) * event-replay remainder events handling ([3ede07f](https://github.com/hirosystems/stacks-blockchain-api/commit/3ede07f134ac121505ca00b5bab7dba93a3def17)) * event-replay supporting parallel insertions ([f33ecee](https://github.com/hirosystems/stacks-blockchain-api/commit/f33ecee858a8d300e5926cb8238617e6e8b935a5)) * events folder as environment var ([701bd1a](https://github.com/hirosystems/stacks-blockchain-api/commit/701bd1a984c4ab064ddb1273a74cdb25975d7c1c)) * ingestion for `TenureChange` and `NakamotoCoinbase` tx types ([#1753](https://github.com/hirosystems/stacks-blockchain-api/issues/1753)) ([7c45f53](https://github.com/hirosystems/stacks-blockchain-api/commit/7c45f53622338170477948d38f549c2136d830c1)) * parallel processing using node cluster ([d02a7e8](https://github.com/hirosystems/stacks-blockchain-api/commit/d02a7e8ad87c9374bdf5f3e14740757984d0be75)) * pox-4 support ([#1754](https://github.com/hirosystems/stacks-blockchain-api/issues/1754)) ([285806f](https://github.com/hirosystems/stacks-blockchain-api/commit/285806f46cebd365cc424a7a0155a531f34d7438)) * processing raw events in parallel ([7a6f241](https://github.com/hirosystems/stacks-blockchain-api/commit/7a6f241923d0511b3d80308990dcf045b22562b6)) * update to latest TenureChange tx payload ([#1767](https://github.com/hirosystems/stacks-blockchain-api/issues/1767)) ([2afb65c](https://github.com/hirosystems/stacks-blockchain-api/commit/2afb65cbb821658416eb41197ce8b72f239970b4)) ### Bug Fixes * add token offering ([8ef039e](https://github.com/hirosystems/stacks-blockchain-api/commit/8ef039e89a083b555b88ce509f4e80d6270d096a)) * allow contract-principals in `/extended/v1/address/:principal/mempool` endpoint [#1685](https://github.com/hirosystems/stacks-blockchain-api/issues/1685) ([#1704](https://github.com/hirosystems/stacks-blockchain-api/issues/1704)) ([163b76a](https://github.com/hirosystems/stacks-blockchain-api/commit/163b76a31a548c84b9d8be8e07ef94e5631b311b)) * better args handlling ([c77ac57](https://github.com/hirosystems/stacks-blockchain-api/commit/c77ac57a9613a85418174355f6922f74676158e5)) * better path handling for workers ([1bd8f17](https://github.com/hirosystems/stacks-blockchain-api/commit/1bd8f17f07fc8bfff30684aa67deed1de56f7b11)) * changed processing order ([62a12bd](https://github.com/hirosystems/stacks-blockchain-api/commit/62a12bdef93c77a5ac6eb5b7e15c20b4c672e041)) * convert `chain_tip` materialized view into a table ([#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751)) ([04b71cc](https://github.com/hirosystems/stacks-blockchain-api/commit/04b71cc392b4e9b6518fd59b79886cc437656de7)) * do not load duckdb binary unless required ([#1776](https://github.com/hirosystems/stacks-blockchain-api/issues/1776)) ([db859ae](https://github.com/hirosystems/stacks-blockchain-api/commit/db859ae980368db22b9d1c4c7096918d5f7f4c4b)) * flaky test ([484d2ea](https://github.com/hirosystems/stacks-blockchain-api/commit/484d2ea0cd765431e8017e42c53669e5bc6e8728)) * flaky test ([65175f5](https://github.com/hirosystems/stacks-blockchain-api/commit/65175f5cca0853c6bb07a9f377b8e39a134c8a8c)) * handle `Problematic` status in `/drop_mempool_tx` event ([#1790](https://github.com/hirosystems/stacks-blockchain-api/issues/1790)) ([ce9b38f](https://github.com/hirosystems/stacks-blockchain-api/commit/ce9b38f051216d149375d64b3dfb90a75ab50fcd)) * import statement in replay controller ([7a10cd8](https://github.com/hirosystems/stacks-blockchain-api/commit/7a10cd8c4bb585c75a2437508802c7e5d908a564)) * insert block transaction data in batches ([#1760](https://github.com/hirosystems/stacks-blockchain-api/issues/1760)) ([bf99e90](https://github.com/hirosystems/stacks-blockchain-api/commit/bf99e90fa56ed04e6cb6bcc83559658f9e551183)) * lint ([01589ea](https://github.com/hirosystems/stacks-blockchain-api/commit/01589eabbb88d2bc6453368a7b753813bd247a34)) * lint ([82eadcb](https://github.com/hirosystems/stacks-blockchain-api/commit/82eadcbe2fefd6ec5fc74b098445a6dedc63528b)) * lint ([8c67ae5](https://github.com/hirosystems/stacks-blockchain-api/commit/8c67ae532b9a992e93e0d00561e331197a5ca8ea)) * move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` ([#1772](https://github.com/hirosystems/stacks-blockchain-api/issues/1772)) ([bf2ef0a](https://github.com/hirosystems/stacks-blockchain-api/commit/bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5)) * on attachments_new events processing ([0707313](https://github.com/hirosystems/stacks-blockchain-api/commit/07073139ccb4b6d71d429864e4612944ef84c646)) * optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([3a02f57](https://github.com/hirosystems/stacks-blockchain-api/commit/3a02f5741f4109c1e662b4e7014189ae95430df8)) * re-enable indexes when finishing the replay ([fc379eb](https://github.com/hirosystems/stacks-blockchain-api/commit/fc379ebab97e41dc20645bfff34fb484251508b9)) * remove dangling promise ([62a48ae](https://github.com/hirosystems/stacks-blockchain-api/commit/62a48ae37d86591dcaa8a928c1b63ddf2b1a6056)) * remove deprecated token endpoints ([#1775](https://github.com/hirosystems/stacks-blockchain-api/issues/1775)) ([18f74b7](https://github.com/hirosystems/stacks-blockchain-api/commit/18f74b7b77c95a81c2f6d47641af229c5c833b8f)) * revert configurable DB index type ([86154b2](https://github.com/hirosystems/stacks-blockchain-api/commit/86154b29e4e4af530da162133c99ebd609fab0e1)) * upgrade semver package to fix ReDoS vulnerability ([6b1605b](https://github.com/hirosystems/stacks-blockchain-api/commit/6b1605b74d7c1bad39fcb491caf4ed51426b7618)) * vercel preview builds ([#1783](https://github.com/hirosystems/stacks-blockchain-api/issues/1783)) ([d36b1c2](https://github.com/hirosystems/stacks-blockchain-api/commit/d36b1c2d37b050eb826e1c80e5ef4674ca0ea699)) --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1153d2707a..4a79511ec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,57 @@ +## [7.6.0-nakamoto.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0...v7.6.0-nakamoto.1) (2024-01-09) + + +### Features + +* `GET /extended/v1/burn_block` ([#1766](https://github.com/hirosystems/stacks-blockchain-api/issues/1766)) ([cb38b68](https://github.com/hirosystems/stacks-blockchain-api/commit/cb38b6811c65aa700d4de527329216ba3c2ff6c9)) +* add `/extended/v2/blocks/:height_or_hash` ([#1774](https://github.com/hirosystems/stacks-blockchain-api/issues/1774)) ([e532a5e](https://github.com/hirosystems/stacks-blockchain-api/commit/e532a5e173340f732536b9236d60585501f2da5f)) +* add `/extended/v2/blocks` endpoint with burn block filters ([#1769](https://github.com/hirosystems/stacks-blockchain-api/issues/1769)) ([ceb7be0](https://github.com/hirosystems/stacks-blockchain-api/commit/ceb7be08daa5ca2d9baaa1a3de9f6c0569987724)) +* add `tx_count` property to `/extended/v2/blocks` ([#1778](https://github.com/hirosystems/stacks-blockchain-api/issues/1778)) ([da4cd56](https://github.com/hirosystems/stacks-blockchain-api/commit/da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f)) +* add dataset store ([4211328](https://github.com/hirosystems/stacks-blockchain-api/commit/42113284381bc7d0913feb05cfecc65b37fdf814)) +* add step to compile duckdb for Alpine image ([0f40e14](https://github.com/hirosystems/stacks-blockchain-api/commit/0f40e14aecd8390b90ea6c5c34a47601f3866e23)) +* better handling of raw events insertion ([bb70ca9](https://github.com/hirosystems/stacks-blockchain-api/commit/bb70ca99c07bf777557bca5e4b9924d104d8f7fd)) +* create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint ([#1782](https://github.com/hirosystems/stacks-blockchain-api/issues/1782)) ([20466a1](https://github.com/hirosystems/stacks-blockchain-api/commit/20466a16573bff1634bc9b6ff1180bb8e0f620a0)) +* disable rosetta via an ENV var ([#1804](https://github.com/hirosystems/stacks-blockchain-api/issues/1804)) ([2d2aee3](https://github.com/hirosystems/stacks-blockchain-api/commit/2d2aee38263c3e457462ba5fd4cf4fd305178039)) +* event-replay new_block events handling ([1708b42](https://github.com/hirosystems/stacks-blockchain-api/commit/1708b42c02b75882ec8ce8d05df5eddc7ef835b9)) +* event-replay new_burn_block events handling ([6c0f448](https://github.com/hirosystems/stacks-blockchain-api/commit/6c0f4481c0f903d707c09e4e46a2330e67f32fff)) +* event-replay raw events handling ([81f43cf](https://github.com/hirosystems/stacks-blockchain-api/commit/81f43cf7c314853f0d849ed8c8f6c0d0d6130a79)) +* event-replay remainder events handling ([3ede07f](https://github.com/hirosystems/stacks-blockchain-api/commit/3ede07f134ac121505ca00b5bab7dba93a3def17)) +* event-replay supporting parallel insertions ([f33ecee](https://github.com/hirosystems/stacks-blockchain-api/commit/f33ecee858a8d300e5926cb8238617e6e8b935a5)) +* events folder as environment var ([701bd1a](https://github.com/hirosystems/stacks-blockchain-api/commit/701bd1a984c4ab064ddb1273a74cdb25975d7c1c)) +* ingestion for `TenureChange` and `NakamotoCoinbase` tx types ([#1753](https://github.com/hirosystems/stacks-blockchain-api/issues/1753)) ([7c45f53](https://github.com/hirosystems/stacks-blockchain-api/commit/7c45f53622338170477948d38f549c2136d830c1)) +* parallel processing using node cluster ([d02a7e8](https://github.com/hirosystems/stacks-blockchain-api/commit/d02a7e8ad87c9374bdf5f3e14740757984d0be75)) +* pox-4 support ([#1754](https://github.com/hirosystems/stacks-blockchain-api/issues/1754)) ([285806f](https://github.com/hirosystems/stacks-blockchain-api/commit/285806f46cebd365cc424a7a0155a531f34d7438)) +* processing raw events in parallel ([7a6f241](https://github.com/hirosystems/stacks-blockchain-api/commit/7a6f241923d0511b3d80308990dcf045b22562b6)) +* update to latest TenureChange tx payload ([#1767](https://github.com/hirosystems/stacks-blockchain-api/issues/1767)) ([2afb65c](https://github.com/hirosystems/stacks-blockchain-api/commit/2afb65cbb821658416eb41197ce8b72f239970b4)) + + +### Bug Fixes + +* add token offering ([8ef039e](https://github.com/hirosystems/stacks-blockchain-api/commit/8ef039e89a083b555b88ce509f4e80d6270d096a)) +* allow contract-principals in `/extended/v1/address/:principal/mempool` endpoint [#1685](https://github.com/hirosystems/stacks-blockchain-api/issues/1685) ([#1704](https://github.com/hirosystems/stacks-blockchain-api/issues/1704)) ([163b76a](https://github.com/hirosystems/stacks-blockchain-api/commit/163b76a31a548c84b9d8be8e07ef94e5631b311b)) +* better args handlling ([c77ac57](https://github.com/hirosystems/stacks-blockchain-api/commit/c77ac57a9613a85418174355f6922f74676158e5)) +* better path handling for workers ([1bd8f17](https://github.com/hirosystems/stacks-blockchain-api/commit/1bd8f17f07fc8bfff30684aa67deed1de56f7b11)) +* changed processing order ([62a12bd](https://github.com/hirosystems/stacks-blockchain-api/commit/62a12bdef93c77a5ac6eb5b7e15c20b4c672e041)) +* convert `chain_tip` materialized view into a table ([#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751)) ([04b71cc](https://github.com/hirosystems/stacks-blockchain-api/commit/04b71cc392b4e9b6518fd59b79886cc437656de7)) +* do not load duckdb binary unless required ([#1776](https://github.com/hirosystems/stacks-blockchain-api/issues/1776)) ([db859ae](https://github.com/hirosystems/stacks-blockchain-api/commit/db859ae980368db22b9d1c4c7096918d5f7f4c4b)) +* flaky test ([484d2ea](https://github.com/hirosystems/stacks-blockchain-api/commit/484d2ea0cd765431e8017e42c53669e5bc6e8728)) +* flaky test ([65175f5](https://github.com/hirosystems/stacks-blockchain-api/commit/65175f5cca0853c6bb07a9f377b8e39a134c8a8c)) +* handle `Problematic` status in `/drop_mempool_tx` event ([#1790](https://github.com/hirosystems/stacks-blockchain-api/issues/1790)) ([ce9b38f](https://github.com/hirosystems/stacks-blockchain-api/commit/ce9b38f051216d149375d64b3dfb90a75ab50fcd)) +* import statement in replay controller ([7a10cd8](https://github.com/hirosystems/stacks-blockchain-api/commit/7a10cd8c4bb585c75a2437508802c7e5d908a564)) +* insert block transaction data in batches ([#1760](https://github.com/hirosystems/stacks-blockchain-api/issues/1760)) ([bf99e90](https://github.com/hirosystems/stacks-blockchain-api/commit/bf99e90fa56ed04e6cb6bcc83559658f9e551183)) +* lint ([01589ea](https://github.com/hirosystems/stacks-blockchain-api/commit/01589eabbb88d2bc6453368a7b753813bd247a34)) +* lint ([82eadcb](https://github.com/hirosystems/stacks-blockchain-api/commit/82eadcbe2fefd6ec5fc74b098445a6dedc63528b)) +* lint ([8c67ae5](https://github.com/hirosystems/stacks-blockchain-api/commit/8c67ae532b9a992e93e0d00561e331197a5ca8ea)) +* move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` ([#1772](https://github.com/hirosystems/stacks-blockchain-api/issues/1772)) ([bf2ef0a](https://github.com/hirosystems/stacks-blockchain-api/commit/bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5)) +* on attachments_new events processing ([0707313](https://github.com/hirosystems/stacks-blockchain-api/commit/07073139ccb4b6d71d429864e4612944ef84c646)) +* optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([3a02f57](https://github.com/hirosystems/stacks-blockchain-api/commit/3a02f5741f4109c1e662b4e7014189ae95430df8)) +* re-enable indexes when finishing the replay ([fc379eb](https://github.com/hirosystems/stacks-blockchain-api/commit/fc379ebab97e41dc20645bfff34fb484251508b9)) +* remove dangling promise ([62a48ae](https://github.com/hirosystems/stacks-blockchain-api/commit/62a48ae37d86591dcaa8a928c1b63ddf2b1a6056)) +* remove deprecated token endpoints ([#1775](https://github.com/hirosystems/stacks-blockchain-api/issues/1775)) ([18f74b7](https://github.com/hirosystems/stacks-blockchain-api/commit/18f74b7b77c95a81c2f6d47641af229c5c833b8f)) +* revert configurable DB index type ([86154b2](https://github.com/hirosystems/stacks-blockchain-api/commit/86154b29e4e4af530da162133c99ebd609fab0e1)) +* upgrade semver package to fix ReDoS vulnerability ([6b1605b](https://github.com/hirosystems/stacks-blockchain-api/commit/6b1605b74d7c1bad39fcb491caf4ed51426b7618)) +* vercel preview builds ([#1783](https://github.com/hirosystems/stacks-blockchain-api/issues/1783)) ([d36b1c2](https://github.com/hirosystems/stacks-blockchain-api/commit/d36b1c2d37b050eb826e1c80e5ef4674ca0ea699)) + ## [7.5.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.4.0...v7.5.0) (2024-01-05) From c9a4df8f43f56a0d9ebbc4a065c54cb32bae350a Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Tue, 9 Jan 2024 15:46:45 +0100 Subject: [PATCH 76/91] fix: support comma-separated strings in array query params (#1809) * fix: support comma-separated strings in array query params * fix: `asset_identifiers` array parsing --- src/api/query-helpers.ts | 6 +++++- src/api/routes/tokens.ts | 16 ++++++++++------ src/api/routes/tx.ts | 15 ++++++++++++--- src/tests/tx-tests.ts | 7 +++++++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/api/query-helpers.ts b/src/api/query-helpers.ts index 4a1cfe8ff6..bd8dd1df7f 100644 --- a/src/api/query-helpers.ts +++ b/src/api/query-helpers.ts @@ -319,7 +319,11 @@ export function parseEventTypeFilter( } } else if (typeof typeQuery === 'string') { try { - eventTypeFilter = parseEventTypeStrings([typeQuery]); + if (typeQuery.includes(',')) { + eventTypeFilter = parseEventTypeStrings(typeQuery.split(',')); + } else { + eventTypeFilter = parseEventTypeStrings([typeQuery]); + } } catch (error) { handleBadRequest(res, next, `invalid 'event type'`); } diff --git a/src/api/routes/tokens.ts b/src/api/routes/tokens.ts index 50bec6ff8d..b69071f48e 100644 --- a/src/api/routes/tokens.ts +++ b/src/api/routes/tokens.ts @@ -33,18 +33,22 @@ export function createTokenRouter(db: PgStore): express.Router { } let assetIdentifiers: string[] | undefined; if (req.query.asset_identifiers !== undefined) { - for (const assetIdentifier of [req.query.asset_identifiers].flat()) { + if (typeof req.query.asset_identifiers === 'string') { + if (req.query.asset_identifiers.includes(',')) { + assetIdentifiers = req.query.asset_identifiers.split(','); + } else { + assetIdentifiers = [req.query.asset_identifiers]; + } + } else { + assetIdentifiers = req.query.asset_identifiers as string[]; + } + for (const assetIdentifier of assetIdentifiers) { if ( typeof assetIdentifier !== 'string' || !isValidPrincipal(assetIdentifier.split('::')[0]) ) { res.status(400).json({ error: `Invalid asset identifier ${assetIdentifier}` }); return; - } else { - if (!assetIdentifiers) { - assetIdentifiers = []; - } - assetIdentifiers?.push(assetIdentifier); } } } diff --git a/src/api/routes/tx.ts b/src/api/routes/tx.ts index f23d5fc81f..4c6073f4c1 100644 --- a/src/api/routes/tx.ts +++ b/src/api/routes/tx.ts @@ -52,7 +52,11 @@ export function createTxRouter(db: PgStore): express.Router { if (Array.isArray(typeQuery)) { txTypeFilter = parseTxTypeStrings(typeQuery as string[]); } else if (typeof typeQuery === 'string') { - txTypeFilter = parseTxTypeStrings([typeQuery]); + if (typeQuery.includes(',')) { + txTypeFilter = parseTxTypeStrings(typeQuery.split(',')); + } else { + txTypeFilter = parseTxTypeStrings([typeQuery]); + } } else if (typeQuery) { throw new Error(`Unexpected tx type query value: ${JSON.stringify(typeQuery)}`); } else { @@ -82,8 +86,13 @@ export function createTxRouter(db: PgStore): express.Router { '/multiple', asyncHandler(async (req, res, next) => { if (typeof req.query.tx_id === 'string') { - // in case req.query.tx_id is a single tx_id string and not an array - req.query.tx_id = [req.query.tx_id]; + // check if tx_id is a comma-seperated list of tx_ids + if (req.query.tx_id.includes(',')) { + req.query.tx_id = req.query.tx_id.split(','); + } else { + // in case req.query.tx_id is a single tx_id string and not an array + req.query.tx_id = [req.query.tx_id]; + } } const txList: string[] = req.query.tx_id as string[]; diff --git a/src/tests/tx-tests.ts b/src/tests/tx-tests.ts index 4677ae66d6..beb866ce79 100644 --- a/src/tests/tx-tests.ts +++ b/src/tests/tx-tests.ts @@ -299,6 +299,13 @@ describe('tx tests', () => { expect(jsonRes[dbTx3.tx_id].result.tx_id).toEqual(dbTx3.tx_id); expect(jsonRes[dbTx3.tx_id].result.tx_type).toEqual('smart_contract'); expect(jsonRes[dbTx3.tx_id].result.smart_contract.clarity_version).toEqual(2); + + // test comma-separated tx_id list + const txIds = [mempoolTx.tx_id, tx1.tx_id, notFoundTxId, dbTx2.tx_id, dbTx3.tx_id].join(','); + const txsListDetail2 = await supertest(api.server).get( + `/extended/v1/tx/multiple?tx_id=${txIds}` + ); + expect(txsListDetail2.body).toEqual(txsListDetail.body); }); test('getTxList returns object', async () => { From 083139316350650c6cc97af377a6ae1cf6006be8 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Tue, 9 Jan 2024 15:47:06 +0100 Subject: [PATCH 77/91] feat: support tenure_change in tx type filter queries (#1808) --- src/api/controllers/db-controller.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 9a8e284099..fe9399b09d 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -77,6 +77,7 @@ export function parseTxTypeStrings(values: string[]): TransactionType[] { case 'token_transfer': case 'coinbase': case 'poison_microblock': + case 'tenure_change': return v; default: throw new Error(`Unexpected tx type: ${JSON.stringify(v)}`); @@ -98,6 +99,8 @@ export function getTxTypeString(typeId: DbTxTypeId): Transaction['tx_type'] { case DbTxTypeId.Coinbase: case DbTxTypeId.CoinbaseToAltRecipient: return 'coinbase'; + case DbTxTypeId.TenureChange: + return 'tenure_change'; default: throw new Error(`Unexpected DbTxTypeId: ${typeId}`); } @@ -139,6 +142,8 @@ export function getTxTypeId(typeString: Transaction['tx_type']): DbTxTypeId[] { return [DbTxTypeId.PoisonMicroblock]; case 'coinbase': return [DbTxTypeId.Coinbase, DbTxTypeId.CoinbaseToAltRecipient]; + case 'tenure_change': + return [DbTxTypeId.TenureChange]; default: throw new Error(`Unexpected tx type string: ${typeString}`); } From e184fb59d0c21d56bced1f5d53c29f1dbedbed51 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Tue, 9 Jan 2024 15:47:54 +0100 Subject: [PATCH 78/91] fix(docs): URL query arrays should be formatted with `form` rather than comma-separated (#1807) * fix(docs): arrays in URL queries should be formatted with `form` rather than comma-separated * docs: update /multiple tx example * chore: schema lint fix --- docs/openapi.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index a3ade99c7d..5ad69e468a 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -207,6 +207,8 @@ paths: in: query description: Filter by transaction type required: false + style: form + explode: true schema: type: array example: coinbase @@ -377,9 +379,15 @@ paths: in: query description: Array of transaction ids required: true + style: form + explode: true schema: type: array - example: "0x0a411719e3bfde95f9e227a2d7f8fac3d6c646b1e6cc186db0e2838a2c6cd9c0" + example: [ + "0x0a411719e3bfde95f9e227a2d7f8fac3d6c646b1e6cc186db0e2838a2c6cd9c0", + "0xfbe6412b46e9db87df991a0d043ff47eb58019f770208cf48e2380337cc31785", + "0x178b77678a758d9f29a147d6399315c83d0f1baf114431fbe4d3587aa5fbba6f" + ] items: type: string - name: event_offset @@ -3113,6 +3121,8 @@ paths: in: query description: identifiers of the token asset classes to filter for required: false + style: form + explode: true schema: type: array example: "SPQZF23W7SEYBFG5JQ496NMY0G7379SRYEDREMSV.Candy::candy" @@ -3446,6 +3456,8 @@ paths: in: query description: Filter the events on event type required: false + style: form + explode: true schema: type: array example: stx_lock From cf736618bf990912582f18b4498cee15e9416e19 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 9 Jan 2024 14:54:39 +0000 Subject: [PATCH 79/91] chore(release): 7.6.0-nakamoto.2 [skip ci] ## [7.6.0-nakamoto.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0-nakamoto.1...v7.6.0-nakamoto.2) (2024-01-09) ### Features * support tenure_change in tx type filter queries ([#1808](https://github.com/hirosystems/stacks-blockchain-api/issues/1808)) ([0831393](https://github.com/hirosystems/stacks-blockchain-api/commit/083139316350650c6cc97af377a6ae1cf6006be8)) ### Bug Fixes * **docs:** URL query arrays should be formatted with `form` rather than comma-separated ([#1807](https://github.com/hirosystems/stacks-blockchain-api/issues/1807)) ([e184fb5](https://github.com/hirosystems/stacks-blockchain-api/commit/e184fb59d0c21d56bced1f5d53c29f1dbedbed51)) * support comma-separated strings in array query params ([#1809](https://github.com/hirosystems/stacks-blockchain-api/issues/1809)) ([c9a4df8](https://github.com/hirosystems/stacks-blockchain-api/commit/c9a4df8f43f56a0d9ebbc4a065c54cb32bae350a)) --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a79511ec2..e26d008325 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [7.6.0-nakamoto.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0-nakamoto.1...v7.6.0-nakamoto.2) (2024-01-09) + + +### Features + +* support tenure_change in tx type filter queries ([#1808](https://github.com/hirosystems/stacks-blockchain-api/issues/1808)) ([0831393](https://github.com/hirosystems/stacks-blockchain-api/commit/083139316350650c6cc97af377a6ae1cf6006be8)) + + +### Bug Fixes + +* **docs:** URL query arrays should be formatted with `form` rather than comma-separated ([#1807](https://github.com/hirosystems/stacks-blockchain-api/issues/1807)) ([e184fb5](https://github.com/hirosystems/stacks-blockchain-api/commit/e184fb59d0c21d56bced1f5d53c29f1dbedbed51)) +* support comma-separated strings in array query params ([#1809](https://github.com/hirosystems/stacks-blockchain-api/issues/1809)) ([c9a4df8](https://github.com/hirosystems/stacks-blockchain-api/commit/c9a4df8f43f56a0d9ebbc4a065c54cb32bae350a)) + ## [7.6.0-nakamoto.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0...v7.6.0-nakamoto.1) (2024-01-09) From 2d45b2eafdec0ca478de65237de953d7bc63e827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Tue, 9 Jan 2024 10:01:22 -0600 Subject: [PATCH 80/91] feat: add `order_by` and `order` params to `/extended/v1/tx/mempool` (#1810) * feat: sort mempool * test: age sort * fix: add enum types * chore: move v2 to proper folder * docs: add to openapi --- docs/openapi.yaml | 16 ++++++ src/api/init.ts | 2 +- src/api/query-helpers.ts | 11 ++++ src/api/routes/tx.ts | 25 +++++++++ src/api/{ => routes}/v2/mempool.ts | 10 ++-- src/datastore/pg-store.ts | 10 +++- src/tests/mempool-tests.ts | 83 ++++++++++++++++++++++++++++++ 7 files changed, 150 insertions(+), 7 deletions(-) rename src/api/{ => routes}/v2/mempool.ts (82%) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 5ad69e468a..489429dbe9 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -263,6 +263,22 @@ paths: required: false schema: type: string + - name: order_by + in: query + description: Option to sort results by transaction age, size, or fee rate. + required: false + schema: + type: string + enum: [age, size, fee] + example: fee + - name: order + in: query + description: Option to sort results in ascending or descending order. + required: false + schema: + type: string + enum: [asc, desc] + example: asc - name: limit in: query description: max number of mempool transactions to fetch diff --git a/src/api/init.ts b/src/api/init.ts index be3b4ce163..2376235500 100644 --- a/src/api/init.ts +++ b/src/api/init.ts @@ -52,7 +52,7 @@ import { import { createV2BlocksRouter } from './routes/v2/blocks'; import { getReqQuery } from './query-helpers'; import { createV2BurnBlocksRouter } from './routes/v2/burn-blocks'; -import { createMempoolRouter } from './v2/mempool'; +import { createMempoolRouter } from './routes/v2/mempool'; export interface ApiServer { expressApp: express.Express; diff --git a/src/api/query-helpers.ts b/src/api/query-helpers.ts index bd8dd1df7f..9011adb6cd 100644 --- a/src/api/query-helpers.ts +++ b/src/api/query-helpers.ts @@ -5,6 +5,17 @@ import { InvalidRequestError, InvalidRequestErrorType } from '../errors'; import { DbEventTypeId } from './../datastore/common'; import { has0xPrefix, hexToBuffer } from '@hirosystems/api-toolkit'; +export enum MempoolOrderByParam { + fee = 'fee', + size = 'size', + age = 'age', +} + +export enum OrderParam { + asc = 'asc', + desc = 'desc', +} + function handleBadRequest(res: Response, next: NextFunction, errorMessage: string): never { const error = new InvalidRequestError(errorMessage, InvalidRequestErrorType.bad_request); res.status(400).json({ error: errorMessage }); diff --git a/src/api/routes/tx.ts b/src/api/routes/tx.ts index 4c6073f4c1..73eae43152 100644 --- a/src/api/routes/tx.ts +++ b/src/api/routes/tx.ts @@ -16,6 +16,8 @@ import { validateRequestHexInput, parseAddressOrTxId, parseEventTypeFilter, + MempoolOrderByParam, + OrderParam, } from '../query-helpers'; import { getPagingQueryLimit, parsePagingQueryInput, ResourceType } from '../pagination'; import { validate } from '../validate'; @@ -162,10 +164,33 @@ export function createTxRouter(db: PgStore): express.Router { InvalidRequestErrorType.invalid_param ); } + + const orderBy = req.query.order_by; + if ( + orderBy !== undefined && + orderBy != MempoolOrderByParam.fee && + orderBy != MempoolOrderByParam.age && + orderBy != MempoolOrderByParam.size + ) { + throw new InvalidRequestError( + `The "order_by" param can only be 'fee', 'age', or 'size'`, + InvalidRequestErrorType.invalid_param + ); + } + const order = req.query.order; + if (order !== undefined && order != OrderParam.asc && order != OrderParam.desc) { + throw new InvalidRequestError( + `The "order" param can only be 'asc' or 'desc'`, + InvalidRequestErrorType.invalid_param + ); + } + const { results: txResults, total } = await db.getMempoolTxList({ offset, limit, includeUnanchored, + orderBy, + order, senderAddress, recipientAddress, address, diff --git a/src/api/v2/mempool.ts b/src/api/routes/v2/mempool.ts similarity index 82% rename from src/api/v2/mempool.ts rename to src/api/routes/v2/mempool.ts index c106b06711..cdd1e6b195 100644 --- a/src/api/v2/mempool.ts +++ b/src/api/routes/v2/mempool.ts @@ -1,13 +1,13 @@ import * as express from 'express'; -import { asyncHandler } from '../async-handler'; +import { asyncHandler } from '../../async-handler'; import { ETagType, getETagCacheHandler, setETagCacheHeaders, -} from '../controllers/cache-controller'; -import { PgStore } from '../../datastore/pg-store'; -import { DbMempoolFeePriority, DbTxTypeId } from '../../datastore/common'; -import { MempoolFeePriorities } from '../../../docs/generated'; +} from '../../controllers/cache-controller'; +import { PgStore } from '../../../datastore/pg-store'; +import { DbMempoolFeePriority, DbTxTypeId } from '../../../datastore/common'; +import { MempoolFeePriorities } from '../../../../docs/generated'; function parseMempoolFeePriority(fees: DbMempoolFeePriority[]): MempoolFeePriorities { const out: MempoolFeePriorities = { diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index f7d640233f..f74b98cdd8 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -101,6 +101,7 @@ import { } from './connection'; import * as path from 'path'; import { PgStoreV2 } from './pg-store-v2'; +import { MempoolOrderByParam, OrderParam } from '../api/query-helpers'; export const MIGRATIONS_DIR = path.join(REPO_DIR, 'migrations'); @@ -1289,6 +1290,8 @@ export class PgStore extends BasePgStore { limit, offset, includeUnanchored, + orderBy, + order, senderAddress, recipientAddress, address, @@ -1296,6 +1299,8 @@ export class PgStore extends BasePgStore { limit: number; offset: number; includeUnanchored: boolean; + orderBy?: MempoolOrderByParam; + order?: OrderParam; senderAddress?: string; recipientAddress?: string; address?: string; @@ -1310,6 +1315,9 @@ export class PgStore extends BasePgStore { senderAddress || recipientAddress || address ? sql`(COUNT(*) OVER())::int AS count` : sql`(SELECT mempool_tx_count FROM chain_tip) AS count`; + const orderBySql = + orderBy == 'fee' ? sql`fee_rate` : orderBy == 'size' ? sql`tx_size` : sql`receipt_time`; + const orderSql = order == 'asc' ? sql`ASC` : sql`DESC`; const resultQuery = await sql<(MempoolTxQueryResult & { count: number })[]>` SELECT ${unsafeCols(sql, [...MEMPOOL_TX_COLUMNS, abiColumn('mempool_txs')])}, ${count} FROM mempool_txs @@ -1333,7 +1341,7 @@ export class PgStore extends BasePgStore { ? sql`OR tx_id IN ${sql(unanchoredTxs)}` : sql`` }) - ORDER BY receipt_time DESC + ORDER BY ${orderBySql} ${orderSql} LIMIT ${limit} OFFSET ${offset} `; diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index 2336355070..92bacde352 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1141,6 +1141,89 @@ describe('mempool tests', () => { expect(JSON.parse(searchResult7.text)).toEqual(expectedResp7); }); + test('fetch mempool-tx list sorted', async () => { + const sendAddr = 'SP25YGP221F01S9SSCGN114MKDAK9VRK8P3KXGEMB'; + const recvAddr = 'SP10EZK56MB87JYF5A704K7N18YAT6G6M09HY22GC'; + + const block = new TestBlockBuilder().addTx().build(); + await db.update(block); + const txs: DbMempoolTxRaw[] = []; + for (let index = 0; index < 5; index++) { + const paddedIndex = ('00' + index).slice(-2); + const mempoolTx: DbMempoolTxRaw = { + pruned: false, + tx_id: `0x89120000000000000000000000000000000000000000000000000000000000${paddedIndex}`, + anchor_mode: 3, + nonce: 0, + raw_tx: bufferToHex(Buffer.from('x'.repeat(index + 1))), + type_id: DbTxTypeId.TokenTransfer, + receipt_time: (new Date(`2020-07-09T15:14:${paddedIndex}Z`).getTime() / 1000) | 0, + status: 1, + post_conditions: '0x01f5', + fee_rate: 100n * BigInt(index + 1), + sponsored: false, + sponsor_address: undefined, + origin_hash_mode: 1, + sender_address: sendAddr, + token_transfer_recipient_address: recvAddr, + token_transfer_amount: 1234n, + token_transfer_memo: '', + }; + txs.push(mempoolTx); + } + await db.updateMempoolTxs({ mempoolTxs: txs }); + + let result = await supertest(api.server).get(`/extended/v1/tx/mempool?order_by=fee&order=desc`); + let json = JSON.parse(result.text); + expect(json.results[0].fee_rate).toBe('500'); + expect(json.results[1].fee_rate).toBe('400'); + expect(json.results[2].fee_rate).toBe('300'); + expect(json.results[3].fee_rate).toBe('200'); + expect(json.results[4].fee_rate).toBe('100'); + + result = await supertest(api.server).get(`/extended/v1/tx/mempool?order_by=fee&order=asc`); + json = JSON.parse(result.text); + expect(json.results[0].fee_rate).toBe('100'); + expect(json.results[1].fee_rate).toBe('200'); + expect(json.results[2].fee_rate).toBe('300'); + expect(json.results[3].fee_rate).toBe('400'); + expect(json.results[4].fee_rate).toBe('500'); + + // Larger transactions were set with higher fees. + result = await supertest(api.server).get(`/extended/v1/tx/mempool?order_by=size&order=desc`); + json = JSON.parse(result.text); + expect(json.results[0].fee_rate).toBe('500'); + expect(json.results[1].fee_rate).toBe('400'); + expect(json.results[2].fee_rate).toBe('300'); + expect(json.results[3].fee_rate).toBe('200'); + expect(json.results[4].fee_rate).toBe('100'); + + result = await supertest(api.server).get(`/extended/v1/tx/mempool?order_by=size&order=asc`); + json = JSON.parse(result.text); + expect(json.results[0].fee_rate).toBe('100'); + expect(json.results[1].fee_rate).toBe('200'); + expect(json.results[2].fee_rate).toBe('300'); + expect(json.results[3].fee_rate).toBe('400'); + expect(json.results[4].fee_rate).toBe('500'); + + // Newer transactions were set with higher fees. + result = await supertest(api.server).get(`/extended/v1/tx/mempool?order_by=age&order=desc`); + json = JSON.parse(result.text); + expect(json.results[0].fee_rate).toBe('500'); + expect(json.results[1].fee_rate).toBe('400'); + expect(json.results[2].fee_rate).toBe('300'); + expect(json.results[3].fee_rate).toBe('200'); + expect(json.results[4].fee_rate).toBe('100'); + + result = await supertest(api.server).get(`/extended/v1/tx/mempool?order_by=age&order=asc`); + json = JSON.parse(result.text); + expect(json.results[0].fee_rate).toBe('100'); + expect(json.results[1].fee_rate).toBe('200'); + expect(json.results[2].fee_rate).toBe('300'); + expect(json.results[3].fee_rate).toBe('400'); + expect(json.results[4].fee_rate).toBe('500'); + }); + test('mempool - contract_call tx abi details are retrieved', async () => { const block1 = new TestBlockBuilder() .addTx() From 02704d6e1d96bfe9b3ecea1c9e982859d8dea86b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 9 Jan 2024 16:12:24 +0000 Subject: [PATCH 81/91] chore(release): 7.6.0-nakamoto.3 [skip ci] ## [7.6.0-nakamoto.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0-nakamoto.2...v7.6.0-nakamoto.3) (2024-01-09) ### Features * add `order_by` and `order` params to `/extended/v1/tx/mempool` ([#1810](https://github.com/hirosystems/stacks-blockchain-api/issues/1810)) ([2d45b2e](https://github.com/hirosystems/stacks-blockchain-api/commit/2d45b2eafdec0ca478de65237de953d7bc63e827)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e26d008325..61690b4dd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.6.0-nakamoto.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0-nakamoto.2...v7.6.0-nakamoto.3) (2024-01-09) + + +### Features + +* add `order_by` and `order` params to `/extended/v1/tx/mempool` ([#1810](https://github.com/hirosystems/stacks-blockchain-api/issues/1810)) ([2d45b2e](https://github.com/hirosystems/stacks-blockchain-api/commit/2d45b2eafdec0ca478de65237de953d7bc63e827)) + ## [7.6.0-nakamoto.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0-nakamoto.1...v7.6.0-nakamoto.2) (2024-01-09) From 2b89b3256dae4eba3a5907db98380aa18fefa58a Mon Sep 17 00:00:00 2001 From: Rafael Cardenas Date: Tue, 9 Jan 2024 10:56:58 -0600 Subject: [PATCH 82/91] chore: trigger release ci run From effbaa7103b81d29dd82587cd839e4b5a22e6a0a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 9 Jan 2024 17:21:08 +0000 Subject: [PATCH 83/91] chore(release): 7.6.0 [skip ci] ## [7.6.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0...v7.6.0) (2024-01-09) ### Features * `GET /extended/v1/burn_block` ([#1766](https://github.com/hirosystems/stacks-blockchain-api/issues/1766)) ([cb38b68](https://github.com/hirosystems/stacks-blockchain-api/commit/cb38b6811c65aa700d4de527329216ba3c2ff6c9)) * add `/extended/v2/blocks/:height_or_hash` ([#1774](https://github.com/hirosystems/stacks-blockchain-api/issues/1774)) ([e532a5e](https://github.com/hirosystems/stacks-blockchain-api/commit/e532a5e173340f732536b9236d60585501f2da5f)) * add `/extended/v2/blocks` endpoint with burn block filters ([#1769](https://github.com/hirosystems/stacks-blockchain-api/issues/1769)) ([ceb7be0](https://github.com/hirosystems/stacks-blockchain-api/commit/ceb7be08daa5ca2d9baaa1a3de9f6c0569987724)) * add `order_by` and `order` params to `/extended/v1/tx/mempool` ([#1810](https://github.com/hirosystems/stacks-blockchain-api/issues/1810)) ([2d45b2e](https://github.com/hirosystems/stacks-blockchain-api/commit/2d45b2eafdec0ca478de65237de953d7bc63e827)) * add `tx_count` property to `/extended/v2/blocks` ([#1778](https://github.com/hirosystems/stacks-blockchain-api/issues/1778)) ([da4cd56](https://github.com/hirosystems/stacks-blockchain-api/commit/da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f)) * add dataset store ([4211328](https://github.com/hirosystems/stacks-blockchain-api/commit/42113284381bc7d0913feb05cfecc65b37fdf814)) * add step to compile duckdb for Alpine image ([0f40e14](https://github.com/hirosystems/stacks-blockchain-api/commit/0f40e14aecd8390b90ea6c5c34a47601f3866e23)) * better handling of raw events insertion ([bb70ca9](https://github.com/hirosystems/stacks-blockchain-api/commit/bb70ca99c07bf777557bca5e4b9924d104d8f7fd)) * create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint ([#1782](https://github.com/hirosystems/stacks-blockchain-api/issues/1782)) ([20466a1](https://github.com/hirosystems/stacks-blockchain-api/commit/20466a16573bff1634bc9b6ff1180bb8e0f620a0)) * disable rosetta via an ENV var ([#1804](https://github.com/hirosystems/stacks-blockchain-api/issues/1804)) ([2d2aee3](https://github.com/hirosystems/stacks-blockchain-api/commit/2d2aee38263c3e457462ba5fd4cf4fd305178039)) * event-replay new_block events handling ([1708b42](https://github.com/hirosystems/stacks-blockchain-api/commit/1708b42c02b75882ec8ce8d05df5eddc7ef835b9)) * event-replay new_burn_block events handling ([6c0f448](https://github.com/hirosystems/stacks-blockchain-api/commit/6c0f4481c0f903d707c09e4e46a2330e67f32fff)) * event-replay raw events handling ([81f43cf](https://github.com/hirosystems/stacks-blockchain-api/commit/81f43cf7c314853f0d849ed8c8f6c0d0d6130a79)) * event-replay remainder events handling ([3ede07f](https://github.com/hirosystems/stacks-blockchain-api/commit/3ede07f134ac121505ca00b5bab7dba93a3def17)) * event-replay supporting parallel insertions ([f33ecee](https://github.com/hirosystems/stacks-blockchain-api/commit/f33ecee858a8d300e5926cb8238617e6e8b935a5)) * events folder as environment var ([701bd1a](https://github.com/hirosystems/stacks-blockchain-api/commit/701bd1a984c4ab064ddb1273a74cdb25975d7c1c)) * ingestion for `TenureChange` and `NakamotoCoinbase` tx types ([#1753](https://github.com/hirosystems/stacks-blockchain-api/issues/1753)) ([7c45f53](https://github.com/hirosystems/stacks-blockchain-api/commit/7c45f53622338170477948d38f549c2136d830c1)) * parallel processing using node cluster ([d02a7e8](https://github.com/hirosystems/stacks-blockchain-api/commit/d02a7e8ad87c9374bdf5f3e14740757984d0be75)) * pox-4 support ([#1754](https://github.com/hirosystems/stacks-blockchain-api/issues/1754)) ([285806f](https://github.com/hirosystems/stacks-blockchain-api/commit/285806f46cebd365cc424a7a0155a531f34d7438)) * processing raw events in parallel ([7a6f241](https://github.com/hirosystems/stacks-blockchain-api/commit/7a6f241923d0511b3d80308990dcf045b22562b6)) * support tenure_change in tx type filter queries ([#1808](https://github.com/hirosystems/stacks-blockchain-api/issues/1808)) ([0831393](https://github.com/hirosystems/stacks-blockchain-api/commit/083139316350650c6cc97af377a6ae1cf6006be8)) * update to latest TenureChange tx payload ([#1767](https://github.com/hirosystems/stacks-blockchain-api/issues/1767)) ([2afb65c](https://github.com/hirosystems/stacks-blockchain-api/commit/2afb65cbb821658416eb41197ce8b72f239970b4)) ### Bug Fixes * add token offering ([8ef039e](https://github.com/hirosystems/stacks-blockchain-api/commit/8ef039e89a083b555b88ce509f4e80d6270d096a)) * allow contract-principals in `/extended/v1/address/:principal/mempool` endpoint [#1685](https://github.com/hirosystems/stacks-blockchain-api/issues/1685) ([#1704](https://github.com/hirosystems/stacks-blockchain-api/issues/1704)) ([163b76a](https://github.com/hirosystems/stacks-blockchain-api/commit/163b76a31a548c84b9d8be8e07ef94e5631b311b)) * better args handlling ([c77ac57](https://github.com/hirosystems/stacks-blockchain-api/commit/c77ac57a9613a85418174355f6922f74676158e5)) * better path handling for workers ([1bd8f17](https://github.com/hirosystems/stacks-blockchain-api/commit/1bd8f17f07fc8bfff30684aa67deed1de56f7b11)) * changed processing order ([62a12bd](https://github.com/hirosystems/stacks-blockchain-api/commit/62a12bdef93c77a5ac6eb5b7e15c20b4c672e041)) * convert `chain_tip` materialized view into a table ([#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751)) ([04b71cc](https://github.com/hirosystems/stacks-blockchain-api/commit/04b71cc392b4e9b6518fd59b79886cc437656de7)) * do not load duckdb binary unless required ([#1776](https://github.com/hirosystems/stacks-blockchain-api/issues/1776)) ([db859ae](https://github.com/hirosystems/stacks-blockchain-api/commit/db859ae980368db22b9d1c4c7096918d5f7f4c4b)) * **docs:** URL query arrays should be formatted with `form` rather than comma-separated ([#1807](https://github.com/hirosystems/stacks-blockchain-api/issues/1807)) ([e184fb5](https://github.com/hirosystems/stacks-blockchain-api/commit/e184fb59d0c21d56bced1f5d53c29f1dbedbed51)) * flaky test ([484d2ea](https://github.com/hirosystems/stacks-blockchain-api/commit/484d2ea0cd765431e8017e42c53669e5bc6e8728)) * flaky test ([65175f5](https://github.com/hirosystems/stacks-blockchain-api/commit/65175f5cca0853c6bb07a9f377b8e39a134c8a8c)) * handle `Problematic` status in `/drop_mempool_tx` event ([#1790](https://github.com/hirosystems/stacks-blockchain-api/issues/1790)) ([ce9b38f](https://github.com/hirosystems/stacks-blockchain-api/commit/ce9b38f051216d149375d64b3dfb90a75ab50fcd)) * import statement in replay controller ([7a10cd8](https://github.com/hirosystems/stacks-blockchain-api/commit/7a10cd8c4bb585c75a2437508802c7e5d908a564)) * insert block transaction data in batches ([#1760](https://github.com/hirosystems/stacks-blockchain-api/issues/1760)) ([bf99e90](https://github.com/hirosystems/stacks-blockchain-api/commit/bf99e90fa56ed04e6cb6bcc83559658f9e551183)) * lint ([01589ea](https://github.com/hirosystems/stacks-blockchain-api/commit/01589eabbb88d2bc6453368a7b753813bd247a34)) * lint ([82eadcb](https://github.com/hirosystems/stacks-blockchain-api/commit/82eadcbe2fefd6ec5fc74b098445a6dedc63528b)) * lint ([8c67ae5](https://github.com/hirosystems/stacks-blockchain-api/commit/8c67ae532b9a992e93e0d00561e331197a5ca8ea)) * move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` ([#1772](https://github.com/hirosystems/stacks-blockchain-api/issues/1772)) ([bf2ef0a](https://github.com/hirosystems/stacks-blockchain-api/commit/bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5)) * on attachments_new events processing ([0707313](https://github.com/hirosystems/stacks-blockchain-api/commit/07073139ccb4b6d71d429864e4612944ef84c646)) * optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([3a02f57](https://github.com/hirosystems/stacks-blockchain-api/commit/3a02f5741f4109c1e662b4e7014189ae95430df8)) * re-enable indexes when finishing the replay ([fc379eb](https://github.com/hirosystems/stacks-blockchain-api/commit/fc379ebab97e41dc20645bfff34fb484251508b9)) * remove dangling promise ([62a48ae](https://github.com/hirosystems/stacks-blockchain-api/commit/62a48ae37d86591dcaa8a928c1b63ddf2b1a6056)) * remove deprecated token endpoints ([#1775](https://github.com/hirosystems/stacks-blockchain-api/issues/1775)) ([18f74b7](https://github.com/hirosystems/stacks-blockchain-api/commit/18f74b7b77c95a81c2f6d47641af229c5c833b8f)) * revert configurable DB index type ([86154b2](https://github.com/hirosystems/stacks-blockchain-api/commit/86154b29e4e4af530da162133c99ebd609fab0e1)) * support comma-separated strings in array query params ([#1809](https://github.com/hirosystems/stacks-blockchain-api/issues/1809)) ([c9a4df8](https://github.com/hirosystems/stacks-blockchain-api/commit/c9a4df8f43f56a0d9ebbc4a065c54cb32bae350a)) * upgrade semver package to fix ReDoS vulnerability ([6b1605b](https://github.com/hirosystems/stacks-blockchain-api/commit/6b1605b74d7c1bad39fcb491caf4ed51426b7618)) * vercel preview builds ([#1783](https://github.com/hirosystems/stacks-blockchain-api/issues/1783)) ([d36b1c2](https://github.com/hirosystems/stacks-blockchain-api/commit/d36b1c2d37b050eb826e1c80e5ef4674ca0ea699)) --- CHANGELOG.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61690b4dd8..e4d5a11523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,61 @@ +## [7.6.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0...v7.6.0) (2024-01-09) + + +### Features + +* `GET /extended/v1/burn_block` ([#1766](https://github.com/hirosystems/stacks-blockchain-api/issues/1766)) ([cb38b68](https://github.com/hirosystems/stacks-blockchain-api/commit/cb38b6811c65aa700d4de527329216ba3c2ff6c9)) +* add `/extended/v2/blocks/:height_or_hash` ([#1774](https://github.com/hirosystems/stacks-blockchain-api/issues/1774)) ([e532a5e](https://github.com/hirosystems/stacks-blockchain-api/commit/e532a5e173340f732536b9236d60585501f2da5f)) +* add `/extended/v2/blocks` endpoint with burn block filters ([#1769](https://github.com/hirosystems/stacks-blockchain-api/issues/1769)) ([ceb7be0](https://github.com/hirosystems/stacks-blockchain-api/commit/ceb7be08daa5ca2d9baaa1a3de9f6c0569987724)) +* add `order_by` and `order` params to `/extended/v1/tx/mempool` ([#1810](https://github.com/hirosystems/stacks-blockchain-api/issues/1810)) ([2d45b2e](https://github.com/hirosystems/stacks-blockchain-api/commit/2d45b2eafdec0ca478de65237de953d7bc63e827)) +* add `tx_count` property to `/extended/v2/blocks` ([#1778](https://github.com/hirosystems/stacks-blockchain-api/issues/1778)) ([da4cd56](https://github.com/hirosystems/stacks-blockchain-api/commit/da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f)) +* add dataset store ([4211328](https://github.com/hirosystems/stacks-blockchain-api/commit/42113284381bc7d0913feb05cfecc65b37fdf814)) +* add step to compile duckdb for Alpine image ([0f40e14](https://github.com/hirosystems/stacks-blockchain-api/commit/0f40e14aecd8390b90ea6c5c34a47601f3866e23)) +* better handling of raw events insertion ([bb70ca9](https://github.com/hirosystems/stacks-blockchain-api/commit/bb70ca99c07bf777557bca5e4b9924d104d8f7fd)) +* create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint ([#1782](https://github.com/hirosystems/stacks-blockchain-api/issues/1782)) ([20466a1](https://github.com/hirosystems/stacks-blockchain-api/commit/20466a16573bff1634bc9b6ff1180bb8e0f620a0)) +* disable rosetta via an ENV var ([#1804](https://github.com/hirosystems/stacks-blockchain-api/issues/1804)) ([2d2aee3](https://github.com/hirosystems/stacks-blockchain-api/commit/2d2aee38263c3e457462ba5fd4cf4fd305178039)) +* event-replay new_block events handling ([1708b42](https://github.com/hirosystems/stacks-blockchain-api/commit/1708b42c02b75882ec8ce8d05df5eddc7ef835b9)) +* event-replay new_burn_block events handling ([6c0f448](https://github.com/hirosystems/stacks-blockchain-api/commit/6c0f4481c0f903d707c09e4e46a2330e67f32fff)) +* event-replay raw events handling ([81f43cf](https://github.com/hirosystems/stacks-blockchain-api/commit/81f43cf7c314853f0d849ed8c8f6c0d0d6130a79)) +* event-replay remainder events handling ([3ede07f](https://github.com/hirosystems/stacks-blockchain-api/commit/3ede07f134ac121505ca00b5bab7dba93a3def17)) +* event-replay supporting parallel insertions ([f33ecee](https://github.com/hirosystems/stacks-blockchain-api/commit/f33ecee858a8d300e5926cb8238617e6e8b935a5)) +* events folder as environment var ([701bd1a](https://github.com/hirosystems/stacks-blockchain-api/commit/701bd1a984c4ab064ddb1273a74cdb25975d7c1c)) +* ingestion for `TenureChange` and `NakamotoCoinbase` tx types ([#1753](https://github.com/hirosystems/stacks-blockchain-api/issues/1753)) ([7c45f53](https://github.com/hirosystems/stacks-blockchain-api/commit/7c45f53622338170477948d38f549c2136d830c1)) +* parallel processing using node cluster ([d02a7e8](https://github.com/hirosystems/stacks-blockchain-api/commit/d02a7e8ad87c9374bdf5f3e14740757984d0be75)) +* pox-4 support ([#1754](https://github.com/hirosystems/stacks-blockchain-api/issues/1754)) ([285806f](https://github.com/hirosystems/stacks-blockchain-api/commit/285806f46cebd365cc424a7a0155a531f34d7438)) +* processing raw events in parallel ([7a6f241](https://github.com/hirosystems/stacks-blockchain-api/commit/7a6f241923d0511b3d80308990dcf045b22562b6)) +* support tenure_change in tx type filter queries ([#1808](https://github.com/hirosystems/stacks-blockchain-api/issues/1808)) ([0831393](https://github.com/hirosystems/stacks-blockchain-api/commit/083139316350650c6cc97af377a6ae1cf6006be8)) +* update to latest TenureChange tx payload ([#1767](https://github.com/hirosystems/stacks-blockchain-api/issues/1767)) ([2afb65c](https://github.com/hirosystems/stacks-blockchain-api/commit/2afb65cbb821658416eb41197ce8b72f239970b4)) + + +### Bug Fixes + +* add token offering ([8ef039e](https://github.com/hirosystems/stacks-blockchain-api/commit/8ef039e89a083b555b88ce509f4e80d6270d096a)) +* allow contract-principals in `/extended/v1/address/:principal/mempool` endpoint [#1685](https://github.com/hirosystems/stacks-blockchain-api/issues/1685) ([#1704](https://github.com/hirosystems/stacks-blockchain-api/issues/1704)) ([163b76a](https://github.com/hirosystems/stacks-blockchain-api/commit/163b76a31a548c84b9d8be8e07ef94e5631b311b)) +* better args handlling ([c77ac57](https://github.com/hirosystems/stacks-blockchain-api/commit/c77ac57a9613a85418174355f6922f74676158e5)) +* better path handling for workers ([1bd8f17](https://github.com/hirosystems/stacks-blockchain-api/commit/1bd8f17f07fc8bfff30684aa67deed1de56f7b11)) +* changed processing order ([62a12bd](https://github.com/hirosystems/stacks-blockchain-api/commit/62a12bdef93c77a5ac6eb5b7e15c20b4c672e041)) +* convert `chain_tip` materialized view into a table ([#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751)) ([04b71cc](https://github.com/hirosystems/stacks-blockchain-api/commit/04b71cc392b4e9b6518fd59b79886cc437656de7)) +* do not load duckdb binary unless required ([#1776](https://github.com/hirosystems/stacks-blockchain-api/issues/1776)) ([db859ae](https://github.com/hirosystems/stacks-blockchain-api/commit/db859ae980368db22b9d1c4c7096918d5f7f4c4b)) +* **docs:** URL query arrays should be formatted with `form` rather than comma-separated ([#1807](https://github.com/hirosystems/stacks-blockchain-api/issues/1807)) ([e184fb5](https://github.com/hirosystems/stacks-blockchain-api/commit/e184fb59d0c21d56bced1f5d53c29f1dbedbed51)) +* flaky test ([484d2ea](https://github.com/hirosystems/stacks-blockchain-api/commit/484d2ea0cd765431e8017e42c53669e5bc6e8728)) +* flaky test ([65175f5](https://github.com/hirosystems/stacks-blockchain-api/commit/65175f5cca0853c6bb07a9f377b8e39a134c8a8c)) +* handle `Problematic` status in `/drop_mempool_tx` event ([#1790](https://github.com/hirosystems/stacks-blockchain-api/issues/1790)) ([ce9b38f](https://github.com/hirosystems/stacks-blockchain-api/commit/ce9b38f051216d149375d64b3dfb90a75ab50fcd)) +* import statement in replay controller ([7a10cd8](https://github.com/hirosystems/stacks-blockchain-api/commit/7a10cd8c4bb585c75a2437508802c7e5d908a564)) +* insert block transaction data in batches ([#1760](https://github.com/hirosystems/stacks-blockchain-api/issues/1760)) ([bf99e90](https://github.com/hirosystems/stacks-blockchain-api/commit/bf99e90fa56ed04e6cb6bcc83559658f9e551183)) +* lint ([01589ea](https://github.com/hirosystems/stacks-blockchain-api/commit/01589eabbb88d2bc6453368a7b753813bd247a34)) +* lint ([82eadcb](https://github.com/hirosystems/stacks-blockchain-api/commit/82eadcbe2fefd6ec5fc74b098445a6dedc63528b)) +* lint ([8c67ae5](https://github.com/hirosystems/stacks-blockchain-api/commit/8c67ae532b9a992e93e0d00561e331197a5ca8ea)) +* move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` ([#1772](https://github.com/hirosystems/stacks-blockchain-api/issues/1772)) ([bf2ef0a](https://github.com/hirosystems/stacks-blockchain-api/commit/bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5)) +* on attachments_new events processing ([0707313](https://github.com/hirosystems/stacks-blockchain-api/commit/07073139ccb4b6d71d429864e4612944ef84c646)) +* optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([3a02f57](https://github.com/hirosystems/stacks-blockchain-api/commit/3a02f5741f4109c1e662b4e7014189ae95430df8)) +* re-enable indexes when finishing the replay ([fc379eb](https://github.com/hirosystems/stacks-blockchain-api/commit/fc379ebab97e41dc20645bfff34fb484251508b9)) +* remove dangling promise ([62a48ae](https://github.com/hirosystems/stacks-blockchain-api/commit/62a48ae37d86591dcaa8a928c1b63ddf2b1a6056)) +* remove deprecated token endpoints ([#1775](https://github.com/hirosystems/stacks-blockchain-api/issues/1775)) ([18f74b7](https://github.com/hirosystems/stacks-blockchain-api/commit/18f74b7b77c95a81c2f6d47641af229c5c833b8f)) +* revert configurable DB index type ([86154b2](https://github.com/hirosystems/stacks-blockchain-api/commit/86154b29e4e4af530da162133c99ebd609fab0e1)) +* support comma-separated strings in array query params ([#1809](https://github.com/hirosystems/stacks-blockchain-api/issues/1809)) ([c9a4df8](https://github.com/hirosystems/stacks-blockchain-api/commit/c9a4df8f43f56a0d9ebbc4a065c54cb32bae350a)) +* upgrade semver package to fix ReDoS vulnerability ([6b1605b](https://github.com/hirosystems/stacks-blockchain-api/commit/6b1605b74d7c1bad39fcb491caf4ed51426b7618)) +* vercel preview builds ([#1783](https://github.com/hirosystems/stacks-blockchain-api/issues/1783)) ([d36b1c2](https://github.com/hirosystems/stacks-blockchain-api/commit/d36b1c2d37b050eb826e1c80e5ef4674ca0ea699)) + ## [7.6.0-nakamoto.3](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0-nakamoto.2...v7.6.0-nakamoto.3) (2024-01-09) From ee0da75d8b545ed3323b4d613e77da3dc9ef47d3 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Wed, 10 Jan 2024 11:27:26 +0100 Subject: [PATCH 84/91] chore: cleanup changelog for v7.6.0 [skip ci] (#1816) --- CHANGELOG.md | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4d5a11523..669e85c7db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,50 +8,27 @@ * add `/extended/v2/blocks` endpoint with burn block filters ([#1769](https://github.com/hirosystems/stacks-blockchain-api/issues/1769)) ([ceb7be0](https://github.com/hirosystems/stacks-blockchain-api/commit/ceb7be08daa5ca2d9baaa1a3de9f6c0569987724)) * add `order_by` and `order` params to `/extended/v1/tx/mempool` ([#1810](https://github.com/hirosystems/stacks-blockchain-api/issues/1810)) ([2d45b2e](https://github.com/hirosystems/stacks-blockchain-api/commit/2d45b2eafdec0ca478de65237de953d7bc63e827)) * add `tx_count` property to `/extended/v2/blocks` ([#1778](https://github.com/hirosystems/stacks-blockchain-api/issues/1778)) ([da4cd56](https://github.com/hirosystems/stacks-blockchain-api/commit/da4cd569a5c5e0c9a6aefc2877d3d8ef8716425f)) -* add dataset store ([4211328](https://github.com/hirosystems/stacks-blockchain-api/commit/42113284381bc7d0913feb05cfecc65b37fdf814)) -* add step to compile duckdb for Alpine image ([0f40e14](https://github.com/hirosystems/stacks-blockchain-api/commit/0f40e14aecd8390b90ea6c5c34a47601f3866e23)) -* better handling of raw events insertion ([bb70ca9](https://github.com/hirosystems/stacks-blockchain-api/commit/bb70ca99c07bf777557bca5e4b9924d104d8f7fd)) * create `/extended/v2/burn-blocks/:height_or_hash/blocks` endpoint ([#1782](https://github.com/hirosystems/stacks-blockchain-api/issues/1782)) ([20466a1](https://github.com/hirosystems/stacks-blockchain-api/commit/20466a16573bff1634bc9b6ff1180bb8e0f620a0)) * disable rosetta via an ENV var ([#1804](https://github.com/hirosystems/stacks-blockchain-api/issues/1804)) ([2d2aee3](https://github.com/hirosystems/stacks-blockchain-api/commit/2d2aee38263c3e457462ba5fd4cf4fd305178039)) -* event-replay new_block events handling ([1708b42](https://github.com/hirosystems/stacks-blockchain-api/commit/1708b42c02b75882ec8ce8d05df5eddc7ef835b9)) -* event-replay new_burn_block events handling ([6c0f448](https://github.com/hirosystems/stacks-blockchain-api/commit/6c0f4481c0f903d707c09e4e46a2330e67f32fff)) -* event-replay raw events handling ([81f43cf](https://github.com/hirosystems/stacks-blockchain-api/commit/81f43cf7c314853f0d849ed8c8f6c0d0d6130a79)) -* event-replay remainder events handling ([3ede07f](https://github.com/hirosystems/stacks-blockchain-api/commit/3ede07f134ac121505ca00b5bab7dba93a3def17)) -* event-replay supporting parallel insertions ([f33ecee](https://github.com/hirosystems/stacks-blockchain-api/commit/f33ecee858a8d300e5926cb8238617e6e8b935a5)) -* events folder as environment var ([701bd1a](https://github.com/hirosystems/stacks-blockchain-api/commit/701bd1a984c4ab064ddb1273a74cdb25975d7c1c)) +* event-replay optimizations ([#1694](https://github.com/hirosystems/stacks-blockchain-api/pull/1694)) ([cb658a9](https://github.com/hirosystems/stacks-blockchain-api/commit/cb658a941f2f12063f1e68a45c6fb2912279d396)) * ingestion for `TenureChange` and `NakamotoCoinbase` tx types ([#1753](https://github.com/hirosystems/stacks-blockchain-api/issues/1753)) ([7c45f53](https://github.com/hirosystems/stacks-blockchain-api/commit/7c45f53622338170477948d38f549c2136d830c1)) -* parallel processing using node cluster ([d02a7e8](https://github.com/hirosystems/stacks-blockchain-api/commit/d02a7e8ad87c9374bdf5f3e14740757984d0be75)) * pox-4 support ([#1754](https://github.com/hirosystems/stacks-blockchain-api/issues/1754)) ([285806f](https://github.com/hirosystems/stacks-blockchain-api/commit/285806f46cebd365cc424a7a0155a531f34d7438)) -* processing raw events in parallel ([7a6f241](https://github.com/hirosystems/stacks-blockchain-api/commit/7a6f241923d0511b3d80308990dcf045b22562b6)) * support tenure_change in tx type filter queries ([#1808](https://github.com/hirosystems/stacks-blockchain-api/issues/1808)) ([0831393](https://github.com/hirosystems/stacks-blockchain-api/commit/083139316350650c6cc97af377a6ae1cf6006be8)) * update to latest TenureChange tx payload ([#1767](https://github.com/hirosystems/stacks-blockchain-api/issues/1767)) ([2afb65c](https://github.com/hirosystems/stacks-blockchain-api/commit/2afb65cbb821658416eb41197ce8b72f239970b4)) ### Bug Fixes -* add token offering ([8ef039e](https://github.com/hirosystems/stacks-blockchain-api/commit/8ef039e89a083b555b88ce509f4e80d6270d096a)) * allow contract-principals in `/extended/v1/address/:principal/mempool` endpoint [#1685](https://github.com/hirosystems/stacks-blockchain-api/issues/1685) ([#1704](https://github.com/hirosystems/stacks-blockchain-api/issues/1704)) ([163b76a](https://github.com/hirosystems/stacks-blockchain-api/commit/163b76a31a548c84b9d8be8e07ef94e5631b311b)) -* better args handlling ([c77ac57](https://github.com/hirosystems/stacks-blockchain-api/commit/c77ac57a9613a85418174355f6922f74676158e5)) -* better path handling for workers ([1bd8f17](https://github.com/hirosystems/stacks-blockchain-api/commit/1bd8f17f07fc8bfff30684aa67deed1de56f7b11)) -* changed processing order ([62a12bd](https://github.com/hirosystems/stacks-blockchain-api/commit/62a12bdef93c77a5ac6eb5b7e15c20b4c672e041)) * convert `chain_tip` materialized view into a table ([#1751](https://github.com/hirosystems/stacks-blockchain-api/issues/1751)) ([04b71cc](https://github.com/hirosystems/stacks-blockchain-api/commit/04b71cc392b4e9b6518fd59b79886cc437656de7)) * do not load duckdb binary unless required ([#1776](https://github.com/hirosystems/stacks-blockchain-api/issues/1776)) ([db859ae](https://github.com/hirosystems/stacks-blockchain-api/commit/db859ae980368db22b9d1c4c7096918d5f7f4c4b)) * **docs:** URL query arrays should be formatted with `form` rather than comma-separated ([#1807](https://github.com/hirosystems/stacks-blockchain-api/issues/1807)) ([e184fb5](https://github.com/hirosystems/stacks-blockchain-api/commit/e184fb59d0c21d56bced1f5d53c29f1dbedbed51)) -* flaky test ([484d2ea](https://github.com/hirosystems/stacks-blockchain-api/commit/484d2ea0cd765431e8017e42c53669e5bc6e8728)) -* flaky test ([65175f5](https://github.com/hirosystems/stacks-blockchain-api/commit/65175f5cca0853c6bb07a9f377b8e39a134c8a8c)) * handle `Problematic` status in `/drop_mempool_tx` event ([#1790](https://github.com/hirosystems/stacks-blockchain-api/issues/1790)) ([ce9b38f](https://github.com/hirosystems/stacks-blockchain-api/commit/ce9b38f051216d149375d64b3dfb90a75ab50fcd)) * import statement in replay controller ([7a10cd8](https://github.com/hirosystems/stacks-blockchain-api/commit/7a10cd8c4bb585c75a2437508802c7e5d908a564)) * insert block transaction data in batches ([#1760](https://github.com/hirosystems/stacks-blockchain-api/issues/1760)) ([bf99e90](https://github.com/hirosystems/stacks-blockchain-api/commit/bf99e90fa56ed04e6cb6bcc83559658f9e551183)) -* lint ([01589ea](https://github.com/hirosystems/stacks-blockchain-api/commit/01589eabbb88d2bc6453368a7b753813bd247a34)) -* lint ([82eadcb](https://github.com/hirosystems/stacks-blockchain-api/commit/82eadcbe2fefd6ec5fc74b098445a6dedc63528b)) -* lint ([8c67ae5](https://github.com/hirosystems/stacks-blockchain-api/commit/8c67ae532b9a992e93e0d00561e331197a5ca8ea)) * move `/extended/v1/burn_block` to `/extended/v2/burn-blocks` ([#1772](https://github.com/hirosystems/stacks-blockchain-api/issues/1772)) ([bf2ef0a](https://github.com/hirosystems/stacks-blockchain-api/commit/bf2ef0a1ba579ef4d1c6fdaa7be623fe71d812d5)) -* on attachments_new events processing ([0707313](https://github.com/hirosystems/stacks-blockchain-api/commit/07073139ccb4b6d71d429864e4612944ef84c646)) * optimize mempool transaction reads and writes ([#1781](https://github.com/hirosystems/stacks-blockchain-api/issues/1781)) ([3a02f57](https://github.com/hirosystems/stacks-blockchain-api/commit/3a02f5741f4109c1e662b4e7014189ae95430df8)) -* re-enable indexes when finishing the replay ([fc379eb](https://github.com/hirosystems/stacks-blockchain-api/commit/fc379ebab97e41dc20645bfff34fb484251508b9)) -* remove dangling promise ([62a48ae](https://github.com/hirosystems/stacks-blockchain-api/commit/62a48ae37d86591dcaa8a928c1b63ddf2b1a6056)) * remove deprecated token endpoints ([#1775](https://github.com/hirosystems/stacks-blockchain-api/issues/1775)) ([18f74b7](https://github.com/hirosystems/stacks-blockchain-api/commit/18f74b7b77c95a81c2f6d47641af229c5c833b8f)) -* revert configurable DB index type ([86154b2](https://github.com/hirosystems/stacks-blockchain-api/commit/86154b29e4e4af530da162133c99ebd609fab0e1)) * support comma-separated strings in array query params ([#1809](https://github.com/hirosystems/stacks-blockchain-api/issues/1809)) ([c9a4df8](https://github.com/hirosystems/stacks-blockchain-api/commit/c9a4df8f43f56a0d9ebbc4a065c54cb32bae350a)) * upgrade semver package to fix ReDoS vulnerability ([6b1605b](https://github.com/hirosystems/stacks-blockchain-api/commit/6b1605b74d7c1bad39fcb491caf4ed51426b7618)) * vercel preview builds ([#1783](https://github.com/hirosystems/stacks-blockchain-api/issues/1783)) ([d36b1c2](https://github.com/hirosystems/stacks-blockchain-api/commit/d36b1c2d37b050eb826e1c80e5ef4674ca0ea699)) From c5a7a8ca5289cdc3eeb0de5bb7d43c05ab960439 Mon Sep 17 00:00:00 2001 From: Yuanhai He Date: Thu, 11 Jan 2024 00:23:24 +0800 Subject: [PATCH 85/91] feat: remove reconcile mempool & debounce stats (#1815) * feat: debounce reconcile mempool Signed-off-by: bestmike007 * feat: wait for next mempool reconcile Signed-off-by: bestmike007 * chore: add comments Signed-off-by: bestmike007 * chore: reconcile inserted and debounce stat Signed-off-by: bestmike007 * chore: use CTE to check and update pruned mempool tx Signed-off-by: bestmike007 * chore: make mempool stat debounce interval configurable Signed-off-by: bestmike007 * chore: add entry to env file Signed-off-by: bestmike007 * feat: mempool stat debounce max interval Signed-off-by: bestmike007 * chore: fix logging Signed-off-by: bestmike007 * chore: fix getUintEnvOrDefault Signed-off-by: bestmike007 * chore: revert use CTE to check and update pruned mempool tx Signed-off-by: bestmike007 * chore: get rid of reconcileMempoolStatus Signed-off-by: bestmike007 * chore: add tests for getUintEnvOrDefault Signed-off-by: bestmike007 --------- Signed-off-by: bestmike007 --- .env | 5 ++ src/datastore/pg-write-store.ts | 129 +++++++++++++++++++------------- src/helpers.ts | 10 +++ src/tests/helpers-tests.ts | 12 ++- src/tests/mempool-tests.ts | 17 ++++- 5 files changed, 121 insertions(+), 52 deletions(-) diff --git a/.env b/.env index e870524c78..9f6393cee7 100644 --- a/.env +++ b/.env @@ -61,6 +61,11 @@ PG_APPLICATION_NAME=stacks-blockchain-api # the same. # STACKS_MEMPOOL_TX_GARBAGE_COLLECTION_THRESHOLD=256 +# To avoid running unnecessary mempool stats during transaction influx, we use a debounce mechanism for the process. +# This variable controls the duration it waits until there are no further mempool updates +# MEMPOOL_STATS_DEBOUNCE_INTERVAL=1000 +# MEMPOOL_STATS_DEBOUNCE_MAX_INTERVAL=10000 + # If specified, an http server providing profiling capability endpoints will be opened on the given port. # This port should not be publicly exposed. # STACKS_PROFILER_PORT=9119 diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 9f98d6821c..397d6c5da7 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -1,4 +1,4 @@ -import { getOrAdd, I32_MAX, getIbdBlockHeight } from '../helpers'; +import { getOrAdd, I32_MAX, getIbdBlockHeight, getUintEnvOrDefault } from '../helpers'; import { DbBlock, DbTx, @@ -97,6 +97,14 @@ import { PgServer, getConnectionArgs, getConnectionConfig } from './connection'; const MIGRATIONS_TABLE = 'pgmigrations'; const INSERT_BATCH_SIZE = 500; +const MEMPOOL_STATS_DEBOUNCE_INTERVAL = getUintEnvOrDefault( + 'MEMPOOL_STATS_DEBOUNCE_INTERVAL', + 1000 +); +const MEMPOOL_STATS_DEBOUNCE_MAX_INTERVAL = getUintEnvOrDefault( + 'MEMPOOL_STATS_DEBOUNCE_MAX_INTERVAL', + 10000 +); class MicroblockGapError extends Error { constructor(message: string) { @@ -271,10 +279,7 @@ export class PgWriteStore extends PgStore { } if (!this.isEventReplay) { - await this.reconcileMempoolStatus(sql); - - const mempoolStats = await this.getMempoolStatsInternal({ sql }); - this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); + this.debounceMempoolStat(); } if (isCanonical) await sql` @@ -664,10 +669,7 @@ export class PgWriteStore extends PgStore { } if (!this.isEventReplay) { - await this.reconcileMempoolStatus(sql); - - const mempoolStats = await this.getMempoolStatsInternal({ sql }); - this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); + this.debounceMempoolStat(); } if (currentMicroblockTip.microblock_canonical) await sql` @@ -705,42 +707,6 @@ export class PgWriteStore extends PgStore { } } - // Find any transactions that are erroneously still marked as both `pending` in the mempool table - // and also confirmed in the mined txs table. Mark these as pruned in the mempool and log warning. - // This must be called _after_ any writes to txs/mempool tables during block and microblock ingestion, - // but _before_ any reads or view refreshes that depend on the mempool table. - // NOTE: this is essentially a work-around for whatever bug is causing the underlying problem. - async reconcileMempoolStatus(sql: PgSqlClient): Promise { - const txsResult = await sql<{ tx_id: string }[]>` - WITH pruned AS ( - UPDATE mempool_txs - SET pruned = true - FROM txs - WHERE - mempool_txs.tx_id = txs.tx_id AND - mempool_txs.pruned = false AND - txs.canonical = true AND - txs.microblock_canonical = true AND - txs.status IN ${sql([ - DbTxStatus.Success, - DbTxStatus.AbortByResponse, - DbTxStatus.AbortByPostCondition, - ])} - RETURNING mempool_txs.tx_id - ), - count_update AS ( - UPDATE chain_tip SET - mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), - mempool_updated_at = NOW() - ) - SELECT tx_id FROM pruned - `; - if (txsResult.length > 0) { - const txs = txsResult.map(tx => tx.tx_id); - logger.warn(`Reconciled mempool txs as pruned for ${txsResult.length} txs`, { txs }); - } - } - async fixBlockZeroData(sql: PgSqlClient, blockOne: DbBlock): Promise { const tablesUpdates: Record = {}; const txsResult = await sql` @@ -1696,21 +1662,84 @@ export class PgWriteStore extends PgStore { SELECT tx_id FROM inserted `; txIds.push(...result.map(r => r.tx_id)); + // The incoming mempool transactions might have already been settled + // We need to mark them as pruned to avoid inconsistent tx state + const pruned_tx = await sql<{ tx_id: string }[]>` + SELECT tx_id + FROM txs + WHERE + tx_id IN ${sql(batch.map(b => b.tx_id))} AND + canonical = true AND + microblock_canonical = true`; + if (pruned_tx.length > 0) { + await sql<{ tx_id: string }[]>` + WITH pruned AS ( + UPDATE mempool_txs + SET pruned = true + WHERE + tx_id IN ${sql(pruned_tx.map(t => t.tx_id))} AND + pruned = false + RETURNING tx_id + ), + count_update AS ( + UPDATE chain_tip SET + mempool_tx_count = mempool_tx_count - (SELECT COUNT(*) FROM pruned), + mempool_updated_at = NOW() + ) + SELECT tx_id FROM pruned`; + } } return txIds; } + private _debounceMempoolStat: { + triggeredAt?: number | null; + debounce?: NodeJS.Timeout | null; + running: boolean; + } = { running: false }; + /** + * Debounce the mempool stat process in case new transactions pour in. + */ + private debounceMempoolStat() { + if (this._debounceMempoolStat.triggeredAt == null) { + this._debounceMempoolStat.triggeredAt = Date.now(); + } + if (this._debounceMempoolStat.running) return; + const waited = Date.now() - this._debounceMempoolStat.triggeredAt; + const delay = Math.max( + 0, + Math.min(MEMPOOL_STATS_DEBOUNCE_MAX_INTERVAL - waited, MEMPOOL_STATS_DEBOUNCE_INTERVAL) + ); + if (this._debounceMempoolStat.debounce != null) { + clearTimeout(this._debounceMempoolStat.debounce); + } + this._debounceMempoolStat.debounce = setTimeout(async () => { + this._debounceMempoolStat.running = true; + this._debounceMempoolStat.triggeredAt = null; + try { + const mempoolStats = await this.getMempoolStatsInternal({ sql: this.sql }); + this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); + } catch (e) { + logger.error(e, `failed to run mempool stats update`); + } finally { + this._debounceMempoolStat.running = false; + this._debounceMempoolStat.debounce = null; + if (this._debounceMempoolStat.triggeredAt != null) { + this.debounceMempoolStat(); + } + } + }, delay); + } + async updateMempoolTxs({ mempoolTxs: txs }: { mempoolTxs: DbMempoolTxRaw[] }): Promise { const updatedTxIds: string[] = []; await this.sqlWriteTransaction(async sql => { const chainTip = await this.getChainTip(); updatedTxIds.push(...(await this.insertDbMempoolTxs(txs, chainTip, sql))); - if (!this.isEventReplay) { - await this.reconcileMempoolStatus(sql); - const mempoolStats = await this.getMempoolStatsInternal({ sql }); - this.eventEmitter.emit('mempoolStatsUpdate', mempoolStats); - } }); + if (!this.isEventReplay) { + this.debounceMempoolStat(); + } for (const txId of updatedTxIds) { await this.notifier?.sendTx({ txId }); } diff --git a/src/helpers.ts b/src/helpers.ts index 2273814ab8..6b68845c94 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -764,3 +764,13 @@ export enum BootContractAddress { mainnet = 'SP000000000000000000002Q6VF78', testnet = 'ST000000000000000000002AMW42H', } + +export function getUintEnvOrDefault(envName: string, defaultValue = 0) { + const v = BigInt(process.env[envName] ?? defaultValue); + if (v < 0n) { + throw new Error( + `Expecting ENV ${envName} to be non-negative number but it is configured as ${process.env[envName]}` + ); + } + return Number(v); +} diff --git a/src/tests/helpers-tests.ts b/src/tests/helpers-tests.ts index 6bd7ab9f0f..67c2574824 100644 --- a/src/tests/helpers-tests.ts +++ b/src/tests/helpers-tests.ts @@ -3,7 +3,7 @@ import * as c32check from 'c32check'; import { bitcoinToStacksAddress, stacksToBitcoinAddress } from 'stacks-encoding-native-js'; import * as c32AddrCache from '../c32-addr-cache'; import { ADDR_CACHE_ENV_VAR } from '../c32-addr-cache'; -import { isValidBitcoinAddress } from '../helpers'; +import { isValidBitcoinAddress, getUintEnvOrDefault } from '../helpers'; import { ECPair, getBitcoinAddressFromKey } from '../ec-helpers'; import { decodeBtcAddress, poxAddressToBtcAddress } from '@stacks/stacking'; import { has0xPrefix } from '@hirosystems/api-toolkit'; @@ -536,3 +536,13 @@ describe('Bitcoin address encoding formats', () => { expect(randP2TRTestnet).toMatch(/^tb1p/); }); }); + +test('getUintEnvOrDefault tests', () => { + const key = 'SOME_UINT_ENV'; + process.env[key] = '123'; + expect(getUintEnvOrDefault(key)).toBe(123); + process.env[key] = '-123'; + expect(() => getUintEnvOrDefault(key)).toThrowError(); + process.env[key] = 'ABC'; + expect(() => getUintEnvOrDefault(key)).toThrowError(); +}); diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index 92bacde352..3b2ee3057d 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1691,7 +1691,22 @@ describe('mempool tests', () => { block: dbBlock2, microblocks: [], minerRewards: [], - txs: [], + txs: [ + { + tx: dbTx1, + stxEvents: [], + stxLockEvents: [], + ftEvents: [], + nftEvents: [], + contractLogEvents: [], + smartContracts: [], + names: [], + namespaces: [], + pox2Events: [], + pox3Events: [], + pox4Events: [], + }, + ], }); // Verify tx pruned from mempool From 867ed305f53630e9317b50c7db4e27bd46b3979b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 10 Jan 2024 16:42:31 +0000 Subject: [PATCH 86/91] chore(release): 7.7.0 [skip ci] ## [7.7.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0...v7.7.0) (2024-01-10) ### Features * remove reconcile mempool & debounce stats ([#1815](https://github.com/hirosystems/stacks-blockchain-api/issues/1815)) ([c5a7a8c](https://github.com/hirosystems/stacks-blockchain-api/commit/c5a7a8ca5289cdc3eeb0de5bb7d43c05ab960439)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 669e85c7db..b26fc26557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.7.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0...v7.7.0) (2024-01-10) + + +### Features + +* remove reconcile mempool & debounce stats ([#1815](https://github.com/hirosystems/stacks-blockchain-api/issues/1815)) ([c5a7a8c](https://github.com/hirosystems/stacks-blockchain-api/commit/c5a7a8ca5289cdc3eeb0de5bb7d43c05ab960439)) + ## [7.6.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.5.0...v7.6.0) (2024-01-09) From 3b502f73149c185265fc8948e75ba064892ce6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20C=C3=A1rdenas?= Date: Thu, 11 Jan 2024 08:11:30 -0600 Subject: [PATCH 87/91] fix: log re-orgs at `INFO` level (#1819) --- src/datastore/common.ts | 59 ++++++++++++------------------ src/datastore/helpers.ts | 64 ++------------------------------- src/datastore/pg-write-store.ts | 35 ++++++++---------- src/tests/datastore-tests.ts | 2 ++ 4 files changed, 42 insertions(+), 118 deletions(-) diff --git a/src/datastore/common.ts b/src/datastore/common.ts index c28dd08623..af08f0b4dc 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -981,43 +981,30 @@ export interface FaucetRequestQueryResult { occurred_at: string; } +interface ReOrgEntities { + blocks: number; + microblocks: number; + minerRewards: number; + txs: number; + stxLockEvents: number; + stxEvents: number; + ftEvents: number; + nftEvents: number; + pox2Events: number; + pox3Events: number; + pox4Events: number; + contractLogs: number; + smartContracts: number; + names: number; + namespaces: number; + subdomains: number; +} + export interface ReOrgUpdatedEntities { - markedCanonical: { - blocks: number; - microblocks: number; - minerRewards: number; - txs: number; - stxLockEvents: number; - stxEvents: number; - ftEvents: number; - nftEvents: number; - pox2Events: number; - pox3Events: number; - pox4Events: number; - contractLogs: number; - smartContracts: number; - names: number; - namespaces: number; - subdomains: number; - }; - markedNonCanonical: { - blocks: number; - microblocks: number; - minerRewards: number; - txs: number; - stxLockEvents: number; - stxEvents: number; - ftEvents: number; - nftEvents: number; - pox2Events: number; - pox3Events: number; - pox4Events: number; - contractLogs: number; - smartContracts: number; - names: number; - namespaces: number; - subdomains: number; - }; + markedCanonical: ReOrgEntities; + markedNonCanonical: ReOrgEntities; + prunedMempoolTxs: number; + restoredMempoolTxs: number; } export interface TransferQueryResult { diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index db41e4865d..a5aabbaa1e 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -1331,67 +1331,7 @@ export function newReOrgUpdatedEntities(): ReOrgUpdatedEntities { namespaces: 0, subdomains: 0, }, + prunedMempoolTxs: 0, + restoredMempoolTxs: 0, }; } - -export function logReorgResultInfo(updatedEntities: ReOrgUpdatedEntities) { - const updates = [ - ['blocks', updatedEntities.markedCanonical.blocks, updatedEntities.markedNonCanonical.blocks], - [ - 'microblocks', - updatedEntities.markedCanonical.microblocks, - updatedEntities.markedNonCanonical.microblocks, - ], - ['txs', updatedEntities.markedCanonical.txs, updatedEntities.markedNonCanonical.txs], - [ - 'miner-rewards', - updatedEntities.markedCanonical.minerRewards, - updatedEntities.markedNonCanonical.minerRewards, - ], - [ - 'stx-lock events', - updatedEntities.markedCanonical.stxLockEvents, - updatedEntities.markedNonCanonical.stxLockEvents, - ], - [ - 'stx-token events', - updatedEntities.markedCanonical.stxEvents, - updatedEntities.markedNonCanonical.stxEvents, - ], - [ - 'non-fungible-token events', - updatedEntities.markedCanonical.nftEvents, - updatedEntities.markedNonCanonical.nftEvents, - ], - [ - 'fungible-token events', - updatedEntities.markedCanonical.ftEvents, - updatedEntities.markedNonCanonical.ftEvents, - ], - [ - 'contract logs', - updatedEntities.markedCanonical.contractLogs, - updatedEntities.markedNonCanonical.contractLogs, - ], - [ - 'smart contracts', - updatedEntities.markedCanonical.smartContracts, - updatedEntities.markedNonCanonical.smartContracts, - ], - ['names', updatedEntities.markedCanonical.names, updatedEntities.markedNonCanonical.names], - [ - 'namespaces', - updatedEntities.markedCanonical.namespaces, - updatedEntities.markedNonCanonical.namespaces, - ], - [ - 'subdomains', - updatedEntities.markedCanonical.subdomains, - updatedEntities.markedNonCanonical.subdomains, - ], - ]; - const markedCanonical = updates.map(e => `${e[1]} ${e[0]}`).join(', '); - logger.debug(`Entities marked as canonical: ${markedCanonical}`); - const markedNonCanonical = updates.map(e => `${e[2]} ${e[0]}`).join(', '); - logger.debug(`Entities marked as non-canonical: ${markedNonCanonical}`); -} diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 397d6c5da7..29a76ded70 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -38,7 +38,6 @@ import { BurnchainRewardInsertValues, TxInsertValues, MempoolTxInsertValues, - MempoolTxQueryResult, SmartContractInsertValues, BnsNameInsertValues, BnsNamespaceInsertValues, @@ -66,17 +65,14 @@ import { setTotalBlockUpdateDataExecutionCost, convertTxQueryResultToDbMempoolTx, markBlockUpdateDataAsNonCanonical, - MEMPOOL_TX_COLUMNS, MICROBLOCK_COLUMNS, parseBlockQueryResult, - parseMempoolTxQueryResult, parseMicroblockQueryResult, parseTxQueryResult, TX_COLUMNS, TX_METADATA_TABLES, validateZonefileHash, newReOrgUpdatedEntities, - logReorgResultInfo, } from './helpers'; import { PgNotifier } from './pg-notifier'; import { MIGRATIONS_DIR, PgStore } from './pg-store'; @@ -2684,12 +2680,16 @@ export class PgWriteStore extends PgStore { false, updatedEntities ); - await this.restoreMempoolTxs(sql, markNonCanonicalResult.txsMarkedNonCanonical); + const restoredMempoolTxs = await this.restoreMempoolTxs( + sql, + markNonCanonicalResult.txsMarkedNonCanonical + ); + updatedEntities.restoredMempoolTxs += restoredMempoolTxs.restoredTxs.length; } - // The canonical microblock tables _must_ be restored _after_ orphaning all other blocks at a given height, - // because there is only 1 row per microblock hash, and both the orphaned blocks at this height and the - // canonical block can be pointed to the same microblocks. + // The canonical microblock tables _must_ be restored _after_ orphaning all other blocks at a + // given height, because there is only 1 row per microblock hash, and both the orphaned blocks + // at this height and the canonical block can be pointed to the same microblocks. const restoredBlock = parseBlockQueryResult(restoredBlockResult[0]); const microCanonicalUpdateResult = await this.updateMicroCanonical(sql, { isCanonical: true, @@ -2712,24 +2712,17 @@ export class PgWriteStore extends PgStore { updatedEntities.markedCanonical.microblocks += microblocksAccepted.size; updatedEntities.markedNonCanonical.microblocks += microblocksOrphaned.size; - microblocksOrphaned.forEach(mb => logger.debug(`Marked microblock as non-canonical: ${mb}`)); - microblocksAccepted.forEach(mb => logger.debug(`Marked microblock as canonical: ${mb}`)); - const markCanonicalResult = await this.markEntitiesCanonical( sql, indexBlockHash, true, updatedEntities ); - const removedTxsResult = await this.pruneMempoolTxs( + const prunedMempoolTxs = await this.pruneMempoolTxs( sql, markCanonicalResult.txsMarkedCanonical ); - if (removedTxsResult.removedTxs.length > 0) { - logger.debug( - `Removed ${removedTxsResult.removedTxs.length} txs from mempool table during reorg handling` - ); - } + updatedEntities.prunedMempoolTxs += prunedMempoolTxs.removedTxs.length; const parentResult = await sql<{ index_block_hash: string }[]>` SELECT index_block_hash FROM blocks @@ -2779,11 +2772,13 @@ export class PgWriteStore extends PgStore { block.parent_index_block_hash }` ); - // This blocks builds off a previously orphaned chain. Restore canonical status for this - // chain. + // This block builds off a previously orphaned chain. Restore canonical status for this chain. if (!parentResult[0].canonical && block.block_height > chainTipHeight) { await this.restoreOrphanedChain(sql, parentResult[0].index_block_hash, updatedEntities); - logReorgResultInfo(updatedEntities); + logger.info( + updatedEntities, + `Re-org resolved. Block ${block.block_height} builds off a previously orphaned chain.` + ); } // Reflect updated transaction totals in `chain_tip` table. const txCountDelta = diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index ce2617c73e..7300089606 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -3607,6 +3607,8 @@ describe('postgres datastore', () => { namespaces: 0, subdomains: 0, }, + prunedMempoolTxs: 0, + restoredMempoolTxs: 0, }); const blockQuery1 = await db.getBlock({ hash: block1.block_hash }); From f11968db6976688b30aeefe8771693310c8b3067 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 11 Jan 2024 14:17:24 +0000 Subject: [PATCH 88/91] chore(release): 7.7.1 [skip ci] ## [7.7.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.7.0...v7.7.1) (2024-01-11) ### Bug Fixes * log re-orgs at `INFO` level ([#1819](https://github.com/hirosystems/stacks-blockchain-api/issues/1819)) ([3b502f7](https://github.com/hirosystems/stacks-blockchain-api/commit/3b502f73149c185265fc8948e75ba064892ce6d2)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b26fc26557..b9bcd2f3dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.7.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.7.0...v7.7.1) (2024-01-11) + + +### Bug Fixes + +* log re-orgs at `INFO` level ([#1819](https://github.com/hirosystems/stacks-blockchain-api/issues/1819)) ([3b502f7](https://github.com/hirosystems/stacks-blockchain-api/commit/3b502f73149c185265fc8948e75ba064892ce6d2)) + ## [7.7.0](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.6.0...v7.7.0) (2024-01-10) From f974dfd2e8d173fd1efca66fbf808adf56377853 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 2 Jan 2024 09:01:15 -0600 Subject: [PATCH 89/91] docs: replace html tags with markdown (#1791) --- docs/openapi.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 489429dbe9..4013f02212 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -10,9 +10,9 @@ info: title: Stacks Blockchain API version: 'STACKS_API_VERSION' description: | - Welcome to the API reference overview for the Stacks Blockchain API. + Welcome to the API reference overview for the [Stacks Blockchain API](https://docs.hiro.so/get-started/stacks-blockchain-api). - Download Postman collection + [Download Postman collection](https://hirosystems.github.io/stacks-blockchain-api/collection.json) tags: - name: Accounts description: Read-only endpoints to obtain Stacks account details From 862b36c3fa896bcf9b5434ecf33c1bc0c9077aed Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Tue, 16 Jan 2024 17:17:52 +0100 Subject: [PATCH 90/91] fix: revive dropped mempool rebroadcasts (#1823) * fix: revive mempool txs that get re-broadcasted after being dropped from the mempool * chore: separate query for reviving mempool txs * test: add test for reviving mempool txs * chore: fix test * chore: fix test * fix: update mempool tx receipt info on reviving --- src/datastore/common.ts | 1 + src/datastore/pg-store.ts | 1 + src/datastore/pg-write-store.ts | 27 +++- src/tests/datastore-tests.ts | 3 + src/tests/mempool-tests.ts | 220 ++++++++++++++++++++++++++++++++ 5 files changed, 250 insertions(+), 2 deletions(-) diff --git a/src/datastore/common.ts b/src/datastore/common.ts index af08f0b4dc..452e6005fa 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -1548,6 +1548,7 @@ export interface DbChainTip { microblock_count: number; tx_count: number; tx_count_unanchored: number; + mempool_tx_count: number; } export enum IndexesState { diff --git a/src/datastore/pg-store.ts b/src/datastore/pg-store.ts index f74b98cdd8..887025bbad 100644 --- a/src/datastore/pg-store.ts +++ b/src/datastore/pg-store.ts @@ -218,6 +218,7 @@ export class PgStore extends BasePgStore { microblock_count: tip?.microblock_count ?? 0, tx_count: tip?.tx_count ?? 0, tx_count_unanchored: tip?.tx_count_unanchored ?? 0, + mempool_tx_count: tip?.mempool_tx_count ?? 0, }; } diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 29a76ded70..6694aea04b 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -1644,6 +1644,27 @@ export class PgWriteStore extends PgStore { tenure_change_signature: tx.tenure_change_signature ?? null, tenure_change_signers: tx.tenure_change_signers ?? null, })); + + // Revive mempool txs that were previously dropped + const revivedTxs = await sql<{ tx_id: string }[]>` + UPDATE mempool_txs + SET pruned = false, + status = ${DbTxStatus.Pending}, + receipt_block_height = ${values[0].receipt_block_height}, + receipt_time = ${values[0].receipt_time} + WHERE tx_id IN ${sql(values.map(v => v.tx_id))} + AND pruned = true + AND NOT EXISTS ( + SELECT 1 + FROM txs + WHERE txs.tx_id = mempool_txs.tx_id + AND txs.canonical = true + AND txs.microblock_canonical = true + ) + RETURNING tx_id + `; + txIds.push(...revivedTxs.map(r => r.tx_id)); + const result = await sql<{ tx_id: string }[]>` WITH inserted AS ( INSERT INTO mempool_txs ${sql(values)} @@ -1652,7 +1673,9 @@ export class PgWriteStore extends PgStore { ), count_update AS ( UPDATE chain_tip SET - mempool_tx_count = mempool_tx_count + (SELECT COUNT(*) FROM inserted), + mempool_tx_count = mempool_tx_count + + (SELECT COUNT(*) FROM inserted) + + ${revivedTxs.count}, mempool_updated_at = NOW() ) SELECT tx_id FROM inserted @@ -2329,7 +2352,7 @@ export class PgWriteStore extends PgStore { const updatedRows = await sql<{ tx_id: string }[]>` WITH restored AS ( UPDATE mempool_txs - SET pruned = FALSE + SET pruned = FALSE, status = ${DbTxStatus.Pending} WHERE tx_id IN ${sql(txIds)} AND pruned = TRUE RETURNING tx_id ), diff --git a/src/tests/datastore-tests.ts b/src/tests/datastore-tests.ts index 7300089606..f5466b7762 100644 --- a/src/tests/datastore-tests.ts +++ b/src/tests/datastore-tests.ts @@ -4108,6 +4108,7 @@ describe('postgres datastore', () => { index_block_hash: '0xcc', burn_block_height: 123, block_count: 3, + mempool_tx_count: 0, microblock_count: 0, microblock_hash: undefined, microblock_sequence: undefined, @@ -4180,6 +4181,7 @@ describe('postgres datastore', () => { microblock_sequence: undefined, tx_count: 2, tx_count_unanchored: 2, + mempool_tx_count: 0, }); const block4b: DbBlock = { @@ -4230,6 +4232,7 @@ describe('postgres datastore', () => { microblock_sequence: undefined, tx_count: 2, // Tx from block 2b now counts, but compensates with tx from block 2 tx_count_unanchored: 2, + mempool_tx_count: 1, }); const b1 = await db.getBlock({ hash: block1.block_hash }); diff --git a/src/tests/mempool-tests.ts b/src/tests/mempool-tests.ts index 3b2ee3057d..1436ce9aa5 100644 --- a/src/tests/mempool-tests.ts +++ b/src/tests/mempool-tests.ts @@ -1726,6 +1726,226 @@ describe('mempool tests', () => { expect(txResult2.body.tx_status).toBe('success'); }); + test('Revive dropped and rebroadcasted mempool tx', async () => { + const senderAddress = 'SP25YGP221F01S9SSCGN114MKDAK9VRK8P3KXGEMB'; + const txId = '0x521234'; + const dbBlock1: DbBlock = { + block_hash: '0x0123', + index_block_hash: '0x1234', + parent_index_block_hash: '0x5678', + parent_block_hash: '0x5678', + parent_microblock_hash: '0x00', + parent_microblock_sequence: 0, + block_height: 1, + burn_block_time: 39486, + burn_block_hash: '0x1234', + burn_block_height: 123, + miner_txid: '0x4321', + canonical: true, + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + tx_count: 1, + }; + const dbBlock1b: DbBlock = { + block_hash: '0x0123bb', + index_block_hash: '0x1234bb', + parent_index_block_hash: '0x5678bb', + parent_block_hash: '0x5678bb', + parent_microblock_hash: '0x00', + parent_microblock_sequence: 0, + block_height: 1, + burn_block_time: 39486, + burn_block_hash: '0x1234bb', + burn_block_height: 123, + miner_txid: '0x4321bb', + canonical: true, + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + tx_count: 1, + }; + const dbBlock2b: DbBlock = { + block_hash: '0x2123', + index_block_hash: '0x2234', + parent_index_block_hash: dbBlock1b.index_block_hash, + parent_block_hash: dbBlock1b.block_hash, + parent_microblock_hash: '0x00', + parent_microblock_sequence: 0, + block_height: 2, + burn_block_time: 39486, + burn_block_hash: '0x1234', + burn_block_height: 123, + miner_txid: '0x4321', + canonical: true, + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + tx_count: 1, + }; + const mempoolTx: DbMempoolTxRaw = { + tx_id: txId, + anchor_mode: 3, + nonce: 0, + raw_tx: bufferToHex(Buffer.from('test-raw-mempool-tx')), + type_id: DbTxTypeId.Coinbase, + status: 1, + post_conditions: '0x01f5', + fee_rate: 1234n, + sponsored: false, + sponsor_address: undefined, + sender_address: senderAddress, + origin_hash_mode: 1, + coinbase_payload: bufferToHex(Buffer.from('hi')), + pruned: false, + receipt_time: 1616063078, + }; + const dbTx1: DbTxRaw = { + ...mempoolTx, + ...dbBlock1, + parent_burn_block_time: 1626122935, + tx_index: 4, + status: DbTxStatus.Success, + raw_result: '0x0100000000000000000000000000000001', // u1 + canonical: true, + microblock_canonical: true, + microblock_sequence: I32_MAX, + microblock_hash: '', + parent_index_block_hash: '', + event_count: 0, + execution_cost_read_count: 0, + execution_cost_read_length: 0, + execution_cost_runtime: 0, + execution_cost_write_count: 0, + execution_cost_write_length: 0, + }; + + await db.updateMempoolTxs({ mempoolTxs: [mempoolTx] }); + + let chainTip = await db.getChainTip(); + expect(chainTip.mempool_tx_count).toBe(1); + + // Verify tx shows up in mempool (non-pruned) + const mempoolResult1 = await supertest(api.server).get( + `/extended/v1/address/${mempoolTx.sender_address}/mempool` + ); + expect(mempoolResult1.body.results[0].tx_id).toBe(txId); + const mempoolCount1 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount1.body.total).toBe(1); + + // Drop mempool tx + await db.dropMempoolTxs({ + status: DbTxStatus.DroppedStaleGarbageCollect, + txIds: [mempoolTx.tx_id], + }); + + // Verify tx is pruned from mempool + const mempoolResult2 = await supertest(api.server).get( + `/extended/v1/address/${mempoolTx.sender_address}/mempool` + ); + expect(mempoolResult2.body.results).toHaveLength(0); + const mempoolCount2 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount2.body.total).toBe(0); + chainTip = await db.getChainTip(); + expect(chainTip.mempool_tx_count).toBe(0); + + // Re-broadcast mempool tx + await db.updateMempoolTxs({ mempoolTxs: [mempoolTx] }); + + // Verify tx shows up in mempool again (revived) + const mempoolResult3 = await supertest(api.server).get( + `/extended/v1/address/${mempoolTx.sender_address}/mempool` + ); + expect(mempoolResult3.body.results[0].tx_id).toBe(txId); + const mempoolCount3 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount3.body.total).toBe(1); + chainTip = await db.getChainTip(); + expect(chainTip.mempool_tx_count).toBe(1); + + // Mine tx in block to prune from mempool + await db.update({ + block: dbBlock1, + microblocks: [], + minerRewards: [], + txs: [ + { + tx: dbTx1, + stxEvents: [], + stxLockEvents: [], + ftEvents: [], + nftEvents: [], + contractLogEvents: [], + smartContracts: [], + names: [], + namespaces: [], + pox2Events: [], + pox3Events: [], + pox4Events: [], + }, + ], + }); + + // Verify tx is pruned from mempool + const mempoolResult4 = await supertest(api.server).get( + `/extended/v1/address/${mempoolTx.sender_address}/mempool` + ); + expect(mempoolResult4.body.results).toHaveLength(0); + const mempoolCount4 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount4.body.total).toBe(0); + chainTip = await db.getChainTip(); + expect(chainTip.mempool_tx_count).toBe(0); + + // Verify tx is mined + const txResult1 = await supertest(api.server).get(`/extended/v1/tx/${txId}`); + expect(txResult1.body.tx_status).toBe('success'); + expect(txResult1.body.canonical).toBe(true); + + // Orphan the block to get the tx orphaned and placed back in the pool + await db.update({ + block: dbBlock1b, + microblocks: [], + minerRewards: [], + txs: [], + }); + await db.update({ + block: dbBlock2b, + microblocks: [], + minerRewards: [], + txs: [], + }); + + // Verify tx is orphaned and back in mempool + const txResult2 = await supertest(api.server).get(`/extended/v1/tx/${txId}`); + expect(txResult2.body.canonical).toBeFalsy(); + + // Verify tx has been revived and is back in the mempool + const mempoolResult5 = await supertest(api.server).get( + `/extended/v1/address/${mempoolTx.sender_address}/mempool` + ); + expect(mempoolResult5.body.results[0].tx_id).toBe(txId); + const mempoolCount5 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount5.body.total).toBe(1); + chainTip = await db.getChainTip(); + expect(chainTip.mempool_tx_count).toBe(1); + + // Re-broadcast mempool tx + await db.updateMempoolTxs({ mempoolTxs: [mempoolTx] }); + + // Verify tx has been revived and is back in the mempool + const mempoolResult6 = await supertest(api.server).get( + `/extended/v1/address/${mempoolTx.sender_address}/mempool` + ); + expect(mempoolResult6.body.results[0].tx_id).toBe(txId); + const mempoolCount6 = await supertest(api.server).get(`/extended/v1/tx/mempool`); + expect(mempoolCount6.body.total).toBe(1); + }); + test('returns fee priorities for mempool transactions', async () => { const mempoolTxs: DbMempoolTxRaw[] = []; for (let i = 0; i < 10; i++) { From 81be954fb3497ee12f5106faf1bf429f9a2d40f6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 16 Jan 2024 16:23:55 +0000 Subject: [PATCH 91/91] chore(release): 7.7.2 [skip ci] ## [7.7.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.7.1...v7.7.2) (2024-01-16) ### Bug Fixes * revive dropped mempool rebroadcasts ([#1823](https://github.com/hirosystems/stacks-blockchain-api/issues/1823)) ([862b36c](https://github.com/hirosystems/stacks-blockchain-api/commit/862b36c3fa896bcf9b5434ecf33c1bc0c9077aed)) --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9bcd2f3dd..4c587dd712 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [7.7.2](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.7.1...v7.7.2) (2024-01-16) + + +### Bug Fixes + +* revive dropped mempool rebroadcasts ([#1823](https://github.com/hirosystems/stacks-blockchain-api/issues/1823)) ([862b36c](https://github.com/hirosystems/stacks-blockchain-api/commit/862b36c3fa896bcf9b5434ecf33c1bc0c9077aed)) + ## [7.7.1](https://github.com/hirosystems/stacks-blockchain-api/compare/v7.7.0...v7.7.1) (2024-01-11)