From d786f00f0fccb44c8c78120e026c309d7bbe6798 Mon Sep 17 00:00:00 2001 From: LumerinIO <102425763+LumerinIO@users.noreply.github.com> Date: Thu, 11 Apr 2024 10:15:56 -0400 Subject: [PATCH 01/35] edit readme (#1) Co-authored-by: abs2023 --- README.md | 94 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index b9ec070..afa35c7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# indexer +# proxy-indexer +Provides a docker container service (that is currently run on ECS/Fargate) that listens for events on the Ethereum blockchain and indexes them in a Postgres database. The service is built using Node.js and uses the ethers.js library to interact with the Ethereum blockchain. ## Start local @@ -7,94 +8,3 @@ ## Build Docker container - docker build --build-arg ETH_NODE_URL="" --build-arg CLONE_FACTORY_ADDRESS="" --build-arg PORT="" . - - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://gitlab.com/TitanInd/proxy/indexer.git -git branch -M main -git push -uf origin main -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://gitlab.com/TitanInd/proxy/indexer/-/settings/integrations) - -## Collaborate with your team - -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) - -## Test and Deploy - -Use the built-in continuous integration in GitLab. - -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) - -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README - -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. - -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. - -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. - -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. - -## License -For open source projects, say how it is licensed. - -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. From 98e367566d9136b15688af87e7fd0e9b64b2f9e0 Mon Sep 17 00:00:00 2001 From: LumerinIO <102425763+LumerinIO@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:10:57 -0400 Subject: [PATCH 02/35] Test sync (#3) * edit readme * update to trigger build in gitlab 1 --------- Co-authored-by: abs2023 --- .gitlab-ci.yml | 1 - README.md | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c596132..950cb37 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,5 @@ # Please keep variables in alphabetical order # variables: - stages: - develop - review diff --git a/README.md b/README.md index afa35c7..3d9dd78 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# proxy-indexer +# proxy-indexer 1.1.0 Provides a docker container service (that is currently run on ECS/Fargate) that listens for events on the Ethereum blockchain and indexes them in a Postgres database. The service is built using Node.js and uses the ethers.js library to interact with the Ethereum blockchain. +Leveraged by both wallet-desktop and Web Marketplace ## Start local From b38f4c15913bfc01451d0f98a399554b13cbd93a Mon Sep 17 00:00:00 2001 From: roguevader <157174704+roguevader@users.noreply.github.com> Date: Thu, 11 Apr 2024 12:30:16 -0400 Subject: [PATCH 03/35] update comment to unprotected branch (#5) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3d9dd78..402562a 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,5 @@ Leveraged by both wallet-desktop and Web Marketplace ## Build Docker container - docker build --build-arg ETH_NODE_URL="" --build-arg CLONE_FACTORY_ADDRESS="" --build-arg PORT="" . + +comment by roguevader \ No newline at end of file From a406a0890da15717089ac8da2d4d984f5bdb5353 Mon Sep 17 00:00:00 2001 From: roguevader <157174704+roguevader@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:52:24 -0400 Subject: [PATCH 04/35] updated readme (#7) --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 402562a..a5ad9d6 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,4 @@ Leveraged by both wallet-desktop and Web Marketplace - npm run dev ## Build Docker container -- docker build --build-arg ETH_NODE_URL="" --build-arg CLONE_FACTORY_ADDRESS="" --build-arg PORT="" . - -comment by roguevader \ No newline at end of file +- docker build --build-arg ETH_NODE_URL="" --build-arg CLONE_FACTORY_ADDRESS="" --build-arg PORT="" . \ No newline at end of file From 654507ab6ba175dc28f25fe173776f25daf855ab Mon Sep 17 00:00:00 2001 From: LumerinIO <102425763+LumerinIO@users.noreply.github.com> Date: Fri, 12 Apr 2024 14:55:37 -0400 Subject: [PATCH 05/35] update environemnt settings for CICD in gitlab (#8) Co-authored-by: abs2023 --- .gitlab-ci.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 950cb37..6ea3e0e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -82,7 +82,9 @@ stages: bedrock-02-dev: - environment: dev + environment: + name: dev + url: https://indexer.dev.lumerin.io/api/healthcheck stage: develop only: - dev @@ -104,7 +106,9 @@ bedrock-02-dev: - echo "$TGT_ENV Updated" titanio-03-stg: - environment: stg + environment: + name: stg + url: https://indexer.stg.lumerin.io/api/healthcheck stage: review only: - stg @@ -126,7 +130,9 @@ titanio-03-stg: - echo "$TGT_ENV Updated" titanio-04-lmn-PROD: - environment: lmn + environment: + name: lmn + url: https://indexer.lumerin.io/api/healthcheck stage: deploy only: - main From a7970f5e9cf7d5f2c5d3844bad5eaa52606a04ad Mon Sep 17 00:00:00 2001 From: Alan-Lumerin <93659489+abs2023@users.noreply.github.com> Date: Fri, 12 Apr 2024 15:01:55 -0400 Subject: [PATCH 06/35] Stg to main (#11) * 1.1.0-STG Community Test (#6) * edit readme (#1) Co-authored-by: abs2023 * Test sync (#3) * edit readme * update to trigger build in gitlab 1 --------- Co-authored-by: abs2023 * update comment to unprotected branch (#5) --------- Co-authored-by: LumerinIO <102425763+LumerinIO@users.noreply.github.com> Co-authored-by: abs2023 * Cicd environment (#10) * edit readme (#1) Co-authored-by: abs2023 * Test sync (#3) * edit readme * update to trigger build in gitlab 1 --------- Co-authored-by: abs2023 * update comment to unprotected branch (#5) * updated readme (#7) * update environemnt settings for CICD in gitlab --------- Co-authored-by: abs2023 Co-authored-by: roguevader <157174704+roguevader@users.noreply.github.com> --------- Co-authored-by: roguevader <157174704+roguevader@users.noreply.github.com> Co-authored-by: LumerinIO <102425763+LumerinIO@users.noreply.github.com> From f36a4f858c627042ade5f6354c2eab337822ce38 Mon Sep 17 00:00:00 2001 From: shev-titan <108101079+shev-titan@users.noreply.github.com> Date: Wed, 8 Jan 2025 18:59:06 +0100 Subject: [PATCH 07/35] feat: update contracts-js 1.2.0 (#13) Co-authored-by: Oleksandr Shevchuk --- package-lock.json | 1337 +++++++++++++++++++++++++++------------------ package.json | 4 +- 2 files changed, 809 insertions(+), 532 deletions(-) diff --git a/package-lock.json b/package-lock.json index c4c4cf4..839608b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", "@fastify/sensible": "^5.0.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v1.0.1", + "contracts-js": "github:Lumerin-protocol/contracts-js#v1.2.0", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -738,19 +738,24 @@ } }, "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==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.6.0.tgz", + "integrity": "sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==", "dependencies": { "ajv": "^8.11.0", "ajv-formats": "^2.1.1", "fast-uri": "^2.0.0" } }, + "node_modules/@fastify/ajv-compiler/node_modules/fast-uri": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", + "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==" + }, "node_modules/@fastify/autoload": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@fastify/autoload/-/autoload-5.8.0.tgz", - "integrity": "sha512-bF86vl+1Kk91S41WIL9NrKhcugGQg/cQ959aTaombkCjA+9YAbgVCKKu2lRqtMsosDZ0CNRfVnaLYoHQIDUI2A==" + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@fastify/autoload/-/autoload-5.10.0.tgz", + "integrity": "sha512-4A6s86qMbjcpWHmJL7cErtjIxOPuW8c67DLiuO8HoJQxuK97vaptoUnK5BTOwRg1ntYqfc3tjwerTTo5NQ3fEQ==" }, "node_modules/@fastify/cors": { "version": "9.0.1", @@ -762,9 +767,19 @@ } }, "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==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.1.tgz", + "integrity": "sha512-hx+wJQr9Ph1hY/dyzY0SxqjumMyqZDlIF6oe71dpRKDHUg7dFQfjG94qqwQ274XRjmUrwKiYadex8XplNHx3CA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, "node_modules/@fastify/error": { "version": "3.4.1", @@ -788,9 +803,9 @@ } }, "node_modules/@fastify/sensible": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@fastify/sensible/-/sensible-5.5.0.tgz", - "integrity": "sha512-D0zpl+nocsRXLceSbc4gasQaO3ZNQR4dy9Uu8Ym0mh8VUdrjpZ4g8Ca9O3pGXbBVOnPIGHUJNTV7Yf9dg/OYdg==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@fastify/sensible/-/sensible-5.6.0.tgz", + "integrity": "sha512-Vq6Z2ZQy10GDqON+hvLF52K99s9et5gVVxTul5n3SIAf0Kq5QjPRUKkAMT3zPAiiGvoHtS3APa/3uaxfDgCODQ==", "dependencies": { "@lukeed/ms": "^2.0.1", "fast-deep-equal": "^3.1.1", @@ -832,33 +847,80 @@ } }, "node_modules/@scure/base": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.5.tgz", - "integrity": "sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz", + "integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==", "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", - "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.0.tgz", + "integrity": "sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA==", "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" + "@noble/curves": "~1.7.0", + "@noble/hashes": "~1.6.0", + "@scure/base": "~1.2.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", + "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", + "dependencies": { + "@noble/hashes": "1.6.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", + "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", + "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.0.tgz", + "integrity": "sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==", "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" + "@noble/hashes": "~1.6.0", + "@scure/base": "~1.2.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", + "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -873,11 +935,11 @@ } }, "node_modules/@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "version": "22.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", + "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.20.0" } }, "node_modules/@types/ws": { @@ -889,9 +951,9 @@ } }, "node_modules/abitype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.0.tgz", - "integrity": "sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.7.tgz", + "integrity": "sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw==", "funding": { "url": "https://github.com/sponsors/wevm" }, @@ -930,14 +992,14 @@ "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -994,11 +1056,6 @@ "node": ">= 8" } }, - "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/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -1030,13 +1087,11 @@ } }, "node_modules/avvio": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.3.0.tgz", - "integrity": "sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.4.0.tgz", + "integrity": "sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==", "dependencies": { "@fastify/error": "^3.3.0", - "archy": "^1.0.0", - "debug": "^4.0.0", "fastq": "^1.17.1" } }, @@ -1078,11 +1133,14 @@ } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bn.js": { @@ -1099,11 +1157,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -1138,15 +1196,41 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -1251,8 +1335,8 @@ "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==" }, "node_modules/contracts-js": { - "version": "1.0.1", - "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#4bb18628576561be8dccf696768164aa79392c2d", + "version": "1.2.0", + "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#ffbadeef7fd12be5c85d373c55f892662e61fe2e", "dependencies": { "ethereum-abi-types-generator": "^1.3.4" }, @@ -1261,9 +1345,9 @@ } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "engines": { "node": ">= 0.6" } @@ -1280,11 +1364,11 @@ } }, "node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", "dependencies": { - "node-fetch": "^2.6.12" + "node-fetch": "^2.7.0" } }, "node_modules/dateformat": { @@ -1295,22 +1379,6 @@ "node": "*" } }, - "node_modules/debug": { - "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" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1344,9 +1412,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "engines": { "node": ">=12" }, @@ -1362,6 +1430,19 @@ "node": ">=12" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -1377,9 +1458,9 @@ } }, "node_modules/elliptic/node_modules/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==" + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -1405,12 +1486,9 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "engines": { "node": ">= 0.4" } @@ -1423,6 +1501,17 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ethereum-abi-types-generator": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/ethereum-abi-types-generator/-/ethereum-abi-types-generator-1.3.4.tgz", @@ -1449,9 +1538,9 @@ "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" }, "node_modules/ethereum-abi-types-generator/node_modules/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==" + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==" }, "node_modules/ethereum-abi-types-generator/node_modules/dotenv": { "version": "8.6.0", @@ -1502,31 +1591,31 @@ "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==" }, "node_modules/ethereum-cryptography": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", - "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dependencies": { - "@noble/curves": "1.3.0", - "@noble/hashes": "1.3.3", - "@scure/bip32": "1.3.3", - "@scure/bip39": "1.2.2" + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" } }, "node_modules/ethereum-cryptography/node_modules/@noble/curves": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", - "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dependencies": { - "@noble/hashes": "1.3.3" + "@noble/hashes": "1.4.0" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", - "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "engines": { "node": ">= 16" }, @@ -1534,35 +1623,43 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ethereum-cryptography/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ethereum-cryptography/node_modules/@scure/bip32": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", - "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", "dependencies": { - "@noble/curves": "~1.3.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.4" + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/ethereum-cryptography/node_modules/@scure/bip39": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", - "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", "dependencies": { - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.4" + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/ethers": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", - "integrity": "sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==", + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", + "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", "funding": [ { "type": "individual", @@ -1577,19 +1674,27 @@ "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", + "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", - "ws": "8.5.0" + "tslib": "2.7.0", + "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ethers/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "node_modules/ethersv5": { "name": "ethers", @@ -1666,9 +1771,9 @@ "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==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==" }, "node_modules/fast-decode-uri-component": { "version": "1.0.1", @@ -1681,19 +1786,40 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-json-stringify": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.12.0.tgz", - "integrity": "sha512-7Nnm9UPa7SfHRbHVA1kJQrGXCRzB7LMlAAqHXQFkEQqueJm1V8owm0FsE/2Do55/4CcdhwiLQERaKomOnKQkyA==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.16.1.tgz", + "integrity": "sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==", "dependencies": { "@fastify/merge-json-schemas": "^0.1.0", "ajv": "^8.10.0", - "ajv-formats": "^2.1.1", + "ajv-formats": "^3.0.1", "fast-deep-equal": "^3.1.3", "fast-uri": "^2.1.0", "json-schema-ref-resolver": "^1.0.1", "rfdc": "^1.2.0" } }, + "node_modules/fast-json-stringify/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/fast-json-stringify/node_modules/fast-uri": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", + "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==" + }, "node_modules/fast-querystring": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", @@ -1703,9 +1829,9 @@ } }, "node_modules/fast-redact": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.4.0.tgz", - "integrity": "sha512-2gwPvyna0zwBdxKnng1suu/dTL5s8XEy2ZqH8mwDUwJdDkV8w5kp+JV26mupdK68HmPMbm6yjW9m7/Ys/BHEHg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", "engines": { "node": ">=6" } @@ -1716,14 +1842,24 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, "node_modules/fast-uri": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.3.0.tgz", - "integrity": "sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, "node_modules/fastify": { - "version": "4.26.2", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.26.2.tgz", - "integrity": "sha512-90pjTuPGrfVKtdpLeLzND5nyC4woXZN5VadiNQCicj/iJU4viNHKhsAnb7jmv1vu2IzkLXyBiCzdWuzeXgQ5Ug==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.29.0.tgz", + "integrity": "sha512-MaaUHUGcCgC8fXQDsDtioaCcag1fmPJ9j64vAKunqZF4aSub040ZGi/ag8NGE2714yREPOKZuHCfpPzuUD3UQQ==", "funding": [ { "type": "github", @@ -1744,7 +1880,7 @@ "fast-json-stringify": "^5.8.0", "find-my-way": "^8.0.0", "light-my-request": "^5.11.0", - "pino": "^8.17.0", + "pino": "^9.0.0", "process-warning": "^3.0.0", "proxy-addr": "^2.0.7", "rfdc": "^1.3.0", @@ -1754,11 +1890,11 @@ } }, "node_modules/fastify-cli": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/fastify-cli/-/fastify-cli-6.1.1.tgz", - "integrity": "sha512-3TinVuHxcEOhwjRLoE9rTeH1IXa73B5fS21amNyTgF2kOnC72sHzp1p6y2RsbPES1NGf2A7+4S11jbfdTOchVQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/fastify-cli/-/fastify-cli-6.3.0.tgz", + "integrity": "sha512-FORXCwuBiNAArMMxp5hTthQCU9Xa7oO1wnCsGSgvuWC2k5ZarEEIXNm5RekcO9koZDQ0NACU6gGRF96Tf7ZI7Q==", "dependencies": { - "@fastify/deepmerge": "^1.2.0", + "@fastify/deepmerge": "^2.0.0", "chalk": "^4.1.2", "chokidar": "^3.5.2", "close-with-grace": "^1.1.0", @@ -1769,8 +1905,7 @@ "generify": "^4.0.0", "help-me": "^4.0.1", "is-docker": "^2.0.0", - "make-promises-safe": "^5.1.0", - "pino-pretty": "^10.1.0", + "pino-pretty": "^11.2.0", "pkg-up": "^3.1.0", "resolve-from": "^5.0.0", "semver": "^7.3.5", @@ -1786,17 +1921,17 @@ "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==" }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "dependencies": { "reusify": "^1.0.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==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1805,13 +1940,13 @@ } }, "node_modules/find-my-way": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.1.0.tgz", - "integrity": "sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.2.2.tgz", + "integrity": "sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-querystring": "^1.0.0", - "safe-regex2": "^2.0.0" + "safe-regex2": "^3.1.0" }, "engines": { "node": ">=14" @@ -1907,15 +2042,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1924,10 +2064,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1954,11 +2107,11 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1988,21 +2141,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "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", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "engines": { "node": ">= 0.4" }, @@ -2034,9 +2176,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -2101,6 +2243,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2120,12 +2263,12 @@ } }, "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -2187,11 +2330,14 @@ } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -2219,12 +2365,29 @@ "node": ">=0.12.0" } }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -2253,13 +2416,13 @@ } }, "node_modules/isows": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", - "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", "funding": [ { "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" + "url": "https://github.com/sponsors/wevm" } ], "peerDependencies": { @@ -2304,11 +2467,11 @@ } }, "node_modules/light-my-request": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.12.0.tgz", - "integrity": "sha512-P526OX6E7aeCIfw/9UyJNsAISfcFETghysaWHQAlQYayynShT08MOj4c6fBCvTWBrHXSvqBAKDp3amUPSCQI4w==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.14.0.tgz", + "integrity": "sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==", "dependencies": { - "cookie": "^0.6.0", + "cookie": "^0.7.0", "process-warning": "^3.0.0", "set-cookie-parser": "^2.4.1" } @@ -2325,22 +2488,6 @@ "node": ">=6" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-promises-safe": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/make-promises-safe/-/make-promises-safe-5.1.0.tgz", - "integrity": "sha512-AfdZ49rtyhQR/6cqVKGoH7y4ql7XkS5HJI1lZm0/5N6CQosy1eYbBJ/qbhkKHzo17UH7M918Bysf6XB9f3kS1g==" - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -2349,6 +2496,14 @@ "tmpl": "1.0.5" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2413,11 +2568,6 @@ "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/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -2446,9 +2596,9 @@ } }, "node_modules/obliterator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", + "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==" }, "node_modules/on-exit-leak-free": { "version": "2.1.2", @@ -2466,6 +2616,59 @@ "wrappy": "1" } }, + "node_modules/ox": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.0.tgz", + "integrity": "sha512-blUzTLidvUlshv0O02CnLFqBLidNzPoAZdIth894avUAotTuWziznv6IENv5idRuOSSP3dH8WzcYw84zVdu0Aw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "dependencies": { + "@noble/hashes": "1.7.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -2519,50 +2722,34 @@ } }, "node_modules/pino": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.19.0.tgz", - "integrity": "sha512-oswmokxkav9bADfJ2ifrvfHUwad6MLp73Uat0IkQWY3iAw5xTRoznXbXksZs8oaOUMpmhVWD+PZogNzllWpJaA==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", + "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", "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": "^3.0.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^4.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" + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", "dependencies": { - "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, - "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", - "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/pino-abstract-transport/node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", @@ -2572,23 +2759,23 @@ } }, "node_modules/pino-pretty": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz", - "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.3.0.tgz", + "integrity": "sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==", "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", + "fast-copy": "^3.0.2", "fast-safe-stringify": "^2.1.1", "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", + "pino-abstract-transport": "^2.0.0", "pump": "^3.0.0", "readable-stream": "^4.0.0", "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", + "sonic-boom": "^4.0.1", "strip-json-comments": "^3.1.1" }, "bin": { @@ -2601,9 +2788,9 @@ "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" }, "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", - "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", @@ -2616,9 +2803,24 @@ } }, "node_modules/pino-std-serializers": { - "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==" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + }, + "node_modules/pino/node_modules/process-warning": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", + "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, "node_modules/pkg-up": { "version": "3.1.0", @@ -2679,22 +2881,14 @@ } }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, "node_modules/quick-format-unescaped": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", @@ -2767,11 +2961,11 @@ } }, "node_modules/ret": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", - "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.4.3.tgz", + "integrity": "sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==", "engines": { - "node": ">=4" + "node": ">=10" } }, "node_modules/reusify": { @@ -2784,9 +2978,9 @@ } }, "node_modules/rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, "node_modules/safe-buffer": { "version": "5.2.1", @@ -2807,18 +3001,34 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.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==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-3.1.0.tgz", + "integrity": "sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==", "dependencies": { - "ret": "~0.2.0" + "ret": "~0.4.0" } }, "node_modules/safe-stable-stringify": { - "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==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", "engines": { "node": ">=10" } @@ -2834,12 +3044,9 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -2853,21 +3060,21 @@ "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==" + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -2884,9 +3091,9 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/sonic-boom": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz", - "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", + "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", "dependencies": { "atomic-sleep": "^1.0.0" } @@ -2962,9 +3169,9 @@ } }, "node_modules/thread-stream": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz", - "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", "dependencies": { "real-require": "^0.2.0" } @@ -3007,9 +3214,9 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/type-is": { "version": "1.6.18", @@ -3024,9 +3231,9 @@ } }, "node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "peer": true, "bin": { "tsc": "bin/tsc", @@ -3037,9 +3244,9 @@ } }, "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==" + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" }, "node_modules/universalify": { "version": "2.0.1", @@ -3049,14 +3256,6 @@ "node": ">= 10.0.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", @@ -3089,9 +3288,9 @@ } }, "node_modules/viem": { - "version": "2.7.22", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.7.22.tgz", - "integrity": "sha512-R/d9AkWXkhiNF4Gk4/A389LSO5PGDdHUBFDKIUkhrdLTDpOhKzbNln6qDry3kYUcmH7lErx3C2eA6rajnc0s9A==", + "version": "2.22.4", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.22.4.tgz", + "integrity": "sha512-35/T2ySpUM0kUVEy2SkaWIAIabSRzF/IZxDdnLxuaI1pwURC92ZiHa9J9nL1rWGl0HTyAqUxcycgJEpOvHrcQA==", "funding": [ { "type": "github", @@ -3099,14 +3298,15 @@ } ], "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "1.0.0", - "isows": "1.0.3", - "ws": "8.13.0" + "@noble/curves": "1.7.0", + "@noble/hashes": "1.6.1", + "@scure/bip32": "1.6.0", + "@scure/bip39": "1.5.0", + "abitype": "1.0.7", + "isows": "1.0.6", + "ox": "0.6.0", + "webauthn-p256": "0.0.10", + "ws": "8.18.0" }, "peerDependencies": { "typescript": ">=5.0.4" @@ -3117,15 +3317,46 @@ } } }, - "node_modules/viem/node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", + "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", + "dependencies": { + "@noble/hashes": "1.6.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@noble/curves/node_modules/@noble/hashes": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", + "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@noble/hashes": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", + "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/viem/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, @@ -3151,26 +3382,27 @@ } }, "node_modules/web3": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-4.6.0.tgz", - "integrity": "sha512-hoI6r29B4kjxINI21rBVaE0Bz0hwtW+Sbppn5ZDTWn5PSQpBW4ecYFDVKVE6K3gbmSjY2fknu2cjBTqha7S53A==", - "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.5.0", - "web3-eth-abi": "^4.2.0", - "web3-eth-accounts": "^4.1.1", - "web3-eth-contract": "^4.2.0", - "web3-eth-ens": "^4.1.0", + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/web3/-/web3-4.16.0.tgz", + "integrity": "sha512-SgoMSBo6EsJ5GFCGar2E/pR2lcR/xmUSuQ61iK6yDqzxmm42aPPxSqZfJz2z/UCR6pk03u77pU8TGV6lgMDdIQ==", + "dependencies": { + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth": "^4.11.1", + "web3-eth-abi": "^4.4.1", + "web3-eth-accounts": "^4.3.1", + "web3-eth-contract": "^4.7.2", + "web3-eth-ens": "^4.4.0", "web3-eth-iban": "^4.0.7", - "web3-eth-personal": "^4.0.8", - "web3-net": "^4.0.7", - "web3-providers-http": "^4.1.0", - "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.1", - "web3-validator": "^2.0.4" + "web3-eth-personal": "^4.1.0", + "web3-net": "^4.1.0", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-rpc-methods": "^1.3.0", + "web3-rpc-providers": "^1.0.0-rc.4", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14.0.0", @@ -3178,18 +3410,18 @@ } }, "node_modules/web3-core": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-4.3.2.tgz", - "integrity": "sha512-uIMVd/j4BgOnwfpY8ZT+QKubOyM4xohEhFZXz9xB8wimXWMMlYVlIK/TbfHqFolS9uOerdSGhsMbcK9lETae8g==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-4.7.1.tgz", + "integrity": "sha512-9KSeASCb/y6BG7rwhgtYC4CvYY66JfkmGNEYb7q1xgjt9BWfkf09MJPaRyoyT5trdOxYDHkT9tDlypvQWaU8UQ==", "dependencies": { - "web3-errors": "^1.1.4", - "web3-eth-accounts": "^4.1.0", + "web3-errors": "^1.3.1", + "web3-eth-accounts": "^4.3.1", "web3-eth-iban": "^4.0.7", - "web3-providers-http": "^4.1.0", - "web3-providers-ws": "^4.0.7", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.0", - "web3-validator": "^2.0.3" + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3200,11 +3432,11 @@ } }, "node_modules/web3-errors": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.1.4.tgz", - "integrity": "sha512-WahtszSqILez+83AxGecVroyZsMuuRT+KmQp4Si5P4Rnqbczno1k748PCrZTS1J4UCPmXMG2/Vt+0Bz2zwXkwQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.1.tgz", + "integrity": "sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==", "dependencies": { - "web3-types": "^1.3.1" + "web3-types": "^1.10.0" }, "engines": { "node": ">=14", @@ -3212,21 +3444,21 @@ } }, "node_modules/web3-eth": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.5.0.tgz", - "integrity": "sha512-crisE46o/SHMVm+XHAXEaR8k76NCImq+hi0QQEJ+VaLZbDobI/Gvog1HwTukDUDRgnYSAFGqD0cTRyAwDurwpA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.11.1.tgz", + "integrity": "sha512-q9zOkzHnbLv44mwgLjLXuyqszHuUgZWsQayD2i/rus2uk0G7hMn11bE2Q3hOVnJS4ws4VCtUznlMxwKQ+38V2w==", "dependencies": { "setimmediate": "^1.0.5", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth-abi": "^4.2.0", - "web3-eth-accounts": "^4.1.1", - "web3-net": "^4.0.7", - "web3-providers-ws": "^4.0.7", - "web3-rpc-methods": "^1.2.0", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.1", - "web3-validator": "^2.0.4" + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth-abi": "^4.4.1", + "web3-eth-accounts": "^4.3.1", + "web3-net": "^4.1.0", + "web3-providers-ws": "^4.0.8", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3234,15 +3466,15 @@ } }, "node_modules/web3-eth-abi": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.2.0.tgz", - "integrity": "sha512-x7dUCmk6th+5N63s5kUusoNtsDJKUUQgl9+jECvGTBOTiyHe/V6aOY0120FUjaAGaapOnR7BImQdhqHv6yT2YQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.4.1.tgz", + "integrity": "sha512-60ecEkF6kQ9zAfbTY04Nc9q4eEYM0++BySpGi8wZ2PD1tw/c0SDvsKhV6IKURxLJhsDlb08dATc3iD6IbtWJmg==", "dependencies": { "abitype": "0.7.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.1", - "web3-validator": "^2.0.4" + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3264,17 +3496,17 @@ } }, "node_modules/web3-eth-accounts": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.1.1.tgz", - "integrity": "sha512-9JqhRi1YhO1hQOEmmBHgEGsME/B1FHMxpA/AK3vhpvQ8QeP6KbJW+cForTLfPpUbkmPxnRunG4PNNaETNlZfrA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.3.1.tgz", + "integrity": "sha512-rTXf+H9OKze6lxi7WMMOF1/2cZvJb2AOnbNQxPhBDssKOllAMzLhg1FbZ4Mf3lWecWfN6luWgRhaeSqO1l+IBQ==", "dependencies": { "@ethereumjs/rlp": "^4.0.1", "crc-32": "^1.2.2", "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.1", - "web3-validator": "^2.0.4" + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3282,37 +3514,49 @@ } }, "node_modules/web3-eth-contract": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.2.0.tgz", - "integrity": "sha512-K7bUypsomTs8/Oa0Lgvq5plsSB5afgKJ79NMuXxvC5jfV+AxNrQyKcr5Vd5yEGNqrdQuIPduGQa8DpuY+rMe1g==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.7.2.tgz", + "integrity": "sha512-3ETqs2pMNPEAc7BVY/C3voOhTUeJdkf2aM3X1v+edbngJLHAxbvxKpOqrcO0cjXzC4uc2Q8Zpf8n8zT5r0eLnA==", "dependencies": { - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.4.0", - "web3-eth-abi": "^4.2.0", - "web3-types": "^1.3.1", - "web3-utils": "^4.1.1", - "web3-validator": "^2.0.4" + "@ethereumjs/rlp": "^5.0.2", + "web3-core": "^4.7.1", + "web3-errors": "^1.3.1", + "web3-eth": "^4.11.1", + "web3-eth-abi": "^4.4.1", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", "npm": ">=6.12.0" } }, + "node_modules/web3-eth-contract/node_modules/@ethereumjs/rlp": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", + "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/web3-eth-ens": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-4.1.0.tgz", - "integrity": "sha512-B+QsXXJb/gJkHb1ZGfErNLeFI9zUf2TsQcvi2+NsSuzFwvjIO5IyrrGtqBmXMLWC8ZikMOHuc8ZfFuGrELl31Q==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-4.4.0.tgz", + "integrity": "sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ==", "dependencies": { "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.3.2", - "web3-errors": "^1.1.4", - "web3-eth": "^4.5.0", - "web3-eth-contract": "^4.2.0", - "web3-net": "^4.0.7", - "web3-types": "^1.5.0", - "web3-utils": "^4.2.1", - "web3-validator": "^2.0.4" + "web3-core": "^4.5.0", + "web3-errors": "^1.2.0", + "web3-eth": "^4.8.0", + "web3-eth-contract": "^4.5.0", + "web3-net": "^4.1.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3335,16 +3579,16 @@ } }, "node_modules/web3-eth-personal": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-4.0.8.tgz", - "integrity": "sha512-sXeyLKJ7ddQdMxz1BZkAwImjqh7OmKxhXoBNF3isDmD4QDpMIwv/t237S3q4Z0sZQamPa/pHebJRWVuvP8jZdw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-4.1.0.tgz", + "integrity": "sha512-RFN83uMuvA5cu1zIwwJh9A/bAj0OBxmGN3tgx19OD/9ygeUZbifOL06jgFzN0t+1ekHqm3DXYQM8UfHpXi7yDQ==", "dependencies": { - "web3-core": "^4.3.0", - "web3-eth": "^4.3.1", - "web3-rpc-methods": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" + "web3-core": "^4.6.0", + "web3-eth": "^4.9.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.8.0", + "web3-utils": "^4.3.1", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3352,14 +3596,14 @@ } }, "node_modules/web3-net": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.0.7.tgz", - "integrity": "sha512-SzEaXFrBjY25iQGk5myaOfO9ZyfTwQEa4l4Ps4HDNVMibgZji3WPzpjq8zomVHMwi8bRp6VV7YS71eEsX7zLow==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.1.0.tgz", + "integrity": "sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA==", "dependencies": { - "web3-core": "^4.3.0", - "web3-rpc-methods": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "web3-core": "^4.4.0", + "web3-rpc-methods": "^1.3.0", + "web3-types": "^1.6.0", + "web3-utils": "^4.3.0" }, "engines": { "node": ">=14", @@ -3367,14 +3611,14 @@ } }, "node_modules/web3-providers-http": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.1.0.tgz", - "integrity": "sha512-6qRUGAhJfVQM41E5t+re5IHYmb5hSaLc02BE2MaRQsz2xKA6RjmHpOA5h/+ojJxEpI9NI2CrfDKOAgtJfoUJQg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.2.0.tgz", + "integrity": "sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ==", "dependencies": { "cross-fetch": "^4.0.0", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" + "web3-errors": "^1.3.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1" }, "engines": { "node": ">=14", @@ -3397,50 +3641,47 @@ } }, "node_modules/web3-providers-ws": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.7.tgz", - "integrity": "sha512-n4Dal9/rQWjS7d6LjyEPM2R458V8blRm0eLJupDEJOOIBhGYlxw5/4FthZZ/cqB7y/sLVi7K09DdYx2MeRtU5w==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.8.tgz", + "integrity": "sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw==", "dependencies": { "@types/ws": "8.5.3", "isomorphic-ws": "^5.0.0", - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "ws": "^8.8.1" + "web3-errors": "^1.2.0", + "web3-types": "^1.7.0", + "web3-utils": "^4.3.1", + "ws": "^8.17.1" }, "engines": { "node": ">=14", "npm": ">=6.12.0" } }, - "node_modules/web3-providers-ws/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "node_modules/web3-rpc-methods": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/web3-rpc-methods/-/web3-rpc-methods-1.3.0.tgz", + "integrity": "sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig==", + "dependencies": { + "web3-core": "^4.4.0", + "web3-types": "^1.6.0", + "web3-validator": "^2.0.6" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=14", + "npm": ">=6.12.0" } }, - "node_modules/web3-rpc-methods": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/web3-rpc-methods/-/web3-rpc-methods-1.2.0.tgz", - "integrity": "sha512-CWJ/g4I4WyYvLkf21wCZAehdhU/VjX/OAPHnqF5/FPDJlogOsOnGXHqi1Z5AP+ocdt395PNubd8jyMMJoYGSBA==", + "node_modules/web3-rpc-providers": { + "version": "1.0.0-rc.4", + "resolved": "https://registry.npmjs.org/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.4.tgz", + "integrity": "sha512-PXosCqHW0EADrYzgmueNHP3Y5jcSmSwH+Dkqvn7EYD0T2jcsdDAIHqk6szBiwIdhumM7gv9Raprsu/s/f7h1fw==", "dependencies": { - "web3-core": "^4.3.2", - "web3-types": "^1.5.0", - "web3-validator": "^2.0.4" + "web3-errors": "^1.3.1", + "web3-providers-http": "^4.2.0", + "web3-providers-ws": "^4.0.8", + "web3-types": "^1.10.0", + "web3-utils": "^4.3.3", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3448,24 +3689,24 @@ } }, "node_modules/web3-types": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.5.0.tgz", - "integrity": "sha512-geWuMIeegQ8AedKAO6wO4G4j1gyQ1F/AyKLMw2vud4bsfZayyzWJgCMDZtjYMm5uo2a7i8j1W3/4QFmzlSy5cw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.10.0.tgz", + "integrity": "sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==", "engines": { "node": ">=14", "npm": ">=6.12.0" } }, "node_modules/web3-utils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.2.1.tgz", - "integrity": "sha512-Fk29BlEqD9Q9Cnw4pBkKw7czcXiRpsSco/BzEUl4ye0ZTSHANQFfjsfQmNm4t7uY11u6Ah+8F3tNjBeU4CA80A==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", + "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", "dependencies": { "ethereum-cryptography": "^2.0.0", "eventemitter3": "^5.0.1", - "web3-errors": "^1.1.4", - "web3-types": "^1.5.0", - "web3-validator": "^2.0.4" + "web3-errors": "^1.3.1", + "web3-types": "^1.10.0", + "web3-validator": "^2.0.6" }, "engines": { "node": ">=14", @@ -3473,14 +3714,14 @@ } }, "node_modules/web3-validator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.4.tgz", - "integrity": "sha512-qRxVePwdW+SByOmTpDZFWHIUAa7PswvxNszrOua6BoGqAhERo5oJZBN+EbWtK/+O+ApNxt5FR3nCPmiZldiOQA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", + "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", "dependencies": { "ethereum-cryptography": "^2.0.0", "util": "^0.12.5", - "web3-errors": "^1.1.4", - "web3-types": "^1.3.1", + "web3-errors": "^1.2.0", + "web3-types": "^1.6.0", "zod": "^3.21.4" }, "engines": { @@ -3488,6 +3729,46 @@ "npm": ">=6.12.0" } }, + "node_modules/webauthn-p256": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz", + "integrity": "sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "dependencies": { + "@noble/curves": "^1.4.0", + "@noble/hashes": "^1.4.0" + } + }, + "node_modules/webauthn-p256/node_modules/@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "dependencies": { + "@noble/hashes": "1.7.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/webauthn-p256/node_modules/@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -3508,15 +3789,16 @@ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, "node_modules/which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "dependencies": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3544,15 +3826,15 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -3576,11 +3858,6 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", @@ -3665,9 +3942,9 @@ } }, "node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index c55d4d3..1ccef11 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", "@fastify/sensible": "^5.0.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v1.0.1", + "contracts-js": "github:Lumerin-protocol/contracts-js#v1.2.0", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -31,4 +31,4 @@ "viem": "^2.7.22", "web3": "^4.5.0" } -} +} \ No newline at end of file From bc5c45a7a9eabeb2586daedc929b774663cda7fa Mon Sep 17 00:00:00 2001 From: shev-titan <108101079+shev-titan@users.noreply.github.com> Date: Wed, 8 Jan 2025 20:40:36 +0100 Subject: [PATCH 08/35] fix: contract purchased abi (#14) Co-authored-by: Oleksandr Shevchuk --- initialize.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/initialize.js b/initialize.js index 571e707..62b4a3a 100644 --- a/initialize.js +++ b/initialize.js @@ -19,7 +19,7 @@ const startWatch = async (client, loader, config, onLogUpdate) => { try { const contractAddresses = await loader.getContractList(); const addresses = [config.CLONE_FACTORY_ADDRESS, ...contractAddresses]; - + const cloneFactoryEvents = [ "contractCreated", "clonefactoryContractPurchased", @@ -29,16 +29,16 @@ const startWatch = async (client, loader, config, onLogUpdate) => { const eventsAbi = [ // Clone Factory Events "event contractCreated(address indexed _address, string _pubkey)", - "event clonefactoryContractPurchased(address indexed _address)", + "event clonefactoryContractPurchased(address indexed _address, address indexed _validator)", "event contractDeleteUpdated(address _address, bool _isDeleted)", "event purchaseInfoUpdated(address indexed _address)", - + // Implementation Events "event closedEarly(uint8 reason)", "event fundsClaimed()", "event destinationUpdated(string newValidatorURL, string newDestURL)", ]; - + const unwatch = client.watchEvent({ address: addresses, events: parseAbi(eventsAbi), @@ -55,7 +55,7 @@ const startWatch = async (client, loader, config, onLogUpdate) => { contractAddress = address; } console.log(`Received log for contract: ${contractAddress}`); - + onLogUpdate(contractAddress, Number(blockNumber)); if (eventName === "contractCreated") { console.log('Got contract created event, restating watch') From b19b17094de9f9311cb907a51e4223af12704bdc Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Thu, 24 Apr 2025 20:30:25 +0200 Subject: [PATCH 09/35] rewrite in ts --- .gitignore | 4 +- Dockerfile | 27 +- app.js | 47 -- initialize.js | 134 ------ package-lock.json | 672 +++++++++++++++++++++++++++-- package.json | 15 +- src/ContractEventsListener.js | 99 ----- src/ContractMapper.js | 88 ---- src/ContractsInMemoryIndexer.js | 147 ------- src/ContractsLoader.js | 68 --- src/app.ts | 46 ++ src/config/{index.js => config.ts} | 19 +- src/indexer-job.ts | 42 ++ src/plugins/README.md | 16 - src/plugins/sensible.js | 14 - src/plugins/support.js | 12 - src/routes/README.md | 27 -- src/routes/admin/index.js | 28 -- src/routes/contracts/index.js | 29 -- src/routes/healthcheck/index.js | 19 - src/routes/root.js | 7 - src/routes/root.ts | 59 +++ src/server.ts | 59 +++ src/services/blockchain.repo.ts | 132 ++++++ src/services/blockchain.types.ts | 50 +++ src/services/cache.repo.ts | 88 ++++ src/services/listener.ts | 90 ++++ src/services/mapper.ts | 90 ++++ src/types/contracts.js | 61 --- src/types/contracts.ts | 53 +++ tsconfig.json | 114 +++++ 31 files changed, 1507 insertions(+), 849 deletions(-) delete mode 100644 app.js delete mode 100644 initialize.js delete mode 100644 src/ContractEventsListener.js delete mode 100644 src/ContractMapper.js delete mode 100644 src/ContractsInMemoryIndexer.js delete mode 100644 src/ContractsLoader.js create mode 100644 src/app.ts rename src/config/{index.js => config.ts} (56%) create mode 100644 src/indexer-job.ts delete mode 100644 src/plugins/README.md delete mode 100644 src/plugins/sensible.js delete mode 100644 src/plugins/support.js delete mode 100644 src/routes/README.md delete mode 100644 src/routes/admin/index.js delete mode 100644 src/routes/contracts/index.js delete mode 100644 src/routes/healthcheck/index.js delete mode 100644 src/routes/root.js create mode 100644 src/routes/root.ts create mode 100644 src/server.ts create mode 100644 src/services/blockchain.repo.ts create mode 100644 src/services/blockchain.types.ts create mode 100644 src/services/cache.repo.ts create mode 100644 src/services/listener.ts create mode 100644 src/services/mapper.ts delete mode 100644 src/types/contracts.js create mode 100644 src/types/contracts.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index db39e22..5c1e4f6 100644 --- a/.gitignore +++ b/.gitignore @@ -60,4 +60,6 @@ profile* .env .env.dev .env.prod -.env.stg \ No newline at end of file +.env.stg + +dist \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 2be8ffc..6bbea42 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,30 @@ -FROM node:current-alpine +# Build stage +FROM node:current-alpine AS builder WORKDIR '/app' RUN apk add git -COPY ./package.json ./ -RUN npm install -g npm@latest -RUN npm install --legacy-peer-deps +COPY ./package*.json ./ + +RUN npm ci + COPY . . +# Build TypeScript +RUN npm run build + +# Create production node_modules +RUN npm prune --production + +# Production stage +FROM node:current-alpine +WORKDIR '/app' + +# Copy only necessary files from builder +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/package*.json ./ +COPY --from=builder /app/node_modules ./node_modules + # keep alphabetically sorted ARG ADMIN_API_KEY ENV ADMIN_API_KEY=$ADMIN_API_KEY @@ -24,4 +41,4 @@ ENV FASTIFY_ADDRESS=0.0.0.0 EXPOSE ${PORT} -CMD npm run start \ No newline at end of file +CMD node dist/app.js \ No newline at end of file diff --git a/app.js b/app.js deleted file mode 100644 index c0e5eea..0000000 --- a/app.js +++ /dev/null @@ -1,47 +0,0 @@ -"use strict"; - -const path = require("node:path"); -const AutoLoad = require("@fastify/autoload"); -const cors = require("@fastify/cors"); - -const { initialize } = require("./initialize"); -const config = require("./src/config"); - -// Pass --options via CLI arguments in command to enable these options. -const options = { - prefix: '/api', -}; - -/** - * @param {import('fastify').FastifyInstance} fastify - * @param {*} opts - */ -module.exports = async function (fastify, opts) { - console.log(`Running server with config: ${JSON.stringify(config)}`) - - // Write cusrom code here - await initialize(config); - - // Do not touch the following lines - - // This loads all plugins defined in plugins - // those should be support plugins that are reused - // through your application - fastify.register(AutoLoad, { - dir: path.join(__dirname, "src/plugins"), - options: Object.assign(options, opts), - }); - - fastify.register(cors, { - origin: "*", - }) - - // This loads all plugins defined in routes - // define your routes in one of these - fastify.register(AutoLoad, { - dir: path.join(__dirname, "src/routes"), - options: Object.assign(options, opts), - }); -}; - -module.exports.options = options; diff --git a/initialize.js b/initialize.js deleted file mode 100644 index 62b4a3a..0000000 --- a/initialize.js +++ /dev/null @@ -1,134 +0,0 @@ -const { Web3 } = require("web3"); -const { createPublicClient, http, parseAbi } = require("viem"); - -const { CloneFactory } = require("contracts-js"); - -const { ContractsLoader } = require("./src/ContractsLoader"); -const { ContractsInMemoryIndexer } = require("./src/ContractsInMemoryIndexer"); -const { ContractMapper } = require("./src/ContractMapper"); - -/** - * - * @param {import('viem').PublicClient} client - * @param {ContractsLoader} loader - * @param {any} config - * @param {(id, blockNumber) => void} onLogUpdate - * @returns {Promise} - */ -const startWatch = async (client, loader, config, onLogUpdate) => { - try { - const contractAddresses = await loader.getContractList(); - const addresses = [config.CLONE_FACTORY_ADDRESS, ...contractAddresses]; - - const cloneFactoryEvents = [ - "contractCreated", - "clonefactoryContractPurchased", - "contractDeleteUpdated", - "purchaseInfoUpdated", - ]; - const eventsAbi = [ - // Clone Factory Events - "event contractCreated(address indexed _address, string _pubkey)", - "event clonefactoryContractPurchased(address indexed _address, address indexed _validator)", - "event contractDeleteUpdated(address _address, bool _isDeleted)", - "event purchaseInfoUpdated(address indexed _address)", - - // Implementation Events - "event closedEarly(uint8 reason)", - "event fundsClaimed()", - "event destinationUpdated(string newValidatorURL, string newDestURL)", - ]; - - const unwatch = client.watchEvent({ - address: addresses, - events: parseAbi(eventsAbi), - poll: true, - pollingInterval: 1000, - onLogs: (logs) => { - console.log(`Received logs: ${logs.length}`); - logs.forEach((log) => { - const { eventName, args, address, blockNumber } = log; - let contractAddress = null; - if (cloneFactoryEvents.includes(eventName)) { - contractAddress = args._address; - } else { - contractAddress = address; - } - console.log(`Received log for contract: ${contractAddress}`); - - onLogUpdate(contractAddress, Number(blockNumber)); - if (eventName === "contractCreated") { - console.log('Got contract created event, restating watch') - unwatch(); - startWatch(client, loader, config, onLogUpdate); - } - }); - }, - onError: (error) => { - console.error("On Error Callback", error); - process.exit(1); - } - }); - console.log( - `Started listen events for contracts: ${JSON.stringify(addresses)}, amount: ${addresses.length}` - ); - return { addresses }; - } catch (err) { - console.error("Error starting watch", err); - process.exit(1); - } -}; - -const initialize = async (config) => { - const httpEthNodeUrl = config.ETH_NODE_URL; - const client = createPublicClient({ - transport: http(httpEthNodeUrl, { - retryCount: 10, - retryInterval: 1000, - }), - }); - - const web3 = new Web3(httpEthNodeUrl); - - const cloneFactory = CloneFactory(web3, config.CLONE_FACTORY_ADDRESS); - - const indexer = ContractsInMemoryIndexer.getInstance(new ContractMapper()); - const loader = new ContractsLoader(web3, cloneFactory); - - /** - * - * @param {string} contractId - * @param {number} blockNumber - * @param {number} [retryCount] - */ - const onEventUpdate = async (contractId, blockNumber, retryCount = 0) => { - try { - await new Promise((resolve) => setTimeout(resolve, retryCount * 1000)); - const contract = await loader.getContract(contractId); - indexer.upsert(contractId, contract, blockNumber); - } catch (error) { - console.error(`Error updating contract ${contractId}, error: `, error, `retryCount: ${retryCount}`); - if (retryCount <= 10) { - onEventUpdate(contractId, blockNumber, retryCount + 1); - } - } - }; - - /** - * - * @param {string} contractId - * @param {Contract} contract - * @param {import("contracts-js").ImplementationContext} implInstance - * @param {number} blockNumber - */ - const onContractLoad = (contractId, contract, implInstance, blockNumber) => { - indexer.upsert(contractId, contract, blockNumber); - }; - - await startWatch(client, loader, config, onEventUpdate); - - await loader.loadAll(onContractLoad); - console.log("All Contracts loaded"); -}; - -module.exports = { initialize }; diff --git a/package-lock.json b/package-lock.json index 839608b..63a74ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", "@fastify/sensible": "^5.0.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v1.2.0", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.0", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -21,6 +21,13 @@ "viem": "^2.7.22", "web3": "^4.5.0" }, + "devDependencies": { + "@types/node": "^22.14.1", + "json-schema-to-ts": "^3.1.1", + "pino-pretty": "^13.0.0", + "tsx": "^4.19.3", + "typescript": "^5.8.3" + }, "engines": { "node": ">=20.x" } @@ -30,6 +37,444 @@ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" }, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", + "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", + "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", + "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", + "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", + "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", + "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", + "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", + "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", + "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", + "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", + "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", + "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", + "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", + "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", + "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", + "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", + "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", + "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", + "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", + "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", + "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", + "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", + "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", + "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", + "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@ethereumjs/rlp": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", @@ -935,11 +1380,12 @@ } }, "node_modules/@types/node": { - "version": "22.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", - "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/ws": { @@ -974,6 +1420,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "dependencies": { "event-target-shim": "^5.0.0" }, @@ -1117,7 +1564,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/bech32": { "version": "1.1.4", @@ -1190,6 +1638,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" @@ -1335,8 +1784,8 @@ "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==" }, "node_modules/contracts-js": { - "version": "1.2.0", - "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#ffbadeef7fd12be5c85d373c55f892662e61fe2e", + "version": "2.0.0", + "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#c08dbe59e88b724a9724b2306e1a3a93374f9453", "dependencies": { "ethereum-abi-types-generator": "^1.3.4" }, @@ -1512,6 +1961,47 @@ "node": ">= 0.4" } }, + "node_modules/esbuild": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", + "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.3", + "@esbuild/android-arm": "0.25.3", + "@esbuild/android-arm64": "0.25.3", + "@esbuild/android-x64": "0.25.3", + "@esbuild/darwin-arm64": "0.25.3", + "@esbuild/darwin-x64": "0.25.3", + "@esbuild/freebsd-arm64": "0.25.3", + "@esbuild/freebsd-x64": "0.25.3", + "@esbuild/linux-arm": "0.25.3", + "@esbuild/linux-arm64": "0.25.3", + "@esbuild/linux-ia32": "0.25.3", + "@esbuild/linux-loong64": "0.25.3", + "@esbuild/linux-mips64el": "0.25.3", + "@esbuild/linux-ppc64": "0.25.3", + "@esbuild/linux-riscv64": "0.25.3", + "@esbuild/linux-s390x": "0.25.3", + "@esbuild/linux-x64": "0.25.3", + "@esbuild/netbsd-arm64": "0.25.3", + "@esbuild/netbsd-x64": "0.25.3", + "@esbuild/openbsd-arm64": "0.25.3", + "@esbuild/openbsd-x64": "0.25.3", + "@esbuild/sunos-x64": "0.25.3", + "@esbuild/win32-arm64": "0.25.3", + "@esbuild/win32-ia32": "0.25.3", + "@esbuild/win32-x64": "0.25.3" + } + }, "node_modules/ethereum-abi-types-generator": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/ethereum-abi-types-generator/-/ethereum-abi-types-generator-1.3.4.tgz", @@ -1748,6 +2238,7 @@ "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==", + "license": "MIT", "engines": { "node": ">=6" } @@ -1761,6 +2252,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", "engines": { "node": ">=0.8.x" } @@ -1915,6 +2407,53 @@ "fastify": "cli.js" } }, + "node_modules/fastify-cli/node_modules/pino-pretty": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.3.0.tgz", + "integrity": "sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/fastify-cli/node_modules/pino-pretty/node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, + "node_modules/fastify-cli/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "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-plugin": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", @@ -2076,6 +2615,19 @@ "node": ">= 0.4" } }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -2237,7 +2789,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/inflight": { "version": "1.0.6", @@ -2450,6 +3003,20 @@ "fast-deep-equal": "^3.1.3" } }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -2759,9 +3326,11 @@ } }, "node_modules/pino-pretty": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.3.0.tgz", - "integrity": "sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", + "integrity": "sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==", + "dev": true, + "license": "MIT", "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", @@ -2773,7 +3342,6 @@ "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pump": "^3.0.0", - "readable-stream": "^4.0.0", "secure-json-parse": "^2.4.0", "sonic-boom": "^4.0.1", "strip-json-comments": "^3.1.1" @@ -2785,22 +3353,8 @@ "node_modules/pino-pretty/node_modules/help-me": { "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/pino-pretty/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "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" - } + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true }, "node_modules/pino-std-serializers": { "version": "7.0.0", @@ -2859,6 +3413,7 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -2931,6 +3486,13 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "license": "MIT" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2960,6 +3522,16 @@ "node": ">=8" } }, + "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, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/ret": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/ret/-/ret-0.4.3.tgz", @@ -3213,11 +3785,38 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "dev": true, + "license": "MIT" + }, "node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, + "node_modules/tsx": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", + "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -3231,10 +3830,10 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", - "peer": true, + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3244,9 +3843,10 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" }, "node_modules/universalify": { "version": "2.0.1", diff --git a/package.json b/package.json index 1ccef11..74a52c8 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "node": ">=20.x" }, "scripts": { - "test": "node --test test/**/*.test.js", - "start": "fastify start -l info app.js", - "dev": "fastify start -w -l info -P app.js" + "dev": "tsx watch src/app.ts | pino-pretty", + "build": "tsc", + "start": "node dist/app.js" }, "author": { "name": "Lumerin", @@ -22,7 +22,7 @@ "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", "@fastify/sensible": "^5.0.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v1.2.0", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.0", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -30,5 +30,12 @@ "fastify-plugin": "^4.0.0", "viem": "^2.7.22", "web3": "^4.5.0" + }, + "devDependencies": { + "@types/node": "^22.14.1", + "json-schema-to-ts": "^3.1.1", + "pino-pretty": "^13.0.0", + "tsx": "^4.19.3", + "typescript": "^5.8.3" } } \ No newline at end of file diff --git a/src/ContractEventsListener.js b/src/ContractEventsListener.js deleted file mode 100644 index e933145..0000000 --- a/src/ContractEventsListener.js +++ /dev/null @@ -1,99 +0,0 @@ -// @ts-check - -class ContractEventsListener { - /** - * @type {ContractEventsListener} - */ - static instance; - - /** - * @param {import('contracts-js').CloneFactoryContext} cloneFactory - * @param {(id: string, blockNumber: number) => void} onUpdate - */ - constructor(cloneFactory, onUpdate) { - this.cloneFactory = cloneFactory; - this.onUpdate = onUpdate; - this.cloneFactoryListener = null; - this.contracts = {}; - } - - /** - * - * @param {string} id - * @param {import('contracts-js').ImplementationContext} instance - */ - listenContract(id, instance) { - if (this.contracts[id]) { - console.log(`Already listening contract (${id}) events`); - return; - } - this.contracts[id] = instance.events.allEvents({}); - this.contracts[id].on("connected", () => { - console.log(`Start listen contract (${id}) events`); - }); - this.contracts[id].on("data", (event) => { - const blockNumber = event.blockNumber; - console.log(`Contract (${id}) updated`); - if (this.onUpdate) { - this.onUpdate(id, blockNumber); - } - }); - this.contracts[id].on('error', (error) => { - console.error(`Error listening contract (${id}) events`, error); - console.log('Restart server'); - process.exit(1); - }); - } - - listenCloneFactory() { - if (this.cloneFactoryListener) { - console.log("Already listening clone factory events"); - return; - } - this.cloneFactoryListener = this.cloneFactory.events.contractCreated({}); - // @ts-ignore ("connected" event is not defined in the type, but exists.) - this.cloneFactoryListener.on("connected", () => { - console.log("Start listen clone factory events"); - }); - this.cloneFactoryListener.on("data", (event) => { - const contractId = event.returnValues._address; - const blockNumber = event.blockNumber; - console.log("New contract created", contractId); - this.onUpdate(contractId, blockNumber); - }); - this.cloneFactoryListener.on('error', (error) => { - console.error("Error listening clone factory events", error); - console.log('Restart server'); - process.exit(1); - }); - } - - /** - * @static - * @param {import('contracts-js').CloneFactoryContext} cloneFactory - * @param {(id: string, blockNumber: number) => void} onUpdate - * @returns {ContractEventsListener} - */ - static create(cloneFactory, onUpdate) { - if (ContractEventsListener.instance) { - return ContractEventsListener.instance; - } - - const instance = new ContractEventsListener(cloneFactory, onUpdate); - ContractEventsListener.instance = instance; - instance.listenCloneFactory(); - return instance; - } - - /** - * @returns {ContractEventsListener} - */ - static getInstance() { - if (!ContractEventsListener.instance) { - throw new Error("ContractEventsListener instance not created"); - } - return ContractEventsListener.instance; - } -} - -module.exports = { ContractEventsListener }; diff --git a/src/ContractMapper.js b/src/ContractMapper.js deleted file mode 100644 index b8e08ce..0000000 --- a/src/ContractMapper.js +++ /dev/null @@ -1,88 +0,0 @@ -// @ts-check - -class ContractMapper { - /** - * Maps a raw contract object to a Contract object. - * @param {string} id - The contract id. - * @param {RawContract} rawContract - The raw contract object. - * @returns {Contract} The mapped Contract object. - */ - map(id, rawContract) { - const { data, futureTerms: rawFutureTerms } = rawContract; - const { _terms: terms } = data; - - const futureTerms = this.mapFutureTerms(rawFutureTerms); - const history = this.mapHistory(rawContract.history); - const stats = this.mapStats(rawContract.stats); - - return { - id, - state: data._state.toString(), - price: terms._price.toString(), - limit: terms._limit.toString(), - speed: terms._speed.toString(), - length: terms._length.toString(), - version: terms._version.toString(), - profitTarget: terms._profitTarget.toString(), - startingBlockTimestamp: data._startingBlockTimestamp.toString(), - buyer: data._buyer, - seller: data._seller, - encrValidatorUrl: data._encryptedPoolData, - isDeleted: data._isDeleted, - balance: data._balance.toString(), - hasFutureTerms: data._hasFutureTerms, - futureTerms, - history, - stats, - }; - } - - /** - * - * @property {import("contracts-js/dist/generated-types/Implementation").FutureTermsResponse} [futureTerms] - * @returns {FutureTerms | undefined} - */ - mapFutureTerms(rawFutureTerms) { - return rawFutureTerms - ? { - price: rawFutureTerms._price.toString(), - limit: rawFutureTerms._limit.toString(), - speed: rawFutureTerms._speed.toString(), - length: rawFutureTerms._length.toString(), - version: rawFutureTerms._version.toString(), - profitTarget: rawFutureTerms._profitTarget.toString(), - } - : undefined; - } - - /** - * - * @param {import("contracts-js/dist/generated-types/Implementation").HistoryentryResponse[]} history - * @returns {ContractHistory[]} - */ - mapHistory(history) { - return history.map((h) => ({ - buyer: h._buyer, - endTime: h._endTime.toString(), - price: h._price.toString(), - speed: h._speed.toString(), - length: h._length.toString(), - purchaseTime: h._purchaseTime.toString(), - isGoodCloseout: h._goodCloseout, - })); - } - - /** - * Maps a stats object to a stats object. - * @param {import("contracts-js/dist/generated-types/Implementation").GetStatsResponse} stats - * @returns {Stats} - */ - mapStats(stats) { - return { - successCount: stats._successCount.toString(), - failCount: stats._failCount.toString(), - }; - } -} - -module.exports = { ContractMapper }; diff --git a/src/ContractsInMemoryIndexer.js b/src/ContractsInMemoryIndexer.js deleted file mode 100644 index eaa3b4d..0000000 --- a/src/ContractsInMemoryIndexer.js +++ /dev/null @@ -1,147 +0,0 @@ -// @ts-check - -const CONTRACT_STATE = { - Available: "0", - Running: "1", -}; - -class ContractsInMemoryIndexer { - /** - * @type {ContractsInMemoryIndexer} - */ - static instance; - - /** - * - * @param {import('./ContractMapper').ContractMapper} mapper - */ - constructor(mapper) { - this.mapper = mapper; - this.contracts = {}; - this.lastSyncedContractBlock = 0; - this.lastSyncedTime = 0; - } - - /** - * - * @param {string} contractId - * @param {RawContract} rawContract - * @param {number} blockNumber - */ - async upsert(contractId, rawContract, blockNumber) { - const id = contractId.toLowerCase(); - const contract = this.mapper.map(id, rawContract); - this.contracts[id] = contract; - this.#setLastSyncedContractBlock(blockNumber); - } - - /** - * @param {string} [walletAddr] - * @returns {Promise} - */ - async getAll(walletAddr) { - const contracts = this.#getAll(); - if (!walletAddr) { - return contracts; - } - return contracts.map((contract) => { - contract.history = this.#filterHistoryByWalletAddr( - contract.history, - walletAddr - ); - return contract; - }); - } - - /** - * - * @param {string} id - * @param {string} [walletAddr] - * @returns {Promise} - */ - async get(id, walletAddr) { - const contract = this.#getOne(id); - if (!contract) return null; - - if (!walletAddr) { - return contract; - } - - contract.history = this.#filterHistoryByWalletAddr( - contract.history, - walletAddr - ); - return contract; - } - - #setLastSyncedContractBlock(blockNumber) { - this.lastSyncedContractBlock = Number(blockNumber); - this.lastSyncedTime = Date.now(); - } - - #filterHistoryByWalletAddr(history, walletAddr) { - return history.filter( - (h) => h.buyer.toLowerCase() === walletAddr.toLowerCase() - ); - } - - /** - * - * @param {ContractHistory[]} history - * @returns - */ - #filterActiveContractFromHistory(history) { - return history.filter((h) => { - return +h.endTime * 1000 < Date.now(); - }); - } - - #getOne(id) { - const contract = this.contracts[id.toLowerCase()]; - if (!contract) { - return null; - } - - const result = JSON.parse(JSON.stringify(contract)); - result.state = this.#getContractState(contract); - result.history = this.#filterActiveContractFromHistory(result.history); - return result; - } - - #getAll() { - const ids = Object.keys(this.contracts); - return ids.map((id) => { - return this.#getOne(id); - }); - } - - /** - * - * @param {Contract} contract - */ - #getContractState(contract) { - const expirationTime = - (+contract.startingBlockTimestamp + +contract.length) * 1000; - if (expirationTime < Date.now()) { - return CONTRACT_STATE.Available; - } - return CONTRACT_STATE.Running; - } - - /** - * - * @param {import('./ContractMapper').ContractMapper} mapper - * @returns - */ - static getInstance(mapper) { - if (!ContractsInMemoryIndexer.instance) { - ContractsInMemoryIndexer.instance = new ContractsInMemoryIndexer(mapper); - } - - return ContractsInMemoryIndexer.instance; - } -} - -module.exports = { - ContractsInMemoryIndexer, -}; diff --git a/src/ContractsLoader.js b/src/ContractsLoader.js deleted file mode 100644 index 1739ffe..0000000 --- a/src/ContractsLoader.js +++ /dev/null @@ -1,68 +0,0 @@ -// @ts-check -const { Implementation } = require("contracts-js"); -const { default: Web3 } = require("web3"); - -class ContractsLoader { - /** - * - * @param {Web3} web3 - * @param {import("contracts-js").CloneFactoryContext} cloneFactory - */ - constructor(web3, cloneFactory) { - this.web3 = web3; - this.cloneFactory = cloneFactory; - } - - /** - * Loads all contracts and stores them in the indexer - * - * @param {(id: string, contract: RawContract, implInstance: import("contracts-js").ImplementationContext, blockNumber: number) => void} onLoad - * @returns {Promise} - */ - async loadAll(onLoad) { - const blockNumber = await this.web3.eth.getBlockNumber(); - const contracts = await this.getContractList(); - return await Promise.all( - contracts.map(async (contractId) => { - const contract = await this.getContract(contractId); - if (typeof onLoad === "function") { - onLoad( - contractId, - contract, - Implementation(this.web3, contractId), - Number(blockNumber) - ); - } - return contract; - }) - ); - } - - /** - * - * @returns {Promise} - */ - async getContractList() { - return await this.cloneFactory.methods.getContractList().call(); - } - - /** - * - * @param {string} contractId - * @returns {Promise} - */ - async getContract(contractId) { - const impl = Implementation(this.web3, contractId); - const data = await impl.methods.getPublicVariablesV2().call(); - - let futureTerms = undefined; - if (data._hasFutureTerms) { - futureTerms = await impl.methods.futureTerms().call(); - } - const history = await impl.methods.getHistory("0", "100").call(); - const stats = await impl.methods.getStats().call(); - return { data, futureTerms, history, stats }; - } -} - -module.exports = { ContractsLoader }; diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 0000000..a19294f --- /dev/null +++ b/src/app.ts @@ -0,0 +1,46 @@ +import { ContractsLoader } from "./services/blockchain.repo"; +import { ContractsInMemoryIndexer } from "./services/cache.repo"; +import { config } from "./config/config"; +import { http } from "viem"; +import { createPublicClient } from "viem"; +import * as indexerJob from "./indexer-job"; +import { startServer } from "./server"; +import { arbitrum, arbitrumSepolia, hardhat } from "viem/chains"; +import { Chain } from "viem"; + +const chains: Record = { + [hardhat.id]: hardhat, + [arbitrumSepolia.id]: arbitrumSepolia, + [arbitrum.id]: arbitrum, +}; + +async function main() { + const client0 = createPublicClient({ + transport: http(config.ETH_NODE_URL, { + retryCount: 10, + retryDelay: 1000, + }), + }); + + const chainId = await client0.getChainId(); + const chain = chains[chainId]; + if (!chain) { + throw new Error(`Chain ${chainId} is not supported`); + } + + const client = createPublicClient({ + transport: http(config.ETH_NODE_URL, { + retryCount: 10, + retryDelay: 1000, + }), + chain, + }); + + const loader = new ContractsLoader(client, config.CLONE_FACTORY_ADDRESS); + const indexer = new ContractsInMemoryIndexer(); + + // TODO: split into multiple phases + await Promise.all([indexerJob.start(config, loader, indexer), startServer(indexer, loader)]); +} + +main(); diff --git a/src/config/index.js b/src/config/config.ts similarity index 56% rename from src/config/index.js rename to src/config/config.ts index 63c2912..a0d457a 100644 --- a/src/config/index.js +++ b/src/config/config.ts @@ -1,4 +1,5 @@ -const envSchema = require("env-schema"); +import envSchema from "env-schema"; +import type { FromSchema, JSONSchema } from "json-schema-to-ts"; const schema = { type: "object", @@ -17,16 +18,20 @@ const schema = { type: "integer", default: 60000, }, + FASTIFY_CLOSE_GRACE_DELAY: { + type: "integer", + default: 500, + }, PORT: { - type: "string", - default: "3000", + type: "integer", + default: 3000, }, }, -}; +} as const satisfies JSONSchema; + +export type Config = FromSchema; -const config = envSchema({ +export const config = envSchema({ schema, dotenv: true, // load .env if it is there, default: false }); - -module.exports = config; diff --git a/src/indexer-job.ts b/src/indexer-job.ts new file mode 100644 index 0000000..702ecbd --- /dev/null +++ b/src/indexer-job.ts @@ -0,0 +1,42 @@ +import { createPublicClient, http, getContract } from "viem"; + +import { abi } from "contracts-js"; + +import { ContractsLoader } from "./services/blockchain.repo"; +import { ContractsInMemoryIndexer } from "./services/cache.repo"; +import { Config } from "./config/config"; +import { startWatchPromise } from "./services/listener"; + +export const start = async ( + config: Config, + loader: ContractsLoader, + indexer: ContractsInMemoryIndexer +) => { + const client = createPublicClient({ + transport: http(config.ETH_NODE_URL, { + retryCount: 10, + retryDelay: 1000, + }), + }); + + console.log("Initial load of contracts"); + const res = await loader.loadAll(); + console.log("Loaded contracts", res.contracts.length); + + for (const contract of res.contracts) { + // fix this upsert function + if (!contract) { + console.log("Contract is undefined", contract); + throw new Error("Contract is undefined"); + } + indexer.upsert(contract, Number(res.blockNumber)); + } + + await startWatchPromise(client, { + initialContractsToWatch: new Set(res.contracts.map((c) => c.id)), + onContractUpdate: async (contractAddr: string, blockNumber: number) => { + const contract = await loader.getContract(contractAddr as `0x${string}`); + indexer.upsert(contract, blockNumber); + }, + }); +}; diff --git a/src/plugins/README.md b/src/plugins/README.md deleted file mode 100644 index 1e61ee5..0000000 --- a/src/plugins/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Plugins Folder - -Plugins define behavior that is common to all the routes in your -application. Authentication, caching, templates, and all the other cross -cutting concerns should be handled by plugins placed in this folder. - -Files in this folder are typically defined through the -[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module, -making them non-encapsulated. They can define decorators and set hooks -that will then be used in the rest of your application. - -Check out: - -* [The hitchhiker's guide to plugins](https://fastify.dev/docs/latest/Guides/Plugins-Guide/) -* [Fastify decorators](https://fastify.dev/docs/latest/Reference/Decorators/). -* [Fastify lifecycle](https://fastify.dev/docs/latest/Reference/Lifecycle/). diff --git a/src/plugins/sensible.js b/src/plugins/sensible.js deleted file mode 100644 index a8d912e..0000000 --- a/src/plugins/sensible.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -const fp = require('fastify-plugin') - -/** - * This plugins adds some utilities to handle http errors - * - * @see https://github.com/fastify/fastify-sensible - */ -module.exports = fp(async function (fastify, opts) { - fastify.register(require('@fastify/sensible'), { - errorHandler: false - }) -}) diff --git a/src/plugins/support.js b/src/plugins/support.js deleted file mode 100644 index b379ecc..0000000 --- a/src/plugins/support.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' - -const fp = require('fastify-plugin') - -// the use of fastify-plugin is required to be able -// to export the decorators to the outer scope - -module.exports = fp(async function (fastify, opts) { - fastify.decorate('someSupport', function () { - return 'hugs' - }) -}) diff --git a/src/routes/README.md b/src/routes/README.md deleted file mode 100644 index fd8d0b2..0000000 --- a/src/routes/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Routes Folder - -Routes define routes within your application. Fastify provides an -easy path to a microservice architecture, in the future you might want -to independently deploy some of those. - -In this folder you should define all the routes that define the endpoints -of your web application. -Each service is a [Fastify -plugin](https://fastify.dev/docs/latest/Reference/Plugins/), it is -encapsulated (it can have its own independent plugins) and it is -typically stored in a file; be careful to group your routes logically, -e.g. all `/users` routes in a `users.js` file. We have added -a `root.js` file for you with a '/' root added. - -If a single file become too large, create a folder and add a `index.js` file there: -this file must be a Fastify plugin, and it will be loaded automatically -by the application. You can now add as many files as you want inside that folder. -In this way you can create complex routes within a single monolith, -and eventually extract them. - -If you need to share functionality between routes, place that -functionality into the `plugins` folder, and share it via -[decorators](https://fastify.dev/docs/latest/Reference/Decorators/). - -If you're a bit confused about using `async/await` to write routes, you would -better take a look at [Promise resolution](https://fastify.dev/docs/latest/Reference/Routes/#promise-resolution) for more details. diff --git a/src/routes/admin/index.js b/src/routes/admin/index.js deleted file mode 100644 index 7084b61..0000000 --- a/src/routes/admin/index.js +++ /dev/null @@ -1,28 +0,0 @@ -"use strict"; - -const Web3 = require("web3").default; -const { CloneFactory } = require("contracts-js"); - -const config = require("../../config"); -const { ContractsInMemoryIndexer } = require("../../ContractsInMemoryIndexer"); -const { ContractsLoader } = require("../../ContractsLoader"); -const { ContractMapper } = require("../../ContractMapper"); - -module.exports = async function (fastify, opts) { - const web3 = new Web3(config.ETH_NODE_URL); - const cloneFactory = CloneFactory(web3, config.CLONE_FACTORY_ADDRESS); - - const indexer = ContractsInMemoryIndexer.getInstance(new ContractMapper()); - const loader = new ContractsLoader(web3, cloneFactory); - - fastify.get("/reloadContracts", async function (request, reply) { - const apiKey = request.query.apiKey; - if (apiKey !== config.ADMIN_API_KEY) { - return fastify.httpErrors.unauthorized(); - } - await loader.loadAll((contractId, contract, _, blockNumber) => { - indexer.upsert(contractId, contract, blockNumber); - }); - return indexer.getAll(); - }); -}; diff --git a/src/routes/contracts/index.js b/src/routes/contracts/index.js deleted file mode 100644 index 17ea021..0000000 --- a/src/routes/contracts/index.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict' - -const { ContractsInMemoryIndexer } = require('../../ContractsInMemoryIndexer'); - -/** - * - * @param {import('fastify').FastifyInstance} fastify - * @param {*} opts - */ -module.exports = async function (fastify, opts) { - const indexer = ContractsInMemoryIndexer.getInstance(); - - fastify.get('/', async function (request, reply) { - const { walletAddr } = request.query; - return indexer.getAll(walletAddr); - }) - - fastify.get('/:id', async function (request, reply) { - const { params, query } = request; - const { id } = params; - const { walletAddr } = query; - - const contract = await indexer.get(id, walletAddr); - if (!contract) { - return fastify.httpErrors.notFound('Contract not found'); - } - return contract; - }) -} diff --git a/src/routes/healthcheck/index.js b/src/routes/healthcheck/index.js deleted file mode 100644 index 6717206..0000000 --- a/src/routes/healthcheck/index.js +++ /dev/null @@ -1,19 +0,0 @@ -"use strict"; - -const { ContractsInMemoryIndexer } = require("../../ContractsInMemoryIndexer"); -const config = require("../../config"); - -module.exports = async function (fastify, opts) { - const indexer = ContractsInMemoryIndexer.getInstance(); - - fastify.get("/", async function (request, reply) { - return { - status: "ok", - version: process.env.npm_package_version, - cloneFactoryAddress: config.CLONE_FACTORY_ADDRESS, - lastSyncedContractBlock: Number(indexer.lastSyncedContractBlock), - lastSyncedTime: Number(indexer.lastSyncedTime), - lastSyncedTimeISO: new Date(indexer.lastSyncedTime).toISOString(), - }; - }); -}; diff --git a/src/routes/root.js b/src/routes/root.js deleted file mode 100644 index 929a987..0000000 --- a/src/routes/root.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict' - -module.exports = async function (fastify, opts) { - fastify.get('/', async function (request, reply) { - return { root: true } - }) -} diff --git a/src/routes/root.ts b/src/routes/root.ts new file mode 100644 index 0000000..b0d8228 --- /dev/null +++ b/src/routes/root.ts @@ -0,0 +1,59 @@ +"use strict"; + +import { FastifyInstance } from "fastify"; +import { ContractsLoader } from "../services/blockchain.repo"; +import { ContractsInMemoryIndexer } from "../services/cache.repo"; +import { Config } from "../config/config"; + +export async function router( + fastify: FastifyInstance, + config: Config, + indexer: ContractsInMemoryIndexer, + loader: ContractsLoader +) { + fastify.get("/", async function () { + return { root: true }; + }); + + fastify.get("/admin/reloadContracts", async function (request) { + const apiKey = request.query.apiKey; + if (apiKey !== config.ADMIN_API_KEY) { + return fastify.httpErrors.unauthorized(); + } + // TODO: stop indexer job and start it again + const all = await loader.loadAll(); + for (const contract of all.contracts) { + indexer.upsert(contract, Number(all.blockNumber)); + } + return indexer.getAll(); + }); + + fastify.get("/contracts", async function (request, reply) { + const { walletAddr } = request.query; + // TODO: add validation + return indexer.getAll(walletAddr); + }); + + fastify.get("/contracts/:id", async function (request, reply) { + const { params, query } = request; + const { id } = params; + const { walletAddr } = query; + + const contract = await indexer.get(id, walletAddr); + if (!contract) { + return fastify.httpErrors.notFound("Contract not found"); + } + return contract; + }); + + fastify.get("/healthcheck", async function (request, reply) { + return { + status: "ok", + version: process.env.npm_package_version, + cloneFactoryAddress: config.CLONE_FACTORY_ADDRESS, + lastSyncedContractBlock: Number(indexer.lastSyncedContractBlock), + lastSyncedTime: Number(indexer.lastSyncedTime), + lastSyncedTimeISO: new Date(indexer.lastSyncedTime).toISOString(), + }; + }); +} diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..c98e545 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,59 @@ +import { config } from "./config/config"; + +import Fastify from "fastify"; +import closeWithGrace from "close-with-grace"; +import AutoLoad from "@fastify/autoload"; +import cors from "@fastify/cors"; +import path from "node:path"; +import { router } from "./routes/root"; +import { ContractsInMemoryIndexer } from "./services/cache.repo"; +import { ContractsLoader } from "./services/blockchain.repo"; +import sensible from "@fastify/sensible"; + +// Register your application as a normal plugin. + +export function startServer(indexer: ContractsInMemoryIndexer, loader: ContractsLoader) { + return new Promise((resolve, reject) => { + const options = { + prefix: "/api", + }; + + const app = Fastify({ + logger: {}, + }); + + app.register(async (instance, opts) => { + console.log(`Running server with config: ${JSON.stringify(config)}`); + + instance.register(sensible); + instance.register(cors, { + origin: "*", + }); + + // This loads all plugins defined in routes + // define your routes in one of these + instance.register(async (instance) => { + router(instance, config, indexer, loader); + }); + }); + + // delay is the number of milliseconds for the graceful close to finish + closeWithGrace( + { delay: config.FASTIFY_CLOSE_GRACE_DELAY }, + async function ({ signal, err, manual }) { + if (err) { + app.log.error(err); + } + await app.close(); + } + ); + + // Start listening. + app.listen({ port: config.PORT }, (err) => { + if (err) { + app.log.error(err); + reject(err); + } + }); + }); +} diff --git a/src/services/blockchain.repo.ts b/src/services/blockchain.repo.ts new file mode 100644 index 0000000..1f92ef0 --- /dev/null +++ b/src/services/blockchain.repo.ts @@ -0,0 +1,132 @@ +import { abi } from "contracts-js"; +import { PublicClient } from "viem"; +import { Contract } from "../types/contracts.js"; +import { mapContract, mapFutureTerms } from "./mapper"; +import { + getCloneFactoryContract, + HistoryEntry, + PublicVariablesV2Entry, + StatsEntry, +} from "./blockchain.types"; + +export class ContractsLoader { + pc: PublicClient; + cloneFactory: ReturnType; + + constructor(pc: PublicClient, cloneFactoryAddr: string) { + this.pc = pc; + this.cloneFactory = getCloneFactoryContract(pc, cloneFactoryAddr); + } + + async loadAll() { + const blockNumber = await this.pc.getBlockNumber(); + const contractIds = await this.cloneFactory.read + .getContractList({ blockNumber }) + .then((res) => res.map((id) => id.toLowerCase() as `0x${string}`)); + + const results = await this.pc.multicall({ + contracts: contractIds.flatMap((id) => [ + { + abi: abi.implementationAbi, + address: id, + functionName: "getPublicVariablesV2", + } as const, + { + abi: abi.implementationAbi, + address: id, + functionName: "getHistory", + args: ["0", "100"], + } as const, + { + abi: abi.implementationAbi, + address: id, + functionName: "getStats", + } as const, + ]), + allowFailure: false, + blockNumber, + }); + + // split results into chunks + const chunks = chunkArray(results, 3) as [PublicVariablesV2Entry, HistoryEntry, StatsEntry][]; + const contractsMap: Record = {}; + + // load future terms for contracts that have them + let indexesToLoadFutureTerms: number[] = []; + let indexesToLoadPrice: number[] = []; + // TODO: reconstruct price for available contracts + + for (let i = 0; i < chunks.length; i++) { + const [publicVariablesV2, history, stats] = chunks[i]; + const contractId = contractIds[i]; + const mapped = mapContract(contractId, publicVariablesV2, undefined, history, stats); + contractsMap[contractId] = mapped; + if (mapped.hasFutureTerms) { + indexesToLoadFutureTerms.push(i); + } + } + + const futureTermsChunks = await this.pc.multicall({ + contracts: indexesToLoadFutureTerms.map( + (i) => + ({ + abi: abi.implementationAbi, + address: contractIds[i], + functionName: "futureTerms", + } as const) + ), + allowFailure: false, + }); + + for (let i = 0; i < futureTermsChunks.length; i++) { + const futureTerms = futureTermsChunks[i]; + const contractId = contractIds[indexesToLoadFutureTerms[i]]; + contractsMap[contractId].futureTerms = mapFutureTerms(futureTerms); + } + + // reconstruct the contracts array by order of contractIds + const contracts = contractIds.map((id) => contractsMap[id]); + return { contracts, blockNumber }; + } + + async getContract(contractId: `0x${string}`): Promise { + const multicall = await this.pc.multicall({ + contracts: [ + { + abi: abi.implementationAbi, + address: contractId, + functionName: "getPublicVariablesV2", + } as const, + { + abi: abi.implementationAbi, + address: contractId, + functionName: "getHistory", + args: [0n, 100n], + } as const, + { + abi: abi.implementationAbi, + address: contractId, + functionName: "getStats", + } as const, + { + abi: abi.implementationAbi, + address: contractId, + functionName: "futureTerms", + } as const, + ], + allowFailure: false, + }); + + const [pub, history, stats, futureTerms] = multicall; + + return mapContract(contractId, pub, futureTerms, history, stats); + } +} + +function chunkArray(array: T[], size: N): T[][] & { length: N } { + const chunks: T[][] = []; + for (let i = 0; i < array.length; i += size) { + chunks.push(array.slice(i, i + size)); + } + return chunks as T[][] & { length: N }; +} diff --git a/src/services/blockchain.types.ts b/src/services/blockchain.types.ts new file mode 100644 index 0000000..da92a7a --- /dev/null +++ b/src/services/blockchain.types.ts @@ -0,0 +1,50 @@ +import { abi } from "contracts-js"; +import { PublicClient } from "viem"; +import { getContract } from "viem"; + +// Using ReturnType applied to the function to alias the type from the blockchain call + +export type PublicVariablesV2Entry = Awaited>; +export type HistoryEntry = Awaited>; +export type StatsEntry = Awaited>; +export type FutureTermsEntry = Awaited>; + +export function getCloneFactoryContract(pc: PublicClient, cloneFactoryAddr: string) { + return getContract({ + address: cloneFactoryAddr as `0x${string}`, + abi: abi.cloneFactoryAbi, + client: pc, + }); +} + +export function getPublicVariablesV2(pc: PublicClient, contractId: string) { + return getContract({ + address: contractId as `0x${string}`, + abi: abi.implementationAbi, + client: pc, + }).read.getPublicVariablesV2(); +} + +export function getHistory(pc: PublicClient, contractId: string) { + return getContract({ + address: contractId as `0x${string}`, + abi: abi.implementationAbi, + client: pc, + }).read.getHistory([0n, 100n]); +} + +export function getStats(pc: PublicClient, contractId: string) { + return getContract({ + address: contractId as `0x${string}`, + abi: abi.implementationAbi, + client: pc, + }).read.getStats(); +} + +export function getFutureTerms(pc: PublicClient, contractId: string) { + return getContract({ + address: contractId as `0x${string}`, + abi: abi.implementationAbi, + client: pc, + }).read.futureTerms(); +} diff --git a/src/services/cache.repo.ts b/src/services/cache.repo.ts new file mode 100644 index 0000000..bd5e091 --- /dev/null +++ b/src/services/cache.repo.ts @@ -0,0 +1,88 @@ +// @ts-check + +import { Contract, CONTRACT_STATE, ContractState, ContractHistory } from "../types/contracts.js"; + +/** + * In-memory indexer(cache) for contracts that keeps track block and time of the last update + */ +export class ContractsInMemoryIndexer { + contracts: Record; + lastSyncedContractBlock: number; + lastSyncedTime: number; + + constructor() { + this.contracts = {}; + this.lastSyncedContractBlock = 0; + this.lastSyncedTime = 0; + } + + async upsert(contract: Contract, blockNumber: number) { + this.contracts[contract.id] = contract; + this.#setLastSyncedContractBlock(blockNumber); + } + + async getAll(filterHistoryByAddr?: string) { + const contracts = this.#getAll(); + if (!filterHistoryByAddr) { + return contracts; + } + return contracts.map((contract) => { + contract.history = this.#filterHistoryByWalletAddr(contract.history, filterHistoryByAddr); + return contract; + }); + } + + async get(id: string, filterHistoryByAddr?: string): Promise { + const contract = this.#getOne(id); + if (!contract) return null; + + if (!filterHistoryByAddr) { + return contract; + } + + contract.history = this.#filterHistoryByWalletAddr(contract.history, filterHistoryByAddr); + return contract; + } + + #setLastSyncedContractBlock(blockNumber: number | string) { + this.lastSyncedContractBlock = Number(blockNumber); + this.lastSyncedTime = Date.now(); + } + + #filterHistoryByWalletAddr(history: ContractHistory[], walletAddr: string) { + return history.filter((h) => h.buyer.toLowerCase() === walletAddr.toLowerCase()); + } + + #filterActiveContractFromHistory(history: ContractHistory[]): ContractHistory[] { + return history.filter((h) => { + return +h.endTime * 1000 < Date.now(); + }); + } + + #getOne(id: string): Contract | null { + const contract = this.contracts[id.toLowerCase()]; + if (!contract) { + return null; + } + + const result = JSON.parse(JSON.stringify(contract)); + result.state = this.#getContractState(contract); + result.history = this.#filterActiveContractFromHistory(result.history); + return result; + } + + #getAll(): Contract[] { + const ids = Object.keys(this.contracts); + return ids.map((id) => { + return this.#getOne(id) as Contract; + }); + } + + #getContractState(contract: Contract): ContractState { + const expirationTime = (+contract.startingBlockTimestamp + +contract.length) * 1000; + if (expirationTime < Date.now()) { + return CONTRACT_STATE.Available; + } + return CONTRACT_STATE.Running; + } +} diff --git a/src/services/listener.ts b/src/services/listener.ts new file mode 100644 index 0000000..ec4f8ca --- /dev/null +++ b/src/services/listener.ts @@ -0,0 +1,90 @@ +import { config } from "../config/config"; +import { parseAbi, PublicClient } from "viem"; + +type StartWatchProps = { + initialContractsToWatch: Set; + onContractUpdate: (contractAddr: string, blockNumber: number) => void; + onError?: (error: Error) => void; + blockNumber?: number; +}; + +export function startWatchPromise(pc: PublicClient, props: StartWatchProps): Promise { + return new Promise((_, reject) => { + const { unwatch } = startWatch(pc, { + ...props, + onError: (err) => { + props.onError?.(err); + unwatch(); + reject(err); + }, + }); + }); +} + +function startWatch(pc: PublicClient, props: StartWatchProps) { + const contractsToWatch = props.initialContractsToWatch; + const addresses = [config.CLONE_FACTORY_ADDRESS, ...contractsToWatch] as `0x${string}`[]; + + const cloneFactoryEvents = [ + "contractCreated", + "clonefactoryContractPurchased", + "contractDeleteUpdated", + "purchaseInfoUpdated", + ]; + const eventsAbi = [ + // Clone Factory Events + "event contractCreated(address indexed _address, string _pubkey)", + "event clonefactoryContractPurchased(address indexed _address, address indexed _validator)", + "event contractDeleteUpdated(address _address, bool _isDeleted)", + "event purchaseInfoUpdated(address indexed _address)", + + // Implementation Events + "event closedEarly(uint8 reason)", + "event fundsClaimed()", + "event destinationUpdated(string newValidatorURL, string newDestURL)", + ]; + + let unwatch: () => void; + + unwatch = pc.watchEvent({ + address: addresses, + events: parseAbi(eventsAbi), + poll: true, + pollingInterval: 1000, + fromBlock: props.blockNumber ? BigInt(props.blockNumber) : undefined, + onLogs: (logs) => { + console.log(`Received logs: ${logs.length}`); + + logs.forEach((log) => { + const { eventName, args, address, blockNumber } = log; + let contractAddress = null; + if (cloneFactoryEvents.includes(eventName)) { + contractAddress = (args as any)._address; + } else { + contractAddress = address; + } + console.log(`Received log for contract: ${contractAddress}`); + + props.onContractUpdate(contractAddress, Number(blockNumber)); + + if (eventName === "contractCreated") { + contractsToWatch.add(contractAddress); + console.log("Got contract created event, restating watch"); + unwatch(); + const newWatch = startWatch(pc, { + ...props, + blockNumber: Number(blockNumber), + initialContractsToWatch: contractsToWatch, + }); + unwatch = newWatch.unwatch; + } + }); + }, + onError: (error) => { + console.error("On Error Callback", error); + props.onError?.(error); + }, + }); + + return { unwatch }; +} diff --git a/src/services/mapper.ts b/src/services/mapper.ts new file mode 100644 index 0000000..4791d7a --- /dev/null +++ b/src/services/mapper.ts @@ -0,0 +1,90 @@ +import { Contract } from "../types/contracts"; +import { FutureTerms, ContractHistory, Stats } from "../types/contracts"; +import { + FutureTermsEntry, + HistoryEntry, + PublicVariablesV2Entry, + StatsEntry, +} from "./blockchain.types"; + +export function mapContract( + address: string, + pub: PublicVariablesV2Entry, + fut: FutureTermsEntry | undefined, + history: HistoryEntry, + stats: StatsEntry +): Contract { + const pubVars = mapPublicVariablesV2(address, pub); + + return { + ...pubVars, + futureTerms: mapFutureTerms(fut), + history: mapHistory(history), + stats: mapStats(stats), + }; +} + +export function mapPublicVariablesV2(addr: string, pub: PublicVariablesV2Entry) { + const [ + state, + terms, + startingBlockTimestamp, + buyer, + seller, + encrValidatorUrl, + isDeleted, + balance, + hasFutureTerms, + ] = pub; + + return { + id: addr.toLowerCase(), + state: state.toString(), + price: terms._price.toString(), + limit: terms._limit.toString(), + speed: terms._speed.toString(), + length: terms._length.toString(), + version: terms._version.toString(), + profitTarget: terms._profitTarget.toString(), + startingBlockTimestamp: startingBlockTimestamp.toString(), + buyer: buyer.toString(), + seller: seller.toString(), + encrValidatorUrl: encrValidatorUrl.toString(), + isDeleted: isDeleted, + balance: balance.toString(), + hasFutureTerms: hasFutureTerms, + }; +} + +export function mapFutureTerms(futureTerms: FutureTermsEntry | undefined): FutureTerms | undefined { + if (!futureTerms) { + return undefined; + } + const [, , speed, length, version, profitTarget] = futureTerms; + return { + speed: speed.toString(), + length: length.toString(), + version: version.toString(), + profitTarget: profitTarget.toString(), + }; +} + +export function mapHistory(history: HistoryEntry): ContractHistory[] { + return history.map((data) => ({ + buyer: data._buyer, + endTime: data._endTime.toString(), + price: data._price.toString(), + speed: data._speed.toString(), + length: data._length.toString(), + purchaseTime: data._purchaseTime.toString(), + isGoodCloseout: data._goodCloseout, + })); +} + +export function mapStats(stats: StatsEntry): Stats { + const [successCount, failCount] = stats; + return { + successCount: successCount.toString(), + failCount: failCount.toString(), + }; +} diff --git a/src/types/contracts.js b/src/types/contracts.js deleted file mode 100644 index ade7b74..0000000 --- a/src/types/contracts.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Represents a contract object from blockchain. - * @typedef {Object} RawContract - * @property {import("contracts-js/dist/generated-types/Implementation").GetPublicVariablesV2Response} data - * @property {import("contracts-js/dist/generated-types/Implementation").FutureTermsResponse} [futureTerms] - * @property {import("contracts-js/dist/generated-types/Implementation").HistoryentryResponse[]} history - * @property {import("contracts-js/dist/generated-types/Implementation").GetStatsResponse} stats - */ - -/** - * Represents a mapped contract object. - * @typedef {Object} Contract - * @property {string} id - * @property {string} state - * @property {string} version - * @property {string} price - * @property {string} limit - * @property {string} speed - * @property {string} length - * @property {string} profitTarget - * @property {string} startingBlockTimestamp - * @property {string} buyer - * @property {string} seller - * @property {string} encrValidatorUrl - * @property {boolean} isDeleted - * @property {string} balance - * @property {boolean} hasFutureTerms - * @property {ContractHistory[]} history - * @property {Stats} stats - * @property {FutureTerms} [futureTerms] - */ - -/** - * Represents a mapped contract stats object. - * @typedef {Object} Stats - * @property {string} successCount - * @property {string} failCount - */ - -/** - * Represents a mapped contract history object. - * @typedef {Object} ContractHistory - * @property {string} buyer - * @property {string} endTime - * @property {string} price - * @property {string} speed - * @property {string} length - * @property {string} purchaseTime - * @property {boolean} isGoodCloseout - */ - -/** - * Represents a mapped future terms object. - * @typedef {Object} FutureTerms - * @property {string} price - * @property {string} limit - * @property {string} speed - * @property {string} length - * @property {string} version - * @property {string} profitTarget - */ diff --git a/src/types/contracts.ts b/src/types/contracts.ts new file mode 100644 index 0000000..e26582b --- /dev/null +++ b/src/types/contracts.ts @@ -0,0 +1,53 @@ +export const CONTRACT_STATE = { + Available: "0", + Running: "1", +} as const; + +export type ContractState = (typeof CONTRACT_STATE)[keyof typeof CONTRACT_STATE]; + +/** Represents an internal contract object.**/ +export type Contract = { + id: string; + state: ContractState; + version: string; + price: string; + limit: string; + speed: string; + length: string; + profitTarget: string; + startingBlockTimestamp: string; + buyer: string; + seller: string; + encrValidatorUrl: string; + isDeleted: boolean; + balance: string; + hasFutureTerms: boolean; + history: ContractHistory[]; + stats: Stats; + futureTerms?: FutureTerms; +}; + +/** Represents an internal stats object.**/ +export type Stats = { + successCount: string; + failCount: string; +}; + +/** Represents an internal contract history object.**/ +export type ContractHistory = { + buyer: string; + endTime: string; + price: string; + speed: string; + length: string; + purchaseTime: string; + isGoodCloseout: boolean; +}; + +/** Represents an internal future terms object.**/ +export type FutureTerms = { + speed: string; + length: string; + version: string; + profitTarget: string; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..b482627 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,114 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "libReplacement": true, /* Enable lib replacement. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "CommonJS" /* Specify what module code is generated. */, + "rootDir": "./src" /* Specify the root folder within your source files. */, + "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */, + "declaration": false /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "noEmit": true /* Disable emitting files from a compilation. */, + // "rewriteRelativeImportExtensions": true /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */, + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": false /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */, + "checkJs": false /* Enable error reporting in type-checked JavaScript files. */, + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */ + // "erasableSyntaxOnly": true, /* Do not allow runtime constructs that are not part of ECMAScript. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +} From 02a511dc7cf4b021214104844ab0517003ec9305 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Fri, 25 Apr 2025 16:06:03 +0200 Subject: [PATCH 10/35] added price calculation --- src/app.ts | 11 ++- src/config/config.ts | 5 +- src/indexer-job.ts | 35 ++++----- src/routes/root.ts | 10 +-- src/server.ts | 10 ++- src/services/blockchain.repo.ts | 6 +- src/services/cache.repo.ts | 74 ++++--------------- src/services/contract.service.ts | 69 +++++++++++++++++ src/services/mapper.ts | 6 +- src/services/price-calculator.ts | 46 ++++++++++++ .../{contracts.ts => hashrate-contract.ts} | 16 ++-- 11 files changed, 184 insertions(+), 104 deletions(-) create mode 100644 src/services/contract.service.ts create mode 100644 src/services/price-calculator.ts rename src/types/{contracts.ts => hashrate-contract.ts} (97%) diff --git a/src/app.ts b/src/app.ts index a19294f..859e5eb 100644 --- a/src/app.ts +++ b/src/app.ts @@ -7,6 +7,8 @@ import * as indexerJob from "./indexer-job"; import { startServer } from "./server"; import { arbitrum, arbitrumSepolia, hardhat } from "viem/chains"; import { Chain } from "viem"; +import { ContractService } from "./services/contract.service"; +import { PriceCalculator } from "./services/price-calculator"; const chains: Record = { [hardhat.id]: hardhat, @@ -38,9 +40,16 @@ async function main() { const loader = new ContractsLoader(client, config.CLONE_FACTORY_ADDRESS); const indexer = new ContractsInMemoryIndexer(); + const service = new ContractService( + indexer, + new PriceCalculator(client, config.HASHRATE_ORACLE_ADDRESS as `0x${string}`) + ); // TODO: split into multiple phases - await Promise.all([indexerJob.start(config, loader, indexer), startServer(indexer, loader)]); + await Promise.all([ + indexerJob.start(client, loader, indexer), + startServer(indexer, loader, service), + ]); } main(); diff --git a/src/config/config.ts b/src/config/config.ts index a0d457a..faca74c 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -3,7 +3,7 @@ import type { FromSchema, JSONSchema } from "json-schema-to-ts"; const schema = { type: "object", - required: ["ETH_NODE_URL", "CLONE_FACTORY_ADDRESS", "ADMIN_API_KEY"], + required: ["ETH_NODE_URL", "CLONE_FACTORY_ADDRESS", "ADMIN_API_KEY", "HASHRATE_ORACLE_ADDRESS"], properties: { ADMIN_API_KEY: { type: "string", @@ -14,6 +14,9 @@ const schema = { ETH_NODE_URL: { type: "string", }, + HASHRATE_ORACLE_ADDRESS: { + type: "string", + }, FASTIFY_PLUGIN_TIMEOUT: { type: "integer", default: 60000, diff --git a/src/indexer-job.ts b/src/indexer-job.ts index 702ecbd..cfdec44 100644 --- a/src/indexer-job.ts +++ b/src/indexer-job.ts @@ -1,42 +1,37 @@ -import { createPublicClient, http, getContract } from "viem"; - -import { abi } from "contracts-js"; - +import { PublicClient } from "viem"; import { ContractsLoader } from "./services/blockchain.repo"; import { ContractsInMemoryIndexer } from "./services/cache.repo"; -import { Config } from "./config/config"; import { startWatchPromise } from "./services/listener"; +import { HashrateContract } from "./types/hashrate-contract"; export const start = async ( - config: Config, + client: PublicClient, loader: ContractsLoader, indexer: ContractsInMemoryIndexer ) => { - const client = createPublicClient({ - transport: http(config.ETH_NODE_URL, { - retryCount: 10, - retryDelay: 1000, - }), - }); - console.log("Initial load of contracts"); + const res = await loader.loadAll(); console.log("Loaded contracts", res.contracts.length); for (const contract of res.contracts) { - // fix this upsert function - if (!contract) { - console.log("Contract is undefined", contract); - throw new Error("Contract is undefined"); - } - indexer.upsert(contract, Number(res.blockNumber)); + await updateContract(contract, Number(res.blockNumber), indexer); } await startWatchPromise(client, { initialContractsToWatch: new Set(res.contracts.map((c) => c.id)), onContractUpdate: async (contractAddr: string, blockNumber: number) => { const contract = await loader.getContract(contractAddr as `0x${string}`); - indexer.upsert(contract, blockNumber); + await updateContract(contract, blockNumber, indexer); }, }); }; + +async function updateContract( + contract: HashrateContract, + blockNumber: number, + indexer: ContractsInMemoryIndexer +) { + indexer.upsert(contract, blockNumber); + console.log("Updated contract in cache", contract.id); +} diff --git a/src/routes/root.ts b/src/routes/root.ts index b0d8228..1cc15e4 100644 --- a/src/routes/root.ts +++ b/src/routes/root.ts @@ -1,13 +1,13 @@ -"use strict"; - import { FastifyInstance } from "fastify"; import { ContractsLoader } from "../services/blockchain.repo"; -import { ContractsInMemoryIndexer } from "../services/cache.repo"; import { Config } from "../config/config"; +import { ContractService } from "../services/contract.service"; +import { ContractsInMemoryIndexer } from "../services/cache.repo"; export async function router( fastify: FastifyInstance, config: Config, + service: ContractService, indexer: ContractsInMemoryIndexer, loader: ContractsLoader ) { @@ -31,7 +31,7 @@ export async function router( fastify.get("/contracts", async function (request, reply) { const { walletAddr } = request.query; // TODO: add validation - return indexer.getAll(walletAddr); + return service.getAll(walletAddr); }); fastify.get("/contracts/:id", async function (request, reply) { @@ -39,7 +39,7 @@ export async function router( const { id } = params; const { walletAddr } = query; - const contract = await indexer.get(id, walletAddr); + const contract = await service.get(id, walletAddr); if (!contract) { return fastify.httpErrors.notFound("Contract not found"); } diff --git a/src/server.ts b/src/server.ts index c98e545..7d9dfb1 100644 --- a/src/server.ts +++ b/src/server.ts @@ -9,10 +9,14 @@ import { router } from "./routes/root"; import { ContractsInMemoryIndexer } from "./services/cache.repo"; import { ContractsLoader } from "./services/blockchain.repo"; import sensible from "@fastify/sensible"; - +import { ContractService } from "./services/contract.service"; // Register your application as a normal plugin. -export function startServer(indexer: ContractsInMemoryIndexer, loader: ContractsLoader) { +export function startServer( + indexer: ContractsInMemoryIndexer, + loader: ContractsLoader, + service: ContractService +) { return new Promise((resolve, reject) => { const options = { prefix: "/api", @@ -33,7 +37,7 @@ export function startServer(indexer: ContractsInMemoryIndexer, loader: Contracts // This loads all plugins defined in routes // define your routes in one of these instance.register(async (instance) => { - router(instance, config, indexer, loader); + router(instance, config, service, indexer, loader); }); }); diff --git a/src/services/blockchain.repo.ts b/src/services/blockchain.repo.ts index 1f92ef0..fb69031 100644 --- a/src/services/blockchain.repo.ts +++ b/src/services/blockchain.repo.ts @@ -1,6 +1,6 @@ import { abi } from "contracts-js"; import { PublicClient } from "viem"; -import { Contract } from "../types/contracts.js"; +import { HashrateContract } from "../types/hashrate-contract.js"; import { mapContract, mapFutureTerms } from "./mapper"; import { getCloneFactoryContract, @@ -49,7 +49,7 @@ export class ContractsLoader { // split results into chunks const chunks = chunkArray(results, 3) as [PublicVariablesV2Entry, HistoryEntry, StatsEntry][]; - const contractsMap: Record = {}; + const contractsMap: Record = {}; // load future terms for contracts that have them let indexesToLoadFutureTerms: number[] = []; @@ -89,7 +89,7 @@ export class ContractsLoader { return { contracts, blockNumber }; } - async getContract(contractId: `0x${string}`): Promise { + async getContract(contractId: `0x${string}`): Promise { const multicall = await this.pc.multicall({ contracts: [ { diff --git a/src/services/cache.repo.ts b/src/services/cache.repo.ts index bd5e091..802a3cd 100644 --- a/src/services/cache.repo.ts +++ b/src/services/cache.repo.ts @@ -1,12 +1,10 @@ -// @ts-check - -import { Contract, CONTRACT_STATE, ContractState, ContractHistory } from "../types/contracts.js"; +import { HashrateContract } from "../types/hashrate-contract.js"; /** * In-memory indexer(cache) for contracts that keeps track block and time of the last update */ export class ContractsInMemoryIndexer { - contracts: Record; + contracts: Record; lastSyncedContractBlock: number; lastSyncedTime: number; @@ -16,73 +14,29 @@ export class ContractsInMemoryIndexer { this.lastSyncedTime = 0; } - async upsert(contract: Contract, blockNumber: number) { - this.contracts[contract.id] = contract; - this.#setLastSyncedContractBlock(blockNumber); - } - - async getAll(filterHistoryByAddr?: string) { - const contracts = this.#getAll(); - if (!filterHistoryByAddr) { - return contracts; - } - return contracts.map((contract) => { - contract.history = this.#filterHistoryByWalletAddr(contract.history, filterHistoryByAddr); - return contract; - }); - } - - async get(id: string, filterHistoryByAddr?: string): Promise { - const contract = this.#getOne(id); - if (!contract) return null; - - if (!filterHistoryByAddr) { - return contract; - } - - contract.history = this.#filterHistoryByWalletAddr(contract.history, filterHistoryByAddr); - return contract; - } - - #setLastSyncedContractBlock(blockNumber: number | string) { - this.lastSyncedContractBlock = Number(blockNumber); - this.lastSyncedTime = Date.now(); - } - - #filterHistoryByWalletAddr(history: ContractHistory[], walletAddr: string) { - return history.filter((h) => h.buyer.toLowerCase() === walletAddr.toLowerCase()); - } - - #filterActiveContractFromHistory(history: ContractHistory[]): ContractHistory[] { - return history.filter((h) => { - return +h.endTime * 1000 < Date.now(); - }); - } - - #getOne(id: string): Contract | null { + get(id: string): HashrateContract | null { const contract = this.contracts[id.toLowerCase()]; if (!contract) { return null; } - const result = JSON.parse(JSON.stringify(contract)); - result.state = this.#getContractState(contract); - result.history = this.#filterActiveContractFromHistory(result.history); - return result; + return contract; } - #getAll(): Contract[] { + getAll(): HashrateContract[] { const ids = Object.keys(this.contracts); return ids.map((id) => { - return this.#getOne(id) as Contract; + return this.get(id)!; }); } - #getContractState(contract: Contract): ContractState { - const expirationTime = (+contract.startingBlockTimestamp + +contract.length) * 1000; - if (expirationTime < Date.now()) { - return CONTRACT_STATE.Available; - } - return CONTRACT_STATE.Running; + upsert(contract: HashrateContract, blockNumber: number) { + this.contracts[contract.id] = contract; + this.#setLastSyncedContractBlock(blockNumber); + } + + #setLastSyncedContractBlock(blockNumber: number | string) { + this.lastSyncedContractBlock = Number(blockNumber); + this.lastSyncedTime = Date.now(); } } diff --git a/src/services/contract.service.ts b/src/services/contract.service.ts new file mode 100644 index 0000000..7b8dd5b --- /dev/null +++ b/src/services/contract.service.ts @@ -0,0 +1,69 @@ +import { + HashrateContract, + CONTRACT_STATE, + ContractHistory, + ContractState, +} from "../types/hashrate-contract"; +import { ContractsInMemoryIndexer } from "./cache.repo"; +import { PriceCalculator } from "./price-calculator"; + +/** Service for managing hashrate contracts. Adds price calculation and optional filtering history by wallet address */ +export class ContractService { + constructor( + private readonly indexer: ContractsInMemoryIndexer, + private readonly priceCalculator: PriceCalculator + ) {} + + async getAll(filterHistoryByAddr?: string): Promise { + const contracts = this.indexer.getAll(); + await Promise.all(contracts.map((c) => this.#adjustContract(c, filterHistoryByAddr))); + return contracts; + } + + async get(id: string, filterHistoryByAddr?: string): Promise { + const contract = this.indexer.get(id); + if (!contract) { + return null; + } + + await this.#adjustContract(contract, filterHistoryByAddr); + return contract; + } + + async #adjustContract(contract: HashrateContract, filterHistoryByAddr?: string) { + contract.price = await this.#calculatePrice(contract).then((price) => price.toString()); + contract.state = this.#getContractState(contract); + + if (filterHistoryByAddr) { + contract.history = this.#filterHistoryByWalletAddr(contract.history, filterHistoryByAddr); + } + contract.history = this.#filterActiveContractFromHistory(contract.history); + } + + async #calculatePrice(contract: HashrateContract) { + const totalHashrateInTH = BigInt(contract.speed) * BigInt(contract.length); + const price = await this.priceCalculator.calculatePrice( + totalHashrateInTH, + BigInt(contract.profitTarget) + ); + return price; + } + + #filterHistoryByWalletAddr(history: ContractHistory[], walletAddr: string) { + return history.filter((h) => h.buyer.toLowerCase() === walletAddr.toLowerCase()); + } + + #filterActiveContractFromHistory(history: ContractHistory[]): ContractHistory[] { + return history.filter((h) => { + return Number(h.endTime) * 1000 < Date.now(); + }); + } + + #getContractState(contract: HashrateContract): ContractState { + const expirationTime = (+contract.startingBlockTimestamp + +contract.length) * 1000; + if (expirationTime < Date.now()) { + return CONTRACT_STATE.Available; + } + return CONTRACT_STATE.Running; + } +} diff --git a/src/services/mapper.ts b/src/services/mapper.ts index 4791d7a..d04ae33 100644 --- a/src/services/mapper.ts +++ b/src/services/mapper.ts @@ -1,5 +1,5 @@ -import { Contract } from "../types/contracts"; -import { FutureTerms, ContractHistory, Stats } from "../types/contracts"; +import { HashrateContract } from "../types/hashrate-contract"; +import { FutureTerms, ContractHistory, Stats } from "../types/hashrate-contract"; import { FutureTermsEntry, HistoryEntry, @@ -13,7 +13,7 @@ export function mapContract( fut: FutureTermsEntry | undefined, history: HistoryEntry, stats: StatsEntry -): Contract { +): HashrateContract { const pubVars = mapPublicVariablesV2(address, pub); return { diff --git a/src/services/price-calculator.ts b/src/services/price-calculator.ts new file mode 100644 index 0000000..eff7e05 --- /dev/null +++ b/src/services/price-calculator.ts @@ -0,0 +1,46 @@ +import { hashrateOracleAbi } from "contracts-js/dist/abi/abi"; +import viem, { PublicClient } from "viem"; + +export class PriceCalculator { + private pricePerTHInToken: bigint | null; + private priceBlockNumber: number | null; + private oracle: ReturnType; + private priceExpirationTime = new Date(0); + private ttl = 60 * 1000; // 1 minute + + constructor(client: PublicClient, hashrateOracleAddr: `0x${string}`) { + this.oracle = getHashrateOracleContract(client, hashrateOracleAddr); + this.pricePerTHInToken = null; + this.priceBlockNumber = null; + } + + async calculatePrice(totalHashrateInTH: bigint, profitTargetPercent: bigint) { + const pricePerTHinTokens = await this.getPricePerTHInTokenCached(); + const priceInTokens = pricePerTHinTokens * totalHashrateInTH; + const priceWithProfit = + priceInTokens + (priceInTokens * BigInt(profitTargetPercent)) / BigInt(100); + return priceWithProfit; + } + + private async getPricePerTHInTokenCached(): Promise { + if (this.priceExpirationTime > new Date() && this.pricePerTHInToken !== null) { + return this.pricePerTHInToken; + } + this.pricePerTHInToken = await this.getPricePerTHInToken(); + this.priceExpirationTime = new Date(Date.now() + this.ttl); + return this.pricePerTHInToken; + } + + private async getPricePerTHInToken() { + const price = await this.oracle.read.getRewardPerTHinToken(); + return price; + } +} + +function getHashrateOracleContract(client: PublicClient, hashrateOracleAddr: `0x${string}`) { + return viem.getContract({ + address: hashrateOracleAddr, + abi: hashrateOracleAbi, + client: client, + }); +} diff --git a/src/types/contracts.ts b/src/types/hashrate-contract.ts similarity index 97% rename from src/types/contracts.ts rename to src/types/hashrate-contract.ts index e26582b..3e6c70d 100644 --- a/src/types/contracts.ts +++ b/src/types/hashrate-contract.ts @@ -1,12 +1,5 @@ -export const CONTRACT_STATE = { - Available: "0", - Running: "1", -} as const; - -export type ContractState = (typeof CONTRACT_STATE)[keyof typeof CONTRACT_STATE]; - /** Represents an internal contract object.**/ -export type Contract = { +export type HashrateContract = { id: string; state: ContractState; version: string; @@ -51,3 +44,10 @@ export type FutureTerms = { version: string; profitTarget: string; }; + +export const CONTRACT_STATE = { + Available: "0", + Running: "1", +} as const; + +export type ContractState = (typeof CONTRACT_STATE)[keyof typeof CONTRACT_STATE]; From 0eea884dd64a1390f2f5af26d76978272ed48463 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Mon, 28 Apr 2025 17:21:59 +0200 Subject: [PATCH 11/35] feat: add price and fees --- .env.example | 1 + .env.local | 9 + Dockerfile | 23 +- package-lock.json | 2450 +++++++----------------------- package.json | 12 +- src/app.ts | 36 +- src/config/config.ts | 40 - src/config/env.ts | 20 + src/indexer-job.ts | 18 +- src/routes/root.ts | 92 +- src/server.ts | 103 +- src/services/contract.service.ts | 14 +- src/services/listener.ts | 12 +- src/services/mapper.ts | 4 +- src/services/price-calculator.ts | 57 +- src/types/hashrate-contract.ts | 7 +- 16 files changed, 787 insertions(+), 2111 deletions(-) create mode 100644 .env.local delete mode 100644 src/config/config.ts create mode 100644 src/config/env.ts diff --git a/.env.example b/.env.example index 210f55b..7291935 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,5 @@ CLONE_FACTORY_ADDRESS=0x15437978300786aDe37f61e02Be1C061e51353D3 ETH_NODE_URL=https://arb-mainnet.g.alchemy.com/v2/{API_KEY} FASTIFY_ADDRESS=0.0.0.0 FASTIFY_PLUGIN_TIMEOUT=60000 +HASHRATE_ORACLE_ADDRESS=0xdc64a140aa3e981100a9beca4e685f962f0cf6c9 PORT=3000 \ No newline at end of file diff --git a/.env.local b/.env.local new file mode 100644 index 0000000..dc2ef5e --- /dev/null +++ b/.env.local @@ -0,0 +1,9 @@ +# for local env with hardhat +ADMIN_API_KEY=1234 +CLONE_FACTORY_ADDRESS=0x610178da211fef7d417bc0e6fed39f05609ad788 +ETH_NODE_URL=http://localhost:8545 +FASTIFY_ADDRESS=0.0.0.0 +FASTIFY_PLUGIN_TIMEOUT=60000 +HASHRATE_ORACLE_ADDRESS=0xdc64a140aa3e981100a9beca4e685f962f0cf6c9 +MULTICALL_ADDRESS=0x68b1d87f95878fe05b998f19b66f4baba5de1aed +PORT=3000 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 6bbea42..e56bcdf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,16 +4,15 @@ WORKDIR '/app' RUN apk add git +# Install dependencies COPY ./package*.json ./ - RUN npm ci - COPY . . -# Build TypeScript +# Build RUN npm run build -# Create production node_modules +# Remove dev dependencies after build RUN npm prune --production # Production stage @@ -25,20 +24,6 @@ COPY --from=builder /app/dist ./dist COPY --from=builder /app/package*.json ./ COPY --from=builder /app/node_modules ./node_modules -# keep alphabetically sorted -ARG ADMIN_API_KEY -ENV ADMIN_API_KEY=$ADMIN_API_KEY -ARG CLONE_FACTORY_ADDRESS -ENV CLONE_FACTORY_ADDRESS=$CLONE_FACTORY_ADDRESS -ARG ETH_NODE_URL -ENV ETH_NODE_URL=$ETH_NODE_URL -ARG FASTIFY_PLUGIN_TIMEOUT -ENV FASTIFY_PLUGIN_TIMEOUT=$FASTIFY_PLUGIN_TIMEOUT -ARG PORT -ENV PORT=$PORT - -ENV FASTIFY_ADDRESS=0.0.0.0 - EXPOSE ${PORT} -CMD node dist/app.js \ No newline at end of file +CMD ["node", "dist/app.js"] \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 63a74ad..d8b6c36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,21 +9,19 @@ "version": "1.1.0", "license": "MIT", "dependencies": { - "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", "@fastify/sensible": "^5.0.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.0", + "@fastify/type-provider-typebox": "^4.1.0", + "@sinclair/typebox": "^0.33.22", + "close-with-grace": "^2.2.0", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.2", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", - "fastify-cli": "^6.1.1", - "fastify-plugin": "^4.0.0", - "viem": "^2.7.22", - "web3": "^4.5.0" + "viem": "^2.7.22" }, "devDependencies": { "@types/node": "^22.14.1", - "json-schema-to-ts": "^3.1.1", "pino-pretty": "^13.0.0", "tsx": "^4.19.3", "typescript": "^5.8.3" @@ -37,19 +35,6 @@ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", @@ -475,21 +460,10 @@ "node": ">=18" } }, - "node_modules/@ethereumjs/rlp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", - "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", - "bin": { - "rlp": "bin/rlp" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.8.0.tgz", + "integrity": "sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==", "funding": [ { "type": "individual", @@ -500,22 +474,23 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz", + "integrity": "sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==", "funding": [ { "type": "individual", @@ -526,20 +501,21 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/networks": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/web": "^5.8.0" } }, "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz", + "integrity": "sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==", "funding": [ { "type": "individual", @@ -550,18 +526,19 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0" } }, "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.8.0.tgz", + "integrity": "sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==", "funding": [ { "type": "individual", @@ -572,18 +549,19 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/rlp": "^5.8.0" } }, "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.8.0.tgz", + "integrity": "sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==", "funding": [ { "type": "individual", @@ -594,14 +572,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0" + "@ethersproject/bytes": "^5.8.0" } }, "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.8.0.tgz", + "integrity": "sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==", "funding": [ { "type": "individual", @@ -612,15 +591,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/properties": "^5.8.0" } }, "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.8.0.tgz", + "integrity": "sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==", "funding": [ { "type": "individual", @@ -631,16 +611,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", "bn.js": "^5.2.1" } }, "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", + "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==", "funding": [ { "type": "individual", @@ -651,14 +632,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.7.0" + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.8.0.tgz", + "integrity": "sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==", "funding": [ { "type": "individual", @@ -669,14 +651,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0" } }, "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.8.0.tgz", + "integrity": "sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==", "funding": [ { "type": "individual", @@ -687,23 +670,24 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" + "@ethersproject/abi": "^5.8.0", + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/transactions": "^5.8.0" } }, "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.8.0.tgz", + "integrity": "sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==", "funding": [ { "type": "individual", @@ -714,22 +698,23 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.8.0.tgz", + "integrity": "sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==", "funding": [ { "type": "individual", @@ -740,25 +725,26 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/basex": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/pbkdf2": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/wordlists": "^5.8.0" } }, "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz", + "integrity": "sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==", "funding": [ { "type": "individual", @@ -769,18 +755,19 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hdnode": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/pbkdf2": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", "aes-js": "3.0.0", "scrypt-js": "3.0.1" } @@ -788,12 +775,13 @@ "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "license": "MIT" }, "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz", + "integrity": "sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==", "funding": [ { "type": "individual", @@ -804,15 +792,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", "js-sha3": "0.8.0" } }, "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", + "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==", "funding": [ { "type": "individual", @@ -822,12 +811,13 @@ "type": "individual", "url": "https://www.buymeacoffee.com/ricmoo" } - ] + ], + "license": "MIT" }, "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.8.0.tgz", + "integrity": "sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==", "funding": [ { "type": "individual", @@ -838,14 +828,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.7.0" + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz", + "integrity": "sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==", "funding": [ { "type": "individual", @@ -856,15 +847,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/sha2": "^5.8.0" } }, "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.8.0.tgz", + "integrity": "sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==", "funding": [ { "type": "individual", @@ -875,14 +867,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.7.0" + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.8.0.tgz", + "integrity": "sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==", "funding": [ { "type": "individual", @@ -893,39 +886,41 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/base64": "^5.8.0", + "@ethersproject/basex": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/networks": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/rlp": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/web": "^5.8.0", "bech32": "1.1.4", - "ws": "7.4.6" + "ws": "8.18.0" } }, "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", "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": { @@ -937,9 +932,9 @@ } }, "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.8.0.tgz", + "integrity": "sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==", "funding": [ { "type": "individual", @@ -950,15 +945,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.8.0.tgz", + "integrity": "sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==", "funding": [ { "type": "individual", @@ -969,15 +965,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.8.0.tgz", + "integrity": "sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==", "funding": [ { "type": "individual", @@ -988,16 +985,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", "hash.js": "1.1.7" } }, "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.8.0.tgz", + "integrity": "sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==", "funding": [ { "type": "individual", @@ -1008,19 +1006,20 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", "bn.js": "^5.2.1", - "elliptic": "6.5.4", + "elliptic": "6.6.1", "hash.js": "1.1.7" } }, "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.8.0.tgz", + "integrity": "sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==", "funding": [ { "type": "individual", @@ -1031,19 +1030,20 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.8.0.tgz", + "integrity": "sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==", "funding": [ { "type": "individual", @@ -1054,16 +1054,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.8.0.tgz", + "integrity": "sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==", "funding": [ { "type": "individual", @@ -1074,22 +1075,23 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/rlp": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0" } }, "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.8.0.tgz", + "integrity": "sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==", "funding": [ { "type": "individual", @@ -1100,16 +1102,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.8.0.tgz", + "integrity": "sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==", "funding": [ { "type": "individual", @@ -1120,28 +1123,29 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/hdnode": "^5.8.0", + "@ethersproject/json-wallets": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/wordlists": "^5.8.0" } }, "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.8.0.tgz", + "integrity": "sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==", "funding": [ { "type": "individual", @@ -1152,18 +1156,19 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.8.0.tgz", + "integrity": "sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==", "funding": [ { "type": "individual", @@ -1174,12 +1179,13 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@fastify/ajv-compiler": { @@ -1197,11 +1203,6 @@ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==" }, - "node_modules/@fastify/autoload": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/@fastify/autoload/-/autoload-5.10.0.tgz", - "integrity": "sha512-4A6s86qMbjcpWHmJL7cErtjIxOPuW8c67DLiuO8HoJQxuK97vaptoUnK5BTOwRg1ntYqfc3tjwerTTo5NQ3fEQ==" - }, "node_modules/@fastify/cors": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz", @@ -1211,21 +1212,6 @@ "mnemonist": "0.39.6" } }, - "node_modules/@fastify/deepmerge": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@fastify/deepmerge/-/deepmerge-2.0.1.tgz", - "integrity": "sha512-hx+wJQr9Ph1hY/dyzY0SxqjumMyqZDlIF6oe71dpRKDHUg7dFQfjG94qqwQ274XRjmUrwKiYadex8XplNHx3CA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] - }, "node_modules/@fastify/error": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", @@ -1261,6 +1247,15 @@ "vary": "^1.1.2" } }, + "node_modules/@fastify/type-provider-typebox": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@fastify/type-provider-typebox/-/type-provider-typebox-4.1.0.tgz", + "integrity": "sha512-mXNBaBEoS6Yf4/O2ujNhu9yEZwvBC7niqRESsiftE9NP1hV6ZdV3ZsFbPf1S520BK3rTZ0F28zr+sMdIXNJlfw==", + "license": "MIT", + "peerDependencies": { + "@sinclair/typebox": ">=0.26 <=0.33" + } + }, "node_modules/@lukeed/ms": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", @@ -1371,10 +1366,17 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@sinclair/typebox": { + "version": "0.33.22", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.33.22.tgz", + "integrity": "sha512-auUj4k+f4pyrIVf4GW5UKquSZFHJWri06QgARy9C0t9ZTjJLIuNIrr1yl9bWcJWJ1Gz1vOvYN1D+QPaIlNMVkQ==", + "license": "MIT" + }, "node_modules/@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -1388,14 +1390,6 @@ "undici-types": "~6.21.0" } }, - "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/abitype": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.7.tgz", @@ -1416,18 +1410,6 @@ } } }, - "node_modules/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==", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/abstract-logging": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", @@ -1473,6 +1455,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -1481,6 +1464,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -1491,22 +1475,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", "engines": { "node": ">= 4.0.0" } @@ -1519,20 +1492,6 @@ "node": ">=8.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/avvio": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.4.0.tgz", @@ -1542,202 +1501,62 @@ "fastq": "^1.17.1" } }, - "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==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" }, "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", + "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", + "license": "MIT", "engines": { "node": "*" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "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/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", + "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", + "license": "MIT" }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/bufferutil": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", + "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", + "hasInstallScript": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "node-gyp-build": "^4.3.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6.14.2" } }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, "node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -1745,14 +1564,16 @@ } }, "node_modules/close-with-grace": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/close-with-grace/-/close-with-grace-1.3.0.tgz", - "integrity": "sha512-lvm0rmLIR5bNz4CRKW6YvCfn9Wg5Wb9A8PJ3Bb+hjyikgC1RO1W3J4z9rBXQYw97mAte7dNSQI8BmUsxdlXQyw==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/close-with-grace/-/close-with-grace-2.2.0.tgz", + "integrity": "sha512-OdcFxnxTm/AMLPHA4Aq3J1BLpkojXP7I4G5QBQLN5TT55ED/rk04rAoDbtfNnfZ988kGXPxh1bdRLeIU9bz/lA==", + "license": "MIT" }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -1763,34 +1584,29 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "license": "MIT", "engines": { "node": ">=0.1.90" } }, - "node_modules/commist": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", - "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==" - }, "node_modules/contracts-js": { - "version": "2.0.0", - "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#c08dbe59e88b724a9724b2306e1a3a93374f9453", + "version": "2.0.2", + "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#c4a273eb36ee6e9e381ed28329a8181104281b51", "dependencies": { "ethereum-abi-types-generator": "^1.3.4" - }, - "peerDependencies": { - "web3": "1.x" } }, "node_modules/cookie": { @@ -1801,29 +1617,11 @@ "node": ">= 0.6" } }, - "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==", - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cross-fetch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", - "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, "engines": { "node": "*" } @@ -1832,26 +1630,11 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1879,23 +1662,11 @@ "node": ">=12" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -1907,19 +1678,22 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==" + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "dependencies": { "once": "^1.4.0" } @@ -1934,33 +1708,6 @@ "dotenv-expand": "^10.0.0" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/esbuild": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", @@ -2006,6 +1753,7 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/ethereum-abi-types-generator/-/ethereum-abi-types-generator-1.3.4.tgz", "integrity": "sha512-5O775BQ9ZkLEJfX7uWkCt8kzt3HcLL/UVp8s6D4wjh6TWW5n1+xjR6jXUXNpCtZSr+gPqj2r2U6sUQ8yZ1+Odw==", + "license": "MIT", "dependencies": { "@types/bn.js": "^4.11.6", "bignumber.js": "^9.0.0", @@ -2025,25 +1773,44 @@ "node_modules/ethereum-abi-types-generator/node_modules/aes-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "license": "MIT" }, "node_modules/ethereum-abi-types-generator/node_modules/bn.js": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", - "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==" + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", + "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", + "license": "MIT" }, "node_modules/ethereum-abi-types-generator/node_modules/dotenv": { "version": "8.6.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "license": "BSD-2-Clause", "engines": { "node": ">=10" } }, - "node_modules/ethereum-abi-types-generator/node_modules/ethers": { - "version": "4.0.49", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", - "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", + "node_modules/ethereum-abi-types-generator/node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/ethereum-abi-types-generator/node_modules/ethers": { + "version": "4.0.49", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", + "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", + "license": "MIT", "dependencies": { "aes-js": "3.0.0", "bn.js": "^4.11.9", @@ -2060,6 +1827,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.0" @@ -2068,83 +1836,26 @@ "node_modules/ethereum-abi-types-generator/node_modules/js-sha3": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==" + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "license": "MIT" }, "node_modules/ethereum-abi-types-generator/node_modules/scrypt-js": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==" + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", + "license": "MIT" }, "node_modules/ethereum-abi-types-generator/node_modules/setimmediate": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==" - }, - "node_modules/ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "dependencies": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "node_modules/ethereum-cryptography/node_modules/@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "dependencies": { - "@noble/hashes": "1.4.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethereum-cryptography/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ethereum-cryptography/node_modules/@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", - "dependencies": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", + "license": "MIT" }, - "node_modules/ethereum-cryptography/node_modules/@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "dependencies": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "node_modules/ethereum-abi-types-generator/node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details." }, "node_modules/ethers": { "version": "6.13.5", @@ -2188,9 +1899,9 @@ }, "node_modules/ethersv5": { "name": "ethers", - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.8.0.tgz", + "integrity": "sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==", "funding": [ { "type": "individual", @@ -2201,46 +1912,38 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/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==", "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "@ethersproject/abi": "5.8.0", + "@ethersproject/abstract-provider": "5.8.0", + "@ethersproject/abstract-signer": "5.8.0", + "@ethersproject/address": "5.8.0", + "@ethersproject/base64": "5.8.0", + "@ethersproject/basex": "5.8.0", + "@ethersproject/bignumber": "5.8.0", + "@ethersproject/bytes": "5.8.0", + "@ethersproject/constants": "5.8.0", + "@ethersproject/contracts": "5.8.0", + "@ethersproject/hash": "5.8.0", + "@ethersproject/hdnode": "5.8.0", + "@ethersproject/json-wallets": "5.8.0", + "@ethersproject/keccak256": "5.8.0", + "@ethersproject/logger": "5.8.0", + "@ethersproject/networks": "5.8.0", + "@ethersproject/pbkdf2": "5.8.0", + "@ethersproject/properties": "5.8.0", + "@ethersproject/providers": "5.8.0", + "@ethersproject/random": "5.8.0", + "@ethersproject/rlp": "5.8.0", + "@ethersproject/sha2": "5.8.0", + "@ethersproject/signing-key": "5.8.0", + "@ethersproject/solidity": "5.8.0", + "@ethersproject/strings": "5.8.0", + "@ethersproject/transactions": "5.8.0", + "@ethersproject/units": "5.8.0", + "@ethersproject/wallet": "5.8.0", + "@ethersproject/web": "5.8.0", + "@ethersproject/wordlists": "5.8.0" } }, "node_modules/eventemitter3": { @@ -2248,15 +1951,6 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, "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", @@ -2265,7 +1959,8 @@ "node_modules/fast-copy": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", - "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==" + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "dev": true }, "node_modules/fast-decode-uri-component": { "version": "1.0.1", @@ -2331,7 +2026,8 @@ "node_modules/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==" + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true }, "node_modules/fast-uri": { "version": "3.0.5", @@ -2381,79 +2077,6 @@ "toad-cache": "^3.3.0" } }, - "node_modules/fastify-cli": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/fastify-cli/-/fastify-cli-6.3.0.tgz", - "integrity": "sha512-FORXCwuBiNAArMMxp5hTthQCU9Xa7oO1wnCsGSgvuWC2k5ZarEEIXNm5RekcO9koZDQ0NACU6gGRF96Tf7ZI7Q==", - "dependencies": { - "@fastify/deepmerge": "^2.0.0", - "chalk": "^4.1.2", - "chokidar": "^3.5.2", - "close-with-grace": "^1.1.0", - "commist": "^3.0.0", - "dotenv": "^16.0.0", - "fastify": "^4.26.1", - "fastify-plugin": "^4.0.0", - "generify": "^4.0.0", - "help-me": "^4.0.1", - "is-docker": "^2.0.0", - "pino-pretty": "^11.2.0", - "pkg-up": "^3.1.0", - "resolve-from": "^5.0.0", - "semver": "^7.3.5", - "yargs-parser": "^21.1.1" - }, - "bin": { - "fastify": "cli.js" - } - }, - "node_modules/fastify-cli/node_modules/pino-pretty": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.3.0.tgz", - "integrity": "sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==", - "license": "MIT", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.2", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^2.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/fastify-cli/node_modules/pino-pretty/node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "license": "MIT" - }, - "node_modules/fastify-cli/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", - "license": "MIT", - "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-plugin": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", @@ -2467,17 +2090,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/find-my-way": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.2.2.tgz", @@ -2492,22 +2104,16 @@ } }, "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", "dependencies": { - "locate-path": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=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==", - "dependencies": { - "is-callable": "^1.1.3" + "node": ">=8" } }, "node_modules/forwarded": { @@ -2522,6 +2128,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -2532,15 +2139,11 @@ "node": ">=10" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -2550,71 +2153,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generify": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/generify/-/generify-4.2.0.tgz", - "integrity": "sha512-b4cVhbPfbgbCZtK0dcUc1lASitXGEAIqukV5DDAyWm25fomWnV+C+a1yXvqikcRZXHN2j0pSDyj3cTfzq8pC7Q==", - "dependencies": { - "isbinaryfile": "^4.0.2", - "pump": "^3.0.0", - "split2": "^3.0.0", - "walker": "^1.0.6" - }, - "bin": { - "generify": "generify.js" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "function-bind": "^1.1.2", - "get-proto": "^1.0.0", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/get-tsconfig": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", @@ -2628,129 +2175,27 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "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", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -2772,36 +2217,6 @@ "node": ">= 0.8" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -2815,159 +2230,15 @@ "node": ">= 0.10" } }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "peerDependencies": { - "ws": "*" - } - }, "node_modules/isows": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", @@ -2986,6 +2257,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, "engines": { "node": ">=10" } @@ -2993,7 +2265,8 @@ "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" }, "node_modules/json-schema-ref-resolver": { "version": "1.0.1", @@ -3003,20 +2276,6 @@ "fast-deep-equal": "^3.1.3" } }, - "node_modules/json-schema-to-ts": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", - "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "ts-algebra": "^2.0.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -3026,6 +2285,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -3044,31 +2304,15 @@ } }, "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "engines": { - "node": ">= 0.4" + "node": ">=8" } }, "node_modules/media-typer": { @@ -3101,28 +2345,20 @@ "node_modules/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==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" }, "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": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "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" - } + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3135,31 +2371,17 @@ "obliterator": "^2.0.1" } }, - "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": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "optional": true, + "peer": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, "node_modules/obliterator": { @@ -3179,6 +2401,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -3240,6 +2463,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -3251,41 +2475,33 @@ } }, "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=8" } }, "node_modules/pino": { @@ -3376,29 +2592,11 @@ } ] }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, @@ -3409,15 +2607,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", @@ -3439,6 +2628,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -3446,32 +2636,8 @@ }, "node_modules/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==" - }, - "node_modules/readable-stream": { - "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", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" }, "node_modules/real-require": { "version": "0.2.0", @@ -3484,19 +2650,14 @@ "node_modules/reflect-metadata": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", - "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "license": "MIT" + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "license": "Apache-2.0" }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -3512,15 +2673,8 @@ "node_modules/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==" - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "engines": { - "node": ">=8" - } + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", @@ -3554,41 +2708,6 @@ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/safe-regex2": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-3.1.0.tgz", @@ -3608,7 +2727,8 @@ "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "license": "MIT" }, "node_modules/secure-json-parse": { "version": "2.7.0", @@ -3629,34 +2749,14 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3670,14 +2770,6 @@ "atomic-sleep": "^1.0.0" } }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -3686,18 +2778,11 @@ "node": ">= 0.8" } }, - "node_modules/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==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3711,6 +2796,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -3722,6 +2808,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { "node": ">=8" }, @@ -3729,17 +2816,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/thread-stream": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", @@ -3748,22 +2824,6 @@ "real-require": "^0.2.0" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/toad-cache": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", @@ -3780,18 +2840,6 @@ "node": ">=0.6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/ts-algebra": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", - "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", - "dev": true, - "license": "MIT" - }, "node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", @@ -3833,6 +2881,7 @@ "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -3852,33 +2901,26 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "peer": true, "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details." - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -3973,362 +3015,6 @@ } } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/web3": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/web3/-/web3-4.16.0.tgz", - "integrity": "sha512-SgoMSBo6EsJ5GFCGar2E/pR2lcR/xmUSuQ61iK6yDqzxmm42aPPxSqZfJz2z/UCR6pk03u77pU8TGV6lgMDdIQ==", - "dependencies": { - "web3-core": "^4.7.1", - "web3-errors": "^1.3.1", - "web3-eth": "^4.11.1", - "web3-eth-abi": "^4.4.1", - "web3-eth-accounts": "^4.3.1", - "web3-eth-contract": "^4.7.2", - "web3-eth-ens": "^4.4.0", - "web3-eth-iban": "^4.0.7", - "web3-eth-personal": "^4.1.0", - "web3-net": "^4.1.0", - "web3-providers-http": "^4.2.0", - "web3-providers-ws": "^4.0.8", - "web3-rpc-methods": "^1.3.0", - "web3-rpc-providers": "^1.0.0-rc.4", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14.0.0", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-4.7.1.tgz", - "integrity": "sha512-9KSeASCb/y6BG7rwhgtYC4CvYY66JfkmGNEYb7q1xgjt9BWfkf09MJPaRyoyT5trdOxYDHkT9tDlypvQWaU8UQ==", - "dependencies": { - "web3-errors": "^1.3.1", - "web3-eth-accounts": "^4.3.1", - "web3-eth-iban": "^4.0.7", - "web3-providers-http": "^4.2.0", - "web3-providers-ws": "^4.0.8", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - }, - "optionalDependencies": { - "web3-providers-ipc": "^4.0.7" - } - }, - "node_modules/web3-errors": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.1.tgz", - "integrity": "sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==", - "dependencies": { - "web3-types": "^1.10.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-4.11.1.tgz", - "integrity": "sha512-q9zOkzHnbLv44mwgLjLXuyqszHuUgZWsQayD2i/rus2uk0G7hMn11bE2Q3hOVnJS4ws4VCtUznlMxwKQ+38V2w==", - "dependencies": { - "setimmediate": "^1.0.5", - "web3-core": "^4.7.1", - "web3-errors": "^1.3.1", - "web3-eth-abi": "^4.4.1", - "web3-eth-accounts": "^4.3.1", - "web3-net": "^4.1.0", - "web3-providers-ws": "^4.0.8", - "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-abi": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-4.4.1.tgz", - "integrity": "sha512-60ecEkF6kQ9zAfbTY04Nc9q4eEYM0++BySpGi8wZ2PD1tw/c0SDvsKhV6IKURxLJhsDlb08dATc3iD6IbtWJmg==", - "dependencies": { - "abitype": "0.7.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-abi/node_modules/abitype": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.7.1.tgz", - "integrity": "sha512-VBkRHTDZf9Myaek/dO3yMmOzB/y2s3Zo6nVU7yaw1G+TvCHAjwaJzNGN9yo4K5D8bU/VZXKP1EJpRhFr862PlQ==", - "peerDependencies": { - "typescript": ">=4.9.4", - "zod": "^3 >=3.19.1" - }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } - } - }, - "node_modules/web3-eth-accounts": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-4.3.1.tgz", - "integrity": "sha512-rTXf+H9OKze6lxi7WMMOF1/2cZvJb2AOnbNQxPhBDssKOllAMzLhg1FbZ4Mf3lWecWfN6luWgRhaeSqO1l+IBQ==", - "dependencies": { - "@ethereumjs/rlp": "^4.0.1", - "crc-32": "^1.2.2", - "ethereum-cryptography": "^2.0.0", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-contract": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-4.7.2.tgz", - "integrity": "sha512-3ETqs2pMNPEAc7BVY/C3voOhTUeJdkf2aM3X1v+edbngJLHAxbvxKpOqrcO0cjXzC4uc2Q8Zpf8n8zT5r0eLnA==", - "dependencies": { - "@ethereumjs/rlp": "^5.0.2", - "web3-core": "^4.7.1", - "web3-errors": "^1.3.1", - "web3-eth": "^4.11.1", - "web3-eth-abi": "^4.4.1", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-contract/node_modules/@ethereumjs/rlp": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", - "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", - "bin": { - "rlp": "bin/rlp.cjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/web3-eth-ens": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-4.4.0.tgz", - "integrity": "sha512-DeyVIS060hNV9g8dnTx92syqvgbvPricE3MerCxe/DquNZT3tD8aVgFfq65GATtpCgDDJffO2bVeHp3XBemnSQ==", - "dependencies": { - "@adraffy/ens-normalize": "^1.8.8", - "web3-core": "^4.5.0", - "web3-errors": "^1.2.0", - "web3-eth": "^4.8.0", - "web3-eth-contract": "^4.5.0", - "web3-net": "^4.1.0", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.0", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-iban": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-4.0.7.tgz", - "integrity": "sha512-8weKLa9KuKRzibC87vNLdkinpUE30gn0IGY027F8doeJdcPUfsa4IlBgNC4k4HLBembBB2CTU0Kr/HAOqMeYVQ==", - "dependencies": { - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7", - "web3-validator": "^2.0.3" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-eth-personal": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-4.1.0.tgz", - "integrity": "sha512-RFN83uMuvA5cu1zIwwJh9A/bAj0OBxmGN3tgx19OD/9ygeUZbifOL06jgFzN0t+1ekHqm3DXYQM8UfHpXi7yDQ==", - "dependencies": { - "web3-core": "^4.6.0", - "web3-eth": "^4.9.0", - "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.8.0", - "web3-utils": "^4.3.1", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-net": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-4.1.0.tgz", - "integrity": "sha512-WWmfvHVIXWEoBDWdgKNYKN8rAy6SgluZ0abyRyXOL3ESr7ym7pKWbfP4fjApIHlYTh8tNqkrdPfM4Dyi6CA0SA==", - "dependencies": { - "web3-core": "^4.4.0", - "web3-rpc-methods": "^1.3.0", - "web3-types": "^1.6.0", - "web3-utils": "^4.3.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-providers-http": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-4.2.0.tgz", - "integrity": "sha512-IPMnDtHB7dVwaB7/mMxAZzyq7d5ezfO1+Vw0bNfAeIi7gaDlJiggp85SdyAfOgov8AMUA/dyiY72kQ0KmjXKvQ==", - "dependencies": { - "cross-fetch": "^4.0.0", - "web3-errors": "^1.3.0", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.1" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-providers-ipc": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-4.0.7.tgz", - "integrity": "sha512-YbNqY4zUvIaK2MHr1lQFE53/8t/ejHtJchrWn9zVbFMGXlTsOAbNoIoZWROrg1v+hCBvT2c9z8xt7e/+uz5p1g==", - "optional": true, - "dependencies": { - "web3-errors": "^1.1.3", - "web3-types": "^1.3.0", - "web3-utils": "^4.0.7" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-providers-ws": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-4.0.8.tgz", - "integrity": "sha512-goJdgata7v4pyzHRsg9fSegUG4gVnHZSHODhNnn6J93ykHkBI1nz4fjlGpcQLUMi4jAMz6SHl9Ibzs2jj9xqPw==", - "dependencies": { - "@types/ws": "8.5.3", - "isomorphic-ws": "^5.0.0", - "web3-errors": "^1.2.0", - "web3-types": "^1.7.0", - "web3-utils": "^4.3.1", - "ws": "^8.17.1" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-rpc-methods": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/web3-rpc-methods/-/web3-rpc-methods-1.3.0.tgz", - "integrity": "sha512-/CHmzGN+IYgdBOme7PdqzF+FNeMleefzqs0LVOduncSaqsppeOEoskLXb2anSpzmQAP3xZJPaTrkQPWSJMORig==", - "dependencies": { - "web3-core": "^4.4.0", - "web3-types": "^1.6.0", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-rpc-providers": { - "version": "1.0.0-rc.4", - "resolved": "https://registry.npmjs.org/web3-rpc-providers/-/web3-rpc-providers-1.0.0-rc.4.tgz", - "integrity": "sha512-PXosCqHW0EADrYzgmueNHP3Y5jcSmSwH+Dkqvn7EYD0T2jcsdDAIHqk6szBiwIdhumM7gv9Raprsu/s/f7h1fw==", - "dependencies": { - "web3-errors": "^1.3.1", - "web3-providers-http": "^4.2.0", - "web3-providers-ws": "^4.0.8", - "web3-types": "^1.10.0", - "web3-utils": "^4.3.3", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-types": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.10.0.tgz", - "integrity": "sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==", - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-4.3.3.tgz", - "integrity": "sha512-kZUeCwaQm+RNc2Bf1V3BYbF29lQQKz28L0y+FA4G0lS8IxtJVGi5SeDTUkpwqqkdHHC7JcapPDnyyzJ1lfWlOw==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "eventemitter3": "^5.0.1", - "web3-errors": "^1.3.1", - "web3-types": "^1.10.0", - "web3-validator": "^2.0.6" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, - "node_modules/web3-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", - "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", - "dependencies": { - "ethereum-cryptography": "^2.0.0", - "util": "^0.12.5", - "web3-errors": "^1.2.0", - "web3-types": "^1.6.0", - "zod": "^3.21.4" - }, - "engines": { - "node": ">=14", - "npm": ">=6.12.0" - } - }, "node_modules/webauthn-p256": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz", @@ -4369,48 +3055,17 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/webidl-conversions": { - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" - }, - "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" }, "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==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4423,7 +3078,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/ws": { "version": "8.17.1", @@ -4449,6 +3105,7 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -4456,12 +3113,14 @@ "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -4480,59 +3139,10 @@ } }, "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/yargs/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -4545,6 +3155,8 @@ "version": "3.24.1", "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "optional": true, + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 74a52c8..aab86e8 100644 --- a/package.json +++ b/package.json @@ -19,21 +19,19 @@ "license": "MIT", "copyright": "Copyright © 2024 Titan Industries (Global) Co. Ltd.", "dependencies": { - "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", "@fastify/sensible": "^5.0.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.0", + "@fastify/type-provider-typebox": "^4.1.0", + "@sinclair/typebox": "^0.33.22", + "close-with-grace": "^2.2.0", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.2", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", - "fastify-cli": "^6.1.1", - "fastify-plugin": "^4.0.0", - "viem": "^2.7.22", - "web3": "^4.5.0" + "viem": "^2.7.22" }, "devDependencies": { "@types/node": "^22.14.1", - "json-schema-to-ts": "^3.1.1", "pino-pretty": "^13.0.0", "tsx": "^4.19.3", "typescript": "^5.8.3" diff --git a/src/app.ts b/src/app.ts index 859e5eb..d0efcc3 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,10 +1,10 @@ import { ContractsLoader } from "./services/blockchain.repo"; import { ContractsInMemoryIndexer } from "./services/cache.repo"; -import { config } from "./config/config"; +import { config } from "./config/env"; import { http } from "viem"; import { createPublicClient } from "viem"; import * as indexerJob from "./indexer-job"; -import { startServer } from "./server"; +import { Server } from "./server"; import { arbitrum, arbitrumSepolia, hardhat } from "viem/chains"; import { Chain } from "viem"; import { ContractService } from "./services/contract.service"; @@ -18,18 +18,26 @@ const chains: Record = { async function main() { const client0 = createPublicClient({ - transport: http(config.ETH_NODE_URL, { - retryCount: 10, - retryDelay: 1000, - }), + transport: http(config.ETH_NODE_URL), }); + console.log("Connecting to blockchain..."); + const chainId = await client0.getChainId(); - const chain = chains[chainId]; + let chain = chains[chainId]; if (!chain) { throw new Error(`Chain ${chainId} is not supported`); } + console.log("Chain ID", chainId); + + if (config.MULTICALL_ADDRESS) { + chain.contracts = { + ...chain.contracts, + multicall3: { address: config.MULTICALL_ADDRESS as `0x${string}` }, + }; + } + const client = createPublicClient({ transport: http(config.ETH_NODE_URL, { retryCount: 10, @@ -42,13 +50,21 @@ async function main() { const indexer = new ContractsInMemoryIndexer(); const service = new ContractService( indexer, - new PriceCalculator(client, config.HASHRATE_ORACLE_ADDRESS as `0x${string}`) + new PriceCalculator( + client, + config.HASHRATE_ORACLE_ADDRESS as `0x${string}`, + config.CLONE_FACTORY_ADDRESS as `0x${string}` + ) ); + const server = new Server(indexer, loader, service); + const log = server.getLogger(); + log.info(`Starting app with config: ${JSON.stringify(config)}`); + // TODO: split into multiple phases await Promise.all([ - indexerJob.start(client, loader, indexer), - startServer(indexer, loader, service), + indexerJob.start(client, loader, indexer, log.child({ module: "indexerJob" })), + server.start(), ]); } diff --git a/src/config/config.ts b/src/config/config.ts deleted file mode 100644 index faca74c..0000000 --- a/src/config/config.ts +++ /dev/null @@ -1,40 +0,0 @@ -import envSchema from "env-schema"; -import type { FromSchema, JSONSchema } from "json-schema-to-ts"; - -const schema = { - type: "object", - required: ["ETH_NODE_URL", "CLONE_FACTORY_ADDRESS", "ADMIN_API_KEY", "HASHRATE_ORACLE_ADDRESS"], - properties: { - ADMIN_API_KEY: { - type: "string", - }, - CLONE_FACTORY_ADDRESS: { - type: "string", - }, - ETH_NODE_URL: { - type: "string", - }, - HASHRATE_ORACLE_ADDRESS: { - type: "string", - }, - FASTIFY_PLUGIN_TIMEOUT: { - type: "integer", - default: 60000, - }, - FASTIFY_CLOSE_GRACE_DELAY: { - type: "integer", - default: 500, - }, - PORT: { - type: "integer", - default: 3000, - }, - }, -} as const satisfies JSONSchema; - -export type Config = FromSchema; - -export const config = envSchema({ - schema, - dotenv: true, // load .env if it is there, default: false -}); diff --git a/src/config/env.ts b/src/config/env.ts new file mode 100644 index 0000000..b1998b6 --- /dev/null +++ b/src/config/env.ts @@ -0,0 +1,20 @@ +import envSchema from "env-schema"; +import { Type, Static } from "@sinclair/typebox"; + +const schema = Type.Object({ + ADMIN_API_KEY: Type.String(), + CLONE_FACTORY_ADDRESS: Type.String(), + ETH_NODE_URL: Type.String(), + HASHRATE_ORACLE_ADDRESS: Type.String(), + FASTIFY_PLUGIN_TIMEOUT: Type.Integer({ default: 60000 }), + FASTIFY_CLOSE_GRACE_DELAY: Type.Integer({ default: 500 }), + MULTICALL_ADDRESS: Type.Optional(Type.String()), + PORT: Type.Integer({ default: 3000 }), +}); + +export type Config = Static; + +export const config = envSchema({ + schema, + dotenv: true, // load .env if it is there, default: false +}); diff --git a/src/indexer-job.ts b/src/indexer-job.ts index cfdec44..2bed5ee 100644 --- a/src/indexer-job.ts +++ b/src/indexer-job.ts @@ -3,35 +3,39 @@ import { ContractsLoader } from "./services/blockchain.repo"; import { ContractsInMemoryIndexer } from "./services/cache.repo"; import { startWatchPromise } from "./services/listener"; import { HashrateContract } from "./types/hashrate-contract"; +import { FastifyBaseLogger } from "fastify"; export const start = async ( client: PublicClient, loader: ContractsLoader, - indexer: ContractsInMemoryIndexer + indexer: ContractsInMemoryIndexer, + log: FastifyBaseLogger ) => { - console.log("Initial load of contracts"); + log.info("Initial load of contracts"); const res = await loader.loadAll(); - console.log("Loaded contracts", res.contracts.length); + log.info("Loaded contracts", res.contracts.length); for (const contract of res.contracts) { - await updateContract(contract, Number(res.blockNumber), indexer); + await updateContract(contract, Number(res.blockNumber), indexer, log); } await startWatchPromise(client, { initialContractsToWatch: new Set(res.contracts.map((c) => c.id)), onContractUpdate: async (contractAddr: string, blockNumber: number) => { const contract = await loader.getContract(contractAddr as `0x${string}`); - await updateContract(contract, blockNumber, indexer); + await updateContract(contract, blockNumber, indexer, log); }, + log, }); }; async function updateContract( contract: HashrateContract, blockNumber: number, - indexer: ContractsInMemoryIndexer + indexer: ContractsInMemoryIndexer, + log: FastifyBaseLogger ) { indexer.upsert(contract, blockNumber); - console.log("Updated contract in cache", contract.id); + log.info("Updated contract in cache", contract.id); } diff --git a/src/routes/root.ts b/src/routes/root.ts index 1cc15e4..28dd22e 100644 --- a/src/routes/root.ts +++ b/src/routes/root.ts @@ -1,52 +1,76 @@ -import { FastifyInstance } from "fastify"; import { ContractsLoader } from "../services/blockchain.repo"; -import { Config } from "../config/config"; +import { Config } from "../config/env"; import { ContractService } from "../services/contract.service"; import { ContractsInMemoryIndexer } from "../services/cache.repo"; +import { ServerType } from "../server"; +import { Type } from "@sinclair/typebox"; export async function router( - fastify: FastifyInstance, + fastify: ServerType, config: Config, service: ContractService, indexer: ContractsInMemoryIndexer, loader: ContractsLoader ) { - fastify.get("/", async function () { - return { root: true }; - }); - - fastify.get("/admin/reloadContracts", async function (request) { - const apiKey = request.query.apiKey; - if (apiKey !== config.ADMIN_API_KEY) { - return fastify.httpErrors.unauthorized(); + fastify.get( + "/admin/reloadContracts", + { + schema: { + querystring: Type.Object({ + apiKey: Type.String(), + }), + }, + }, + async function (request) { + if (request.query.apiKey !== config.ADMIN_API_KEY) { + return fastify.httpErrors.unauthorized(); + } + // TODO: stop indexer job and start it again + const all = await loader.loadAll(); + for (const contract of all.contracts) { + indexer.upsert(contract, Number(all.blockNumber)); + } + return indexer.getAll(); } - // TODO: stop indexer job and start it again - const all = await loader.loadAll(); - for (const contract of all.contracts) { - indexer.upsert(contract, Number(all.blockNumber)); - } - return indexer.getAll(); - }); + ); - fastify.get("/contracts", async function (request, reply) { - const { walletAddr } = request.query; - // TODO: add validation - return service.getAll(walletAddr); - }); - - fastify.get("/contracts/:id", async function (request, reply) { - const { params, query } = request; - const { id } = params; - const { walletAddr } = query; + fastify.get( + "/contracts", + { + schema: { + querystring: Type.Object({ + walletAddr: Type.Optional(Type.String()), + }), + }, + }, + async function (request) { + const { walletAddr } = request.query; + return service.getAll(walletAddr); + } + ); - const contract = await service.get(id, walletAddr); - if (!contract) { - return fastify.httpErrors.notFound("Contract not found"); + fastify.get( + "/contracts/:id", + { + schema: { + params: Type.Object({ + id: Type.String(), + }), + querystring: Type.Object({ + walletAddr: Type.Optional(Type.String()), + }), + }, + }, + async function (request) { + const contract = await service.get(request.params.id, request.query.walletAddr); + if (!contract) { + return fastify.httpErrors.notFound("Contract not found"); + } + return contract; } - return contract; - }); + ); - fastify.get("/healthcheck", async function (request, reply) { + fastify.get("/healthcheck", async function () { return { status: "ok", version: process.env.npm_package_version, diff --git a/src/server.ts b/src/server.ts index 7d9dfb1..61318cf 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,63 +1,76 @@ -import { config } from "./config/config"; - +import { config } from "./config/env"; import Fastify from "fastify"; import closeWithGrace from "close-with-grace"; -import AutoLoad from "@fastify/autoload"; import cors from "@fastify/cors"; -import path from "node:path"; import { router } from "./routes/root"; import { ContractsInMemoryIndexer } from "./services/cache.repo"; import { ContractsLoader } from "./services/blockchain.repo"; import sensible from "@fastify/sensible"; import { ContractService } from "./services/contract.service"; -// Register your application as a normal plugin. - -export function startServer( - indexer: ContractsInMemoryIndexer, - loader: ContractsLoader, - service: ContractService -) { - return new Promise((resolve, reject) => { - const options = { - prefix: "/api", - }; - - const app = Fastify({ - logger: {}, - }); +import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox"; - app.register(async (instance, opts) => { - console.log(`Running server with config: ${JSON.stringify(config)}`); +export class Server { + private app: ServerType; - instance.register(sensible); - instance.register(cors, { - origin: "*", - }); + constructor( + readonly indexer: ContractsInMemoryIndexer, + readonly loader: ContractsLoader, + readonly service: ContractService + ) { + this.app = createServer(); - // This loads all plugins defined in routes - // define your routes in one of these - instance.register(async (instance) => { + this.app.register( + async (instance, opts) => { + instance.register(sensible); + instance.register(cors, { + origin: "*", + }); router(instance, config, service, indexer, loader); - }); - }); - // delay is the number of milliseconds for the graceful close to finish - closeWithGrace( - { delay: config.FASTIFY_CLOSE_GRACE_DELAY }, - async function ({ signal, err, manual }) { - if (err) { - app.log.error(err); - } - await app.close(); + // This loads all plugins defined in routes + // define your routes in one of these + }, + { + prefix: "/api", } ); + } - // Start listening. - app.listen({ port: config.PORT }, (err) => { - if (err) { - app.log.error(err); - reject(err); - } + getLogger() { + return this.app.log; + } + + async start() { + return new Promise((resolve, reject) => { + const app = this.app; + // delay is the number of milliseconds for the graceful close to finish + closeWithGrace( + { delay: config.FASTIFY_CLOSE_GRACE_DELAY }, + async function ({ signal, err, manual }) { + if (err) { + app.log.error(err); + } + await app.close(); + } + ); + + // Start listening. + app.listen({ port: config.PORT }, (err) => { + if (err) { + app.log.error(err); + reject(err); + } + }); }); - }); + } } + +function createServer() { + const server = Fastify({ + logger: {}, + }).withTypeProvider(); + + return server; +} + +export type ServerType = ReturnType; diff --git a/src/services/contract.service.ts b/src/services/contract.service.ts index 7b8dd5b..d269221 100644 --- a/src/services/contract.service.ts +++ b/src/services/contract.service.ts @@ -31,7 +31,9 @@ export class ContractService { } async #adjustContract(contract: HashrateContract, filterHistoryByAddr?: string) { - contract.price = await this.#calculatePrice(contract).then((price) => price.toString()); + const { price, fee } = await this.#calculatePriceAndFee(contract); + contract.price = price.toString(); + contract.fee = fee.toString(); contract.state = this.#getContractState(contract); if (filterHistoryByAddr) { @@ -40,13 +42,13 @@ export class ContractService { contract.history = this.#filterActiveContractFromHistory(contract.history); } - async #calculatePrice(contract: HashrateContract) { - const totalHashrateInTH = BigInt(contract.speed) * BigInt(contract.length); - const price = await this.priceCalculator.calculatePrice( - totalHashrateInTH, + async #calculatePriceAndFee(contract: HashrateContract) { + const totalHashes = BigInt(contract.speed) * BigInt(contract.length); + const { price, fee } = await this.priceCalculator.calculatePriceAndFee( + totalHashes, BigInt(contract.profitTarget) ); - return price; + return { price, fee }; } #filterHistoryByWalletAddr(history: ContractHistory[], walletAddr: string) { diff --git a/src/services/listener.ts b/src/services/listener.ts index ec4f8ca..f9ec18a 100644 --- a/src/services/listener.ts +++ b/src/services/listener.ts @@ -1,11 +1,13 @@ -import { config } from "../config/config"; +import { config } from "../config/env"; import { parseAbi, PublicClient } from "viem"; +import { FastifyBaseLogger } from "fastify"; type StartWatchProps = { initialContractsToWatch: Set; onContractUpdate: (contractAddr: string, blockNumber: number) => void; onError?: (error: Error) => void; blockNumber?: number; + log: FastifyBaseLogger; }; export function startWatchPromise(pc: PublicClient, props: StartWatchProps): Promise { @@ -53,7 +55,7 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { pollingInterval: 1000, fromBlock: props.blockNumber ? BigInt(props.blockNumber) : undefined, onLogs: (logs) => { - console.log(`Received logs: ${logs.length}`); + props.log.info(`Received logs: ${logs.length}`); logs.forEach((log) => { const { eventName, args, address, blockNumber } = log; @@ -63,13 +65,13 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { } else { contractAddress = address; } - console.log(`Received log for contract: ${contractAddress}`); + props.log.info(`Received log for contract: ${contractAddress}`); props.onContractUpdate(contractAddress, Number(blockNumber)); if (eventName === "contractCreated") { contractsToWatch.add(contractAddress); - console.log("Got contract created event, restating watch"); + props.log.info("Got contract created event, restating watch"); unwatch(); const newWatch = startWatch(pc, { ...props, @@ -81,7 +83,7 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { }); }, onError: (error) => { - console.error("On Error Callback", error); + props.log.error("On Error Callback", error); props.onError?.(error); }, }); diff --git a/src/services/mapper.ts b/src/services/mapper.ts index d04ae33..65560d9 100644 --- a/src/services/mapper.ts +++ b/src/services/mapper.ts @@ -1,4 +1,4 @@ -import { HashrateContract } from "../types/hashrate-contract"; +import { ContractState, HashrateContract } from "../types/hashrate-contract"; import { FutureTerms, ContractHistory, Stats } from "../types/hashrate-contract"; import { FutureTermsEntry, @@ -18,6 +18,8 @@ export function mapContract( return { ...pubVars, + state: pubVars.state as ContractState, + fee: "0", futureTerms: mapFutureTerms(fut), history: mapHistory(history), stats: mapStats(stats), diff --git a/src/services/price-calculator.ts b/src/services/price-calculator.ts index eff7e05..1d34b11 100644 --- a/src/services/price-calculator.ts +++ b/src/services/price-calculator.ts @@ -1,46 +1,73 @@ -import { hashrateOracleAbi } from "contracts-js/dist/abi/abi"; -import viem, { PublicClient } from "viem"; +import { PublicClient, getContract } from "viem"; +import { hashrateOracleAbi, cloneFactoryAbi } from "contracts-js/dist/abi/abi"; export class PriceCalculator { private pricePerTHInToken: bigint | null; - private priceBlockNumber: number | null; private oracle: ReturnType; + private cloneFactory: ReturnType; private priceExpirationTime = new Date(0); private ttl = 60 * 1000; // 1 minute + private feeRate?: bigint; + private feeDecimals?: bigint; - constructor(client: PublicClient, hashrateOracleAddr: `0x${string}`) { + constructor( + client: PublicClient, + hashrateOracleAddr: `0x${string}`, + cloneFactoryAddr: `0x${string}` + ) { this.oracle = getHashrateOracleContract(client, hashrateOracleAddr); + this.cloneFactory = getCloneFactoryContract(client, cloneFactoryAddr); this.pricePerTHInToken = null; - this.priceBlockNumber = null; } - async calculatePrice(totalHashrateInTH: bigint, profitTargetPercent: bigint) { - const pricePerTHinTokens = await this.getPricePerTHInTokenCached(); - const priceInTokens = pricePerTHinTokens * totalHashrateInTH; + async calculatePriceAndFee( + totalHashes: bigint, + profitTargetPercent: bigint + ): Promise<{ price: bigint; fee: bigint }> { + const hashesPerToken = await this.getHashesPerTokenCached(); + const priceInTokens = totalHashes / hashesPerToken; const priceWithProfit = priceInTokens + (priceInTokens * BigInt(profitTargetPercent)) / BigInt(100); - return priceWithProfit; + const { rate, decimals } = await this.getFeeRate(); + const fee = (priceWithProfit * rate) / 10n ** decimals; + return { price: priceWithProfit, fee }; } - private async getPricePerTHInTokenCached(): Promise { + private async getHashesPerTokenCached(): Promise { if (this.priceExpirationTime > new Date() && this.pricePerTHInToken !== null) { return this.pricePerTHInToken; } - this.pricePerTHInToken = await this.getPricePerTHInToken(); + this.pricePerTHInToken = await this.getHashesPerToken(); this.priceExpirationTime = new Date(Date.now() + this.ttl); - return this.pricePerTHInToken; + return this.pricePerTHInToken!; } - private async getPricePerTHInToken() { - const price = await this.oracle.read.getRewardPerTHinToken(); + private async getHashesPerToken() { + const price = await this.oracle.read.getHashesforToken(); return price; } + + private async getFeeRate() { + if (!this.feeRate || !this.feeDecimals) { + this.feeRate = await this.cloneFactory.read.validatorFeeRateScaled(); + this.feeDecimals = BigInt(await this.cloneFactory.read.VALIDATOR_FEE_DECIMALS()); + } + return { rate: this.feeRate, decimals: this.feeDecimals }; + } } function getHashrateOracleContract(client: PublicClient, hashrateOracleAddr: `0x${string}`) { - return viem.getContract({ + return getContract({ address: hashrateOracleAddr, abi: hashrateOracleAbi, client: client, }); } + +function getCloneFactoryContract(client: PublicClient, cloneFactoryAddr: `0x${string}`) { + return getContract({ + address: cloneFactoryAddr, + abi: cloneFactoryAbi, + client: client, + }); +} diff --git a/src/types/hashrate-contract.ts b/src/types/hashrate-contract.ts index 3e6c70d..fe06294 100644 --- a/src/types/hashrate-contract.ts +++ b/src/types/hashrate-contract.ts @@ -4,10 +4,11 @@ export type HashrateContract = { state: ContractState; version: string; price: string; + fee: string; limit: string; - speed: string; - length: string; - profitTarget: string; + speed: string; // in hashes per second + length: string; // in seconds + profitTarget: string; // in percent startingBlockTimestamp: string; buyer: string; seller: string; From c1fce4aa1be6cf8423d70eb827738290103e1f60 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Tue, 29 Apr 2025 18:21:58 +0200 Subject: [PATCH 12/35] feat: optimize blockchain node usage --- package-lock.json | 12 ++++++++++++ package.json | 4 +++- src/app.ts | 23 ++++++++++++++++------- src/config/env.ts | 11 +++++++++++ src/indexer-job.ts | 2 +- src/server.ts | 12 +++++++----- src/services/contract.service.ts | 29 +++++++++++++++++++---------- src/services/listener.ts | 30 +++++++++++++++++------------- src/services/price-calculator.ts | 25 +++++++++++++++++-------- 9 files changed, 103 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index d8b6c36..f58c767 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,11 +13,13 @@ "@fastify/sensible": "^5.0.0", "@fastify/type-provider-typebox": "^4.1.0", "@sinclair/typebox": "^0.33.22", + "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.2", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", + "pino": "^9.6.0", "viem": "^2.7.22" }, "devDependencies": { @@ -1475,6 +1477,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/async-mutex": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.5.0.tgz", + "integrity": "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -2508,6 +2519,7 @@ "version": "9.6.0", "resolved": "https://registry.npmjs.org/pino/-/pino-9.6.0.tgz", "integrity": "sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", diff --git a/package.json b/package.json index aab86e8..2183893 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,13 @@ "@fastify/sensible": "^5.0.0", "@fastify/type-provider-typebox": "^4.1.0", "@sinclair/typebox": "^0.33.22", + "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.2", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", + "pino": "^9.6.0", "viem": "^2.7.22" }, "devDependencies": { @@ -36,4 +38,4 @@ "tsx": "^4.19.3", "typescript": "^5.8.3" } -} \ No newline at end of file +} diff --git a/src/app.ts b/src/app.ts index d0efcc3..e60bb7b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -9,6 +9,7 @@ import { arbitrum, arbitrumSepolia, hardhat } from "viem/chains"; import { Chain } from "viem"; import { ContractService } from "./services/contract.service"; import { PriceCalculator } from "./services/price-calculator"; +import pino from "pino"; const chains: Record = { [hardhat.id]: hardhat, @@ -21,7 +22,11 @@ async function main() { transport: http(config.ETH_NODE_URL), }); - console.log("Connecting to blockchain..."); + const log = pino({ + level: config.LOG_LEVEL, + }); + + log.info("Connecting to blockchain..."); const chainId = await client0.getChainId(); let chain = chains[chainId]; @@ -29,7 +34,7 @@ async function main() { throw new Error(`Chain ${chainId} is not supported`); } - console.log("Chain ID", chainId); + log.info("Chain ID", chainId); if (config.MULTICALL_ADDRESS) { chain.contracts = { @@ -38,10 +43,14 @@ async function main() { }; } + const ethClientLogger = log.child({ module: "ethClient" }); const client = createPublicClient({ transport: http(config.ETH_NODE_URL, { - retryCount: 10, - retryDelay: 1000, + retryCount: 5, + retryDelay: 200, + onFetchRequest: async (request) => { + ethClientLogger.debug("requesting blockchain: %s", await request.json()); + }, }), chain, }); @@ -53,12 +62,12 @@ async function main() { new PriceCalculator( client, config.HASHRATE_ORACLE_ADDRESS as `0x${string}`, - config.CLONE_FACTORY_ADDRESS as `0x${string}` + config.CLONE_FACTORY_ADDRESS as `0x${string}`, + log.child({ module: "priceCalculator" }) ) ); - const server = new Server(indexer, loader, service); - const log = server.getLogger(); + const server = new Server(indexer, loader, service, log.child({ module: "server" })); log.info(`Starting app with config: ${JSON.stringify(config)}`); // TODO: split into multiple phases diff --git a/src/config/env.ts b/src/config/env.ts index b1998b6..17447b9 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -8,6 +8,17 @@ const schema = Type.Object({ HASHRATE_ORACLE_ADDRESS: Type.String(), FASTIFY_PLUGIN_TIMEOUT: Type.Integer({ default: 60000 }), FASTIFY_CLOSE_GRACE_DELAY: Type.Integer({ default: 500 }), + LOG_LEVEL: Type.Union( + [ + Type.Literal("trace"), + Type.Literal("debug"), + Type.Literal("info"), + Type.Literal("warn"), + Type.Literal("error"), + Type.Literal("fatal"), + ], + { default: "info" } + ), MULTICALL_ADDRESS: Type.Optional(Type.String()), PORT: Type.Integer({ default: 3000 }), }); diff --git a/src/indexer-job.ts b/src/indexer-job.ts index 2bed5ee..9bb80f0 100644 --- a/src/indexer-job.ts +++ b/src/indexer-job.ts @@ -37,5 +37,5 @@ async function updateContract( log: FastifyBaseLogger ) { indexer.upsert(contract, blockNumber); - log.info("Updated contract in cache", contract.id); + log.info(`Contract ${contract.id} updated in cache`); } diff --git a/src/server.ts b/src/server.ts index 61318cf..931c6b2 100644 --- a/src/server.ts +++ b/src/server.ts @@ -8,6 +8,7 @@ import { ContractsLoader } from "./services/blockchain.repo"; import sensible from "@fastify/sensible"; import { ContractService } from "./services/contract.service"; import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox"; +import pino, { Logger } from "pino"; export class Server { private app: ServerType; @@ -15,9 +16,10 @@ export class Server { constructor( readonly indexer: ContractsInMemoryIndexer, readonly loader: ContractsLoader, - readonly service: ContractService + readonly service: ContractService, + readonly log: Logger ) { - this.app = createServer(); + this.app = createServer(log); this.app.register( async (instance, opts) => { @@ -25,7 +27,7 @@ export class Server { instance.register(cors, { origin: "*", }); - router(instance, config, service, indexer, loader); + router(instance as ServerType, config, service, indexer, loader); // This loads all plugins defined in routes // define your routes in one of these @@ -65,9 +67,9 @@ export class Server { } } -function createServer() { +function createServer(log: pino.BaseLogger) { const server = Fastify({ - logger: {}, + logger: log, }).withTypeProvider(); return server; diff --git a/src/services/contract.service.ts b/src/services/contract.service.ts index d269221..ab4e478 100644 --- a/src/services/contract.service.ts +++ b/src/services/contract.service.ts @@ -16,8 +16,7 @@ export class ContractService { async getAll(filterHistoryByAddr?: string): Promise { const contracts = this.indexer.getAll(); - await Promise.all(contracts.map((c) => this.#adjustContract(c, filterHistoryByAddr))); - return contracts; + return Promise.all(contracts.map((c) => this.#adjustContract(c, filterHistoryByAddr))); } async get(id: string, filterHistoryByAddr?: string): Promise { @@ -26,20 +25,30 @@ export class ContractService { return null; } - await this.#adjustContract(contract, filterHistoryByAddr); - return contract; + return await this.#adjustContract(contract, filterHistoryByAddr); } - async #adjustContract(contract: HashrateContract, filterHistoryByAddr?: string) { + async #adjustContract( + contract: HashrateContract, + filterHistoryByAddr?: string + ): Promise { const { price, fee } = await this.#calculatePriceAndFee(contract); - contract.price = price.toString(); - contract.fee = fee.toString(); - contract.state = this.#getContractState(contract); + return { + ...contract, + price: price.toString(), + fee: fee.toString(), + state: this.#getContractState(contract), + history: this.#filterHistory(contract.history, filterHistoryByAddr), + }; + } + + #filterHistory(history: ContractHistory[], filterHistoryByAddr?: string) { + let historyCopy = [...history]; if (filterHistoryByAddr) { - contract.history = this.#filterHistoryByWalletAddr(contract.history, filterHistoryByAddr); + historyCopy = this.#filterHistoryByWalletAddr(historyCopy, filterHistoryByAddr); } - contract.history = this.#filterActiveContractFromHistory(contract.history); + return this.#filterActiveContractFromHistory(historyCopy); } async #calculatePriceAndFee(contract: HashrateContract) { diff --git a/src/services/listener.ts b/src/services/listener.ts index f9ec18a..2013bd4 100644 --- a/src/services/listener.ts +++ b/src/services/listener.ts @@ -1,6 +1,10 @@ import { config } from "../config/env"; -import { parseAbi, PublicClient } from "viem"; +import { getAbiItem, parseAbi, PublicClient } from "viem"; import { FastifyBaseLogger } from "fastify"; +import { abi } from "contracts-js"; + +const cfAbi = abi.cloneFactoryAbi; +const implAbi = abi.implementationAbi; type StartWatchProps = { initialContractsToWatch: Set; @@ -33,24 +37,24 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { "contractDeleteUpdated", "purchaseInfoUpdated", ]; - const eventsAbi = [ - // Clone Factory Events - "event contractCreated(address indexed _address, string _pubkey)", - "event clonefactoryContractPurchased(address indexed _address, address indexed _validator)", - "event contractDeleteUpdated(address _address, bool _isDeleted)", - "event purchaseInfoUpdated(address indexed _address)", + const eventsAbi2 = [ + // Clone Factory Events + getAbiItem({ abi: cfAbi, name: "contractCreated" }), + getAbiItem({ abi: cfAbi, name: "clonefactoryContractPurchased" }), + getAbiItem({ abi: cfAbi, name: "contractDeleteUpdated" }), + getAbiItem({ abi: cfAbi, name: "purchaseInfoUpdated" }), // Implementation Events - "event closedEarly(uint8 reason)", - "event fundsClaimed()", - "event destinationUpdated(string newValidatorURL, string newDestURL)", + getAbiItem({ abi: implAbi, name: "closedEarly" }), + getAbiItem({ abi: implAbi, name: "fundsClaimed" }), + getAbiItem({ abi: implAbi, name: "destinationUpdated" }), ]; let unwatch: () => void; unwatch = pc.watchEvent({ address: addresses, - events: parseAbi(eventsAbi), + events: eventsAbi2, poll: true, pollingInterval: 1000, fromBlock: props.blockNumber ? BigInt(props.blockNumber) : undefined, @@ -65,7 +69,7 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { } else { contractAddress = address; } - props.log.info(`Received log for contract: ${contractAddress}`); + props.log.info(`Received ${eventName}, for ${contractAddress} contract`); props.onContractUpdate(contractAddress, Number(blockNumber)); @@ -83,7 +87,7 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { }); }, onError: (error) => { - props.log.error("On Error Callback", error); + props.log.error("Event listener error", error); props.onError?.(error); }, }); diff --git a/src/services/price-calculator.ts b/src/services/price-calculator.ts index 1d34b11..ca14419 100644 --- a/src/services/price-calculator.ts +++ b/src/services/price-calculator.ts @@ -1,23 +1,29 @@ import { PublicClient, getContract } from "viem"; import { hashrateOracleAbi, cloneFactoryAbi } from "contracts-js/dist/abi/abi"; +import { Logger } from "pino"; +import { Mutex } from "async-mutex"; export class PriceCalculator { private pricePerTHInToken: bigint | null; private oracle: ReturnType; private cloneFactory: ReturnType; private priceExpirationTime = new Date(0); - private ttl = 60 * 1000; // 1 minute + private ttl = 10 * 1000; // 10 seconds private feeRate?: bigint; private feeDecimals?: bigint; + private mutex = new Mutex(); + private log: Logger; constructor( client: PublicClient, hashrateOracleAddr: `0x${string}`, - cloneFactoryAddr: `0x${string}` + cloneFactoryAddr: `0x${string}`, + log: Logger ) { this.oracle = getHashrateOracleContract(client, hashrateOracleAddr); this.cloneFactory = getCloneFactoryContract(client, cloneFactoryAddr); this.pricePerTHInToken = null; + this.log = log; } async calculatePriceAndFee( @@ -34,16 +40,19 @@ export class PriceCalculator { } private async getHashesPerTokenCached(): Promise { - if (this.priceExpirationTime > new Date() && this.pricePerTHInToken !== null) { - return this.pricePerTHInToken; - } - this.pricePerTHInToken = await this.getHashesPerToken(); - this.priceExpirationTime = new Date(Date.now() + this.ttl); - return this.pricePerTHInToken!; + return await this.mutex.runExclusive(async () => { + if (this.priceExpirationTime > new Date() && this.pricePerTHInToken !== null) { + return this.pricePerTHInToken; + } + this.pricePerTHInToken = await this.getHashesPerToken(); + this.priceExpirationTime = new Date(Date.now() + this.ttl); + return this.pricePerTHInToken!; + }); } private async getHashesPerToken() { const price = await this.oracle.read.getHashesforToken(); + this.log.info("fetched hashes per token: %s", price); return price; } From a134d60039125f40ea3e4c7d71bb0ed60540bbb3 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Wed, 30 Apr 2025 15:59:46 -0400 Subject: [PATCH 13/35] initial framework for ghbuild and gldeploy --- .github/workflows/build.yml | 259 ++++++++++++++++++++++++++++++++++++ .gitlab-ci.yml | 155 --------------------- LICENSE | 2 +- package.json | 2 +- 4 files changed, 261 insertions(+), 157 deletions(-) create mode 100644 .github/workflows/build.yml delete mode 100644 .gitlab-ci.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..0a5c8d7 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,259 @@ +name: CI-CD + +on: + workflow_dispatch: + inputs: + build_container: + description: "Build container image" + required: true + type: boolean + + push: + branches: + - main + - test + - dev + - cicd/* + + paths: [".github/**", "src/**"] + + pull_request: + types: [opened, reopened, synchronize] + paths: [".github/**", "src/**", "Dockerfile"] + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +env: + TEST_ENV_VAR: "test" + +jobs: + Generate-Tag: + runs-on: ubuntu-latest + name: Generate Tag Name + outputs: + tag_name: ${{ steps.gen_tag_name.outputs.tag_name }} + vtag: ${{ steps.gen_tag_name.outputs.vtag }} + vfull: ${{ steps.gen_tag_name.outputs.vfull }} + image_name: ${{ steps.gen_tag_name.outputs.image_name }} + artifacts_base_url: ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.gen_tag_name.outputs.tag_name }} + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Determine tag name + id: gen_tag_name + shell: bash + run: | + IMAGE_NAME="ghcr.io/lumerin-protocol/proxy-indexer" + VMAJ_NEW=2 + VMIN_NEW=0 + VPAT_NEW=0 + set +o pipefail + VLAST=$(git describe --tags --abbrev=0 --match='v[1-9]*' refs/remotes/origin/main 2>/dev/null | cut -c2-) + + if [ -n "$VLAST" ]; then + eval $(echo "$VLAST" | awk -F '.' '{print "VMAJ="$1" VMIN="$2" VPAT="$3}') + else + VMAJ=0 + VMIN=0 + VPAT=0 + fi + + if [ "$GITHUB_REF_NAME" = "main" ]; then + if [ "$VMAJ_NEW" -gt "$VMAJ" ]; then + VMAJ=$VMAJ_NEW + VMIN=$VMIN_NEW + VPAT=$VPAT_NEW + else + VMIN=$((VMIN+1)) + VPAT=0 + fi + VFULL=${VMAJ}.${VMIN}.${VPAT} + VTAG=v$VFULL + else + MB=$(git merge-base refs/remotes/origin/main HEAD) + VPAT=$(git rev-list --count --no-merges ${MB}..HEAD) + VFULL=${VMAJ}.${VMIN}.${VPAT} + RNAME=${GITHUB_REF_NAME##*/} + [ "$GITHUB_EVENT_NAME" = "pull_request" ] && RNAME=pr${GITHUB_REF_NAME%/merge} + VTAG=v${VFULL}-${RNAME} + fi + + # Output variables for use in subsequent jobs environment + echo "::set-output name=tag_name::${VTAG}" + echo "::set-output name=vtag::${VTAG}" + echo "::set-output name=vfull::${VFULL}" + echo "::set-output name=image_name::${IMAGE_NAME}" + echo "✅ New Build Tag: $VTAG" >> $GITHUB_STEP_SUMMARY + echo "✅ Docker Image: ${IMAGE_NAME}:${VTAG}" >> $GITHUB_STEP_SUMMARY + echo "❌ Old Major Tag: $VLAST" >> $GITHUB_STEP_SUMMARY + + Build-Indexer-Container: + name: Build Indexer Container + if: + ( + (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'test' || github.base_ref == 'dev')) || + (github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/cicd/') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' || github.ref == 'refs/heads/dev')) || + (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) + ) + runs-on: ubuntu-latest + needs: Generate-Tag + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Build Docker Image to Test + run: | + echo "Injecting version $FULLTAG into package.json" + sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package.json + cat package.json | grep '"version"' # Optional: Verify the change + echo "Injecting version $FULLTAG into package-lock.json" + sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package-lock.json + cat package-lock.json | grep '"version"' # Optional: Verify the change + BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} + BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} + BUILDCOMMIT=${{ github.sha }} + docker build \ + --platform linux/amd64 \ + --build-arg TAG_NAME=$BUILDTAG \ + --build-arg COMMIT=$BUILDCOMMIT \ + --load \ + -t $BUILDIMAGE:$BUILDTAG \ + -f ./Dockerfile \ + . || (echo "❌ Failed to build image with tag: $BUILDIMAGE:$BUILDTAG" && exit 1) + echo "✅ Indexer Container Build Successful!" + + GHCR-Build-and-Push: + name: Build & Push Docker Image + if: | + ( + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test')) || + (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) + ) + needs: + - Generate-Tag + - Build-Indexer-Container + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and Push Multi-Platform Docker Image + run: | + echo "Injecting version $FULLTAG into package.json" + sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package.json + cat package.json | grep '"version"' # Optional: Verify the change + echo "Injecting version $FULLTAG into package-lock.json" + sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package-lock.json + cat package-lock.json | grep '"version"' # Optional: Verify the change + BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} + BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} + BUILDCOMMIT=${{ github.sha }} + docker buildx build \ + --platform linux/amd64 \ + --build-arg TAG_NAME=$BUILDTAG \ + --build-arg COMMIT=$BUILDCOMMIT \ + --push \ + -t $BUILDIMAGE:$BUILDTAG \ + -f ./Dockerfile \ + . || (echo "❌ Failed to push image with tag: $BUILDIMAGE:$BUILDTAG" && exit 1) + echo "✅ Indexer Container Build and Push of $BUILDIMAGE:$BUILDTAG Successful!" + + - name: Optionally Push Latest Tag + if: ${{ github.ref == 'refs/heads/main' }} + run: | + BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} + BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} + docker pull $BUILDIMAGE:$BUILDTAG || (echo "❌ Failed to pull image: $BUILDIMAGE:$BUILDTAG" && exit 1) + docker tag $BUILDIMAGE:$BUILDTAG $BUILDIMAGE:latest || (echo "❌ Failed to tag image as :latest" && exit 1) + docker push $BUILDIMAGE:latest || (echo "❌ Failed to push image as :latest" && exit 1) + echo "✅ Indexer Container Push $BUILDIMAGE:latest Tag Successful!" + + GitLab-Deploy-Indexer: + name: Deploy Indexer to GitLab + if: | + ( + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test')) + ) + needs: + - Generate-Tag + - GHCR-Build-and-Push + runs-on: ubuntu-latest + steps: + - name: Clone + id: checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Install dependencies + run: | + sudo apt-get update && sudo apt-get install -y jq + + - name: Trigger GitLab Pipeline + run: | + BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} + FULLTAG=${{ needs.Generate-Tag.outputs.vfull }} + echo "Triggering GitLab Deploy for branch ${{ github.ref_name }} with tag $BUILDTAG" + # Determine branch + if [ "${{ github.ref_name }}" == "test" ]; then + GITLABBRANCH="dev" + elif [ "${{ github.ref_name }}" == "main" ]; then + GITLABBRANCH="main" + else + echo "❌ This branch is not configured to trigger GitLab pipelines." + exit 1 + fi + echo "✅ Sending Request to GitLab branch: $GITLABBRANCH" + response=$(curl --silent \ + --request POST \ + --url "${{ secrets.GITLAB_TRIGGER_URL }}" \ + --form "token=${{ secrets.GITLAB_TRIGGER_TOKEN }}" \ + --form "ref=$GITLABBRANCH" \ + --form "variables[SOURCE_REPO]=${{ github.repository }}" \ + --form "variables[SOURCE_BRANCH]=${{ github.ref_name }}" \ + --form "variables[GITHUB_VFULL]=$FULLTAG" \ + --form "variables[GITHUB_TAG]=$BUILDTAG") + + # Parse JSON response using jq + gitlab_status=$(echo "$response" | jq -r '.status // "unknown"') + gitlab_web_url=$(echo "$response" | jq -r '.web_url // "N/A"') + + # Log the response + echo "GitLab Response: $response" + + # Validate the status field + if [[ "$gitlab_status" =~ ^(created|preparing|success|running|scheduled)$ ]]; then + echo "✅ GitLab pipeline triggered successfully! Status: $gitlab_status" + echo "Pipeline details: $gitlab_web_url" + else + echo "❌ GitLab pipeline FAILED. Invalid status: $gitlab_status" + echo "Pipeline details: $gitlab_web_url" + exit 1 + fi diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 6ea3e0e..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,155 +0,0 @@ -# Please keep variables in alphabetical order -# variables: -stages: - - develop - - review - - deploy - -.ecr_login_script: &ecr_login_script | - echo "**************************" - echo "*** ECR Login to Shared Titanio-NET Repo in USE-1" - echo "**************************" - docker system prune -af - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $CI_AWS_TitanIO_NET_ECR - -.create_image_tag: &create_image_tag | - echo "**************************" - echo "*** Tag Image " - echo "**************************" - IMAGE_TAG="$(echo $CI_COMMIT_SHA | head -c 8)-$TGT_ENV" - echo $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG - -.build_image: &build_image | - echo "*****************************" - echo "Building & Pushing image..." - echo "*****************************" - docker build \ - --build-arg ADMIN_API_KEY=$ADMIN_API_KEY \ - --build-arg CLONE_FACTORY_ADDRESS=$CLONE_FACTORY_ADDRESS \ - --build-arg ETH_NODE_URL=$INDEXER_ETH_NODE \ - --build-arg FASTIFY_PLUGIN_TIMEOUT=60000 \ - --build-arg PORT=80 \ - -t $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG --no-cache . - - echo "**************************" - echo "*** Tag Image with $TGT_ENV-latest" - echo "**************************" - docker tag $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$TGT_ENV-latest - - echo "**************************" - echo "*** Push Images" - echo "**************************" - docker push $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG - docker push $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$TGT_ENV-latest - -.update_raw_task_definition: &update_raw_task_definition | - echo "**************************" - aws ecs describe-task-definition --region $AWS_DEFAULT_REGION --task-definition tsk-$CI_AWS_ECS_SVC > output.json - echo "**************************" - echo "*** Original Task Definition" - echo "**************************" - jq . output.json - - # Update the Image - jq '.taskDefinition.containerDefinitions[].image = "'$CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$TGT_ENV-latest'"' output.json > updated.json - - # Extract JUST Task Definition from the output.json file - jq '.taskDefinition' updated.json > extracted.json - - # Remove sections that are not needed - jq 'del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredBy, .registeredAt)' extracted.json > input.json - sed -i 's/'$CI_AWS_ACCOUNT_SBX'/'$TGT_ACCOUNT'/g' input.json - - echo "**************************" - echo "*** New Task Definition" - echo "**************************" - jq . input.json - -.deploy_new_task_definition: &deploy_new_task_definition | - aws ecs register-task-definition --region $AWS_DEFAULT_REGION --cli-input-json file://input.json - REVISION=$(aws ecs describe-task-definition --task-definition tsk-$CI_AWS_ECS_SVC --region $AWS_DEFAULT_REGION | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//' | cut -d "," -f 1) - echo "****************************************************" - echo "****************************************************" - echo "*** Update Task: " - echo "*** - AWS Account: Titanio-$TGT_ENV" - echo "*** - Cluster: ecs-$CI_AWS_ECS_CLUSTER-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION" - echo "*** - Service: svc-$CI_AWS_ECS_SVC-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION" - echo "*** - Task: tsk-$CI_AWS_ECS_SVC:$REVISION" - echo "*** - Image: $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG" - echo "****************************************************" - echo "****************************************************" - aws ecs update-service --region $AWS_DEFAULT_REGION --cluster ecs-$CI_AWS_ECS_CLUSTER-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION --service svc-$CI_AWS_ECS_SVC-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION --task-definition tsk-$CI_AWS_ECS_SVC:$REVISION - - -bedrock-02-dev: - environment: - name: dev - url: https://indexer.dev.lumerin.io/api/healthcheck - stage: develop - only: - - dev - image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest - tags: - - devops - - bedrock - - titanio-dev - - shell - variables: - TGT_ACCOUNT: $CI_AWS_ACCOUNT_DEV - TGT_ENV: dev - script: - - *ecr_login_script - - *create_image_tag - - *build_image - - *update_raw_task_definition - - *deploy_new_task_definition - - echo "$TGT_ENV Updated" - -titanio-03-stg: - environment: - name: stg - url: https://indexer.stg.lumerin.io/api/healthcheck - stage: review - only: - - stg - image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest - tags: - - devops - - bedrock - - titanio-stg - - shell - variables: - TGT_ACCOUNT: $CI_AWS_ACCOUNT_STG - TGT_ENV: stg - script: - - *ecr_login_script - - *create_image_tag - - *build_image - - *update_raw_task_definition - - *deploy_new_task_definition - - echo "$TGT_ENV Updated" - -titanio-04-lmn-PROD: - environment: - name: lmn - url: https://indexer.lumerin.io/api/healthcheck - stage: deploy - only: - - main - when: manual - image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest - tags: - - devops - - bedrock - - titanio-lmn - - shell - variables: - TGT_ACCOUNT: $CI_AWS_ACCOUNT_LMN - TGT_ENV: lmn - script: - - *ecr_login_script - - *create_image_tag - - *build_image - - *update_raw_task_definition - - *deploy_new_task_definition - - echo "$TGT_ENV Updated" \ No newline at end of file diff --git a/LICENSE b/LICENSE index 0f88733..0d42e78 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright 2024 Titan Industries (Global) Co. Ltd.. +Copyright 2025 Titan Industries (Global) Co. Ltd.. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/package.json b/package.json index 1ccef11..a37e13d 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "url": "https://lumerin.io" }, "license": "MIT", - "copyright": "Copyright © 2024 Titan Industries (Global) Co. Ltd.", + "copyright": "Copyright © 5 Titan Industries (Global) Co. Ltd.", "dependencies": { "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", From 109712150cd0256be4124bd93914a860f3f32a3d Mon Sep 17 00:00:00 2001 From: abs2023 Date: Wed, 30 Apr 2025 16:11:12 -0400 Subject: [PATCH 14/35] kick CI-CD --- .github/workflows/build.yml | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0a5c8d7..1275c50 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,11 +15,11 @@ on: - dev - cicd/* - paths: [".github/**", "src/**"] + paths: [".github/**", "src/**", "Dockerfile", "package.json", "package-lock.json", "LICENSE", "README.md"] pull_request: types: [opened, reopened, synchronize] - paths: [".github/**", "src/**", "Dockerfile"] + paths: [".github/**", "src/**", "Dockerfile", "package.json", "package-lock.json", "LICENSE", "README.md"] concurrency: group: ci-${{ github.ref }} diff --git a/README.md b/README.md index a5ad9d6..734e425 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# proxy-indexer 1.1.0 +# proxy-indexer 2.0.1 Provides a docker container service (that is currently run on ECS/Fargate) that listens for events on the Ethereum blockchain and indexes them in a Postgres database. The service is built using Node.js and uses the ethers.js library to interact with the Ethereum blockchain. Leveraged by both wallet-desktop and Web Marketplace From 7db527c9d09e0365facfbf8c5ceb7128f8fa8af3 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Wed, 30 Apr 2025 16:12:39 -0400 Subject: [PATCH 15/35] update sed for version --- .github/workflows/build.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1275c50..908d33a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -116,12 +116,6 @@ jobs: - name: Build Docker Image to Test run: | - echo "Injecting version $FULLTAG into package.json" - sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package.json - cat package.json | grep '"version"' # Optional: Verify the change - echo "Injecting version $FULLTAG into package-lock.json" - sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package-lock.json - cat package-lock.json | grep '"version"' # Optional: Verify the change BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} BUILDCOMMIT=${{ github.sha }} @@ -166,11 +160,11 @@ jobs: - name: Build and Push Multi-Platform Docker Image run: | echo "Injecting version $FULLTAG into package.json" - sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package.json - cat package.json | grep '"version"' # Optional: Verify the change + sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package.json + cat ./package.json | grep '"version"' # Optional: Verify the change echo "Injecting version $FULLTAG into package-lock.json" - sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" package-lock.json - cat package-lock.json | grep '"version"' # Optional: Verify the change + sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package-lock.json + cat ./package-lock.json | grep '"version"' # Optional: Verify the change BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} BUILDCOMMIT=${{ github.sha }} From a7ae96da98720244445d72aa872396f73cae2da8 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Wed, 30 Apr 2025 16:24:25 -0400 Subject: [PATCH 16/35] fix conflicts --- .gitlab-ci.yml | 155 ------------------------------------------------- package.json | 2 +- 2 files changed, 1 insertion(+), 156 deletions(-) delete mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index db340a4..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,155 +0,0 @@ -# Please keep variables in alphabetical order -# variables: -stages: - - develop - - review - - deploy - -.ecr_login_script: &ecr_login_script | - echo "**************************" - echo "*** ECR Login to Shared Titanio-NET Repo in USE-1" - echo "**************************" - docker system prune -af - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $CI_AWS_TitanIO_NET_ECR - -.create_image_tag: &create_image_tag | - echo "**************************" - echo "*** Tag Image " - echo "**************************" - IMAGE_TAG="$(echo $CI_COMMIT_SHA | head -c 8)-$TGT_ENV" - echo $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG - -.build_image: &build_image | - echo "*****************************" - echo "Building & Pushing image..." - echo "*****************************" - docker build \ - --build-arg ADMIN_API_KEY=$ADMIN_API_KEY \ - --build-arg CLONE_FACTORY_ADDRESS=$CLONE_FACTORY_ADDRESS \ - --build-arg ETH_NODE_URL=$INDEXER_ETH_NODE \ - --build-arg FASTIFY_PLUGIN_TIMEOUT=60000 \ - --build-arg PORT=80 \ - -t $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG --no-cache . - - echo "**************************" - echo "*** Tag Image with $TGT_ENV-latest" - echo "**************************" - docker tag $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$TGT_ENV-latest - - echo "**************************" - echo "*** Push Images" - echo "**************************" - docker push $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG - docker push $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$TGT_ENV-latest - -.update_raw_task_definition: &update_raw_task_definition | - echo "**************************" - aws ecs describe-task-definition --region $AWS_DEFAULT_REGION --task-definition tsk-$CI_AWS_ECS_SVC > output.json - echo "**************************" - echo "*** Original Task Definition" - echo "**************************" - jq . output.json - - # Update the Image - jq '.taskDefinition.containerDefinitions[].image = "'$CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$TGT_ENV-latest'"' output.json > updated.json - - # Extract JUST Task Definition from the output.json file - jq '.taskDefinition' updated.json > extracted.json - - # Remove sections that are not needed - jq 'del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredBy, .registeredAt)' extracted.json > input.json - sed -i 's/'$CI_AWS_ACCOUNT_SBX'/'$TGT_ACCOUNT'/g' input.json - - echo "**************************" - echo "*** New Task Definition" - echo "**************************" - jq . input.json - -.deploy_new_task_definition: &deploy_new_task_definition | - aws ecs register-task-definition --region $AWS_DEFAULT_REGION --cli-input-json file://input.json - REVISION=$(aws ecs describe-task-definition --task-definition tsk-$CI_AWS_ECS_SVC --region $AWS_DEFAULT_REGION | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//' | cut -d "," -f 1) - echo "****************************************************" - echo "****************************************************" - echo "*** Update Task: " - echo "*** - AWS Account: Titanio-$TGT_ENV" - echo "*** - Cluster: ecs-$CI_AWS_ECS_CLUSTER-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION" - echo "*** - Service: svc-$CI_AWS_ECS_SVC-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION" - echo "*** - Task: tsk-$CI_AWS_ECS_SVC:$REVISION" - echo "*** - Image: $CI_AWS_TitanIO_NET_ECR/$CI_AWS_ECS_SVC:$IMAGE_TAG" - echo "****************************************************" - echo "****************************************************" - aws ecs update-service --region $AWS_DEFAULT_REGION --cluster ecs-$CI_AWS_ECS_CLUSTER-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION --service svc-$CI_AWS_ECS_SVC-$TGT_ENV-$CI_AWS_ECS_CLUSTER_REGION --task-definition tsk-$CI_AWS_ECS_SVC:$REVISION - - -bedrock-02-dev: - environment: - name: dev - url: https://indexer.dev.lumerin.io/api/healthcheck - stage: develop - only: - - dev - image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest - tags: - - devops - - bedrock - - titanio-dev - - shell - variables: - TGT_ACCOUNT: $CI_AWS_ACCOUNT_DEV - TGT_ENV: dev - script: - - *ecr_login_script - - *create_image_tag - - *build_image - - *update_raw_task_definition - - *deploy_new_task_definition - - echo "$TGT_ENV Updated" - -titanio-03-stg: - environment: - name: stg - url: https://indexer.stg.lumerin.io/api/healthcheck - stage: review - only: - - stg - image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest - tags: - - devops - - bedrock - - titanio-stg - - shell - variables: - TGT_ACCOUNT: $CI_AWS_ACCOUNT_STG - TGT_ENV: stg - script: - - *ecr_login_script - - *create_image_tag - - *build_image - - *update_raw_task_definition - - *deploy_new_task_definition - - echo "$TGT_ENV Updated" - -titanio-04-lmn-PROD: - environment: - name: lmn - url: https://indexer.lumerin.io/api/healthcheck - stage: deploy - only: - - main - when: manual - image: registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest - tags: - - devops - - bedrock - - titanio-lmn - - shell - variables: - TGT_ACCOUNT: $CI_AWS_ACCOUNT_LMN - TGT_ENV: lmn - script: - - *ecr_login_script - - *create_image_tag - - *build_image - - *update_raw_task_definition - - *deploy_new_task_definition - - echo "$TGT_ENV Updated" diff --git a/package.json b/package.json index a37e13d..eed5644 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "url": "https://lumerin.io" }, "license": "MIT", - "copyright": "Copyright © 5 Titan Industries (Global) Co. Ltd.", + "copyright": "Copyright © 2025 Titan Industries (Global) Co. Ltd.", "dependencies": { "@fastify/autoload": "^5.0.0", "@fastify/cors": "^9.0.1", From f590c2e0c833fc153423a26b59d58166aa15b42b Mon Sep 17 00:00:00 2001 From: abs2023 Date: Wed, 30 Apr 2025 16:28:58 -0400 Subject: [PATCH 17/35] fix variable order --- .github/workflows/build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 908d33a..469be7a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -159,15 +159,16 @@ jobs: - name: Build and Push Multi-Platform Docker Image run: | + BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} + BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} + BUILDCOMMIT=${{ github.sha }} + FULLTAG=${{ needs.Generate-Tag.outputs.vfull }} echo "Injecting version $FULLTAG into package.json" sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package.json cat ./package.json | grep '"version"' # Optional: Verify the change echo "Injecting version $FULLTAG into package-lock.json" sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package-lock.json cat ./package-lock.json | grep '"version"' # Optional: Verify the change - BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} - BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} - BUILDCOMMIT=${{ github.sha }} docker buildx build \ --platform linux/amd64 \ --build-arg TAG_NAME=$BUILDTAG \ From cc2f5d21ee8c89bec3ea3362e508cb2ca1187223 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Wed, 30 Apr 2025 16:33:08 -0400 Subject: [PATCH 18/35] fixing jobs --- .github/workflows/build.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 469be7a..fff77cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -116,6 +116,9 @@ jobs: - name: Build Docker Image to Test run: | + # Ensure we're in the workspace directory + cd $GITHUB_WORKSPACE + BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} BUILDCOMMIT=${{ github.sha }} @@ -159,15 +162,27 @@ jobs: - name: Build and Push Multi-Platform Docker Image run: | + # Ensure we're in the workspace directory + cd $GITHUB_WORKSPACE + BUILDTAG=${{ needs.Generate-Tag.outputs.tag_name }} BUILDIMAGE=${{ needs.Generate-Tag.outputs.image_name }} BUILDCOMMIT=${{ github.sha }} FULLTAG=${{ needs.Generate-Tag.outputs.vfull }} + + # Debug: Show current directory and file existence + pwd + ls -la + echo "Checking if package.json exists..." + [ -f ./package.json ] && echo "package.json exists" || echo "package.json does not exist" + echo "Checking if package-lock.json exists..." + [ -f ./package-lock.json ] && echo "package-lock.json exists" || echo "package-lock.json does not exist" + echo "Injecting version $FULLTAG into package.json" - sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package.json + sed -i "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package.json cat ./package.json | grep '"version"' # Optional: Verify the change echo "Injecting version $FULLTAG into package-lock.json" - sed -i "" "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package-lock.json + sed -i "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package-lock.json cat ./package-lock.json | grep '"version"' # Optional: Verify the change docker buildx build \ --platform linux/amd64 \ From d50e7eee9b17bcdd981ae331486c9555d5926e2a Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Fri, 2 May 2025 16:23:26 +0200 Subject: [PATCH 19/35] ignore .env.test --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5c1e4f6..9e8191c 100644 --- a/.gitignore +++ b/.gitignore @@ -58,8 +58,7 @@ profile* *flamegraph* .env -.env.dev +.env.test .env.prod -.env.stg dist \ No newline at end of file From b51b50b28587524b5708774afa9a7136aa189591 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Sat, 3 May 2025 11:21:00 -0400 Subject: [PATCH 20/35] update to use VAR for gitlab_trigger_url (visibility) --- .github/workflows/build.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fff77cb..81376e4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -175,15 +175,9 @@ jobs: ls -la echo "Checking if package.json exists..." [ -f ./package.json ] && echo "package.json exists" || echo "package.json does not exist" - echo "Checking if package-lock.json exists..." - [ -f ./package-lock.json ] && echo "package-lock.json exists" || echo "package-lock.json does not exist" - echo "Injecting version $FULLTAG into package.json" sed -i "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package.json cat ./package.json | grep '"version"' # Optional: Verify the change - echo "Injecting version $FULLTAG into package-lock.json" - sed -i "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package-lock.json - cat ./package-lock.json | grep '"version"' # Optional: Verify the change docker buildx build \ --platform linux/amd64 \ --build-arg TAG_NAME=$BUILDTAG \ @@ -243,7 +237,7 @@ jobs: echo "✅ Sending Request to GitLab branch: $GITLABBRANCH" response=$(curl --silent \ --request POST \ - --url "${{ secrets.GITLAB_TRIGGER_URL }}" \ + --url "${{ vars.GITLAB_TRIGGER_URL }}" \ --form "token=${{ secrets.GITLAB_TRIGGER_TOKEN }}" \ --form "ref=$GITLABBRANCH" \ --form "variables[SOURCE_REPO]=${{ github.repository }}" \ From 7b5b4d8bd7a9e6bfcd3199dc6f84bd485c450106 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Sat, 3 May 2025 20:20:40 -0400 Subject: [PATCH 21/35] listen on all ports --- src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.ts b/src/server.ts index 931c6b2..9880e19 100644 --- a/src/server.ts +++ b/src/server.ts @@ -57,7 +57,7 @@ export class Server { ); // Start listening. - app.listen({ port: config.PORT }, (err) => { + app.listen({ port: config.PORT, host: '0.0.0.0' }, (err) => { if (err) { app.log.error(err); reject(err); From cae0a2acaedd3ea2c660869f0c2a5b50c2a5d6f7 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Sun, 4 May 2025 11:03:15 -0400 Subject: [PATCH 22/35] modify and simplify dependecies --- .github/workflows/build.yml | 11 +++-------- Dockerfile | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 81376e4..da85b4f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -97,12 +97,11 @@ jobs: echo "✅ Docker Image: ${IMAGE_NAME}:${VTAG}" >> $GITHUB_STEP_SUMMARY echo "❌ Old Major Tag: $VLAST" >> $GITHUB_STEP_SUMMARY - Build-Indexer-Container: - name: Build Indexer Container + Test-Build-Indexer-Container: + name: Test Build Indexer Container if: ( (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'test' || github.base_ref == 'dev')) || - (github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/cicd/') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' || github.ref == 'refs/heads/dev')) || (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) ) runs-on: ubuntu-latest @@ -141,7 +140,6 @@ jobs: ) needs: - Generate-Tag - - Build-Indexer-Container runs-on: ubuntu-latest steps: - name: Checkout repository @@ -150,9 +148,6 @@ jobs: fetch-depth: 0 fetch-tags: true - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: @@ -178,7 +173,7 @@ jobs: echo "Injecting version $FULLTAG into package.json" sed -i "s/\"version\": \".*\"/\"version\": \"$FULLTAG\"/" ./package.json cat ./package.json | grep '"version"' # Optional: Verify the change - docker buildx build \ + docker build \ --platform linux/amd64 \ --build-arg TAG_NAME=$BUILDTAG \ --build-arg COMMIT=$BUILDCOMMIT \ diff --git a/Dockerfile b/Dockerfile index e56bcdf..88e7fc8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ COPY ./package*.json ./ RUN npm ci COPY . . -# Build +# Build NPM RUN npm run build # Remove dev dependencies after build From 60c1629e27e2dcb51700581e79381957791cefb4 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Sun, 4 May 2025 11:05:54 -0400 Subject: [PATCH 23/35] made sure to test build on push to dev as well as any PR to dev/test/main branches --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index da85b4f..63212c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -101,6 +101,7 @@ jobs: name: Test Build Indexer Container if: ( + (github.event_name == 'push' && github.ref == 'refs/heads/dev') || (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'test' || github.base_ref == 'dev')) || (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) ) From e3d78b914011cfe760a6d7c97ed9a3aea5aef6a0 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Mon, 5 May 2025 14:27:32 +0200 Subject: [PATCH 24/35] fix: buyer address --- package-lock.json | 6 +++--- package.json | 4 ++-- src/app.ts | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f58c767..b15cfbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.2", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.3", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -1614,8 +1614,8 @@ } }, "node_modules/contracts-js": { - "version": "2.0.2", - "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#c4a273eb36ee6e9e381ed28329a8181104281b51", + "version": "2.0.3", + "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#cec7c7c093355a71e3dd73c98846e9b5fb64a9bc", "dependencies": { "ethereum-abi-types-generator": "^1.3.4" } diff --git a/package.json b/package.json index b69912e..8474e09 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.2", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.3", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -38,4 +38,4 @@ "tsx": "^4.19.3", "typescript": "^5.8.3" } -} +} \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index e60bb7b..669d0ab 100644 --- a/src/app.ts +++ b/src/app.ts @@ -37,10 +37,12 @@ async function main() { log.info("Chain ID", chainId); if (config.MULTICALL_ADDRESS) { + log.info("Using custom multicall address", config.MULTICALL_ADDRESS); chain.contracts = { ...chain.contracts, multicall3: { address: config.MULTICALL_ADDRESS as `0x${string}` }, }; + log.info("Multicall address", config.MULTICALL_ADDRESS); } const ethClientLogger = log.child({ module: "ethClient" }); From 80df51be0806711bf373d348fc31f1b8ff05b74b Mon Sep 17 00:00:00 2001 From: abs2023 Date: Mon, 5 May 2025 09:52:15 -0400 Subject: [PATCH 25/35] remove test branch ... dev and main only --- .github/workflows/build.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 63212c5..8653b2e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,6 @@ on: push: branches: - main - - test - dev - cicd/* @@ -101,8 +100,7 @@ jobs: name: Test Build Indexer Container if: ( - (github.event_name == 'push' && github.ref == 'refs/heads/dev') || - (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'test' || github.base_ref == 'dev')) || + (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'dev')) || (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) ) runs-on: ubuntu-latest @@ -136,7 +134,7 @@ jobs: name: Build & Push Docker Image if: | ( - (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test')) || + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) || (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) ) needs: @@ -198,7 +196,7 @@ jobs: name: Deploy Indexer to GitLab if: | ( - (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test')) + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) ) needs: - Generate-Tag @@ -222,7 +220,7 @@ jobs: FULLTAG=${{ needs.Generate-Tag.outputs.vfull }} echo "Triggering GitLab Deploy for branch ${{ github.ref_name }} with tag $BUILDTAG" # Determine branch - if [ "${{ github.ref_name }}" == "test" ]; then + if [ "${{ github.ref_name }}" == "dev" ]; then GITLABBRANCH="dev" elif [ "${{ github.ref_name }}" == "main" ]; then GITLABBRANCH="main" From 07b98f40915322127d33a0c591b08dc0b17bfc36 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Wed, 14 May 2025 13:28:26 +0200 Subject: [PATCH 26/35] fix: listen to fee updated event --- package-lock.json | 721 +++++++++++++++---------------- package.json | 4 +- src/app.ts | 15 +- src/indexer-job.ts | 17 +- src/routes/root.ts | 4 +- src/server.ts | 6 +- src/services/blockchain.repo.ts | 7 + src/services/cache.repo.ts | 36 +- src/services/contract.service.ts | 7 +- src/services/listener.ts | 10 + src/services/mapper.ts | 2 +- src/services/price-calculator.ts | 23 +- src/types/hashrate-contract.ts | 1 - 13 files changed, 443 insertions(+), 410 deletions(-) diff --git a/package-lock.json b/package-lock.json index b15cfbb..e3309b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.3", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.5", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -35,12 +35,13 @@ "node_modules/@adraffy/ens-normalize": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", - "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "cpu": [ "ppc64" ], @@ -55,9 +56,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", - "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", "cpu": [ "arm" ], @@ -72,9 +73,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", - "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", "cpu": [ "arm64" ], @@ -89,9 +90,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", - "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", "cpu": [ "x64" ], @@ -106,9 +107,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", - "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", "cpu": [ "arm64" ], @@ -123,9 +124,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", - "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", "cpu": [ "x64" ], @@ -140,9 +141,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", - "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", "cpu": [ "arm64" ], @@ -157,9 +158,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", - "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", "cpu": [ "x64" ], @@ -174,9 +175,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", - "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", "cpu": [ "arm" ], @@ -191,9 +192,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", - "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", "cpu": [ "arm64" ], @@ -208,9 +209,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", - "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", "cpu": [ "ia32" ], @@ -225,9 +226,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", - "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", "cpu": [ "loong64" ], @@ -242,9 +243,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", - "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", "cpu": [ "mips64el" ], @@ -259,9 +260,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", - "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", "cpu": [ "ppc64" ], @@ -276,9 +277,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", - "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", "cpu": [ "riscv64" ], @@ -293,9 +294,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", - "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", "cpu": [ "s390x" ], @@ -310,9 +311,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", - "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", "cpu": [ "x64" ], @@ -327,9 +328,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", - "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", "cpu": [ "arm64" ], @@ -344,9 +345,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", - "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", "cpu": [ "x64" ], @@ -361,9 +362,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", - "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", "cpu": [ "arm64" ], @@ -378,9 +379,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", - "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", "cpu": [ "x64" ], @@ -395,9 +396,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", - "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", "cpu": [ "x64" ], @@ -412,9 +413,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", - "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", "cpu": [ "arm64" ], @@ -429,9 +430,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", - "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", "cpu": [ "ia32" ], @@ -446,9 +447,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", - "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", "cpu": [ "x64" ], @@ -1194,6 +1195,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.6.0.tgz", "integrity": "sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==", + "license": "MIT", "dependencies": { "ajv": "^8.11.0", "ajv-formats": "^2.1.1", @@ -1203,12 +1205,14 @@ "node_modules/@fastify/ajv-compiler/node_modules/fast-uri": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", - "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==" + "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==", + "license": "MIT" }, "node_modules/@fastify/cors": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz", "integrity": "sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==", + "license": "MIT", "dependencies": { "fastify-plugin": "^4.0.0", "mnemonist": "0.39.6" @@ -1217,12 +1221,14 @@ "node_modules/@fastify/error": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", - "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==" + "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==", + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "fast-json-stringify": "^5.7.0" } @@ -1231,6 +1237,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", "integrity": "sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" } @@ -1239,6 +1246,7 @@ "version": "5.6.0", "resolved": "https://registry.npmjs.org/@fastify/sensible/-/sensible-5.6.0.tgz", "integrity": "sha512-Vq6Z2ZQy10GDqON+hvLF52K99s9et5gVVxTul5n3SIAf0Kq5QjPRUKkAMT3zPAiiGvoHtS3APa/3uaxfDgCODQ==", + "license": "MIT", "dependencies": { "@lukeed/ms": "^2.0.1", "fast-deep-equal": "^3.1.1", @@ -1262,6 +1270,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "license": "MIT", "engines": { "node": ">=8" } @@ -1270,6 +1279,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", "dependencies": { "@noble/hashes": "1.3.2" }, @@ -1281,6 +1291,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", "engines": { "node": ">= 16" }, @@ -1289,32 +1300,35 @@ } }, "node_modules/@scure/base": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz", - "integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.5.tgz", + "integrity": "sha512-9rE6EOVeIQzt5TSu4v+K523F8u6DhBsoZWPGKlnCshhlDhy0kJzUX4V+tr2dWmzF1GdekvThABoEQBGBQI7xZw==", + "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.0.tgz", - "integrity": "sha512-82q1QfklrUUdXJzjuRU7iG7D7XiFx5PHYVS0+oeNKhyDLT7WPqs6pBcM2W5ZdwOwKCwoE1Vy1se+DHjcXwCYnA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "license": "MIT", "dependencies": { - "@noble/curves": "~1.7.0", - "@noble/hashes": "~1.6.0", - "@scure/base": "~1.2.1" + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32/node_modules/@noble/curves": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", - "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", + "license": "MIT", "dependencies": { - "@noble/hashes": "1.6.0" + "@noble/hashes": "1.7.2" }, "engines": { "node": "^14.21.3 || >=16" @@ -1323,21 +1337,11 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/@scure/bip32/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", - "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", - "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "license": "MIT", "engines": { "node": "^14.21.3 || >=16" }, @@ -1346,21 +1350,23 @@ } }, "node_modules/@scure/bip39": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.0.tgz", - "integrity": "sha512-Dop+ASYhnrwm9+HA/HwXg7j2ZqM6yk2fyLWb5znexjctFY3+E+eU8cIWI0Pql0Qx4hPZCijlGq4OL71g+Uz30A==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "license": "MIT", "dependencies": { - "@noble/hashes": "~1.6.0", - "@scure/base": "~1.2.1" + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip39/node_modules/@noble/hashes": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", - "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "license": "MIT", "engines": { "node": "^14.21.3 || >=16" }, @@ -1384,18 +1390,19 @@ } }, "node_modules/@types/node": { - "version": "22.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", - "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "version": "22.15.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", + "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, "node_modules/abitype": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.7.tgz", - "integrity": "sha512-ZfYYSktDQUwc2eduYu8C4wOs+RDPmnRYMh7zNfzeMtGGgb0U+6tLGjixUic6mXf5xKKCcgT5Qp6cv39tOARVFw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", + "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" }, @@ -1415,17 +1422,20 @@ "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==" + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", + "license": "MIT" }, "node_modules/aes-js": { "version": "4.0.0-beta.5", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -1441,6 +1451,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -1499,6 +1510,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", "engines": { "node": ">=8.0.0" } @@ -1507,6 +1519,7 @@ "version": "8.4.0", "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.4.0.tgz", "integrity": "sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==", + "license": "MIT", "dependencies": { "@fastify/error": "^3.3.0", "fastq": "^1.17.1" @@ -1539,21 +1552,6 @@ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", "license": "MIT" }, - "node_modules/bufferutil": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", - "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1602,7 +1600,8 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/colors": { "version": "1.4.0", @@ -1614,8 +1613,8 @@ } }, "node_modules/contracts-js": { - "version": "2.0.3", - "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#cec7c7c093355a71e3dd73c98846e9b5fb64a9bc", + "version": "2.0.5", + "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#9cda3315738c9a8f1667c9f45996f921e199f0bb", "dependencies": { "ethereum-abi-types-generator": "^1.3.4" } @@ -1624,6 +1623,7 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -1633,6 +1633,7 @@ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -1650,14 +1651,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -1669,6 +1672,7 @@ "version": "10.0.0", "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" } @@ -1705,6 +1709,7 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, + "license": "MIT", "dependencies": { "once": "^1.4.0" } @@ -1713,6 +1718,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/env-schema/-/env-schema-5.2.1.tgz", "integrity": "sha512-gWMNrQ3dVHAZcCx7epiFwgXcyfBh4heD/6+OK3bEbke3uL+KqwYA9nUOwzJyRZh1cJOFcwdPuY1n0GKSFlSWAg==", + "license": "MIT", "dependencies": { "ajv": "^8.0.0", "dotenv": "^16.0.0", @@ -1720,9 +1726,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", - "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1733,31 +1739,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.3", - "@esbuild/android-arm": "0.25.3", - "@esbuild/android-arm64": "0.25.3", - "@esbuild/android-x64": "0.25.3", - "@esbuild/darwin-arm64": "0.25.3", - "@esbuild/darwin-x64": "0.25.3", - "@esbuild/freebsd-arm64": "0.25.3", - "@esbuild/freebsd-x64": "0.25.3", - "@esbuild/linux-arm": "0.25.3", - "@esbuild/linux-arm64": "0.25.3", - "@esbuild/linux-ia32": "0.25.3", - "@esbuild/linux-loong64": "0.25.3", - "@esbuild/linux-mips64el": "0.25.3", - "@esbuild/linux-ppc64": "0.25.3", - "@esbuild/linux-riscv64": "0.25.3", - "@esbuild/linux-s390x": "0.25.3", - "@esbuild/linux-x64": "0.25.3", - "@esbuild/netbsd-arm64": "0.25.3", - "@esbuild/netbsd-x64": "0.25.3", - "@esbuild/openbsd-arm64": "0.25.3", - "@esbuild/openbsd-x64": "0.25.3", - "@esbuild/sunos-x64": "0.25.3", - "@esbuild/win32-arm64": "0.25.3", - "@esbuild/win32-ia32": "0.25.3", - "@esbuild/win32-x64": "0.25.3" + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" } }, "node_modules/ethereum-abi-types-generator": { @@ -1856,22 +1862,10 @@ "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", "license": "MIT" }, - "node_modules/ethereum-abi-types-generator/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", - "license": "MIT" - }, - "node_modules/ethereum-abi-types-generator/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details." - }, "node_modules/ethers": { - "version": "6.13.5", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", - "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.14.0.tgz", + "integrity": "sha512-KgHwltNSMdbrGWEyKkM0Rt2s+u1nDH/5BVDQakLinzGEJi4bWindBzZSCC4gKsbZjwDTI6ex/8suR9Ihbmz4IQ==", "funding": [ { "type": "individual", @@ -1882,6 +1876,7 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", @@ -1899,14 +1894,22 @@ "version": "22.7.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", + "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, "node_modules/ethers/node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" }, "node_modules/ethersv5": { "name": "ethers", @@ -1960,33 +1963,39 @@ "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" }, "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==" + "integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==", + "license": "MIT" }, "node_modules/fast-copy": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", - "dev": true + "dev": true, + "license": "MIT" }, "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==" + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", + "license": "MIT" }, "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==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, "node_modules/fast-json-stringify": { "version": "5.16.1", "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.16.1.tgz", "integrity": "sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==", + "license": "MIT", "dependencies": { "@fastify/merge-json-schemas": "^0.1.0", "ajv": "^8.10.0", @@ -2001,6 +2010,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", "dependencies": { "ajv": "^8.0.0" }, @@ -2016,12 +2026,14 @@ "node_modules/fast-json-stringify/node_modules/fast-uri": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", - "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==" + "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==", + "license": "MIT" }, "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==", + "license": "MIT", "dependencies": { "fast-decode-uri-component": "^1.0.1" } @@ -2030,6 +2042,7 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -2038,12 +2051,13 @@ "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==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", "funding": [ { "type": "github", @@ -2053,12 +2067,13 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/fastify": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.29.0.tgz", - "integrity": "sha512-MaaUHUGcCgC8fXQDsDtioaCcag1fmPJ9j64vAKunqZF4aSub040ZGi/ag8NGE2714yREPOKZuHCfpPzuUD3UQQ==", + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.29.1.tgz", + "integrity": "sha512-m2kMNHIG92tSNWv+Z3UeTR9AWLLuo7KctC7mlFPtMEVrfjIhmQhkQnT9v15qA/BfVq3vvj134Y0jl9SBje3jXQ==", "funding": [ { "type": "github", @@ -2069,6 +2084,7 @@ "url": "https://opencollective.com/fastify" } ], + "license": "MIT", "dependencies": { "@fastify/ajv-compiler": "^3.5.0", "@fastify/error": "^3.4.0", @@ -2091,12 +2107,14 @@ "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==" + "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==", + "license": "MIT" }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -2105,6 +2123,7 @@ "version": "8.2.2", "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.2.2.tgz", "integrity": "sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-querystring": "^1.0.0", @@ -2131,6 +2150,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2156,6 +2176,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -2202,6 +2223,13 @@ "minimalistic-assert": "^1.0.1" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true, + "license": "MIT" + }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -2217,6 +2245,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -2231,12 +2260,14 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -2260,6 +2291,7 @@ "url": "https://github.com/sponsors/wevm" } ], + "license": "MIT", "peerDependencies": { "ws": "*" } @@ -2269,6 +2301,7 @@ "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -2283,6 +2316,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3" } @@ -2290,7 +2324,8 @@ "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==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, "node_modules/jsonfile": { "version": "6.1.0", @@ -2308,6 +2343,7 @@ "version": "5.14.0", "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.14.0.tgz", "integrity": "sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==", + "license": "BSD-3-Clause", "dependencies": { "cookie": "^0.7.0", "process-warning": "^3.0.0", @@ -2330,6 +2366,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2338,6 +2375,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2346,6 +2384,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -2370,6 +2409,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2378,32 +2418,22 @@ "version": "0.39.6", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz", "integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==", + "license": "MIT", "dependencies": { "obliterator": "^2.0.1" } }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "license": "MIT", - "optional": true, - "peer": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/obliterator": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", - "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==" + "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", + "license": "MIT" }, "node_modules/on-exit-leak-free": { "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==", + "license": "MIT", "engines": { "node": ">=14.0.0" } @@ -2413,20 +2443,22 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/ox": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.0.tgz", - "integrity": "sha512-blUzTLidvUlshv0O02CnLFqBLidNzPoAZdIth894avUAotTuWziznv6IENv5idRuOSSP3dH8WzcYw84zVdu0Aw==", + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", + "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/wevm" } ], + "license": "MIT", "dependencies": { "@adraffy/ens-normalize": "^1.10.1", "@noble/curves": "^1.6.0", @@ -2446,11 +2478,12 @@ } }, "node_modules/ox/node_modules/@noble/curves": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", - "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", "dependencies": { - "@noble/hashes": "1.7.0" + "@noble/hashes": "1.8.0" }, "engines": { "node": "^14.21.3 || >=16" @@ -2460,9 +2493,10 @@ } }, "node_modules/ox/node_modules/@noble/hashes": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", - "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", "engines": { "node": "^14.21.3 || >=16" }, @@ -2541,18 +2575,11 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", "dependencies": { "split2": "^4.0.0" } }, - "node_modules/pino-abstract-transport/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/pino-pretty": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.0.0.tgz", @@ -2578,16 +2605,11 @@ "pino-pretty": "bin.js" } }, - "node_modules/pino-pretty/node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "dev": true - }, "node_modules/pino-std-serializers": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", - "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==" + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "license": "MIT" }, "node_modules/pino/node_modules/process-warning": { "version": "4.0.1", @@ -2602,7 +2624,8 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ] + ], + "license": "MIT" }, "node_modules/prettier": { "version": "2.8.8", @@ -2622,12 +2645,14 @@ "node_modules/process-warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==" + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "license": "MIT" }, "node_modules/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==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -2641,6 +2666,7 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, + "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -2649,12 +2675,14 @@ "node_modules/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==" + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", "engines": { "node": ">= 12.13.0" } @@ -2678,6 +2706,7 @@ "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==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2702,14 +2731,16 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/ret/-/ret-0.4.3.tgz", "integrity": "sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==", + "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -2718,12 +2749,14 @@ "node_modules/rfdc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" }, "node_modules/safe-regex2": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-3.1.0.tgz", "integrity": "sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==", + "license": "MIT", "dependencies": { "ret": "~0.4.0" } @@ -2732,6 +2765,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", "engines": { "node": ">=10" } @@ -2745,12 +2779,14 @@ "node_modules/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==" + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -2767,25 +2803,44 @@ "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==" + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, + "node_modules/setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", + "license": "MIT" }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/sonic-boom": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz", "integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==", + "license": "MIT", "dependencies": { "atomic-sleep": "^1.0.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -2821,6 +2876,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -2832,6 +2888,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "license": "MIT", "dependencies": { "real-require": "^0.2.0" } @@ -2840,6 +2897,7 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", + "license": "MIT", "engines": { "node": ">=12" } @@ -2848,19 +2906,21 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "version": "4.19.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", + "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2881,6 +2941,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -2918,49 +2979,41 @@ "node": ">= 10.0.0" } }, - "node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } + "node_modules/uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details." }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/viem": { - "version": "2.22.4", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.22.4.tgz", - "integrity": "sha512-35/T2ySpUM0kUVEy2SkaWIAIabSRzF/IZxDdnLxuaI1pwURC92ZiHa9J9nL1rWGl0HTyAqUxcycgJEpOvHrcQA==", + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.29.2.tgz", + "integrity": "sha512-cukRxab90jvQ+TDD84sU3qB3UmejYqgCw4cX8SfWzvh7JPfZXI3kAMUaT5OSR2As1Mgvx1EJawccwPjGqkSSwA==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/wevm" } ], + "license": "MIT", "dependencies": { - "@noble/curves": "1.7.0", - "@noble/hashes": "1.6.1", - "@scure/bip32": "1.6.0", - "@scure/bip39": "1.5.0", - "abitype": "1.0.7", + "@noble/curves": "1.8.2", + "@noble/hashes": "1.7.2", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", "isows": "1.0.6", - "ox": "0.6.0", - "webauthn-p256": "0.0.10", - "ws": "8.18.0" + "ox": "0.6.9", + "ws": "8.18.1" }, "peerDependencies": { "typescript": ">=5.0.4" @@ -2972,11 +3025,12 @@ } }, "node_modules/viem/node_modules/@noble/curves": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.7.0.tgz", - "integrity": "sha512-UTMhXK9SeDhFJVrHeUJ5uZlI6ajXg10O6Ddocf9S6GjbSBVZsJo88HzKwXznNfGpMTRDyJkqMjNDPYgf0qFWnw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", + "license": "MIT", "dependencies": { - "@noble/hashes": "1.6.0" + "@noble/hashes": "1.7.2" }, "engines": { "node": "^14.21.3 || >=16" @@ -2985,21 +3039,11 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/viem/node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.0.tgz", - "integrity": "sha512-YUULf0Uk4/mAA89w+k3+yUYh6NrEvxZa5T6SY3wlMvE2chHkxFUUIDI8/XW1QSC357iA5pSnqt7XEhvFOqmDyQ==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/viem/node_modules/@noble/hashes": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", - "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "license": "MIT", "engines": { "node": "^14.21.3 || >=16" }, @@ -3008,9 +3052,10 @@ } }, "node_modules/viem/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -3027,46 +3072,6 @@ } } }, - "node_modules/webauthn-p256": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz", - "integrity": "sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "dependencies": { - "@noble/curves": "^1.4.0", - "@noble/hashes": "^1.4.0" - } - }, - "node_modules/webauthn-p256/node_modules/@noble/curves": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", - "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", - "dependencies": { - "@noble/hashes": "1.7.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/webauthn-p256/node_modules/@noble/hashes": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", - "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", @@ -3091,12 +3096,14 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -3162,16 +3169,6 @@ "engines": { "node": ">=6" } - }, - "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", - "optional": true, - "peer": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } } } } diff --git a/package.json b/package.json index 8474e09..0456cbe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "contracts-indexer", - "version": "1.1.0", + "version": "1.1.1", "description": "", "main": "index.js", "engines": { @@ -25,7 +25,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.3", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.5", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", diff --git a/src/app.ts b/src/app.ts index 669d0ab..1e3becc 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,5 +1,5 @@ import { ContractsLoader } from "./services/blockchain.repo"; -import { ContractsInMemoryIndexer } from "./services/cache.repo"; +import { Cache } from "./services/cache.repo"; import { config } from "./config/env"; import { http } from "viem"; import { createPublicClient } from "viem"; @@ -58,23 +58,26 @@ async function main() { }); const loader = new ContractsLoader(client, config.CLONE_FACTORY_ADDRESS); - const indexer = new ContractsInMemoryIndexer(); + const feeRate = await loader.getFeeRate(); + const cache = new Cache(); + cache.setFeeRate(feeRate); + const service = new ContractService( - indexer, + cache, new PriceCalculator( client, config.HASHRATE_ORACLE_ADDRESS as `0x${string}`, - config.CLONE_FACTORY_ADDRESS as `0x${string}`, + cache, log.child({ module: "priceCalculator" }) ) ); - const server = new Server(indexer, loader, service, log.child({ module: "server" })); + const server = new Server(cache, loader, service, log.child({ module: "server" })); log.info(`Starting app with config: ${JSON.stringify(config)}`); // TODO: split into multiple phases await Promise.all([ - indexerJob.start(client, loader, indexer, log.child({ module: "indexerJob" })), + indexerJob.start(client, loader, cache, log.child({ module: "indexerJob" })), server.start(), ]); } diff --git a/src/indexer-job.ts b/src/indexer-job.ts index 9bb80f0..f872aec 100644 --- a/src/indexer-job.ts +++ b/src/indexer-job.ts @@ -1,6 +1,6 @@ import { PublicClient } from "viem"; import { ContractsLoader } from "./services/blockchain.repo"; -import { ContractsInMemoryIndexer } from "./services/cache.repo"; +import { Cache } from "./services/cache.repo"; import { startWatchPromise } from "./services/listener"; import { HashrateContract } from "./types/hashrate-contract"; import { FastifyBaseLogger } from "fastify"; @@ -8,7 +8,7 @@ import { FastifyBaseLogger } from "fastify"; export const start = async ( client: PublicClient, loader: ContractsLoader, - indexer: ContractsInMemoryIndexer, + indexer: Cache, log: FastifyBaseLogger ) => { log.info("Initial load of contracts"); @@ -17,23 +17,28 @@ export const start = async ( log.info("Loaded contracts", res.contracts.length); for (const contract of res.contracts) { - await updateContract(contract, Number(res.blockNumber), indexer, log); + updateContract(contract, Number(res.blockNumber), indexer, log); } await startWatchPromise(client, { initialContractsToWatch: new Set(res.contracts.map((c) => c.id)), onContractUpdate: async (contractAddr: string, blockNumber: number) => { const contract = await loader.getContract(contractAddr as `0x${string}`); - await updateContract(contract, blockNumber, indexer, log); + updateContract(contract, blockNumber, indexer, log); + }, + onFeeUpdate: async (feeRateScaled: bigint) => { + const decimals = await loader.cloneFactory.read.VALIDATOR_FEE_DECIMALS(); + log.info("Fee rate updated", { feeRateScaled, decimals }); + indexer.setFeeRate({ value: feeRateScaled, decimals: BigInt(decimals) }); }, log, }); }; -async function updateContract( +function updateContract( contract: HashrateContract, blockNumber: number, - indexer: ContractsInMemoryIndexer, + indexer: Cache, log: FastifyBaseLogger ) { indexer.upsert(contract, blockNumber); diff --git a/src/routes/root.ts b/src/routes/root.ts index 28dd22e..503d109 100644 --- a/src/routes/root.ts +++ b/src/routes/root.ts @@ -1,7 +1,7 @@ import { ContractsLoader } from "../services/blockchain.repo"; import { Config } from "../config/env"; import { ContractService } from "../services/contract.service"; -import { ContractsInMemoryIndexer } from "../services/cache.repo"; +import { Cache } from "../services/cache.repo"; import { ServerType } from "../server"; import { Type } from "@sinclair/typebox"; @@ -9,7 +9,7 @@ export async function router( fastify: ServerType, config: Config, service: ContractService, - indexer: ContractsInMemoryIndexer, + indexer: Cache, loader: ContractsLoader ) { fastify.get( diff --git a/src/server.ts b/src/server.ts index 9880e19..0368caa 100644 --- a/src/server.ts +++ b/src/server.ts @@ -3,7 +3,7 @@ import Fastify from "fastify"; import closeWithGrace from "close-with-grace"; import cors from "@fastify/cors"; import { router } from "./routes/root"; -import { ContractsInMemoryIndexer } from "./services/cache.repo"; +import { Cache } from "./services/cache.repo"; import { ContractsLoader } from "./services/blockchain.repo"; import sensible from "@fastify/sensible"; import { ContractService } from "./services/contract.service"; @@ -14,7 +14,7 @@ export class Server { private app: ServerType; constructor( - readonly indexer: ContractsInMemoryIndexer, + readonly indexer: Cache, readonly loader: ContractsLoader, readonly service: ContractService, readonly log: Logger @@ -57,7 +57,7 @@ export class Server { ); // Start listening. - app.listen({ port: config.PORT, host: '0.0.0.0' }, (err) => { + app.listen({ port: config.PORT, host: "0.0.0.0" }, (err) => { if (err) { app.log.error(err); reject(err); diff --git a/src/services/blockchain.repo.ts b/src/services/blockchain.repo.ts index fb69031..bbbec2b 100644 --- a/src/services/blockchain.repo.ts +++ b/src/services/blockchain.repo.ts @@ -121,6 +121,13 @@ export class ContractsLoader { return mapContract(contractId, pub, futureTerms, history, stats); } + + async getFeeRate() { + return { + value: await this.cloneFactory.read.validatorFeeRateScaled(), + decimals: BigInt(await this.cloneFactory.read.VALIDATOR_FEE_DECIMALS()), + }; + } } function chunkArray(array: T[], size: N): T[][] & { length: N } { diff --git a/src/services/cache.repo.ts b/src/services/cache.repo.ts index 802a3cd..2ebb868 100644 --- a/src/services/cache.repo.ts +++ b/src/services/cache.repo.ts @@ -3,16 +3,13 @@ import { HashrateContract } from "../types/hashrate-contract.js"; /** * In-memory indexer(cache) for contracts that keeps track block and time of the last update */ -export class ContractsInMemoryIndexer { - contracts: Record; - lastSyncedContractBlock: number; - lastSyncedTime: number; - - constructor() { - this.contracts = {}; - this.lastSyncedContractBlock = 0; - this.lastSyncedTime = 0; - } +export class Cache { + contracts: Record = {}; + lastSyncedContractBlock: number = 0; + lastSyncedTime: number = 0; + feeRate: FeeRate = { value: 0n, decimals: 0n }; + + constructor() {} get(id: string): HashrateContract | null { const contract = this.contracts[id.toLowerCase()]; @@ -35,8 +32,27 @@ export class ContractsInMemoryIndexer { this.#setLastSyncedContractBlock(blockNumber); } + getFeeRate(): FeeRate { + return { + value: this.feeRate.value, + decimals: this.feeRate.decimals, + }; + } + + setFeeRate(param: FeeRate) { + this.feeRate = { + value: param.value, + decimals: param.decimals, + }; + } + #setLastSyncedContractBlock(blockNumber: number | string) { this.lastSyncedContractBlock = Number(blockNumber); this.lastSyncedTime = Date.now(); } } + +export type FeeRate = { + value: bigint; + decimals: bigint; +}; diff --git a/src/services/contract.service.ts b/src/services/contract.service.ts index ab4e478..614f6a2 100644 --- a/src/services/contract.service.ts +++ b/src/services/contract.service.ts @@ -4,15 +4,12 @@ import { ContractHistory, ContractState, } from "../types/hashrate-contract"; -import { ContractsInMemoryIndexer } from "./cache.repo"; +import { Cache } from "./cache.repo"; import { PriceCalculator } from "./price-calculator"; /** Service for managing hashrate contracts. Adds price calculation and optional filtering history by wallet address */ export class ContractService { - constructor( - private readonly indexer: ContractsInMemoryIndexer, - private readonly priceCalculator: PriceCalculator - ) {} + constructor(private readonly indexer: Cache, private readonly priceCalculator: PriceCalculator) {} async getAll(filterHistoryByAddr?: string): Promise { const contracts = this.indexer.getAll(); diff --git a/src/services/listener.ts b/src/services/listener.ts index 2013bd4..b59809d 100644 --- a/src/services/listener.ts +++ b/src/services/listener.ts @@ -2,6 +2,7 @@ import { config } from "../config/env"; import { getAbiItem, parseAbi, PublicClient } from "viem"; import { FastifyBaseLogger } from "fastify"; import { abi } from "contracts-js"; +import { FeeRate } from "./cache.repo"; const cfAbi = abi.cloneFactoryAbi; const implAbi = abi.implementationAbi; @@ -9,6 +10,7 @@ const implAbi = abi.implementationAbi; type StartWatchProps = { initialContractsToWatch: Set; onContractUpdate: (contractAddr: string, blockNumber: number) => void; + onFeeUpdate: (newFeeRateScaled: bigint) => void; onError?: (error: Error) => void; blockNumber?: number; log: FastifyBaseLogger; @@ -36,6 +38,7 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { "clonefactoryContractPurchased", "contractDeleteUpdated", "purchaseInfoUpdated", + "validatorFeeRateUpdated", ]; const eventsAbi2 = [ @@ -44,6 +47,7 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { getAbiItem({ abi: cfAbi, name: "clonefactoryContractPurchased" }), getAbiItem({ abi: cfAbi, name: "contractDeleteUpdated" }), getAbiItem({ abi: cfAbi, name: "purchaseInfoUpdated" }), + getAbiItem({ abi: cfAbi, name: "validatorFeeRateUpdated" }), // Implementation Events getAbiItem({ abi: implAbi, name: "closedEarly" }), getAbiItem({ abi: implAbi, name: "fundsClaimed" }), @@ -63,6 +67,12 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { logs.forEach((log) => { const { eventName, args, address, blockNumber } = log; + + if (eventName === "validatorFeeRateUpdated") { + props.log.info("Received validatorFeeRateUpdated event"); + return props.onFeeUpdate(args._validatorFeeRateScaled!); + } + let contractAddress = null; if (cloneFactoryEvents.includes(eventName)) { contractAddress = (args as any)._address; diff --git a/src/services/mapper.ts b/src/services/mapper.ts index 65560d9..96cbed1 100644 --- a/src/services/mapper.ts +++ b/src/services/mapper.ts @@ -43,7 +43,7 @@ export function mapPublicVariablesV2(addr: string, pub: PublicVariablesV2Entry) id: addr.toLowerCase(), state: state.toString(), price: terms._price.toString(), - limit: terms._limit.toString(), + fee: terms._fee.toString(), speed: terms._speed.toString(), length: terms._length.toString(), version: terms._version.toString(), diff --git a/src/services/price-calculator.ts b/src/services/price-calculator.ts index ca14419..2e2227e 100644 --- a/src/services/price-calculator.ts +++ b/src/services/price-calculator.ts @@ -2,27 +2,30 @@ import { PublicClient, getContract } from "viem"; import { hashrateOracleAbi, cloneFactoryAbi } from "contracts-js/dist/abi/abi"; import { Logger } from "pino"; import { Mutex } from "async-mutex"; +import { FeeRate } from "./cache.repo"; + +interface FeeRateGetter { + getFeeRate(): FeeRate; +} export class PriceCalculator { private pricePerTHInToken: bigint | null; private oracle: ReturnType; - private cloneFactory: ReturnType; private priceExpirationTime = new Date(0); private ttl = 10 * 1000; // 10 seconds - private feeRate?: bigint; - private feeDecimals?: bigint; private mutex = new Mutex(); + private feeRateGetter: FeeRateGetter; private log: Logger; constructor( client: PublicClient, hashrateOracleAddr: `0x${string}`, - cloneFactoryAddr: `0x${string}`, + feeRateGetter: FeeRateGetter, log: Logger ) { this.oracle = getHashrateOracleContract(client, hashrateOracleAddr); - this.cloneFactory = getCloneFactoryContract(client, cloneFactoryAddr); this.pricePerTHInToken = null; + this.feeRateGetter = feeRateGetter; this.log = log; } @@ -34,8 +37,8 @@ export class PriceCalculator { const priceInTokens = totalHashes / hashesPerToken; const priceWithProfit = priceInTokens + (priceInTokens * BigInt(profitTargetPercent)) / BigInt(100); - const { rate, decimals } = await this.getFeeRate(); - const fee = (priceWithProfit * rate) / 10n ** decimals; + const { value, decimals } = await this.getFeeRate(); + const fee = (priceWithProfit * value) / 10n ** decimals; return { price: priceWithProfit, fee }; } @@ -57,11 +60,7 @@ export class PriceCalculator { } private async getFeeRate() { - if (!this.feeRate || !this.feeDecimals) { - this.feeRate = await this.cloneFactory.read.validatorFeeRateScaled(); - this.feeDecimals = BigInt(await this.cloneFactory.read.VALIDATOR_FEE_DECIMALS()); - } - return { rate: this.feeRate, decimals: this.feeDecimals }; + return this.feeRateGetter.getFeeRate(); } } diff --git a/src/types/hashrate-contract.ts b/src/types/hashrate-contract.ts index fe06294..62a8316 100644 --- a/src/types/hashrate-contract.ts +++ b/src/types/hashrate-contract.ts @@ -5,7 +5,6 @@ export type HashrateContract = { version: string; price: string; fee: string; - limit: string; speed: string; // in hashes per second length: string; // in seconds profitTarget: string; // in percent From 759969edd3b308d1ab4528b5d6a5e961fee73ebb Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Mon, 26 May 2025 16:03:31 +0200 Subject: [PATCH 27/35] feat: validator indexing --- .env.example | 8 ++ biome.json | 24 ++++ package-lock.json | 175 ++++++++++++++++++++++++- package.json | 9 +- src/app.ts | 41 +++--- src/config/env.ts | 4 +- src/indexer-job.ts | 27 ++-- src/routes/root.ts | 57 ++++---- src/server.ts | 36 +++-- src/services/blockchain.repo.ts | 60 ++++++--- src/services/blockchain.types.ts | 2 +- src/services/cache.repo.ts | 47 ++++++- src/services/contract.service.ts | 62 +++++---- src/services/contract.service.types.ts | 5 + src/services/listener.ts | 93 +++++++------ src/services/mapper.ts | 16 ++- src/services/price-calculator.ts | 20 +-- src/types/hashrate-contract.ts | 4 + src/types/history.ts | 10 ++ 19 files changed, 507 insertions(+), 193 deletions(-) create mode 100644 biome.json create mode 100644 src/services/contract.service.types.ts create mode 100644 src/types/history.ts diff --git a/.env.example b/.env.example index 7291935..ab42c31 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,15 @@ +#dev ADMIN_API_KEY=1234 CLONE_FACTORY_ADDRESS=0x15437978300786aDe37f61e02Be1C061e51353D3 ETH_NODE_URL=https://arb-mainnet.g.alchemy.com/v2/{API_KEY} FASTIFY_ADDRESS=0.0.0.0 FASTIFY_PLUGIN_TIMEOUT=60000 HASHRATE_ORACLE_ADDRESS=0xdc64a140aa3e981100a9beca4e685f962f0cf6c9 +PORT=3000 + +#local +ADMIN_API_KEY=1234 +CLONE_FACTORY_ADDRESS=0xb7f8bc63bbcad18155201308c8f3540b07f84f5e +ETH_NODE_URL=http://localhost:8545 +HASHRATE_ORACLE_ADDRESS=0xdc64a140aa3e981100a9beca4e685f962f0cf6c9 PORT=3000 \ No newline at end of file diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..599f3ea --- /dev/null +++ b/biome.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", + "organizeImports": { + "enabled": true + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 120, + "ignore": ["node_modules", "build"] + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "style": { + "noNonNullAssertion": "off", + "useImportType": "info" + } + }, + "ignore": ["node_modules", "dist"] + } +} diff --git a/package-lock.json b/package-lock.json index e3309b1..0baaadc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "contracts-indexer", - "version": "1.1.0", + "version": "1.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "contracts-indexer", - "version": "1.1.0", + "version": "1.1.1", "license": "MIT", "dependencies": { "@fastify/cors": "^9.0.1", @@ -15,7 +15,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.5", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.6", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -23,6 +23,7 @@ "viem": "^2.7.22" }, "devDependencies": { + "@biomejs/biome": "^1.9.4", "@types/node": "^22.14.1", "pino-pretty": "^13.0.0", "tsx": "^4.19.3", @@ -38,6 +39,170 @@ "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", "license": "MIT" }, + "node_modules/@biomejs/biome": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", + "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", + "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", + "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", + "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", + "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", + "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", + "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", + "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", + "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.4", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", @@ -1613,8 +1778,8 @@ } }, "node_modules/contracts-js": { - "version": "2.0.5", - "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#9cda3315738c9a8f1667c9f45996f921e199f0bb", + "version": "2.0.6", + "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#7f8e8f28fb2fcc3394bcf04c09d14c174269ef1c", "dependencies": { "ethereum-abi-types-generator": "^1.3.4" } diff --git a/package.json b/package.json index 0456cbe..b815984 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "scripts": { "dev": "tsx watch src/app.ts | pino-pretty", "build": "tsc", - "start": "node dist/app.js" + "start": "node dist/app.js", + "lint": "biome check .", + "lint:fix": "biome check . --write" }, "author": { "name": "Lumerin", @@ -25,7 +27,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.5", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.6", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -33,9 +35,10 @@ "viem": "^2.7.22" }, "devDependencies": { + "@biomejs/biome": "^1.9.4", "@types/node": "^22.14.1", "pino-pretty": "^13.0.0", "tsx": "^4.19.3", "typescript": "^5.8.3" } -} \ No newline at end of file +} diff --git a/src/app.ts b/src/app.ts index 1e3becc..3b86200 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,15 +1,16 @@ -import { ContractsLoader } from "./services/blockchain.repo"; -import { Cache } from "./services/cache.repo"; -import { config } from "./config/env"; +import { abi } from "contracts-js"; +import pino from "pino"; import { http } from "viem"; import { createPublicClient } from "viem"; +import type { Chain } from "viem"; +import { arbitrum, arbitrumSepolia, hardhat } from "viem/chains"; +import { config } from "./config/env"; import * as indexerJob from "./indexer-job"; import { Server } from "./server"; -import { arbitrum, arbitrumSepolia, hardhat } from "viem/chains"; -import { Chain } from "viem"; +import { ContractsLoader } from "./services/blockchain.repo"; +import { Cache } from "./services/cache.repo"; import { ContractService } from "./services/contract.service"; import { PriceCalculator } from "./services/price-calculator"; -import pino from "pino"; const chains: Record = { [hardhat.id]: hardhat, @@ -29,12 +30,12 @@ async function main() { log.info("Connecting to blockchain..."); const chainId = await client0.getChainId(); - let chain = chains[chainId]; + const chain = chains[chainId]; if (!chain) { throw new Error(`Chain ${chainId} is not supported`); } - log.info("Chain ID", chainId); + log.info("Chain ID %s", chainId); if (config.MULTICALL_ADDRESS) { log.info("Using custom multicall address", config.MULTICALL_ADDRESS); @@ -57,7 +58,15 @@ async function main() { chain, }); - const loader = new ContractsLoader(client, config.CLONE_FACTORY_ADDRESS); + const feeTokenAddr = await client.readContract({ + abi: abi.cloneFactoryAbi, + address: config.CLONE_FACTORY_ADDRESS as `0x${string}`, + functionName: "feeToken", + }); + + log.info("Fee token address", feeTokenAddr); + + const loader = new ContractsLoader(client, config.CLONE_FACTORY_ADDRESS, feeTokenAddr); const feeRate = await loader.getFeeRate(); const cache = new Cache(); cache.setFeeRate(feeRate); @@ -68,18 +77,18 @@ async function main() { client, config.HASHRATE_ORACLE_ADDRESS as `0x${string}`, cache, - log.child({ module: "priceCalculator" }) - ) + log.child({ module: "priceCalculator" }), + ), ); const server = new Server(cache, loader, service, log.child({ module: "server" })); log.info(`Starting app with config: ${JSON.stringify(config)}`); // TODO: split into multiple phases - await Promise.all([ - indexerJob.start(client, loader, cache, log.child({ module: "indexerJob" })), - server.start(), - ]); + await Promise.all([indexerJob.start(client, loader, cache, log.child({ module: "indexerJob" })), server.start()]); } -main(); +main().catch((err) => { + console.error("Exiting app due to error", err); + process.exit(1); +}); diff --git a/src/config/env.ts b/src/config/env.ts index 17447b9..c5973be 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -1,5 +1,5 @@ +import { type Static, Type } from "@sinclair/typebox"; import envSchema from "env-schema"; -import { Type, Static } from "@sinclair/typebox"; const schema = Type.Object({ ADMIN_API_KEY: Type.String(), @@ -17,7 +17,7 @@ const schema = Type.Object({ Type.Literal("error"), Type.Literal("fatal"), ], - { default: "info" } + { default: "info" }, ), MULTICALL_ADDRESS: Type.Optional(Type.String()), PORT: Type.Integer({ default: 3000 }), diff --git a/src/indexer-job.ts b/src/indexer-job.ts index f872aec..dc6ed56 100644 --- a/src/indexer-job.ts +++ b/src/indexer-job.ts @@ -1,16 +1,11 @@ -import { PublicClient } from "viem"; -import { ContractsLoader } from "./services/blockchain.repo"; -import { Cache } from "./services/cache.repo"; +import type { FastifyBaseLogger } from "fastify"; +import type { PublicClient } from "viem"; +import type { ContractsLoader } from "./services/blockchain.repo"; +import type { Cache } from "./services/cache.repo"; import { startWatchPromise } from "./services/listener"; -import { HashrateContract } from "./types/hashrate-contract"; -import { FastifyBaseLogger } from "fastify"; +import type { HashrateContract } from "./types/hashrate-contract"; -export const start = async ( - client: PublicClient, - loader: ContractsLoader, - indexer: Cache, - log: FastifyBaseLogger -) => { +export const start = async (client: PublicClient, loader: ContractsLoader, indexer: Cache, log: FastifyBaseLogger) => { log.info("Initial load of contracts"); const res = await loader.loadAll(); @@ -35,12 +30,8 @@ export const start = async ( }); }; -function updateContract( - contract: HashrateContract, - blockNumber: number, - indexer: Cache, - log: FastifyBaseLogger -) { - indexer.upsert(contract, blockNumber); +function updateContract(contract: HashrateContract, blockNumber: number, cache: Cache, log: FastifyBaseLogger) { + cache.upsert(contract, blockNumber); + cache.setValidatorHistory(contract.id as `0x${string}`, contract.history); log.info(`Contract ${contract.id} updated in cache`); } diff --git a/src/routes/root.ts b/src/routes/root.ts index 503d109..43746f8 100644 --- a/src/routes/root.ts +++ b/src/routes/root.ts @@ -1,16 +1,16 @@ -import { ContractsLoader } from "../services/blockchain.repo"; -import { Config } from "../config/env"; -import { ContractService } from "../services/contract.service"; -import { Cache } from "../services/cache.repo"; -import { ServerType } from "../server"; import { Type } from "@sinclair/typebox"; +import type { Config } from "../config/env"; +import type { ServerType } from "../server"; +import type { ContractsLoader } from "../services/blockchain.repo"; +import type { Cache } from "../services/cache.repo"; +import type { ContractService } from "../services/contract.service"; export async function router( fastify: ServerType, config: Config, service: ContractService, indexer: Cache, - loader: ContractsLoader + loader: ContractsLoader, ) { fastify.get( "/admin/reloadContracts", @@ -21,7 +21,7 @@ export async function router( }), }, }, - async function (request) { + async (request) => { if (request.query.apiKey !== config.ADMIN_API_KEY) { return fastify.httpErrors.unauthorized(); } @@ -31,7 +31,7 @@ export async function router( indexer.upsert(contract, Number(all.blockNumber)); } return indexer.getAll(); - } + }, ); fastify.get( @@ -43,10 +43,10 @@ export async function router( }), }, }, - async function (request) { + async (request) => { const { walletAddr } = request.query; return service.getAll(walletAddr); - } + }, ); fastify.get( @@ -61,23 +61,36 @@ export async function router( }), }, }, - async function (request) { + async (request) => { const contract = await service.get(request.params.id, request.query.walletAddr); if (!contract) { return fastify.httpErrors.notFound("Contract not found"); } return contract; - } + }, + ); + + fastify.get( + "/validator/:validatorAddr", + { + schema: { + params: Type.Object({ + validatorAddr: Type.String(), + }), + }, + }, + async (request) => { + const { validatorAddr } = request.params; + return service.getValidatorHistory(validatorAddr); + }, ); - fastify.get("/healthcheck", async function () { - return { - status: "ok", - version: process.env.npm_package_version, - cloneFactoryAddress: config.CLONE_FACTORY_ADDRESS, - lastSyncedContractBlock: Number(indexer.lastSyncedContractBlock), - lastSyncedTime: Number(indexer.lastSyncedTime), - lastSyncedTimeISO: new Date(indexer.lastSyncedTime).toISOString(), - }; - }); + fastify.get("/healthcheck", async () => ({ + status: "ok", + version: process.env.npm_package_version, + cloneFactoryAddress: config.CLONE_FACTORY_ADDRESS, + lastSyncedContractBlock: Number(indexer.lastSyncedContractBlock), + lastSyncedTime: Number(indexer.lastSyncedTime), + lastSyncedTimeISO: new Date(indexer.lastSyncedTime).toISOString(), + })); } diff --git a/src/server.ts b/src/server.ts index 0368caa..97fb853 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,14 +1,15 @@ -import { config } from "./config/env"; -import Fastify from "fastify"; -import closeWithGrace from "close-with-grace"; import cors from "@fastify/cors"; -import { router } from "./routes/root"; -import { Cache } from "./services/cache.repo"; -import { ContractsLoader } from "./services/blockchain.repo"; import sensible from "@fastify/sensible"; -import { ContractService } from "./services/contract.service"; -import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox"; -import pino, { Logger } from "pino"; +import type { TypeBoxTypeProvider } from "@fastify/type-provider-typebox"; +import closeWithGrace from "close-with-grace"; +import Fastify from "fastify"; +import type pino from "pino"; +import type { Logger } from "pino"; +import { config } from "./config/env"; +import { router } from "./routes/root"; +import type { ContractsLoader } from "./services/blockchain.repo"; +import type { Cache } from "./services/cache.repo"; +import type { ContractService } from "./services/contract.service"; export class Server { private app: ServerType; @@ -17,7 +18,7 @@ export class Server { readonly indexer: Cache, readonly loader: ContractsLoader, readonly service: ContractService, - readonly log: Logger + readonly log: Logger, ) { this.app = createServer(log); @@ -34,7 +35,7 @@ export class Server { }, { prefix: "/api", - } + }, ); } @@ -46,15 +47,12 @@ export class Server { return new Promise((resolve, reject) => { const app = this.app; // delay is the number of milliseconds for the graceful close to finish - closeWithGrace( - { delay: config.FASTIFY_CLOSE_GRACE_DELAY }, - async function ({ signal, err, manual }) { - if (err) { - app.log.error(err); - } - await app.close(); + closeWithGrace({ delay: config.FASTIFY_CLOSE_GRACE_DELAY }, async ({ signal, err, manual }) => { + if (err) { + app.log.error(err); } - ); + await app.close(); + }); // Start listening. app.listen({ port: config.PORT, host: "0.0.0.0" }, (err) => { diff --git a/src/services/blockchain.repo.ts b/src/services/blockchain.repo.ts index bbbec2b..43039c8 100644 --- a/src/services/blockchain.repo.ts +++ b/src/services/blockchain.repo.ts @@ -1,21 +1,23 @@ import { abi } from "contracts-js"; -import { PublicClient } from "viem"; -import { HashrateContract } from "../types/hashrate-contract.js"; -import { mapContract, mapFutureTerms } from "./mapper"; +import type { PublicClient } from "viem"; +import type { HashrateContract } from "../types/hashrate-contract.js"; import { + type HistoryEntry, + type PublicVariablesV2Entry, + type StatsEntry, getCloneFactoryContract, - HistoryEntry, - PublicVariablesV2Entry, - StatsEntry, } from "./blockchain.types"; +import { mapContract, mapFutureTerms } from "./mapper"; export class ContractsLoader { pc: PublicClient; cloneFactory: ReturnType; + feeTokenAddr: `0x${string}`; - constructor(pc: PublicClient, cloneFactoryAddr: string) { + constructor(pc: PublicClient, cloneFactoryAddr: string, feeTokenAddr: `0x${string}`) { this.pc = pc; this.cloneFactory = getCloneFactoryContract(pc, cloneFactoryAddr); + this.feeTokenAddr = feeTokenAddr; } async loadAll() { @@ -42,24 +44,39 @@ export class ContractsLoader { address: id, functionName: "getStats", } as const, + { + abi: abi.implementationAbi, + address: id, + functionName: "validator", + } as const, + { + abi: abi.lumerinTokenAbi, + address: this.feeTokenAddr, + functionName: "balanceOf", + args: [id], + } as const, ]), allowFailure: false, blockNumber, }); // split results into chunks - const chunks = chunkArray(results, 3) as [PublicVariablesV2Entry, HistoryEntry, StatsEntry][]; + const chunks = chunkArray(results, 5) as [ + PublicVariablesV2Entry, + HistoryEntry, + StatsEntry, + `0x${string}`, + bigint, + ][]; const contractsMap: Record = {}; // load future terms for contracts that have them - let indexesToLoadFutureTerms: number[] = []; - let indexesToLoadPrice: number[] = []; - // TODO: reconstruct price for available contracts + const indexesToLoadFutureTerms: number[] = []; for (let i = 0; i < chunks.length; i++) { - const [publicVariablesV2, history, stats] = chunks[i]; + const [publicVariablesV2, history, stats, validator, balance] = chunks[i]; const contractId = contractIds[i]; - const mapped = mapContract(contractId, publicVariablesV2, undefined, history, stats); + const mapped = mapContract(contractId, publicVariablesV2, undefined, history, stats, validator, balance); contractsMap[contractId] = mapped; if (mapped.hasFutureTerms) { indexesToLoadFutureTerms.push(i); @@ -73,7 +90,7 @@ export class ContractsLoader { abi: abi.implementationAbi, address: contractIds[i], functionName: "futureTerms", - } as const) + }) as const, ), allowFailure: false, }); @@ -113,13 +130,24 @@ export class ContractsLoader { address: contractId, functionName: "futureTerms", } as const, + { + abi: abi.implementationAbi, + address: contractId, + functionName: "validator", + } as const, + { + abi: abi.lumerinTokenAbi, + address: this.feeTokenAddr, + functionName: "balanceOf", + args: [contractId], + } as const, ], allowFailure: false, }); - const [pub, history, stats, futureTerms] = multicall; + const [pub, history, stats, futureTerms, validator, balance] = multicall; - return mapContract(contractId, pub, futureTerms, history, stats); + return mapContract(contractId, pub, futureTerms, history, stats, validator, balance); } async getFeeRate() { diff --git a/src/services/blockchain.types.ts b/src/services/blockchain.types.ts index da92a7a..fe71da6 100644 --- a/src/services/blockchain.types.ts +++ b/src/services/blockchain.types.ts @@ -1,5 +1,5 @@ import { abi } from "contracts-js"; -import { PublicClient } from "viem"; +import type { PublicClient } from "viem"; import { getContract } from "viem"; // Using ReturnType applied to the function to alias the type from the blockchain call diff --git a/src/services/cache.repo.ts b/src/services/cache.repo.ts index 2ebb868..bb6f72e 100644 --- a/src/services/cache.repo.ts +++ b/src/services/cache.repo.ts @@ -1,15 +1,14 @@ -import { HashrateContract } from "../types/hashrate-contract.js"; +import type { ContractHistory, HashrateContract } from "../types/hashrate-contract.js"; /** * In-memory indexer(cache) for contracts that keeps track block and time of the last update */ export class Cache { contracts: Record = {}; - lastSyncedContractBlock: number = 0; - lastSyncedTime: number = 0; + lastSyncedContractBlock = 0; + lastSyncedTime = 0; feeRate: FeeRate = { value: 0n, decimals: 0n }; - - constructor() {} + validatorHistory: Map> = new Map(); // validator -> buyer+purchaseTime -> history get(id: string): HashrateContract | null { const contract = this.contracts[id.toLowerCase()]; @@ -27,6 +26,44 @@ export class Cache { }); } + getValidatorHistory(validator: `0x${string}`): ValidatorHistoryEntry[] { + const res: ValidatorHistoryEntry[] = []; + const history = this.validatorHistory.get(validator); + if (!history) { + return res; + } + for (const [_, value] of history.entries()) { + res.push({ ...value }); + } + return res; + } + + validatorHistoryKey(contractAddr: `0x${string}`, purchaseTime: string) { + return `${contractAddr}-${purchaseTime}`; + } + + setValidatorHistory(contractAddr: `0x${string}`, history: ContractHistory[]) { + for (const h of history) { + let singleValidatorHistory = this.validatorHistory.get(h.validator); + if (!singleValidatorHistory) { + singleValidatorHistory = new Map(); + this.validatorHistory.set(h.validator, singleValidatorHistory); + } + + const key = this.validatorHistoryKey(contractAddr, h.purchaseTime); + singleValidatorHistory.set(key, { + buyer: h.buyer as `0x${string}`, + purchaseTime: h.purchaseTime, + endTime: h.endTime, + price: h.price, + fee: h.fee, + speed: h.speed, + length: h.length, + contract: contractAddr, + }); + } + } + upsert(contract: HashrateContract, blockNumber: number) { this.contracts[contract.id] = contract; this.#setLastSyncedContractBlock(blockNumber); diff --git a/src/services/contract.service.ts b/src/services/contract.service.ts index 614f6a2..8ab77ba 100644 --- a/src/services/contract.service.ts +++ b/src/services/contract.service.ts @@ -1,34 +1,49 @@ import { - HashrateContract, CONTRACT_STATE, - ContractHistory, - ContractState, + type ContractHistory, + type ContractState, + type HashrateContract, } from "../types/hashrate-contract"; -import { Cache } from "./cache.repo"; -import { PriceCalculator } from "./price-calculator"; +import type { Cache } from "./cache.repo"; +import type { GetResponse } from "./contract.service.types"; +import type { PriceCalculator } from "./price-calculator"; /** Service for managing hashrate contracts. Adds price calculation and optional filtering history by wallet address */ export class ContractService { - constructor(private readonly indexer: Cache, private readonly priceCalculator: PriceCalculator) {} + constructor( + private readonly indexer: Cache, + private readonly priceCalculator: PriceCalculator, + ) {} - async getAll(filterHistoryByAddr?: string): Promise { + async getAll(filterHistoryByAddr?: string): Promise> { const contracts = this.indexer.getAll(); - return Promise.all(contracts.map((c) => this.#adjustContract(c, filterHistoryByAddr))); + const data = await Promise.all(contracts.map((c) => this.#adjustContract(c, filterHistoryByAddr))); + return { + data, + blockNumber: this.indexer.lastSyncedContractBlock, + }; } - async get(id: string, filterHistoryByAddr?: string): Promise { + async get(id: string, filterHistoryByAddr?: string): Promise> { const contract = this.indexer.get(id); - if (!contract) { - return null; - } + const data = contract && (await this.#adjustContract(contract, filterHistoryByAddr)); + + return { + data, + blockNumber: this.indexer.lastSyncedContractBlock, + }; + } + + async getValidatorHistory(validatorAddr: string): Promise> { + const history = this.indexer.getValidatorHistory(validatorAddr as `0x${string}`); - return await this.#adjustContract(contract, filterHistoryByAddr); + return { + data: history, + blockNumber: this.indexer.lastSyncedContractBlock, + }; } - async #adjustContract( - contract: HashrateContract, - filterHistoryByAddr?: string - ): Promise { + async #adjustContract(contract: HashrateContract, filterHistoryByAddr?: string): Promise { const { price, fee } = await this.#calculatePriceAndFee(contract); return { @@ -45,15 +60,12 @@ export class ContractService { if (filterHistoryByAddr) { historyCopy = this.#filterHistoryByWalletAddr(historyCopy, filterHistoryByAddr); } - return this.#filterActiveContractFromHistory(historyCopy); + return historyCopy; } async #calculatePriceAndFee(contract: HashrateContract) { const totalHashes = BigInt(contract.speed) * BigInt(contract.length); - const { price, fee } = await this.priceCalculator.calculatePriceAndFee( - totalHashes, - BigInt(contract.profitTarget) - ); + const { price, fee } = await this.priceCalculator.calculatePriceAndFee(totalHashes, BigInt(contract.profitTarget)); return { price, fee }; } @@ -61,12 +73,6 @@ export class ContractService { return history.filter((h) => h.buyer.toLowerCase() === walletAddr.toLowerCase()); } - #filterActiveContractFromHistory(history: ContractHistory[]): ContractHistory[] { - return history.filter((h) => { - return Number(h.endTime) * 1000 < Date.now(); - }); - } - #getContractState(contract: HashrateContract): ContractState { const expirationTime = (+contract.startingBlockTimestamp + +contract.length) * 1000; if (expirationTime < Date.now()) { diff --git a/src/services/contract.service.types.ts b/src/services/contract.service.types.ts new file mode 100644 index 0000000..8527588 --- /dev/null +++ b/src/services/contract.service.types.ts @@ -0,0 +1,5 @@ +// generic response type for all get requests +export type GetResponse = { + data: T; + blockNumber: number; +}; diff --git a/src/services/listener.ts b/src/services/listener.ts index b59809d..df9954e 100644 --- a/src/services/listener.ts +++ b/src/services/listener.ts @@ -1,8 +1,7 @@ -import { config } from "../config/env"; -import { getAbiItem, parseAbi, PublicClient } from "viem"; -import { FastifyBaseLogger } from "fastify"; import { abi } from "contracts-js"; -import { FeeRate } from "./cache.repo"; +import type { FastifyBaseLogger } from "fastify"; +import { type PublicClient, getAbiItem, isAddressEqual } from "viem"; +import { config } from "../config/env"; const cfAbi = abi.cloneFactoryAbi; const implAbi = abi.implementationAbi; @@ -31,15 +30,8 @@ export function startWatchPromise(pc: PublicClient, props: StartWatchProps): Pro function startWatch(pc: PublicClient, props: StartWatchProps) { const contractsToWatch = props.initialContractsToWatch; - const addresses = [config.CLONE_FACTORY_ADDRESS, ...contractsToWatch] as `0x${string}`[]; - const cloneFactoryEvents = [ - "contractCreated", - "clonefactoryContractPurchased", - "contractDeleteUpdated", - "purchaseInfoUpdated", - "validatorFeeRateUpdated", - ]; + const addresses = [config.CLONE_FACTORY_ADDRESS, ...contractsToWatch] as `0x${string}`[]; const eventsAbi2 = [ // Clone Factory Events @@ -50,8 +42,8 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { getAbiItem({ abi: cfAbi, name: "validatorFeeRateUpdated" }), // Implementation Events getAbiItem({ abi: implAbi, name: "closedEarly" }), - getAbiItem({ abi: implAbi, name: "fundsClaimed" }), getAbiItem({ abi: implAbi, name: "destinationUpdated" }), + getAbiItem({ abi: implAbi, name: "fundsClaimed" }), ]; let unwatch: () => void; @@ -65,36 +57,57 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { onLogs: (logs) => { props.log.info(`Received logs: ${logs.length}`); - logs.forEach((log) => { + for (const log of logs) { const { eventName, args, address, blockNumber } = log; + props.log.info( + `Received ${log.eventName} on ${log.address} with args ${JSON.stringify(log.args)}` + ); - if (eventName === "validatorFeeRateUpdated") { - props.log.info("Received validatorFeeRateUpdated event"); - return props.onFeeUpdate(args._validatorFeeRateScaled!); - } - - let contractAddress = null; - if (cloneFactoryEvents.includes(eventName)) { - contractAddress = (args as any)._address; - } else { - contractAddress = address; - } - props.log.info(`Received ${eventName}, for ${contractAddress} contract`); - - props.onContractUpdate(contractAddress, Number(blockNumber)); - - if (eventName === "contractCreated") { - contractsToWatch.add(contractAddress); - props.log.info("Got contract created event, restating watch"); - unwatch(); - const newWatch = startWatch(pc, { - ...props, - blockNumber: Number(blockNumber), - initialContractsToWatch: contractsToWatch, - }); - unwatch = newWatch.unwatch; + switch (eventName) { + // + // contract update emitted on implementation contract + // + case "closedEarly": + return props.onContractUpdate(address, Number(blockNumber)); + case "destinationUpdated": + return props.onContractUpdate(address, Number(blockNumber)); + case "fundsClaimed": + return props.onContractUpdate(address, Number(blockNumber)); + // + // contract update emitted on clonefactory contract + // + case "clonefactoryContractPurchased": + return props.onContractUpdate(args._address!, Number(blockNumber)); + case "contractDeleteUpdated": + return props.onContractUpdate(args._address!, Number(blockNumber)); + case "purchaseInfoUpdated": + // this event is emitted both on clonefactory and implementation contract with the same abi + if (isAddressEqual(address, config.CLONE_FACTORY_ADDRESS as `0x${string}`)) { + props.onContractUpdate(args._address!, Number(blockNumber)); + } + return; + // + // contract created has to restart the watch + // + case "contractCreated": { + contractsToWatch.add(args._address!); + props.log.info("Got contract created event, restating watch"); + unwatch(); + const newWatch = startWatch(pc, { + ...props, + blockNumber: Number(blockNumber + 1n), + initialContractsToWatch: contractsToWatch, + }); + unwatch = newWatch.unwatch; + return props.onContractUpdate(args._address!, Number(blockNumber)); + } + // + // other events + // + case "validatorFeeRateUpdated": + return props.onFeeUpdate(args._validatorFeeRateScaled!); } - }); + } }, onError: (error) => { props.log.error("Event listener error", error); diff --git a/src/services/mapper.ts b/src/services/mapper.ts index 96cbed1..88fe55b 100644 --- a/src/services/mapper.ts +++ b/src/services/mapper.ts @@ -1,6 +1,6 @@ -import { ContractState, HashrateContract } from "../types/hashrate-contract"; -import { FutureTerms, ContractHistory, Stats } from "../types/hashrate-contract"; -import { +import type { ContractState, HashrateContract } from "../types/hashrate-contract"; +import type { ContractHistory, FutureTerms, Stats } from "../types/hashrate-contract"; +import type { FutureTermsEntry, HistoryEntry, PublicVariablesV2Entry, @@ -12,7 +12,9 @@ export function mapContract( pub: PublicVariablesV2Entry, fut: FutureTermsEntry | undefined, history: HistoryEntry, - stats: StatsEntry + stats: StatsEntry, + validator: `0x${string}`, + feeBalance: bigint ): HashrateContract { const pubVars = mapPublicVariablesV2(address, pub); @@ -23,6 +25,8 @@ export function mapContract( futureTerms: mapFutureTerms(fut), history: mapHistory(history), stats: mapStats(stats), + validator, + feeBalance: feeBalance.toString(), }; } @@ -74,12 +78,14 @@ export function mapFutureTerms(futureTerms: FutureTermsEntry | undefined): Futur export function mapHistory(history: HistoryEntry): ContractHistory[] { return history.map((data) => ({ buyer: data._buyer, + validator: data._validator, endTime: data._endTime.toString(), price: data._price.toString(), + fee: data._fee.toString(), speed: data._speed.toString(), length: data._length.toString(), purchaseTime: data._purchaseTime.toString(), - isGoodCloseout: data._goodCloseout, + isGoodCloseout: data._purchaseTime + data._length === data._endTime, })); } diff --git a/src/services/price-calculator.ts b/src/services/price-calculator.ts index 2e2227e..ba82b21 100644 --- a/src/services/price-calculator.ts +++ b/src/services/price-calculator.ts @@ -1,8 +1,8 @@ -import { PublicClient, getContract } from "viem"; -import { hashrateOracleAbi, cloneFactoryAbi } from "contracts-js/dist/abi/abi"; -import { Logger } from "pino"; import { Mutex } from "async-mutex"; -import { FeeRate } from "./cache.repo"; +import { cloneFactoryAbi, hashrateOracleAbi } from "contracts-js/dist/abi/abi"; +import type { Logger } from "pino"; +import { type PublicClient, getContract } from "viem"; +import type { FeeRate } from "./cache.repo"; interface FeeRateGetter { getFeeRate(): FeeRate; @@ -17,12 +17,7 @@ export class PriceCalculator { private feeRateGetter: FeeRateGetter; private log: Logger; - constructor( - client: PublicClient, - hashrateOracleAddr: `0x${string}`, - feeRateGetter: FeeRateGetter, - log: Logger - ) { + constructor(client: PublicClient, hashrateOracleAddr: `0x${string}`, feeRateGetter: FeeRateGetter, log: Logger) { this.oracle = getHashrateOracleContract(client, hashrateOracleAddr); this.pricePerTHInToken = null; this.feeRateGetter = feeRateGetter; @@ -31,12 +26,11 @@ export class PriceCalculator { async calculatePriceAndFee( totalHashes: bigint, - profitTargetPercent: bigint + profitTargetPercent: bigint, ): Promise<{ price: bigint; fee: bigint }> { const hashesPerToken = await this.getHashesPerTokenCached(); const priceInTokens = totalHashes / hashesPerToken; - const priceWithProfit = - priceInTokens + (priceInTokens * BigInt(profitTargetPercent)) / BigInt(100); + const priceWithProfit = priceInTokens + (priceInTokens * BigInt(profitTargetPercent)) / BigInt(100); const { value, decimals } = await this.getFeeRate(); const fee = (priceWithProfit * value) / 10n ** decimals; return { price: priceWithProfit, fee }; diff --git a/src/types/hashrate-contract.ts b/src/types/hashrate-contract.ts index 62a8316..1e3cb0e 100644 --- a/src/types/hashrate-contract.ts +++ b/src/types/hashrate-contract.ts @@ -14,10 +14,12 @@ export type HashrateContract = { encrValidatorUrl: string; isDeleted: boolean; balance: string; + feeBalance: string; hasFutureTerms: boolean; history: ContractHistory[]; stats: Stats; futureTerms?: FutureTerms; + validator: `0x${string}`; }; /** Represents an internal stats object.**/ @@ -29,8 +31,10 @@ export type Stats = { /** Represents an internal contract history object.**/ export type ContractHistory = { buyer: string; + validator: string; endTime: string; price: string; + fee: string; speed: string; length: string; purchaseTime: string; diff --git a/src/types/history.ts b/src/types/history.ts new file mode 100644 index 0000000..b94ecc2 --- /dev/null +++ b/src/types/history.ts @@ -0,0 +1,10 @@ +type ValidatorHistoryEntry = { + contract: `0x${string}`; + purchaseTime: string; + endTime: string; + price: string; + fee: string; + speed: string; + length: string; + buyer: `0x${string}`; +}; From f7539ade2ebccdeae4e3259b0e67d13cc0155724 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Mon, 9 Jun 2025 15:12:03 +0200 Subject: [PATCH 28/35] fix: handling only single event from each block --- src/services/listener.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/services/listener.ts b/src/services/listener.ts index df9954e..d4ce795 100644 --- a/src/services/listener.ts +++ b/src/services/listener.ts @@ -68,24 +68,29 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { // contract update emitted on implementation contract // case "closedEarly": - return props.onContractUpdate(address, Number(blockNumber)); + props.onContractUpdate(address, Number(blockNumber)); + break; case "destinationUpdated": - return props.onContractUpdate(address, Number(blockNumber)); + props.onContractUpdate(address, Number(blockNumber)); + break; case "fundsClaimed": - return props.onContractUpdate(address, Number(blockNumber)); + props.onContractUpdate(address, Number(blockNumber)); + break; // // contract update emitted on clonefactory contract // case "clonefactoryContractPurchased": - return props.onContractUpdate(args._address!, Number(blockNumber)); + props.onContractUpdate(args._address!, Number(blockNumber)); + break; case "contractDeleteUpdated": - return props.onContractUpdate(args._address!, Number(blockNumber)); + props.onContractUpdate(args._address!, Number(blockNumber)); + break; case "purchaseInfoUpdated": // this event is emitted both on clonefactory and implementation contract with the same abi if (isAddressEqual(address, config.CLONE_FACTORY_ADDRESS as `0x${string}`)) { props.onContractUpdate(args._address!, Number(blockNumber)); } - return; + break; // // contract created has to restart the watch // @@ -99,13 +104,15 @@ function startWatch(pc: PublicClient, props: StartWatchProps) { initialContractsToWatch: contractsToWatch, }); unwatch = newWatch.unwatch; - return props.onContractUpdate(args._address!, Number(blockNumber)); + props.onContractUpdate(args._address!, Number(blockNumber)); + break; } // // other events // case "validatorFeeRateUpdated": - return props.onFeeUpdate(args._validatorFeeRateScaled!); + props.onFeeUpdate(args._validatorFeeRateScaled!); + break; } } }, From 2f4c4b13c674647e77d7a1db1b054abc6843a784 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Mon, 9 Jun 2025 15:12:16 +0200 Subject: [PATCH 29/35] feat: local https support --- .env.example | 3 ++- package-lock.json | 35 +++++++++++++++++++++++++++++++++++ package.json | 3 ++- src/app.ts | 11 +++++++---- src/config/env.ts | 3 ++- src/server.ts | 35 +++++++++++++++++++++++++++-------- 6 files changed, 75 insertions(+), 15 deletions(-) diff --git a/.env.example b/.env.example index ab42c31..12118ed 100644 --- a/.env.example +++ b/.env.example @@ -12,4 +12,5 @@ ADMIN_API_KEY=1234 CLONE_FACTORY_ADDRESS=0xb7f8bc63bbcad18155201308c8f3540b07f84f5e ETH_NODE_URL=http://localhost:8545 HASHRATE_ORACLE_ADDRESS=0xdc64a140aa3e981100a9beca4e685f962f0cf6c9 -PORT=3000 \ No newline at end of file +PORT=3000 +HTTPS=true // use for local https \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0baaadc..0bd2795 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@biomejs/biome": "^1.9.4", "@types/node": "^22.14.1", "pino-pretty": "^13.0.0", + "selfsigned": "^2.4.1", "tsx": "^4.19.3", "typescript": "^5.8.3" }, @@ -1563,6 +1564,16 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/abitype": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", @@ -2588,6 +2599,16 @@ "obliterator": "^2.0.1" } }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/obliterator": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", @@ -2947,6 +2968,20 @@ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", "license": "BSD-3-Clause" }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", diff --git a/package.json b/package.json index b815984..bc67ca8 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "@biomejs/biome": "^1.9.4", "@types/node": "^22.14.1", "pino-pretty": "^13.0.0", + "selfsigned": "^2.4.1", "tsx": "^4.19.3", "typescript": "^5.8.3" } -} +} \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index 3b86200..dcfc266 100644 --- a/src/app.ts +++ b/src/app.ts @@ -77,15 +77,18 @@ async function main() { client, config.HASHRATE_ORACLE_ADDRESS as `0x${string}`, cache, - log.child({ module: "priceCalculator" }), - ), + log.child({ module: "priceCalculator" }) + ) ); - const server = new Server(cache, loader, service, log.child({ module: "server" })); + const server = new Server(cache, loader, service, log.child({ module: "server" }), config.HTTPS); log.info(`Starting app with config: ${JSON.stringify(config)}`); // TODO: split into multiple phases - await Promise.all([indexerJob.start(client, loader, cache, log.child({ module: "indexerJob" })), server.start()]); + await Promise.all([ + indexerJob.start(client, loader, cache, log.child({ module: "indexerJob" })), + server.start(), + ]); } main().catch((err) => { diff --git a/src/config/env.ts b/src/config/env.ts index c5973be..9fdedad 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -17,10 +17,11 @@ const schema = Type.Object({ Type.Literal("error"), Type.Literal("fatal"), ], - { default: "info" }, + { default: "info" } ), MULTICALL_ADDRESS: Type.Optional(Type.String()), PORT: Type.Integer({ default: 3000 }), + HTTPS: Type.Boolean({ default: false }), }); export type Config = Static; diff --git a/src/server.ts b/src/server.ts index 97fb853..0bdf4ca 100644 --- a/src/server.ts +++ b/src/server.ts @@ -10,6 +10,8 @@ import { router } from "./routes/root"; import type { ContractsLoader } from "./services/blockchain.repo"; import type { Cache } from "./services/cache.repo"; import type { ContractService } from "./services/contract.service"; +import selfsigned from "selfsigned"; +import type { ServerOptions } from "node:https"; export class Server { private app: ServerType; @@ -19,8 +21,9 @@ export class Server { readonly loader: ContractsLoader, readonly service: ContractService, readonly log: Logger, + readonly isHttps: boolean ) { - this.app = createServer(log); + this.app = createServer(log, isHttps); this.app.register( async (instance, opts) => { @@ -35,7 +38,7 @@ export class Server { }, { prefix: "/api", - }, + } ); } @@ -47,12 +50,15 @@ export class Server { return new Promise((resolve, reject) => { const app = this.app; // delay is the number of milliseconds for the graceful close to finish - closeWithGrace({ delay: config.FASTIFY_CLOSE_GRACE_DELAY }, async ({ signal, err, manual }) => { - if (err) { - app.log.error(err); + closeWithGrace( + { delay: config.FASTIFY_CLOSE_GRACE_DELAY }, + async ({ signal, err, manual }) => { + if (err) { + app.log.error(err); + } + await app.close(); } - await app.close(); - }); + ); // Start listening. app.listen({ port: config.PORT, host: "0.0.0.0" }, (err) => { @@ -65,9 +71,22 @@ export class Server { } } -function createServer(log: pino.BaseLogger) { +function createServer(log: pino.BaseLogger, isHttps: boolean) { + let https: ServerOptions | null = null; + + if (isHttps) { + const attrs = [{ name: "commonName", value: "localhost" }]; + const pems = selfsigned.generate(attrs, { days: 365 }); + https = { + key: pems.private, + cert: pems.cert, + }; + } + const server = Fastify({ logger: log, + disableRequestLogging: true, + https, }).withTypeProvider(); return server; From 75677b105ca9e38f6fbafdd2d51adee061b89464 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Tue, 10 Jun 2025 15:41:13 +0200 Subject: [PATCH 30/35] healthcheck version --- package.json | 2 +- src/routes/root.ts | 13 +++++++------ tsconfig.json | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index bc67ca8..26a65e6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "contracts-indexer", - "version": "1.1.1", + "version": "1.1.2", "description": "", "main": "index.js", "engines": { diff --git a/src/routes/root.ts b/src/routes/root.ts index 43746f8..e03e1fb 100644 --- a/src/routes/root.ts +++ b/src/routes/root.ts @@ -4,13 +4,14 @@ import type { ServerType } from "../server"; import type { ContractsLoader } from "../services/blockchain.repo"; import type { Cache } from "../services/cache.repo"; import type { ContractService } from "../services/contract.service"; +import packageJson from "../../package.json"; export async function router( fastify: ServerType, config: Config, service: ContractService, indexer: Cache, - loader: ContractsLoader, + loader: ContractsLoader ) { fastify.get( "/admin/reloadContracts", @@ -31,7 +32,7 @@ export async function router( indexer.upsert(contract, Number(all.blockNumber)); } return indexer.getAll(); - }, + } ); fastify.get( @@ -46,7 +47,7 @@ export async function router( async (request) => { const { walletAddr } = request.query; return service.getAll(walletAddr); - }, + } ); fastify.get( @@ -67,7 +68,7 @@ export async function router( return fastify.httpErrors.notFound("Contract not found"); } return contract; - }, + } ); fastify.get( @@ -82,12 +83,12 @@ export async function router( async (request) => { const { validatorAddr } = request.params; return service.getValidatorHistory(validatorAddr); - }, + } ); fastify.get("/healthcheck", async () => ({ status: "ok", - version: process.env.npm_package_version, + version: packageJson.version || "unknown", cloneFactoryAddress: config.CLONE_FACTORY_ADDRESS, lastSyncedContractBlock: Number(indexer.lastSyncedContractBlock), lastSyncedTime: Number(indexer.lastSyncedTime), diff --git a/tsconfig.json b/tsconfig.json index b482627..d2c0864 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -44,7 +44,7 @@ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ // "noUncheckedSideEffectImports": true, /* Check side effect imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true /* Enable importing .json files. */, // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ From b319e8dfafa57876e9107681ed33be45d4191d05 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Tue, 10 Jun 2025 15:51:15 +0200 Subject: [PATCH 31/35] fix: remove selfsigned --- .env.example | 3 +-- src/app.ts | 2 +- src/config/env.ts | 1 - src/server.ts | 21 +++------------------ 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/.env.example b/.env.example index 12118ed..ab42c31 100644 --- a/.env.example +++ b/.env.example @@ -12,5 +12,4 @@ ADMIN_API_KEY=1234 CLONE_FACTORY_ADDRESS=0xb7f8bc63bbcad18155201308c8f3540b07f84f5e ETH_NODE_URL=http://localhost:8545 HASHRATE_ORACLE_ADDRESS=0xdc64a140aa3e981100a9beca4e685f962f0cf6c9 -PORT=3000 -HTTPS=true // use for local https \ No newline at end of file +PORT=3000 \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index dcfc266..5e9a12b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -81,7 +81,7 @@ async function main() { ) ); - const server = new Server(cache, loader, service, log.child({ module: "server" }), config.HTTPS); + const server = new Server(cache, loader, service, log.child({ module: "server" })); log.info(`Starting app with config: ${JSON.stringify(config)}`); // TODO: split into multiple phases diff --git a/src/config/env.ts b/src/config/env.ts index 9fdedad..b24eff6 100644 --- a/src/config/env.ts +++ b/src/config/env.ts @@ -21,7 +21,6 @@ const schema = Type.Object({ ), MULTICALL_ADDRESS: Type.Optional(Type.String()), PORT: Type.Integer({ default: 3000 }), - HTTPS: Type.Boolean({ default: false }), }); export type Config = Static; diff --git a/src/server.ts b/src/server.ts index 0bdf4ca..6d6ff5b 100644 --- a/src/server.ts +++ b/src/server.ts @@ -10,8 +10,6 @@ import { router } from "./routes/root"; import type { ContractsLoader } from "./services/blockchain.repo"; import type { Cache } from "./services/cache.repo"; import type { ContractService } from "./services/contract.service"; -import selfsigned from "selfsigned"; -import type { ServerOptions } from "node:https"; export class Server { private app: ServerType; @@ -20,10 +18,9 @@ export class Server { readonly indexer: Cache, readonly loader: ContractsLoader, readonly service: ContractService, - readonly log: Logger, - readonly isHttps: boolean + readonly log: Logger ) { - this.app = createServer(log, isHttps); + this.app = createServer(log); this.app.register( async (instance, opts) => { @@ -71,22 +68,10 @@ export class Server { } } -function createServer(log: pino.BaseLogger, isHttps: boolean) { - let https: ServerOptions | null = null; - - if (isHttps) { - const attrs = [{ name: "commonName", value: "localhost" }]; - const pems = selfsigned.generate(attrs, { days: 365 }); - https = { - key: pems.private, - cert: pems.cert, - }; - } - +function createServer(log: pino.BaseLogger) { const server = Fastify({ logger: log, disableRequestLogging: true, - https, }).withTypeProvider(); return server; From 4eb08bf5490471fc5e3bd80ef85726e9fe0e0f30 Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Tue, 10 Jun 2025 16:00:17 +0200 Subject: [PATCH 32/35] feat: add uptime --- src/routes/root.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/routes/root.ts b/src/routes/root.ts index e03e1fb..6dcb9ab 100644 --- a/src/routes/root.ts +++ b/src/routes/root.ts @@ -13,6 +13,8 @@ export async function router( indexer: Cache, loader: ContractsLoader ) { + const startTime = Date.now(); + fastify.get( "/admin/reloadContracts", { @@ -89,6 +91,7 @@ export async function router( fastify.get("/healthcheck", async () => ({ status: "ok", version: packageJson.version || "unknown", + uptimeSeconds: (Date.now() - startTime) / 1000, cloneFactoryAddress: config.CLONE_FACTORY_ADDRESS, lastSyncedContractBlock: Number(indexer.lastSyncedContractBlock), lastSyncedTime: Number(indexer.lastSyncedTime), From 449d1600b38daf3d7db130d07773a11d4241a57c Mon Sep 17 00:00:00 2001 From: "Oleksandr (Shev) Shevchuk" Date: Wed, 25 Jun 2025 17:39:05 +0200 Subject: [PATCH 33/35] fix: adjust to getHistory blockchain call signature change --- package-lock.json | 10 +++++----- package.json | 4 ++-- src/services/blockchain.repo.ts | 16 ++++++++++++---- src/services/blockchain.types.ts | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0bd2795..7926d11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "contracts-indexer", - "version": "1.1.1", + "version": "1.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "contracts-indexer", - "version": "1.1.1", + "version": "1.1.2", "license": "MIT", "dependencies": { "@fastify/cors": "^9.0.1", @@ -15,7 +15,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.6", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.7", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -1789,8 +1789,8 @@ } }, "node_modules/contracts-js": { - "version": "2.0.6", - "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#7f8e8f28fb2fcc3394bcf04c09d14c174269ef1c", + "version": "2.0.7", + "resolved": "git+ssh://git@github.com/Lumerin-protocol/contracts-js.git#e19cd0301992bf1717ccb2315e02ade3b1337079", "dependencies": { "ethereum-abi-types-generator": "^1.3.4" } diff --git a/package.json b/package.json index 26a65e6..c16c91d 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@sinclair/typebox": "^0.33.22", "async-mutex": "^0.5.0", "close-with-grace": "^2.2.0", - "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.6", + "contracts-js": "github:Lumerin-protocol/contracts-js#v2.0.7", "env-schema": "^5.2.1", "ethers": "^6.11.1", "fastify": "^4.26.1", @@ -42,4 +42,4 @@ "tsx": "^4.19.3", "typescript": "^5.8.3" } -} \ No newline at end of file +} diff --git a/src/services/blockchain.repo.ts b/src/services/blockchain.repo.ts index 43039c8..02026f5 100644 --- a/src/services/blockchain.repo.ts +++ b/src/services/blockchain.repo.ts @@ -66,7 +66,7 @@ export class ContractsLoader { HistoryEntry, StatsEntry, `0x${string}`, - bigint, + bigint ][]; const contractsMap: Record = {}; @@ -76,7 +76,15 @@ export class ContractsLoader { for (let i = 0; i < chunks.length; i++) { const [publicVariablesV2, history, stats, validator, balance] = chunks[i]; const contractId = contractIds[i]; - const mapped = mapContract(contractId, publicVariablesV2, undefined, history, stats, validator, balance); + const mapped = mapContract( + contractId, + publicVariablesV2, + undefined, + history, + stats, + validator, + balance + ); contractsMap[contractId] = mapped; if (mapped.hasFutureTerms) { indexesToLoadFutureTerms.push(i); @@ -90,7 +98,7 @@ export class ContractsLoader { abi: abi.implementationAbi, address: contractIds[i], functionName: "futureTerms", - }) as const, + } as const) ), allowFailure: false, }); @@ -118,7 +126,7 @@ export class ContractsLoader { abi: abi.implementationAbi, address: contractId, functionName: "getHistory", - args: [0n, 100n], + args: [0n, 100], } as const, { abi: abi.implementationAbi, diff --git a/src/services/blockchain.types.ts b/src/services/blockchain.types.ts index fe71da6..54892f6 100644 --- a/src/services/blockchain.types.ts +++ b/src/services/blockchain.types.ts @@ -30,7 +30,7 @@ export function getHistory(pc: PublicClient, contractId: string) { address: contractId as `0x${string}`, abi: abi.implementationAbi, client: pc, - }).read.getHistory([0n, 100n]); + }).read.getHistory([0n, 100]); } export function getStats(pc: PublicClient, contractId: string) { From ce824b10f191ed0244d88b14f646d2a220eee552 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Thu, 26 Jun 2025 17:23:56 -0400 Subject: [PATCH 34/35] add stg branch capability --- .github/workflows/build.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8653b2e..543bb6c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,6 +11,7 @@ on: push: branches: - main + - stg - dev - cicd/* @@ -100,7 +101,7 @@ jobs: name: Test Build Indexer Container if: ( - (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'dev')) || + (github.event_name == 'pull_request' && (github.base_ref == 'main' || github.base_ref == 'dev' || github.base_ref == 'stg')) || (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) ) runs-on: ubuntu-latest @@ -134,7 +135,7 @@ jobs: name: Build & Push Docker Image if: | ( - (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) || + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/stg')) || (github.event_name == 'workflow_dispatch' && (github.event.inputs.build_container == 'true')) ) needs: @@ -196,7 +197,7 @@ jobs: name: Deploy Indexer to GitLab if: | ( - (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/stg')) ) needs: - Generate-Tag @@ -222,6 +223,8 @@ jobs: # Determine branch if [ "${{ github.ref_name }}" == "dev" ]; then GITLABBRANCH="dev" + elif [ "${{ github.ref_name }}" == "stg" ]; then + GITLABBRANCH="stg" elif [ "${{ github.ref_name }}" == "main" ]; then GITLABBRANCH="main" else From 9bda2da24b757128c2a64aa61fb1a4d484b03b66 Mon Sep 17 00:00:00 2001 From: abs2023 Date: Thu, 26 Jun 2025 17:32:29 -0400 Subject: [PATCH 35/35] changed license file to test pipelines --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 0d42e78..c2b8c31 100644 --- a/LICENSE +++ b/LICENSE @@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file